Merge "adb: win32: LinePrinter Unicode support"
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..f9c3b4a
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,31 @@
+{
+ "presubmit": [
+ {
+ "name": "adbd_test"
+ },
+ {
+ "name": "debuggerd_test"
+ },
+ {
+ "name": "init_tests"
+ },
+ {
+ "name": "libbase_test"
+ },
+ {
+ "name": "libprocinfo_test"
+ },
+ {
+ "name": "memunreachable_test"
+ },
+ {
+ "name": "memunreachable_binder_test"
+ },
+ {
+ "name": "propertyinfoserializer_tests"
+ },
+ {
+ "name": "ziparchive-tests"
+ }
+ ]
+}
diff --git a/adb/Android.bp b/adb/Android.bp
index 1469e77..36bfad4 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -24,7 +24,7 @@
"-Wno-missing-field-initializers",
"-Wvla",
],
- rtti: true,
+ cpp_std: "experimental",
use_version_lib: true,
@@ -41,7 +41,10 @@
target: {
android: {
- cflags: ["-DADB_HOST=0"],
+ cflags: [
+ "-DADB_HOST=0",
+ "-Wthread-safety",
+ ],
},
host: {
@@ -68,7 +71,7 @@
"-DUNICODE=1",
"-D_UNICODE=1",
- // -std=gnu++11 doesn't set _GNU_SOURCE on Windows.
+ // Unlike on Linux, -std=gnu++ doesn't set _GNU_SOURCE on Windows.
"-D_GNU_SOURCE",
// MinGW hides some things behind _POSIX_SOURCE.
@@ -277,6 +280,19 @@
// will violate ODR
shared_libs: [],
+ required: [
+ "deploypatchgenerator",
+ ],
+
+ // Archive adb, adb.exe.
+ dist: {
+ targets: [
+ "dist_files",
+ "sdk",
+ "win_sdk",
+ ],
+ },
+
target: {
darwin: {
cflags: [
@@ -307,6 +323,8 @@
"daemon/auth.cpp",
"daemon/jdwp_service.cpp",
"daemon/usb.cpp",
+ "daemon/usb_ffs.cpp",
+ "daemon/usb_legacy.cpp",
],
local_include_dirs: [
@@ -337,6 +355,7 @@
compile_multilib: "both",
srcs: [
+ "daemon/abb_service.cpp",
"daemon/file_sync_service.cpp",
"daemon/framebuffer_service.cpp",
"daemon/mdns.cpp",
@@ -357,10 +376,6 @@
"libavb_user",
"libdiagnose_usb",
"libqemu_pipe",
-
- // `daemon/shell_service.cpp` uses selinux_android_setcon(), which is not exposed by
- // libselinux.
- "libselinux",
],
shared_libs: [
@@ -375,7 +390,16 @@
"libfs_mgr",
"liblog",
"libmdnssd",
+ "libselinux",
],
+
+ target: {
+ recovery: {
+ exclude_srcs: [
+ "daemon/abb_service.cpp",
+ ],
+ },
+ },
}
cc_library {
@@ -440,6 +464,40 @@
],
}
+cc_binary {
+ name: "abb",
+
+ defaults: ["adb_defaults"],
+ recovery_available: false,
+
+ srcs: [
+ "daemon/abb.cpp",
+ ],
+
+ cflags: [
+ "-D_GNU_SOURCE",
+ "-Wno-deprecated-declarations",
+ ],
+
+ strip: {
+ keep_symbols: true,
+ },
+
+ static_libs: [
+ "libadbd_core",
+ "libadbd_services",
+ "libcmd",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libutils",
+ "libselinux",
+ ],
+}
+
cc_test {
name: "adbd_test",
defaults: ["adb_defaults"],
@@ -485,7 +543,7 @@
},
}
-python_binary_host {
+python_test_host {
name: "adb_integration_test_device",
main: "test_device.py",
srcs: [
@@ -494,6 +552,8 @@
libs: [
"adb_py",
],
+ test_config: "adb_integration_test_device.xml",
+ test_suites: ["general-tests"],
version: {
py2: {
enabled: true,
diff --git a/adb/Android.mk b/adb/Android.mk
deleted file mode 100644
index 8b2d558..0000000
--- a/adb/Android.mk
+++ /dev/null
@@ -1,8 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-# Archive adb, adb.exe.
-$(call dist-for-goals,dist_files sdk win_sdk,$(HOST_OUT_EXECUTABLES)/adb)
-
-ifdef HOST_CROSS_OS
-$(call dist-for-goals,dist_files sdk win_sdk,$(ALL_MODULES.host_cross_adb.BUILT))
-endif
diff --git a/adb/NOTICE b/adb/NOTICE
index ff47c95..9ffcc08 100644
--- a/adb/NOTICE
+++ b/adb/NOTICE
@@ -189,63 +189,3 @@
END OF TERMS AND CONDITIONS
-------------------------------------------------------------
-libwinpthread license:
-------------------------------------------------------------
-Copyright (c) 2011 mingw-w64 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.
-
-
-/*
- * Parts of this library are derived by:
- *
- * Posix Threads library for Microsoft Windows
- *
- * Use at own risk, there is no implied warranty to this code.
- * It uses undocumented features of Microsoft Windows that can change
- * at any time in the future.
- *
- * (C) 2010 Lockless Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of Lockless Inc. nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
- * 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 COPYRIGHT HOLDER 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.
- */
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 791899e..06e4c50 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -73,39 +73,6 @@
android::base::GetExecutablePath().c_str());
}
-void fatal(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- char buf[1024];
- vsnprintf(buf, sizeof(buf), fmt, ap);
-
-#if ADB_HOST
- fprintf(stderr, "error: %s\n", buf);
-#else
- LOG(ERROR) << "error: " << buf;
-#endif
-
- va_end(ap);
- abort();
-}
-
-void fatal_errno(const char* fmt, ...) {
- int err = errno;
- va_list ap;
- va_start(ap, fmt);
- char buf[1024];
- vsnprintf(buf, sizeof(buf), fmt, ap);
-
-#if ADB_HOST
- fprintf(stderr, "error: %s: %s\n", buf, strerror(err));
-#else
- LOG(ERROR) << "error: " << buf << ": " << strerror(err);
-#endif
-
- va_end(ap);
- abort();
-}
-
uint32_t calculate_apacket_checksum(const apacket* p) {
uint32_t sum = 0;
for (size_t i = 0; i < p->msg.data_length; ++i) {
@@ -118,7 +85,7 @@
{
apacket* p = new apacket();
if (p == nullptr) {
- fatal("failed to allocate an apacket");
+ LOG(FATAL) << "failed to allocate an apacket";
}
memset(&p->msg, 0, sizeof(p->msg));
@@ -390,9 +357,14 @@
case A_OPEN: /* OPEN(local-id, 0, "destination") */
if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
- // TODO: Switch to string_view.
- std::string address(p->payload.begin(), p->payload.end());
- asocket* s = create_local_service_socket(address.c_str(), t);
+ std::string_view address(p->payload.begin(), p->payload.size());
+
+ // Historically, we received service names as a char*, and stopped at the first NUL
+ // byte. The client sent strings with null termination, which post-string_view, start
+ // being interpreted as part of the string, unless we explicitly strip them.
+ address = StripTrailingNulls(address);
+
+ asocket* s = create_local_service_socket(address, t);
if (s == nullptr) {
send_close(0, p->msg.arg0, t);
} else {
@@ -633,11 +605,11 @@
fprintf(stderr, "Full server startup log: %s\n", GetLogFilePath().c_str());
fprintf(stderr, "Server had pid: %d\n", pid);
- unique_fd fd(adb_open(GetLogFilePath().c_str(), O_RDONLY));
+ android::base::unique_fd fd(unix_open(GetLogFilePath(), O_RDONLY));
if (fd == -1) return;
// Let's not show more than 128KiB of log...
- adb_lseek(fd, -128 * 1024, SEEK_END);
+ unix_lseek(fd, -128 * 1024, SEEK_END);
std::string content;
if (!android::base::ReadFdToString(fd, &content)) return;
@@ -827,7 +799,7 @@
memcmp(temp, expected, expected_length) == 0) {
got_ack = true;
} else {
- ReportServerStartupFailure(GetProcessId(process_handle.get()));
+ ReportServerStartupFailure(pinfo.dwProcessId);
return -1;
}
} else {
diff --git a/adb/adb.h b/adb/adb.h
index f434e2d..d79cd2d 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -124,9 +124,6 @@
void print_packet(const char* label, apacket* p);
-void fatal(const char* fmt, ...) __attribute__((noreturn, format(__printf__, 1, 2)));
-void fatal_errno(const char* fmt, ...) __attribute__((noreturn, format(__printf__, 1, 2)));
-
void handle_packet(apacket* p, atransport* t);
int launch_server(const std::string& socket_spec);
@@ -142,9 +139,9 @@
atransport* find_emulator_transport_by_console_port(int console_port);
#endif
-int service_to_fd(const char* name, atransport* transport);
+int service_to_fd(std::string_view name, atransport* transport);
#if !ADB_HOST
-unique_fd daemon_service_to_fd(const char* name, atransport* transport);
+unique_fd daemon_service_to_fd(std::string_view name, atransport* transport);
#endif
#if ADB_HOST
@@ -152,6 +149,14 @@
#endif
#if !ADB_HOST
+asocket* daemon_service_to_socket(std::string_view name);
+#endif
+
+#if !ADB_HOST
+unique_fd execute_binder_command(std::string_view command);
+#endif
+
+#if !ADB_HOST
int init_jdwp(void);
asocket* create_jdwp_service_socket();
asocket* create_jdwp_tracker_service_socket();
@@ -201,6 +206,9 @@
#define CHUNK_SIZE (64 * 1024)
+// Argument delimeter for adb abb command.
+#define ABB_ARG_DELIMETER ('\0')
+
#if !ADB_HOST
#define USB_FFS_ADB_PATH "/dev/usb-ffs/adb/"
#define USB_FFS_ADB_EP(x) USB_FFS_ADB_PATH #x
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 715e04f..2fc8478 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -36,6 +36,7 @@
void adb_auth_init();
int adb_auth_keygen(const char* filename);
+int adb_auth_pubkey(const char* filename);
std::string adb_auth_get_userkey();
std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys();
diff --git a/adb/adb_integration_test_device.xml b/adb/adb_integration_test_device.xml
new file mode 100644
index 0000000..b892377
--- /dev/null
+++ b/adb/adb_integration_test_device.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<configuration description="Config to run adb integration tests for device">
+ <option name="test-suite-tag" value="adb_tests" />
+ <option name="test-suite-tag" value="adb_integration_device" />
+ <target_preparer class="com.android.tradefed.targetprep.SemaphoreTokenTargetPreparer">
+ <option name="disable" value="false" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.adb.AdbStopServerPreparer" />
+ <test class="com.android.tradefed.testtype.python.PythonBinaryHostTest" >
+ <option name="par-file-name" value="adb_integration_test_device" />
+ <option name="inject-android-serial" value="true" />
+ <option name="test-timeout" value="2m" />
+ </test>
+</configuration>
diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp
index 6cc274b..605d27d 100644
--- a/adb/adb_io.cpp
+++ b/adb/adb_io.cpp
@@ -20,6 +20,11 @@
#include <unistd.h>
+#if !ADB_HOST
+#include <sys/socket.h>
+#include <sys/un.h>
+#endif
+
#include <thread>
#include <android-base/stringprintf.h>
@@ -38,7 +43,8 @@
// The cost of sending two strings outweighs the cost of formatting.
// "adb sync" performance is affected by this.
- return WriteFdFmt(fd, "%04x%.*s", length, length, s.c_str());
+ auto str = android::base::StringPrintf("%04x", length).append(s);
+ return WriteFdExactly(fd, str);
}
bool ReadProtocolString(int fd, std::string* s, std::string* error) {
@@ -181,3 +187,79 @@
return false;
}
}
+
+#if defined(__linux__)
+bool SendFileDescriptor(int socket_fd, int fd) {
+ struct msghdr msg;
+ struct iovec iov;
+ char dummy = '!';
+ union {
+ cmsghdr cm;
+ char buffer[CMSG_SPACE(sizeof(int))];
+ } cm_un;
+
+ iov.iov_base = &dummy;
+ iov.iov_len = 1;
+ msg.msg_name = nullptr;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+ msg.msg_control = cm_un.buffer;
+ msg.msg_controllen = sizeof(cm_un.buffer);
+
+ cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ ((int*)CMSG_DATA(cmsg))[0] = fd;
+
+ int ret = TEMP_FAILURE_RETRY(sendmsg(socket_fd, &msg, 0));
+ if (ret < 0) {
+ D("sending file descriptor via socket %d failed: %s", socket_fd, strerror(errno));
+ return false;
+ }
+
+ D("sent file descriptor %d to via socket %d", fd, socket_fd);
+ return true;
+}
+
+bool ReceiveFileDescriptor(int socket_fd, unique_fd* fd, std::string* error) {
+ char dummy = '!';
+ union {
+ cmsghdr cm;
+ char buffer[CMSG_SPACE(sizeof(int))];
+ } cm_un;
+
+ iovec iov;
+ iov.iov_base = &dummy;
+ iov.iov_len = 1;
+
+ msghdr msg;
+ msg.msg_name = nullptr;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+ msg.msg_control = cm_un.buffer;
+ msg.msg_controllen = sizeof(cm_un.buffer);
+
+ cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ ((int*)(CMSG_DATA(cmsg)))[0] = -1;
+
+ int rc = TEMP_FAILURE_RETRY(recvmsg(socket_fd, &msg, 0));
+ if (rc <= 0) {
+ *error = perror_str("receiving file descriptor via socket failed");
+ D("receiving file descriptor via socket %d failed: %s", socket_fd, strerror(errno));
+ return false;
+ }
+
+ fd->reset(((int*)(CMSG_DATA(cmsg)))[0]);
+ D("received file descriptor %d to via socket %d", fd->get(), socket_fd);
+
+ return true;
+}
+#endif
diff --git a/adb/adb_io.h b/adb/adb_io.h
index aa550af..2ccaa32 100644
--- a/adb/adb_io.h
+++ b/adb/adb_io.h
@@ -21,6 +21,8 @@
#include <string>
+#include "adb_unique_fd.h"
+
// Sends the protocol "OKAY" message.
bool SendOkay(int fd);
@@ -73,4 +75,12 @@
// Same as above, but formats the string to send.
bool WriteFdFmt(int fd, const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
+#if !ADB_HOST
+// Sends an FD via Unix domain socket.
+bool SendFileDescriptor(int socket_fd, int fd);
+
+// Receives an FD via Unix domain socket.
+bool ReceiveFileDescriptor(int socket_fd, unique_fd* fd, std::string* error);
+#endif
+
#endif /* ADB_IO_H */
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
index 611b239..91b73a9 100644
--- a/adb/adb_io_test.cpp
+++ b/adb/adb_io_test.cpp
@@ -28,7 +28,6 @@
#include <string>
#include <android-base/file.h>
-#include <android-base/test_utils.h>
// All of these tests fail on Windows because they use the C Runtime open(),
// but the adb_io APIs expect file descriptors from adb_open(). This could
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index f4a92e3..be457a6 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -21,6 +21,7 @@
#include <algorithm>
#include <list>
+#include <memory>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -29,7 +30,6 @@
#include "socket_spec.h"
#include "sysdeps.h"
-#include "sysdeps/memory.h"
#include "transport.h"
// A listener is an entity which binds to a local port and, upon receiving a connection on that
@@ -105,7 +105,7 @@
s = create_local_socket(fd);
if (s) {
s->transport = listener->transport;
- connect_to_remote(s, listener->connect_to.c_str());
+ connect_to_remote(s, listener->connect_to);
return;
}
diff --git a/adb/adb_trace.cpp b/adb/adb_trace.cpp
index a8ec5fb..2bd6a3e 100644
--- a/adb/adb_trace.cpp
+++ b/adb/adb_trace.cpp
@@ -41,6 +41,11 @@
const char* tag, const char* file, unsigned int line,
const char* message) {
android::base::StderrLogger(id, severity, tag, file, line, message);
+#if defined(_WIN32)
+ // stderr can be buffered on Windows (and setvbuf doesn't seem to work), so explicitly flush.
+ fflush(stderr);
+#endif
+
#if !ADB_HOST
// Only print logs of INFO or higher to logcat, so that `adb logcat` with adbd tracing on
// doesn't result in exponential logging.
@@ -67,8 +72,7 @@
}
void start_device_log(void) {
- int fd = unix_open(get_log_file_name().c_str(),
- O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
+ int fd = unix_open(get_log_file_name(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
if (fd == -1) {
return;
}
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index ffac315..6960345 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -49,19 +49,19 @@
#if defined(_WIN32)
-constexpr char kNullFileName[] = "NUL";
+static constexpr char kNullFileName[] = "NUL";
#else
-constexpr char kNullFileName[] = "/dev/null";
+static constexpr char kNullFileName[] = "/dev/null";
#endif
void close_stdin() {
int fd = unix_open(kNullFileName, O_RDONLY);
if (fd == -1) {
- fatal_errno("failed to open %s", kNullFileName);
+ PLOG(FATAL) << "failed to open " << kNullFileName;
}
if (TEMP_FAILURE_RETRY(dup2(fd, STDIN_FILENO)) == -1) {
- fatal_errno("failed to redirect stdin to %s", kNullFileName);
+ PLOG(FATAL) << "failed to redirect stdin to " << kNullFileName;
}
unix_close(fd);
}
@@ -186,6 +186,48 @@
return line;
}
+std::string dump_header(const amessage* msg) {
+ unsigned command = msg->command;
+ int len = msg->data_length;
+ char cmd[9];
+ char arg0[12], arg1[12];
+ int n;
+
+ for (n = 0; n < 4; n++) {
+ int b = (command >> (n * 8)) & 255;
+ if (b < 32 || b >= 127) break;
+ cmd[n] = (char)b;
+ }
+ if (n == 4) {
+ cmd[4] = 0;
+ } else {
+ // There is some non-ASCII name in the command, so dump the hexadecimal value instead
+ snprintf(cmd, sizeof cmd, "%08x", command);
+ }
+
+ if (msg->arg0 < 256U)
+ snprintf(arg0, sizeof arg0, "%d", msg->arg0);
+ else
+ snprintf(arg0, sizeof arg0, "0x%x", msg->arg0);
+
+ if (msg->arg1 < 256U)
+ snprintf(arg1, sizeof arg1, "%d", msg->arg1);
+ else
+ snprintf(arg1, sizeof arg1, "0x%x", msg->arg1);
+
+ return android::base::StringPrintf("[%s] arg0=%s arg1=%s (len=%d) ", cmd, arg0, arg1, len);
+}
+
+std::string dump_packet(const char* name, const char* func, const apacket* p) {
+ std::string result = name;
+ result += ": ";
+ result += func;
+ result += ": ";
+ result += dump_header(&p->msg);
+ result += dump_hex(p->payload.data(), p->payload.size());
+ return result;
+}
+
std::string perror_str(const char* msg) {
return android::base::StringPrintf("%s: %s", msg, strerror(errno));
}
@@ -251,6 +293,9 @@
struct passwd pwent;
struct passwd* result;
int pwent_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (pwent_max == -1) {
+ pwent_max = 16384;
+ }
std::vector<char> buf(pwent_max);
int rc = getpwuid_r(getuid(), &pwent, buf.data(), buf.size(), &result);
if (rc == 0 && result) {
@@ -274,18 +319,6 @@
return android_dir;
}
-int syntax_error(const char* fmt, ...) {
- fprintf(stderr, "adb: usage: ");
-
- va_list ap;
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- fprintf(stderr, "\n");
- return 1;
-}
-
std::string GetLogFilePath() {
#if defined(_WIN32)
const char log_name[] = "adb.log";
@@ -295,13 +328,13 @@
DWORD nchars = GetTempPathW(arraysize(temp_path), temp_path);
if (nchars >= arraysize(temp_path) || nchars == 0) {
// If string truncation or some other error.
- fatal("cannot retrieve temporary file path: %s\n",
- android::base::SystemErrorCodeToString(GetLastError()).c_str());
+ LOG(FATAL) << "cannot retrieve temporary file path: "
+ << android::base::SystemErrorCodeToString(GetLastError());
}
std::string temp_path_utf8;
if (!android::base::WideToUTF8(temp_path, &temp_path_utf8)) {
- fatal_errno("cannot convert temporary file path from UTF-16 to UTF-8");
+ PLOG(FATAL) << "cannot convert temporary file path from UTF-16 to UTF-8";
}
return temp_path_utf8 + log_name;
@@ -311,3 +344,33 @@
return android::base::StringPrintf("%s/adb.%u.log", tmp_dir, getuid());
#endif
}
+
+[[noreturn]] static void error_exit_va(int error, const char* fmt, va_list va) {
+ fflush(stdout);
+ fprintf(stderr, "%s: ", android::base::Basename(android::base::GetExecutablePath()).c_str());
+
+ vfprintf(stderr, fmt, va);
+
+ if (error != 0) {
+ fprintf(stderr, ": %s", strerror(error));
+ }
+
+ putc('\n', stderr);
+ fflush(stderr);
+
+ exit(EXIT_FAILURE);
+}
+
+void error_exit(const char* fmt, ...) {
+ va_list va;
+ va_start(va, fmt);
+ error_exit_va(0, fmt, va);
+ va_end(va);
+}
+
+void perror_exit(const char* fmt, ...) {
+ va_list va;
+ va_start(va, fmt);
+ error_exit_va(errno, fmt, va);
+ va_end(va);
+}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index f764a0e..8253487 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -14,17 +14,18 @@
* limitations under the License.
*/
-#ifndef _ADB_UTILS_H_
-#define _ADB_UTILS_H_
+#pragma once
#include <condition_variable>
#include <mutex>
#include <string>
+#include <string_view>
+#include <type_traits>
#include <vector>
#include <android-base/macros.h>
-int syntax_error(const char*, ...);
+#include "adb.h"
void close_stdin();
@@ -42,12 +43,17 @@
std::string escape_arg(const std::string& s);
std::string dump_hex(const void* ptr, size_t byte_count);
+std::string dump_header(const amessage* msg);
+std::string dump_packet(const char* name, const char* func, const apacket* p);
std::string perror_str(const char* msg);
+[[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);
-extern int adb_close(int fd);
+int adb_close(int fd);
// Given forward/reverse targets, returns true if they look sane. If an error is found, fills
// |error| and returns false.
@@ -91,4 +97,46 @@
std::string GetLogFilePath();
-#endif
+inline std::string_view StripTrailingNulls(std::string_view str) {
+ size_t n = 0;
+ for (auto it = str.rbegin(); it != str.rend(); ++it) {
+ if (*it != '\0') {
+ break;
+ }
+ ++n;
+ }
+
+ str.remove_suffix(n);
+ return str;
+}
+
+// Base-10 stroll on a string_view.
+template <typename T>
+inline bool ParseUint(T* result, std::string_view str, std::string_view* remaining) {
+ if (str.empty() || !isdigit(str[0])) {
+ 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;
+ }
+ *result = value;
+ if (remaining) {
+ *remaining = str.substr(it - str.begin());
+ }
+ return true;
+}
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
index 341323f..bb09425 100644
--- a/adb/adb_utils_test.cpp
+++ b/adb/adb_utils_test.cpp
@@ -30,8 +30,8 @@
#include "sysdeps.h"
+#include <android-base/file.h>
#include <android-base/macros.h>
-#include <android-base/test_utils.h>
#ifdef _WIN32
static std::string subdir(const char* parent, const char* child) {
@@ -181,3 +181,48 @@
EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:a", &error));
EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:22x", &error));
}
+
+void TestParseUint(std::string_view string, bool expected_success, uint32_t expected_value = 0) {
+ // Standalone.
+ {
+ uint32_t value;
+ std::string_view remaining;
+ bool success = ParseUint(&value, string, &remaining);
+ EXPECT_EQ(success, expected_success);
+ if (expected_success) {
+ EXPECT_EQ(value, expected_value);
+ }
+ EXPECT_TRUE(remaining.empty());
+ }
+
+ // With trailing text.
+ {
+ std::string text = std::string(string) + "foo";
+ uint32_t value;
+ std::string_view remaining;
+ bool success = ParseUint(&value, text, &remaining);
+ EXPECT_EQ(success, expected_success);
+ if (expected_success) {
+ EXPECT_EQ(value, expected_value);
+ EXPECT_EQ(remaining, "foo");
+ }
+ }
+}
+
+TEST(adb_utils, ParseUint) {
+ TestParseUint("", false);
+ TestParseUint("foo", false);
+ TestParseUint("foo123", false);
+ TestParseUint("-1", false);
+
+ TestParseUint("123", true, 123);
+ TestParseUint("9999999999999999999999999", false);
+ TestParseUint(std::to_string(UINT32_MAX), true, UINT32_MAX);
+ TestParseUint("0" + std::to_string(UINT32_MAX), true, UINT32_MAX);
+ TestParseUint(std::to_string(static_cast<uint64_t>(UINT32_MAX) + 1), false);
+ TestParseUint("0" + std::to_string(static_cast<uint64_t>(UINT32_MAX) + 1), false);
+
+ std::string x = std::to_string(UINT32_MAX) + "123";
+ std::string_view substr = std::string_view(x).substr(0, std::to_string(UINT32_MAX).size());
+ TestParseUint(substr, true, UINT32_MAX);
+}
diff --git a/adb/benchmark_device.py b/adb/benchmark_device.py
index 00c2315..e56ef5a 100755
--- a/adb/benchmark_device.py
+++ b/adb/benchmark_device.py
@@ -60,8 +60,6 @@
if device == None:
device = adb.get_device()
- lock_max(device)
-
remote_path = "/dev/null"
local_path = "/tmp/adb_benchmark_temp"
@@ -69,7 +67,7 @@
f.truncate(file_size_mb * 1024 * 1024)
speeds = list()
- for _ in range(0, 5):
+ for _ in range(0, 10):
begin = time.time()
device.push(local=local_path, remote=remote_path)
end = time.time()
@@ -81,15 +79,13 @@
if device == None:
device = adb.get_device()
- lock_max(device)
-
remote_path = "/data/local/tmp/adb_benchmark_temp"
local_path = "/tmp/adb_benchmark_temp"
device.shell(["dd", "if=/dev/zero", "of=" + remote_path, "bs=1m",
"count=" + str(file_size_mb)])
speeds = list()
- for _ in range(0, 5):
+ for _ in range(0, 10):
begin = time.time()
device.pull(remote=remote_path, local=local_path)
end = time.time()
@@ -101,10 +97,8 @@
if device == None:
device = adb.get_device()
- lock_max(device)
-
speeds = list()
- for _ in range(0, 5):
+ for _ in range(0, 10):
begin = time.time()
device.shell(["dd", "if=/dev/zero", "bs=1m",
"count=" + str(file_size_mb)])
@@ -114,7 +108,10 @@
analyze("shell %dMiB" % file_size_mb, speeds)
def main():
- benchmark_pull()
+ device = adb.get_device()
+ unlock(device)
+ benchmark_push(device)
+ benchmark_pull(device)
if __name__ == "__main__":
main()
diff --git a/adb/client/adb_client.cpp b/adb/client/adb_client.cpp
index 1959258..9a25d10 100644
--- a/adb/client/adb_client.cpp
+++ b/adb/client/adb_client.cpp
@@ -144,48 +144,51 @@
}
std::string reason;
- int fd = socket_spec_connect(__adb_server_socket_spec, &reason);
- if (fd < 0) {
+ unique_fd fd;
+ if (!socket_spec_connect(&fd, __adb_server_socket_spec, nullptr, nullptr, &reason)) {
*error = android::base::StringPrintf("cannot connect to daemon at %s: %s",
__adb_server_socket_spec, reason.c_str());
return -2;
}
- if (memcmp(&service[0], "host", 4) != 0 && switch_socket_transport(fd, error)) {
+ if (memcmp(&service[0], "host", 4) != 0 && switch_socket_transport(fd.get(), error)) {
return -1;
}
- if (!SendProtocolString(fd, service)) {
+ if (!SendProtocolString(fd.get(), service)) {
*error = perror_str("write failure during connection");
- adb_close(fd);
return -1;
}
- if (!adb_status(fd, error)) {
- adb_close(fd);
+ if (!adb_status(fd.get(), error)) {
return -1;
}
- D("_adb_connect: return fd %d", fd);
- return fd;
+ D("_adb_connect: return fd %d", fd.get());
+ return fd.release();
}
bool adb_kill_server() {
D("adb_kill_server");
std::string reason;
- int fd = socket_spec_connect(__adb_server_socket_spec, &reason);
- if (fd < 0) {
+ unique_fd fd;
+ if (!socket_spec_connect(&fd, __adb_server_socket_spec, nullptr, nullptr, &reason)) {
fprintf(stderr, "cannot connect to daemon at %s: %s\n", __adb_server_socket_spec,
reason.c_str());
return true;
}
- if (!SendProtocolString(fd, "host:kill")) {
+ if (!SendProtocolString(fd.get(), "host:kill")) {
fprintf(stderr, "error: write failure during connection: %s\n", strerror(errno));
return false;
}
- ReadOrderlyShutdown(fd);
+ // The server might send OKAY, so consume that.
+ char buf[4];
+ ReadFdExactly(fd.get(), buf, 4);
+ // Now that no more data is expected, wait for socket orderly shutdown or error, indicating
+ // server death.
+ ReadOrderlyShutdown(fd.get());
return true;
}
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index 95574ed..21e0874 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -14,40 +14,47 @@
* limitations under the License.
*/
-#define TRACE_TAG ADB
+#include "adb_install.h"
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <algorithm>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include "adb.h"
#include "adb_client.h"
-#include "adb_install.h"
+#include "adb_unique_fd.h"
#include "adb_utils.h"
#include "client/file_sync_client.h"
#include "commandline.h"
#include "fastdeploy.h"
#include "sysdeps.h"
-#include <algorithm>
-#include <iostream>
-#include <string>
-#include <vector>
+static constexpr int kFastDeployMinApi = 24;
-#include <unistd.h>
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/test_utils.h>
-
-static bool _use_legacy_install() {
+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 !CanUseFeature(features, kFeatureCmd);
+ return CanUseFeature(features, feature);
+}
+
+static bool use_legacy_install() {
+ return !can_use_feature(kFeatureCmd);
+}
+
+static bool is_apex_supported() {
+ return can_use_feature(kFeatureApex);
}
static int pm_command(int argc, const char** argv) {
@@ -104,7 +111,7 @@
}
int uninstall_app(int argc, const char** argv) {
- if (_use_legacy_install()) {
+ if (use_legacy_install()) {
return uninstall_app_legacy(argc, argv);
}
return uninstall_app_streamed(argc, argv);
@@ -130,13 +137,26 @@
}
static int install_app_streamed(int argc, const char** argv, bool use_fastdeploy,
- bool use_localagent, const char* adb_path) {
+ bool use_localagent) {
printf("Performing Streamed Install\n");
// The last argument must be the APK file
const char* file = argv[argc - 1];
- if (!android::base::EndsWithIgnoreCase(file, ".apk")) {
- return syntax_error("filename doesn't end .apk: %s", file);
+ if (!android::base::EndsWithIgnoreCase(file, ".apk") &&
+ !android::base::EndsWithIgnoreCase(file, ".apex")) {
+ error_exit("filename doesn't end .apk or .apex: %s", file);
+ }
+
+ bool is_apex = false;
+ if (android::base::EndsWithIgnoreCase(file, ".apex")) {
+ is_apex = true;
+ }
+ if (is_apex && !is_apex_supported()) {
+ error_exit(".apex is not supported on the target device");
+ }
+
+ if (is_apex && use_fastdeploy) {
+ error_exit("--fastdeploy doesn't support .apex files");
}
if (use_fastdeploy == true) {
@@ -144,40 +164,16 @@
TemporaryFile patchTmpFile;
FILE* metadataFile = fopen(metadataTmpFile.path, "wb");
- int metadata_len = extract_metadata(file, metadataFile);
+ extract_metadata(file, metadataFile);
fclose(metadataFile);
- int result = -1;
- if (metadata_len <= 0) {
- printf("failed to extract metadata %d\n", metadata_len);
- return 1;
- } else {
- int create_patch_result = create_patch(file, metadataTmpFile.path, patchTmpFile.path,
- use_localagent, adb_path);
- if (create_patch_result != 0) {
- printf("Patch creation failure, error code: %d\n", create_patch_result);
- result = create_patch_result;
- goto cleanup_streamed_apk;
- } else {
- std::vector<const char*> pm_args;
- // pass all but 1st (command) and last (apk path) parameters through to pm for
- // session creation
- for (int i = 1; i < argc - 1; i++) {
- pm_args.push_back(argv[i]);
- }
- int apply_patch_result =
- install_patch(file, patchTmpFile.path, pm_args.size(), pm_args.data());
- if (apply_patch_result != 0) {
- printf("Patch application failure, error code: %d\n", apply_patch_result);
- result = apply_patch_result;
- goto cleanup_streamed_apk;
- }
- }
- }
-
- cleanup_streamed_apk:
+ create_patch(file, metadataTmpFile.path, patchTmpFile.path);
+ // 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, patchTmpFile.path, pm_args.size(), pm_args.data());
delete_device_patch_file(file);
- return result;
+ return 0;
} else {
struct stat sb;
if (stat(file, &sb) == -1) {
@@ -185,8 +181,8 @@
return 1;
}
- int localFd = adb_open(file, O_RDONLY);
- if (localFd < 0) {
+ 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;
}
@@ -203,19 +199,19 @@
// do last to override any user specified value
cmd += " " + android::base::StringPrintf("-S %" PRIu64, static_cast<uint64_t>(sb.st_size));
- int remoteFd = adb_connect(cmd, &error);
- if (remoteFd < 0) {
+ 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());
- adb_close(localFd);
return 1;
}
char buf[BUFSIZ];
- copy_to_file(localFd, remoteFd);
- read_status_line(remoteFd, buf, sizeof(buf));
-
- adb_close(localFd);
- adb_close(remoteFd);
+ 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);
@@ -226,65 +222,40 @@
}
}
-static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy, bool use_localagent,
- const char* adb_path) {
- static const char* const DATA_DEST = "/data/local/tmp/%s";
- static const char* const SD_DEST = "/sdcard/tmp/%s";
- const char* where = DATA_DEST;
-
+static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy,
+ bool use_localagent) {
printf("Performing Push Install\n");
- for (int i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-s")) {
- where = SD_DEST;
- }
- }
-
// Find last APK argument.
// All other arguments passed through verbatim.
int last_apk = -1;
for (int i = argc - 1; i >= 0; i--) {
+ if (android::base::EndsWithIgnoreCase(argv[i], ".apex")) {
+ error_exit("APEX packages are only compatible with Streamed Install");
+ }
if (android::base::EndsWithIgnoreCase(argv[i], ".apk")) {
last_apk = i;
break;
}
}
- if (last_apk == -1) return syntax_error("need APK file on command line");
+ if (last_apk == -1) error_exit("need APK file on command line");
int result = -1;
std::vector<const char*> apk_file = {argv[last_apk]};
std::string apk_dest =
- android::base::StringPrintf(where, android::base::Basename(argv[last_apk]).c_str());
-
- TemporaryFile metadataTmpFile;
- TemporaryFile patchTmpFile;
+ "/data/local/tmp/" + android::base::Basename(argv[last_apk]);
if (use_fastdeploy == true) {
+ TemporaryFile metadataTmpFile;
+ TemporaryFile patchTmpFile;
+
FILE* metadataFile = fopen(metadataTmpFile.path, "wb");
- int metadata_len = extract_metadata(apk_file[0], metadataFile);
+ extract_metadata(apk_file[0], metadataFile);
fclose(metadataFile);
- if (metadata_len <= 0) {
- printf("failed to extract metadata %d\n", metadata_len);
- return 1;
- } else {
- int create_patch_result = create_patch(apk_file[0], metadataTmpFile.path,
- patchTmpFile.path, use_localagent, adb_path);
- if (create_patch_result != 0) {
- printf("Patch creation failure, error code: %d\n", create_patch_result);
- result = create_patch_result;
- goto cleanup_apk;
- } else {
- int apply_patch_result =
- apply_patch_on_device(apk_file[0], patchTmpFile.path, apk_dest.c_str());
- if (apply_patch_result != 0) {
- printf("Patch application failure, error code: %d\n", apply_patch_result);
- result = apply_patch_result;
- goto cleanup_apk;
- }
- }
- }
+ create_patch(apk_file[0], metadataTmpFile.path, patchTmpFile.path);
+ apply_patch_on_device(apk_file[0], patchTmpFile.path, apk_dest.c_str());
} else {
if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
}
@@ -293,7 +264,9 @@
result = pm_command(argc, argv);
cleanup_apk:
- delete_device_patch_file(apk_file[0]);
+ if (use_fastdeploy == true) {
+ delete_device_patch_file(apk_file[0]);
+ }
delete_device_file(apk_dest);
return result;
}
@@ -327,9 +300,6 @@
} else if (!strcmp(argv[i], "--no-fastdeploy")) {
processedArgIndicies.push_back(i);
use_fastdeploy = false;
- } else if (!strcmp(argv[i], "-f")) {
- processedArgIndicies.push_back(i);
- use_fastdeploy = true;
} else if (!strcmp(argv[i], "--force-agent")) {
processedArgIndicies.push_back(i);
agent_update_strategy = FastDeploy_AgentUpdateAlways;
@@ -345,24 +315,18 @@
use_localagent = true;
#endif
}
- // TODO: --installlog <filename>
}
if (installMode == INSTALL_DEFAULT) {
- if (_use_legacy_install()) {
+ if (use_legacy_install()) {
installMode = INSTALL_PUSH;
} else {
installMode = INSTALL_STREAM;
}
}
- if (installMode == INSTALL_STREAM && _use_legacy_install() == true) {
- return syntax_error("Attempting to use streaming install on unsupported deivce.");
- }
-
- if (use_fastdeploy == true && is_reinstall == false) {
- printf("Fast Deploy is only available with -r.\n");
- use_fastdeploy = false;
+ if (installMode == INSTALL_STREAM && use_legacy_install() == true) {
+ error_exit("Attempting to use streaming install on unsupported device");
}
if (use_fastdeploy == true && get_device_api_level() < kFastDeployMinApi) {
@@ -379,28 +343,26 @@
passthrough_argv.push_back(argv[i]);
}
}
-
- std::string adb_path = android::base::GetExecutablePath();
-
- if (adb_path.length() == 0) {
- return 1;
+ if (passthrough_argv.size() < 2) {
+ error_exit("install requires an apk argument");
}
+
if (use_fastdeploy == true) {
- bool agent_up_to_date =
- update_agent(agent_update_strategy, use_localagent, adb_path.c_str());
- if (agent_up_to_date == false) {
- printf("Failed to update agent, exiting\n");
- return 1;
- }
+ 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);
}
switch (installMode) {
case INSTALL_PUSH:
return install_app_legacy(passthrough_argv.size(), passthrough_argv.data(),
- use_fastdeploy, use_localagent, adb_path.c_str());
+ use_fastdeploy, use_localagent);
case INSTALL_STREAM:
return install_app_streamed(passthrough_argv.size(), passthrough_argv.data(),
- use_fastdeploy, use_localagent, adb_path.c_str());
+ use_fastdeploy, use_localagent);
case INSTALL_DEFAULT:
default:
return 1;
@@ -414,8 +376,13 @@
uint64_t total_size = 0;
for (int i = argc - 1; i >= 0; i--) {
const char* file = argv[i];
+ if (android::base::EndsWithIgnoreCase(argv[i], ".apex")) {
+ error_exit("APEX packages are not compatible with install-multiple");
+ }
- if (android::base::EndsWithIgnoreCase(file, ".apk")) {
+ if (android::base::EndsWithIgnoreCase(file, ".apk") ||
+ android::base::EndsWithIgnoreCase(file, ".dm") ||
+ android::base::EndsWithIgnoreCase(file, ".fsv_sig")) {
struct stat sb;
if (stat(file, &sb) != -1) total_size += sb.st_size;
first_apk = i;
@@ -424,10 +391,10 @@
}
}
- if (first_apk == -1) return syntax_error("need APK file on command line");
+ if (first_apk == -1) error_exit("need APK file on command line");
std::string install_cmd;
- if (_use_legacy_install()) {
+ if (use_legacy_install()) {
install_cmd = "exec:pm";
} else {
install_cmd = "exec:cmd package";
@@ -441,14 +408,15 @@
// Create install session
std::string error;
- int fd = adb_connect(cmd, &error);
- if (fd < 0) {
- fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
- return EXIT_FAILURE;
- }
char buf[BUFSIZ];
- read_status_line(fd, buf, sizeof(buf));
- adb_close(fd);
+ {
+ unique_fd fd(adb_connect(cmd, &error));
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
+ return EXIT_FAILURE;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
+ }
int session_id = -1;
if (!strncmp("Success", buf, 7)) {
@@ -477,31 +445,27 @@
}
std::string cmd =
- android::base::StringPrintf("%s install-write -S %" PRIu64 " %d %d_%s -",
+ android::base::StringPrintf("%s install-write -S %" PRIu64 " %d %s -",
install_cmd.c_str(), static_cast<uint64_t>(sb.st_size),
- session_id, i, android::base::Basename(file).c_str());
+ session_id, android::base::Basename(file).c_str());
- int localFd = adb_open(file, O_RDONLY);
- if (localFd < 0) {
+ 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;
goto finalize_session;
}
std::string error;
- int remoteFd = adb_connect(cmd, &error);
- if (remoteFd < 0) {
+ unique_fd remote_fd(adb_connect(cmd, &error));
+ if (remote_fd < 0) {
fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
- adb_close(localFd);
success = 0;
goto finalize_session;
}
- copy_to_file(localFd, remoteFd);
- read_status_line(remoteFd, buf, sizeof(buf));
-
- adb_close(localFd);
- adb_close(remoteFd);
+ copy_to_file(local_fd.get(), remote_fd.get());
+ read_status_line(remote_fd.get(), buf, sizeof(buf));
if (strncmp("Success", buf, 7)) {
fprintf(stderr, "adb: failed to write %s\n", file);
@@ -515,13 +479,14 @@
// 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);
- fd = adb_connect(service, &error);
- if (fd < 0) {
- fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
- return EXIT_FAILURE;
+ {
+ unique_fd fd(adb_connect(service, &error));
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
+ return EXIT_FAILURE;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
}
- read_status_line(fd, buf, sizeof(buf));
- adb_close(fd);
if (!strncmp("Success", buf, 7)) {
fputs(buf, stdout);
@@ -532,23 +497,214 @@
return EXIT_FAILURE;
}
+int install_multi_package(int argc, const char** argv) {
+ // Find all APK arguments starting at end.
+ // All other arguments passed through verbatim.
+ bool apex_found = false;
+ int first_package = -1;
+ for (int i = argc - 1; i >= 0; i--) {
+ const char* file = argv[i];
+ if (android::base::EndsWithIgnoreCase(file, ".apk") ||
+ android::base::EndsWithIgnoreCase(file, ".apex")) {
+ first_package = i;
+ if (android::base::EndsWithIgnoreCase(file, ".apex")) {
+ apex_found = true;
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (first_package == -1) error_exit("need APK or APEX files on command line");
+
+ if (use_legacy_install()) {
+ fprintf(stderr, "adb: multi-package install is not supported on this device\n");
+ return EXIT_FAILURE;
+ }
+ std::string install_cmd = "exec:cmd package";
+
+ std::string multi_package_cmd =
+ android::base::StringPrintf("%s install-create --multi-package", install_cmd.c_str());
+ if (apex_found) {
+ multi_package_cmd += " --staged";
+ }
+
+ // Create multi-package install session
+ std::string error;
+ char buf[BUFSIZ];
+ {
+ unique_fd fd(adb_connect(multi_package_cmd, &error));
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for create multi-package: %s\n", error.c_str());
+ return EXIT_FAILURE;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
+ }
+
+ int parent_session_id = -1;
+ if (!strncmp("Success", buf, 7)) {
+ char* start = strrchr(buf, '[');
+ char* end = strrchr(buf, ']');
+ if (start && end) {
+ *end = '\0';
+ parent_session_id = strtol(start + 1, nullptr, 10);
+ }
+ }
+ if (parent_session_id < 0) {
+ fprintf(stderr, "adb: failed to create multi-package session\n");
+ fputs(buf, stderr);
+ return EXIT_FAILURE;
+ }
+
+ fprintf(stdout, "Created parent session ID %d.\n", parent_session_id);
+
+ std::vector<int> session_ids;
+
+ // Valid session, now create the individual sessions and stream the APKs
+ int success = EXIT_FAILURE;
+ std::string individual_cmd =
+ android::base::StringPrintf("%s install-create", install_cmd.c_str());
+ std::string all_session_ids = "";
+ for (int i = 1; i < first_package; i++) {
+ individual_cmd += " " + escape_arg(argv[i]);
+ }
+ if (apex_found) {
+ individual_cmd += " --staged";
+ }
+ std::string individual_apex_cmd = individual_cmd + " --apex";
+ std::string cmd = "";
+ for (int i = first_package; i < argc; i++) {
+ const char* file = argv[i];
+ char buf[BUFSIZ];
+ {
+ unique_fd fd;
+ // Create individual install session
+ if (android::base::EndsWithIgnoreCase(file, ".apex")) {
+ fd.reset(adb_connect(individual_apex_cmd, &error));
+ } else {
+ fd.reset(adb_connect(individual_cmd, &error));
+ }
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
+ goto finalize_multi_package_session;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
+ }
+
+ int session_id = -1;
+ if (!strncmp("Success", buf, 7)) {
+ char* start = strrchr(buf, '[');
+ char* end = strrchr(buf, ']');
+ if (start && end) {
+ *end = '\0';
+ session_id = strtol(start + 1, nullptr, 10);
+ }
+ }
+ if (session_id < 0) {
+ fprintf(stderr, "adb: failed to create multi-package session\n");
+ fputs(buf, stderr);
+ goto finalize_multi_package_session;
+ }
+
+ fprintf(stdout, "Created child session ID %d.\n", session_id);
+ session_ids.push_back(session_id);
+
+ struct stat sb;
+ if (stat(file, &sb) == -1) {
+ fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
+ goto finalize_multi_package_session;
+ }
+
+ std::string cmd =
+ android::base::StringPrintf("%s install-write -S %" PRIu64 " %d %d_%s -",
+ install_cmd.c_str(), static_cast<uint64_t>(sb.st_size),
+ session_id, i, android::base::Basename(file).c_str());
+
+ 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));
+ goto finalize_multi_package_session;
+ }
+
+ std::string error;
+ unique_fd remote_fd(adb_connect(cmd, &error));
+ if (remote_fd < 0) {
+ fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
+ goto finalize_multi_package_session;
+ }
+
+ copy_to_file(local_fd.get(), remote_fd.get());
+ read_status_line(remote_fd.get(), buf, sizeof(buf));
+
+ if (strncmp("Success", buf, 7)) {
+ fprintf(stderr, "adb: failed to write %s\n", file);
+ fputs(buf, stderr);
+ goto finalize_multi_package_session;
+ }
+
+ all_session_ids += android::base::StringPrintf(" %d", session_id);
+ }
+
+ cmd = android::base::StringPrintf("%s install-add-session %d%s", install_cmd.c_str(),
+ parent_session_id, all_session_ids.c_str());
+ {
+ unique_fd fd(adb_connect(cmd, &error));
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for install-add-session: %s\n", error.c_str());
+ goto finalize_multi_package_session;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
+ }
+
+ if (strncmp("Success", buf, 7)) {
+ fprintf(stderr, "adb: failed to link sessions (%s)\n", cmd.c_str());
+ fputs(buf, stderr);
+ goto finalize_multi_package_session;
+ }
+
+ // no failures means we can proceed with the assumption of success
+ success = 0;
+
+finalize_multi_package_session:
+ // Commit session if we streamed everything okay; otherwise abandon
+ std::string service =
+ android::base::StringPrintf("%s install-%s %d", install_cmd.c_str(),
+ success == 0 ? "commit" : "abandon", parent_session_id);
+ {
+ unique_fd fd(adb_connect(service, &error));
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
+ return EXIT_FAILURE;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
+ }
+
+ if (!strncmp("Success", buf, 7)) {
+ fputs(buf, stdout);
+ if (success == 0) {
+ return 0;
+ }
+ } else {
+ fprintf(stderr, "adb: failed to finalize session\n");
+ fputs(buf, stderr);
+ }
+
+ // try to abandon all remaining sessions
+ for (std::size_t i = 0; i < session_ids.size(); i++) {
+ service = android::base::StringPrintf("%s install-abandon %d", install_cmd.c_str(),
+ session_ids[i]);
+ fprintf(stderr, "Attempting to abandon session ID %d\n", session_ids[i]);
+ unique_fd fd(adb_connect(service, &error));
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
+ continue;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
+ }
+ return EXIT_FAILURE;
+}
+
int delete_device_file(const std::string& filename) {
std::string cmd = "rm -f " + escape_arg(filename);
return send_shell_command(cmd);
}
-
-int delete_host_file(const std::string& filename) {
-#ifdef _WIN32
- BOOL delete_return = DeleteFileA(filename.c_str());
- if (delete_return != 0) {
- return 0;
- } else {
- DWORD last_error = GetLastError();
- printf("Error [%ld] deleting: %s\n", last_error, filename.c_str());
- return delete_return;
- }
-#else
- std::string cmd = "rm -f " + escape_arg(filename);
- return system(cmd.c_str());
-#endif
-}
diff --git a/adb/client/adb_install.h b/adb/client/adb_install.h
index e9410a9..9946604 100644
--- a/adb/client/adb_install.h
+++ b/adb/client/adb_install.h
@@ -14,16 +14,15 @@
* limitations under the License.
*/
-#ifndef ADB_INSTALL_H
-#define ADB_INSTALL_H
+#pragma once
-#include "fastdeploy.h"
+#include <string>
int install_app(int argc, const char** argv);
int install_multiple_app(int argc, const char** argv);
+int install_multi_package(int argc, const char** argv);
int uninstall_app(int argc, const char** argv);
int delete_device_file(const std::string& filename);
int delete_host_file(const std::string& filename);
-#endif
diff --git a/adb/client/auth.cpp b/adb/client/auth.cpp
index 71c19b8..bcb829b 100644
--- a/adb/client/auth.cpp
+++ b/adb/client/auth.cpp
@@ -43,6 +43,7 @@
#include "adb.h"
#include "adb_auth.h"
+#include "adb_io.h"
#include "adb_utils.h"
#include "sysdeps.h"
#include "transport.h"
@@ -52,30 +53,7 @@
*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() {
- LOG(INFO) << "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 && !defined ADB_HOST_ON_TARGET
- if (username.empty() && getlogin()) username = getlogin();
-#endif
- if (username.empty()) hostname = "unknown";
-
- return " " + username + "@" + hostname;
-}
-
-static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) {
- LOG(INFO) << "write_public_keyfile...";
-
+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))) {
LOG(ERROR) << "Failed to convert to public key";
@@ -88,20 +66,10 @@
return false;
}
- std::string content;
- content.resize(expected_length);
- size_t actual_length = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(&content[0]), binary_key_data,
+ out->resize(expected_length);
+ size_t actual_length = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(out->data()), binary_key_data,
sizeof(binary_key_data));
- content.resize(actual_length);
-
- content += get_user_info();
-
- std::string path(private_key_path + ".pub");
- if (!android::base::WriteStringToFile(content, path)) {
- PLOG(ERROR) << "Failed to write public key to '" << path << "'";
- return false;
- }
-
+ out->resize(actual_length);
return true;
}
@@ -140,11 +108,6 @@
goto out;
}
- if (!write_public_keyfile(rsa, file)) {
- D("Failed to write public key");
- goto out;
- }
-
ret = 1;
out:
@@ -170,36 +133,41 @@
return result;
}
-static bool read_key_file(const std::string& file) {
- LOG(INFO) << "read_key_file '" << file << "'...";
-
+static std::shared_ptr<RSA> read_key_file(const std::string& file) {
std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
if (!fp) {
PLOG(ERROR) << "Failed to open '" << file << "'";
- return false;
+ return nullptr;
}
RSA* key = RSA_new();
if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) {
LOG(ERROR) << "Failed to read key";
RSA_free(key);
+ return nullptr;
+ }
+
+ return std::shared_ptr<RSA>(key, RSA_free);
+}
+
+static bool load_key(const std::string& file) {
+ std::shared_ptr<RSA> key = read_key_file(file);
+ if (!key) {
return false;
}
std::lock_guard<std::mutex> lock(g_keys_mutex);
- std::string fingerprint = hash_key(key);
+ std::string fingerprint = hash_key(key.get());
if (g_keys.find(fingerprint) != g_keys.end()) {
LOG(INFO) << "ignoring already-loaded key: " << file;
- RSA_free(key);
} else {
- g_keys[fingerprint] = std::shared_ptr<RSA>(key, RSA_free);
+ g_keys[fingerprint] = std::move(key);
}
-
return true;
}
-static bool read_keys(const std::string& path, bool allow_dir = true) {
- LOG(INFO) << "read_keys '" << path << "'...";
+static bool load_keys(const std::string& path, bool allow_dir = true) {
+ LOG(INFO) << "load_keys '" << path << "'...";
struct stat st;
if (stat(path.c_str(), &st) != 0) {
@@ -208,7 +176,7 @@
}
if (S_ISREG(st.st_mode)) {
- return read_key_file(path);
+ return load_key(path);
} else if (S_ISDIR(st.st_mode)) {
if (!allow_dir) {
// inotify isn't recursive. It would break expectations to load keys in nested
@@ -237,7 +205,7 @@
continue;
}
- result |= read_key_file((path + OS_PATH_SEPARATOR + name));
+ result |= load_key((path + OS_PATH_SEPARATOR + name));
}
return result;
}
@@ -250,7 +218,7 @@
return adb_get_android_dir_path() + OS_PATH_SEPARATOR + "adbkey";
}
-static bool get_user_key() {
+static bool generate_userkey() {
std::string path = get_user_key_path();
if (path.empty()) {
PLOG(ERROR) << "Error getting user key filename";
@@ -266,7 +234,7 @@
}
}
- return read_key_file(path);
+ return load_key(path);
}
static std::set<std::string> get_vendor_keys() {
@@ -320,26 +288,42 @@
return result;
}
+static bool pubkey_from_privkey(std::string* out, const std::string& path) {
+ std::shared_ptr<RSA> privkey = read_key_file(path);
+ if (!privkey) {
+ return false;
+ }
+ return calculate_public_key(out, privkey.get());
+}
+
std::string adb_auth_get_userkey() {
std::string path = get_user_key_path();
if (path.empty()) {
PLOG(ERROR) << "Error getting user key filename";
return "";
}
- path += ".pub";
- std::string content;
- if (!android::base::ReadFileToString(path, &content)) {
- PLOG(ERROR) << "Can't load '" << path << "'";
+ std::string result;
+ if (!pubkey_from_privkey(&result, path)) {
return "";
}
- return content;
+ return result;
}
int adb_auth_keygen(const char* filename) {
return (generate_key(filename) == 0);
}
+int adb_auth_pubkey(const char* filename) {
+ std::string pubkey;
+ if (!pubkey_from_privkey(&pubkey, filename)) {
+ return 1;
+ }
+ pubkey.push_back('\n');
+
+ return WriteFdExactly(STDOUT_FILENO, pubkey.data(), pubkey.size()) ? 0 : 1;
+}
+
#if defined(__linux__)
static void adb_auth_inotify_update(int fd, unsigned fd_event, void*) {
LOG(INFO) << "adb_auth_inotify_update called";
@@ -380,7 +364,7 @@
LOG(INFO) << "ignoring new directory at '" << path << "'";
} else {
LOG(INFO) << "observed new file at '" << path << "'";
- read_keys(path, false);
+ load_keys(path, false);
}
} else {
LOG(WARNING) << "unmonitored event for " << path << ": 0x" << std::hex
@@ -420,8 +404,8 @@
void adb_auth_init() {
LOG(INFO) << "adb_auth_init...";
- if (!get_user_key()) {
- LOG(ERROR) << "Failed to get user key";
+ if (!generate_userkey()) {
+ LOG(ERROR) << "Failed to generate user key";
return;
}
@@ -432,7 +416,7 @@
#endif
for (const std::string& path : key_paths) {
- read_keys(path.c_str());
+ load_keys(path.c_str());
}
}
diff --git a/adb/client/bugreport.cpp b/adb/client/bugreport.cpp
index fe98737..8ca44e8 100644
--- a/adb/client/bugreport.cpp
+++ b/adb/client/bugreport.cpp
@@ -197,7 +197,7 @@
};
int Bugreport::DoIt(int argc, const char** argv) {
- if (argc > 2) return syntax_error("adb bugreport [PATH]");
+ if (argc > 2) error_exit("usage: adb bugreport [PATH]");
// Gets bugreportz version.
std::string bugz_stdout, bugz_stderr;
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index b55ae95..e963e3d 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -63,7 +63,6 @@
#include "services.h"
#include "shell_protocol.h"
#include "sysdeps/chrono.h"
-#include "sysdeps/memory.h"
extern int gListenAll;
@@ -72,8 +71,7 @@
static std::string product_file(const std::string& file) {
const char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
if (ANDROID_PRODUCT_OUT == nullptr) {
- fprintf(stderr, "adb: product directory not specified; set $ANDROID_PRODUCT_OUT\n");
- exit(1);
+ error_exit("product directory not specified; set $ANDROID_PRODUCT_OUT");
}
return std::string{ANDROID_PRODUCT_OUT} + OS_PATH_SEPARATOR_STR + file;
}
@@ -130,7 +128,7 @@
" pull [-a] REMOTE... LOCAL\n"
" copy files/dirs from device\n"
" -a: preserve file timestamp and mode\n"
- " sync [all|data|odm|oem|product|system|vendor]\n"
+ " sync [all|data|odm|oem|product_services|product|system|vendor]\n"
" sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)\n"
" -l: list but don't copy\n"
"\n"
@@ -144,22 +142,23 @@
" -x: disable remote exit codes and stdout/stderr separation\n"
" emu COMMAND run emulator console command\n"
"\n"
- "app installation:\n"
+ "app installation (see also `adb shell cmd package help`):\n"
" install [-lrtsdg] [--instant] PACKAGE\n"
+ " push a single package to the device and install it\n"
" install-multiple [-lrtsdpg] [--instant] PACKAGE...\n"
- " push package(s) to the device and install them\n"
- " -l: forward lock application\n"
+ " push multiple APKs to the device for a single package and install them\n"
+ " install-multi-package [-lrtsdpg] [--instant] PACKAGE...\n"
+ " push one or more packages to the device and install them atomically\n"
" -r: replace existing application\n"
" -t: allow test packages\n"
- " -s: install application on sdcard\n"
" -d: allow version code downgrade (debuggable packages only)\n"
" -p: partial application install (install-multiple only)\n"
" -g: grant all runtime permissions\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"
- " -f/--fastdeploy: use fast deploy (only valid with -r)\n"
- " --no-fastdeploy: prevent use of fast deploy (only valid with -r)\n"
+ " --fastdeploy: use fast deploy\n"
+ " --no-fastdeploy: prevent use of fast deploy\n"
" --force-agent: force update of deployment agent when using fast deploy\n"
" --date-check-agent: update deployment agent when local version is newer and using fast deploy\n"
" --version-check-agent: update deployment agent when local version has different version code and using fast deploy\n"
@@ -187,7 +186,6 @@
" enable-verity re-enable dm-verity checking on userdebug builds\n"
" keygen FILE\n"
" generate adb public/private key; private key stored in FILE,\n"
- " public key stored in FILE.pub (existing files overwritten)\n"
"\n"
"scripting:\n"
" wait-for[-TRANSPORT]-STATE\n"
@@ -197,7 +195,9 @@
" get-state print offline | bootloader | device\n"
" get-serialno print <serial-number>\n"
" get-devpath print <device-path>\n"
- " remount remount partitions read-write\n"
+ " remount [-R]\n"
+ " remount partitions read-write. if a reboot is required, -R will\n"
+ " will automatically reboot the device.\n"
" reboot [bootloader|recovery|sideload|sideload-auto-reboot]\n"
" reboot the device; defaults to booting system image but\n"
" supports bootloader and recovery too. sideload reboots\n"
@@ -206,8 +206,8 @@
" sideload OTAPACKAGE sideload the given full OTA package\n"
" root restart adbd with root permissions\n"
" unroot restart adbd without root permissions\n"
- " usb restart adb server listening on USB\n"
- " tcpip PORT restart adb server listening on TCP on PORT\n"
+ " usb restart adbd listening on USB\n"
+ " tcpip PORT restart adbd listening on TCP on PORT\n"
"\n"
"internal debugging:\n"
" start-server ensure that there is a server running\n"
@@ -319,7 +319,7 @@
#ifdef _WIN32
old_stdin_mode = _setmode(STDIN_FILENO, _O_BINARY);
if (old_stdin_mode == -1) {
- fatal_errno("could not set stdin to binary");
+ PLOG(FATAL) << "could not set stdin to binary";
}
#endif
}
@@ -328,7 +328,7 @@
if (outFd == STDOUT_FILENO) {
old_stdout_mode = _setmode(STDOUT_FILENO, _O_BINARY);
if (old_stdout_mode == -1) {
- fatal_errno("could not set stdout to binary");
+ PLOG(FATAL) << "could not set stdout to binary";
}
}
#endif
@@ -339,7 +339,7 @@
stdin_raw_restore();
#ifdef _WIN32
if (_setmode(STDIN_FILENO, old_stdin_mode) == -1) {
- fatal_errno("could not restore stdin mode");
+ PLOG(FATAL) << "could not restore stdin mode";
}
#endif
}
@@ -347,15 +347,14 @@
#ifdef _WIN32
if (outFd == STDOUT_FILENO) {
if (_setmode(STDOUT_FILENO, old_stdout_mode) == -1) {
- fatal_errno("could not restore stdout mode");
+ PLOG(FATAL) << "could not restore stdout mode";
}
}
#endif
}
void copy_to_file(int inFd, int outFd) {
- constexpr size_t BUFSIZE = 32 * 1024;
- std::vector<char> buf(BUFSIZE);
+ std::vector<char> buf(32 * 1024);
int len;
long total = 0;
int old_stdin_mode = -1;
@@ -367,9 +366,9 @@
while (true) {
if (inFd == STDIN_FILENO) {
- len = unix_read(inFd, buf.data(), BUFSIZE);
+ len = unix_read(inFd, buf.data(), buf.size());
} else {
- len = adb_read(inFd, buf.data(), BUFSIZE);
+ len = adb_read(inFd, buf.data(), buf.size());
}
if (len == 0) {
D("copy_to_file() : read 0 bytes; exiting");
@@ -585,12 +584,8 @@
//
// On success returns the remote exit code if |use_shell_protocol| is true,
// 0 otherwise. On failure returns 1.
-static int RemoteShell(bool use_shell_protocol, const std::string& type_arg,
- char escape_char,
- const std::string& command) {
- std::string service_string = ShellServiceString(use_shell_protocol,
- type_arg, command);
-
+static int RemoteShell(bool use_shell_protocol, const std::string& type_arg, char escape_char,
+ bool empty_command, const std::string& service_string) {
// Old devices can't handle a service string that's longer than MAX_PAYLOAD_V1.
// Use |use_shell_protocol| to determine whether to allow a command longer than that.
if (service_string.size() > MAX_PAYLOAD_V1 && !use_shell_protocol) {
@@ -601,8 +596,7 @@
// Make local stdin raw if the device allocates a PTY, which happens if:
// 1. We are explicitly asking for a PTY shell, or
// 2. We don't specify shell type and are starting an interactive session.
- bool raw_stdin = (type_arg == kShellServiceArgPty ||
- (type_arg.empty() && command.empty()));
+ bool raw_stdin = (type_arg == kShellServiceArgPty || (type_arg.empty() && empty_command));
std::string error;
int fd = adb_connect(service_string, &error);
@@ -662,9 +656,9 @@
static int adb_shell(int argc, const char** argv) {
FeatureSet features;
- std::string error;
- if (!adb_get_feature_set(&features, &error)) {
- fprintf(stderr, "error: %s\n", error.c_str());
+ std::string error_message;
+ if (!adb_get_feature_set(&features, &error_message)) {
+ fprintf(stderr, "error: %s\n", error_message.c_str());
return 1;
}
@@ -687,7 +681,7 @@
switch (opt) {
case 'e':
if (!(strlen(optarg) == 1 || strcmp(optarg, "none") == 0)) {
- return syntax_error("-e requires a single-character argument or 'none'");
+ error_exit("-e requires a single-character argument or 'none'");
}
escape_char = (strcmp(optarg, "none") == 0) ? 0 : optarg[0];
break;
@@ -762,7 +756,40 @@
command = android::base::Join(std::vector<const char*>(argv + optind, argv + argc), ' ');
}
- return RemoteShell(use_shell_protocol, shell_type_arg, escape_char, command);
+ std::string service_string = ShellServiceString(use_shell_protocol, shell_type_arg, command);
+ return RemoteShell(use_shell_protocol, shell_type_arg, escape_char, command.empty(),
+ service_string);
+}
+
+static int adb_abb(int argc, const char** argv) {
+ FeatureSet features;
+ std::string error_message;
+ if (!adb_get_feature_set(&features, &error_message)) {
+ fprintf(stderr, "error: %s\n", error_message.c_str());
+ return 1;
+ }
+
+ if (!CanUseFeature(features, kFeatureAbb)) {
+ error_exit("abb is not supported by the device");
+ }
+
+ // 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);
+ }
+
+ D("abb -e 0x%x [%*.s]\n", escape_char, static_cast<int>(service_string.size()),
+ service_string.data());
+
+ return RemoteShell(use_shell_protocol, shell_type_arg, escape_char, empty_command,
+ service_string);
}
static int adb_sideload_legacy(const char* filename, int in_fd, int size) {
@@ -842,14 +869,19 @@
return -1;
}
- std::string service = android::base::StringPrintf(
- "sideload-host:%d:%d", static_cast<int>(sb.st_size), SIDELOAD_HOST_BLOCK_SIZE);
+ std::string service =
+ android::base::StringPrintf("sideload-host:%" PRId64 ":%d",
+ static_cast<int64_t>(sb.st_size), SIDELOAD_HOST_BLOCK_SIZE);
std::string error;
unique_fd device_fd(adb_connect(service, &error));
if (device_fd < 0) {
- // Try falling back to the older (<= K) sideload method. Maybe this
- // is an older device that doesn't support sideload-host.
fprintf(stderr, "adb: sideload connection failed: %s\n", error.c_str());
+
+ // If this is a small enough package, maybe this is an older device that doesn't
+ // support sideload-host. Try falling back to the older (<= K) sideload method.
+ if (sb.st_size > INT_MAX) {
+ return -1;
+ }
fprintf(stderr, "adb: trying pre-KitKat sideload method...\n");
return adb_sideload_legacy(filename, package_fd, static_cast<int>(sb.st_size));
}
@@ -859,7 +891,7 @@
char buf[SIDELOAD_HOST_BLOCK_SIZE];
- size_t xfer = 0;
+ int64_t xfer = 0;
int last_percent = -1;
while (true) {
if (!ReadFdExactly(device_fd, buf, 8)) {
@@ -875,20 +907,22 @@
return 0;
}
- int block = strtol(buf, nullptr, 10);
-
- size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
- if (offset >= static_cast<size_t>(sb.st_size)) {
- fprintf(stderr, "adb: failed to read block %d past end\n", block);
+ int64_t block = strtoll(buf, nullptr, 10);
+ int64_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
+ if (offset >= static_cast<int64_t>(sb.st_size)) {
+ fprintf(stderr,
+ "adb: failed to read block %" PRId64 " at offset %" PRId64 ", past end %" PRId64
+ "\n",
+ block, offset, static_cast<int64_t>(sb.st_size));
return -1;
}
size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
- if ((offset + SIDELOAD_HOST_BLOCK_SIZE) > static_cast<size_t>(sb.st_size)) {
+ if ((offset + SIDELOAD_HOST_BLOCK_SIZE) > static_cast<int64_t>(sb.st_size)) {
to_write = sb.st_size - offset;
}
- if (adb_lseek(package_fd, offset, SEEK_SET) != static_cast<int>(offset)) {
+ if (adb_lseek(package_fd, offset, SEEK_SET) != offset) {
fprintf(stderr, "adb: failed to seek to package block: %s\n", strerror(errno));
return -1;
}
@@ -928,31 +962,29 @@
*/
static int ppp(int argc, const char** argv) {
#if defined(_WIN32)
- fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
- return -1;
+ error_exit("adb %s not implemented on Win32", argv[0]);
+ __builtin_unreachable();
#else
- if (argc < 2) return syntax_error("adb %s <adb service name> [ppp opts]", argv[0]);
+ if (argc < 2) error_exit("usage: adb %s <adb service name> [ppp opts]", argv[0]);
const char* adb_service_name = argv[1];
- std::string error;
- int fd = adb_connect(adb_service_name, &error);
+ std::string error_message;
+ int fd = adb_connect(adb_service_name, &error_message);
if (fd < 0) {
- fprintf(stderr, "adb: could not open adb service %s: %s\n", adb_service_name, error.c_str());
- return 1;
+ error_exit("could not open adb service %s: %s", adb_service_name, error_message.c_str());
}
pid_t pid = fork();
+ if (pid == -1) {
+ perror_exit("fork failed");
+ }
- if (pid < 0) {
- perror("from fork()");
- return 1;
- } else if (pid == 0) {
- int err;
+ if (pid == 0) {
+ // child side
int i;
- const char **ppp_args;
// copy args
- ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
+ const char** ppp_args = (const char**)alloca(sizeof(char*) * argc + 1);
ppp_args[0] = "pppd";
for (i = 2 ; i < argc ; i++) {
//argv[2] and beyond become ppp_args[1] and beyond
@@ -960,25 +992,18 @@
}
ppp_args[i-1] = nullptr;
- // child side
-
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
adb_close(STDERR_FILENO);
adb_close(fd);
- err = execvp("pppd", (char * const *)ppp_args);
-
- if (err < 0) {
- perror("execing pppd");
- }
- exit(-1);
- } else {
- // parent side
-
- adb_close(fd);
- return 0;
+ execvp("pppd", (char* const*)ppp_args);
+ perror_exit("exec pppd failed");
}
+
+ // parent side
+ adb_close(fd);
+ return 0;
#endif /* !defined(_WIN32) */
}
@@ -1156,7 +1181,7 @@
/* find, extract, and use any -f argument */
for (int i = 1; i < argc; i++) {
if (!strcmp("-f", argv[i])) {
- if (i == argc - 1) return syntax_error("backup -f passed with no filename");
+ if (i == argc - 1) error_exit("backup -f passed with no filename");
filename = argv[i+1];
for (int j = i+2; j <= argc; ) {
argv[i++] = argv[j++];
@@ -1168,7 +1193,7 @@
// Bare "adb backup" or "adb backup -f filename" are not valid invocations ---
// a list of packages is required.
- if (argc < 2) return syntax_error("backup either needs a list of packages or -all/-shared");
+ if (argc < 2) error_exit("backup either needs a list of packages or -all/-shared");
adb_unlink(filename);
int outFd = adb_creat(filename, 0640);
@@ -1204,7 +1229,7 @@
}
static int restore(int argc, const char** argv) {
- if (argc != 2) return syntax_error("restore requires an argument");
+ if (argc != 2) error_exit("restore requires an argument");
const char* filename = argv[1];
int tarFd = adb_open(filename, O_RDONLY);
@@ -1258,8 +1283,7 @@
} else if (!strcmp(*arg, "--")) {
ignore_flags = true;
} else {
- syntax_error("unrecognized option '%s'", *arg);
- exit(1);
+ error_exit("unrecognized option '%s'", *arg);
}
}
++arg;
@@ -1284,6 +1308,42 @@
return 0;
}
+static int adb_connect_command_bidirectional(const std::string& command) {
+ std::string error;
+ int fd = adb_connect(command, &error);
+ if (fd < 0) {
+ fprintf(stderr, "error: %s\n", error.c_str());
+ return 1;
+ }
+
+ static constexpr auto forward = [](int src, int sink, bool exit_on_end) {
+ char buf[4096];
+ while (true) {
+ int rc = adb_read(src, buf, sizeof(buf));
+ if (rc == 0) {
+ if (exit_on_end) {
+ exit(0);
+ } else {
+ adb_shutdown(sink, SHUT_WR);
+ }
+ return;
+ } else if (rc < 0) {
+ perror_exit("read failed");
+ }
+ if (!WriteFdExactly(sink, buf, rc)) {
+ perror_exit("write failed");
+ }
+ }
+ };
+
+ std::thread read(forward, fd, STDOUT_FILENO, true);
+ std::thread write(forward, STDIN_FILENO, fd, false);
+ read.join();
+ write.join();
+ adb_close(fd);
+ return 0;
+}
+
static int adb_query_command(const std::string& command) {
std::string result;
std::string error;
@@ -1337,7 +1397,7 @@
/* this is a special flag used only when the ADB client launches the ADB Server */
is_daemon = true;
} else if (!strcmp(argv[0], "--reply-fd")) {
- if (argc < 2) return syntax_error("--reply-fd requires an argument");
+ if (argc < 2) error_exit("--reply-fd requires an argument");
const char* reply_fd_str = argv[1];
argc--;
argv++;
@@ -1350,7 +1410,7 @@
if (isdigit(argv[0][2])) {
serial = argv[0] + 2;
} else {
- if (argc < 2 || argv[0][2] != '\0') return syntax_error("-s requires an argument");
+ if (argc < 2 || argv[0][2] != '\0') error_exit("-s requires an argument");
serial = argv[1];
argc--;
argv++;
@@ -1366,7 +1426,7 @@
}
transport_id = strtoll(id, const_cast<char**>(&id), 10);
if (*id != '\0') {
- return syntax_error("invalid transport id");
+ error_exit("invalid transport id");
}
} else if (!strcmp(argv[0],"-d")) {
transport_type = kTransportUsb;
@@ -1376,7 +1436,7 @@
gListenAll = 1;
} else if (!strncmp(argv[0], "-H", 2)) {
if (argv[0][2] == '\0') {
- if (argc < 2) return syntax_error("-H requires an argument");
+ if (argc < 2) error_exit("-H requires an argument");
server_host_str = argv[1];
argc--;
argv++;
@@ -1385,7 +1445,7 @@
}
} else if (!strncmp(argv[0], "-P", 2)) {
if (argv[0][2] == '\0') {
- if (argc < 2) return syntax_error("-P requires an argument");
+ if (argc < 2) error_exit("-P requires an argument");
server_port_str = argv[1];
argc--;
argv++;
@@ -1393,7 +1453,7 @@
server_port_str = argv[0] + 2;
}
} else if (!strcmp(argv[0], "-L")) {
- if (argc < 2) return syntax_error("-L requires an argument");
+ if (argc < 2) error_exit("-L requires an argument");
server_socket_str = argv[1];
argc--;
argv++;
@@ -1406,7 +1466,7 @@
}
if ((server_host_str || server_port_str) && server_socket_str) {
- return syntax_error("-L is incompatible with -H or -P");
+ error_exit("-L is incompatible with -H or -P");
}
// If -L, -H, or -P are specified, ignore environment variables.
@@ -1423,11 +1483,10 @@
server_port_str = server_port_str ? server_port_str : getenv("ANDROID_ADB_SERVER_PORT");
if (server_port_str && strlen(server_port_str) > 0) {
if (!android::base::ParseInt(server_port_str, &server_port, 1, 65535)) {
- fprintf(stderr,
- "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive"
- " number less than 65535. Got \"%s\"\n",
+ error_exit(
+ "$ANDROID_ADB_SERVER_PORT must be a positive number less than 65535: "
+ "got \"%s\"",
server_port_str);
- exit(1);
}
}
@@ -1439,7 +1498,7 @@
rc = asprintf(&temp, "tcp:%d", server_port);
}
if (rc < 0) {
- fatal("failed to allocate server socket specification");
+ LOG(FATAL) << "failed to allocate server socket specification";
}
server_socket_str = temp;
}
@@ -1501,7 +1560,7 @@
} else if (argc == 2 && !strcmp(argv[1], "-l")) {
listopt = argv[1];
} else {
- return syntax_error("adb devices [-l]");
+ error_exit("adb devices [-l]");
}
std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
@@ -1509,28 +1568,27 @@
return adb_query_command(query);
}
else if (!strcmp(argv[0], "connect")) {
- if (argc != 2) return syntax_error("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) return syntax_error("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] : "");
return adb_query_command(query);
- }
- else if (!strcmp(argv[0], "emu")) {
+ } else if (!strcmp(argv[0], "abb")) {
+ return adb_abb(argc, argv);
+ } else if (!strcmp(argv[0], "emu")) {
return adb_send_emulator_command(argc, argv, serial);
- }
- else if (!strcmp(argv[0], "shell")) {
+ } else if (!strcmp(argv[0], "shell")) {
return adb_shell(argc, argv);
- }
- else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
+ } else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
int exec_in = !strcmp(argv[0], "exec-in");
- if (argc < 2) return syntax_error("adb %s command", argv[0]);
+ if (argc < 2) error_exit("usage: adb %s command", argv[0]);
std::string cmd = "exec:";
cmd += argv[1];
@@ -1555,34 +1613,37 @@
adb_close(fd);
return 0;
- }
- else if (!strcmp(argv[0], "kill-server")) {
+ } else if (!strcmp(argv[0], "kill-server")) {
return adb_kill_server() ? 0 : 1;
- }
- else if (!strcmp(argv[0], "sideload")) {
- if (argc != 2) return syntax_error("sideload requires an argument");
+ } else if (!strcmp(argv[0], "sideload")) {
+ if (argc != 2) error_exit("sideload requires an argument");
if (adb_sideload_host(argv[1])) {
return 1;
} else {
return 0;
}
} else if (!strcmp(argv[0], "tcpip")) {
- if (argc != 2) return syntax_error("tcpip requires an argument");
+ if (argc != 2) error_exit("tcpip requires an argument");
int port;
if (!android::base::ParseInt(argv[1], &port, 1, 65535)) {
- return syntax_error("tcpip: invalid port: %s", argv[1]);
+ error_exit("tcpip: invalid port: %s", argv[1]);
}
return adb_connect_command(android::base::StringPrintf("tcpip:%d", port));
}
+ // clang-format off
else if (!strcmp(argv[0], "remount") ||
!strcmp(argv[0], "reboot") ||
!strcmp(argv[0], "reboot-bootloader") ||
+ !strcmp(argv[0], "reboot-fastboot") ||
!strcmp(argv[0], "usb") ||
!strcmp(argv[0], "disable-verity") ||
!strcmp(argv[0], "enable-verity")) {
+ // clang-format on
std::string command;
if (!strcmp(argv[0], "reboot-bootloader")) {
command = "reboot:bootloader";
+ } else if (!strcmp(argv[0], "reboot-fastboot")) {
+ command = "reboot:fastboot";
} else if (argc > 1) {
command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
} else {
@@ -1597,7 +1658,7 @@
} else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
bool reverse = !strcmp(argv[0], "reverse");
--argc;
- if (argc < 1) return syntax_error("%s requires an argument", argv[0]);
+ if (argc < 1) error_exit("%s requires an argument", argv[0]);
++argv;
// Determine the <host-prefix> for this command.
@@ -1616,46 +1677,44 @@
}
}
- std::string cmd, error;
+ std::string cmd, error_message;
if (strcmp(argv[0], "--list") == 0) {
- if (argc != 1) return syntax_error("--list doesn't take any arguments");
+ if (argc != 1) error_exit("--list doesn't take any arguments");
return adb_query_command(host_prefix + ":list-forward");
} else if (strcmp(argv[0], "--remove-all") == 0) {
- if (argc != 1) return syntax_error("--remove-all doesn't take any arguments");
+ if (argc != 1) error_exit("--remove-all doesn't take any arguments");
cmd = host_prefix + ":killforward-all";
} else if (strcmp(argv[0], "--remove") == 0) {
// forward --remove <local>
- if (argc != 2) return syntax_error("--remove requires an argument");
+ if (argc != 2) error_exit("--remove requires an argument");
cmd = host_prefix + ":killforward:" + argv[1];
} else if (strcmp(argv[0], "--no-rebind") == 0) {
// forward --no-rebind <local> <remote>
- if (argc != 3) return syntax_error("--no-rebind takes two arguments");
- if (forward_targets_are_valid(argv[1], argv[2], &error)) {
+ 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];
}
} else {
// forward <local> <remote>
- if (argc != 2) return syntax_error("forward takes two arguments");
- if (forward_targets_are_valid(argv[0], argv[1], &error)) {
+ 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];
}
}
- if (!error.empty()) {
- fprintf(stderr, "error: %s\n", error.c_str());
- return 1;
+ if (!error_message.empty()) {
+ error_exit("error: %s", error_message.c_str());
}
- int fd = adb_connect(cmd, &error);
- if (fd < 0 || !adb_status(fd, &error)) {
+ int fd = adb_connect(cmd, &error_message);
+ if (fd < 0 || !adb_status(fd, &error_message)) {
adb_close(fd);
- fprintf(stderr, "error: %s\n", error.c_str());
- return 1;
+ error_exit("error: %s", error_message.c_str());
}
// Server or device may optionally return a resolved TCP port number.
std::string resolved_port;
- if (ReadProtocolString(fd, &resolved_port, &error) && !resolved_port.empty()) {
+ if (ReadProtocolString(fd, &resolved_port, &error_message) && !resolved_port.empty()) {
printf("%s\n", resolved_port.c_str());
}
@@ -1664,41 +1723,38 @@
}
/* do_sync_*() commands */
else if (!strcmp(argv[0], "ls")) {
- if (argc != 2) return syntax_error("ls requires an argument");
+ if (argc != 2) error_exit("ls requires an argument");
return do_sync_ls(argv[1]) ? 0 : 1;
- }
- else if (!strcmp(argv[0], "push")) {
+ } else if (!strcmp(argv[0], "push")) {
bool copy_attrs = false;
bool sync = false;
std::vector<const char*> srcs;
const char* dst = nullptr;
parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, &sync);
- if (srcs.empty() || !dst) return syntax_error("push requires an argument");
+ if (srcs.empty() || !dst) error_exit("push requires an argument");
return do_sync_push(srcs, dst, sync) ? 0 : 1;
- }
- else if (!strcmp(argv[0], "pull")) {
+ } else if (!strcmp(argv[0], "pull")) {
bool copy_attrs = false;
std::vector<const char*> srcs;
const char* dst = ".";
parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, nullptr);
- if (srcs.empty()) return syntax_error("pull requires an argument");
+ if (srcs.empty()) error_exit("pull requires an argument");
return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
- }
- else if (!strcmp(argv[0], "install")) {
- if (argc < 2) return syntax_error("install requires an argument");
+ } else if (!strcmp(argv[0], "install")) {
+ if (argc < 2) error_exit("install requires an argument");
return install_app(argc, argv);
- }
- else if (!strcmp(argv[0], "install-multiple")) {
- if (argc < 2) return syntax_error("install-multiple requires an argument");
+ } else if (!strcmp(argv[0], "install-multiple")) {
+ if (argc < 2) error_exit("install-multiple requires an argument");
return install_multiple_app(argc, argv);
- }
- else if (!strcmp(argv[0], "uninstall")) {
- if (argc < 2) return syntax_error("uninstall requires an argument");
+ } else if (!strcmp(argv[0], "install-multi-package")) {
+ if (argc < 3) 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");
return uninstall_app(argc, argv);
- }
- else if (!strcmp(argv[0], "sync")) {
+ } else if (!strcmp(argv[0], "sync")) {
std::string src;
bool list_only = false;
if (argc < 2) {
@@ -1709,11 +1765,12 @@
} else if (argc == 2) {
src = argv[1];
} else {
- return syntax_error("adb sync [-l] [PARTITION]");
+ error_exit("usage: adb sync [-l] [PARTITION]");
}
if (src.empty()) src = "all";
- std::vector<std::string> partitions{"data", "odm", "oem", "product", "system", "vendor"};
+ std::vector<std::string> partitions{"data", "odm", "oem", "product", "product_services",
+ "system", "vendor"};
bool found = false;
for (const auto& partition : partitions) {
if (src == "all" || src == partition) {
@@ -1723,64 +1780,57 @@
if (!do_sync_sync(src_dir, "/" + partition, list_only)) return 1;
}
}
- return found ? 0 : syntax_error("don't know how to sync %s partition", src.c_str());
+ if (!found) error_exit("don't know how to sync %s partition", src.c_str());
+ return 0;
}
/* passthrough commands */
- else if (!strcmp(argv[0],"get-state") ||
- !strcmp(argv[0],"get-serialno") ||
- !strcmp(argv[0],"get-devpath"))
- {
+ else if (!strcmp(argv[0], "get-state") || !strcmp(argv[0], "get-serialno") ||
+ !strcmp(argv[0], "get-devpath")) {
return adb_query_command(format_host_command(argv[0]));
}
/* other commands */
- else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
+ else if (!strcmp(argv[0], "logcat") || !strcmp(argv[0], "lolcat") ||
+ !strcmp(argv[0], "longcat")) {
return logcat(argc, argv);
- }
- else if (!strcmp(argv[0],"ppp")) {
+ } else if (!strcmp(argv[0], "ppp")) {
return ppp(argc, argv);
- }
- else if (!strcmp(argv[0], "start-server")) {
+ } else if (!strcmp(argv[0], "start-server")) {
std::string error;
const int result = adb_connect("host:start-server", &error);
if (result < 0) {
fprintf(stderr, "error: %s\n", error.c_str());
}
return result;
- }
- else if (!strcmp(argv[0], "backup")) {
+ } else if (!strcmp(argv[0], "backup")) {
return backup(argc, argv);
- }
- else if (!strcmp(argv[0], "restore")) {
+ } else if (!strcmp(argv[0], "restore")) {
return restore(argc, argv);
- }
- else if (!strcmp(argv[0], "keygen")) {
- if (argc != 2) return syntax_error("keygen requires an argument");
+ } else if (!strcmp(argv[0], "keygen")) {
+ if (argc != 2) error_exit("keygen requires an argument");
// Always print key generation information for keygen command.
adb_trace_enable(AUTH);
return adb_auth_keygen(argv[1]);
- }
- else if (!strcmp(argv[0], "jdwp")) {
+ } else if (!strcmp(argv[0], "pubkey")) {
+ if (argc != 2) error_exit("pubkey requires an argument");
+ return adb_auth_pubkey(argv[1]);
+ } else if (!strcmp(argv[0], "jdwp")) {
return adb_connect_command("jdwp");
- }
- else if (!strcmp(argv[0], "track-jdwp")) {
+ } else if (!strcmp(argv[0], "track-jdwp")) {
return adb_connect_command("track-jdwp");
- }
- else if (!strcmp(argv[0], "track-devices")) {
+ } else if (!strcmp(argv[0], "track-devices")) {
return adb_connect_command("host:track-devices");
} else if (!strcmp(argv[0], "raw")) {
if (argc != 2) {
- return syntax_error("adb raw SERVICE");
+ error_exit("usage: adb raw SERVICE");
}
- return adb_connect_command(argv[1]);
+ return adb_connect_command_bidirectional(argv[1]);
}
-
/* "adb /?" is a common idiom under Windows */
else if (!strcmp(argv[0], "--help") || !strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
help();
return 0;
- }
- else if (!strcmp(argv[0], "--version") || !strcmp(argv[0], "version")) {
+ } else if (!strcmp(argv[0], "--version") || !strcmp(argv[0], "version")) {
fprintf(stdout, "%s", adb_version().c_str());
return 0;
} else if (!strcmp(argv[0], "features")) {
@@ -1812,11 +1862,11 @@
std::string err;
return adb_query_command("host:reconnect-offline");
} else {
- return syntax_error("adb reconnect [device|offline]");
+ error_exit("usage: adb reconnect [device|offline]");
}
}
}
- syntax_error("unknown command %s", argv[0]);
- return 1;
+ error_exit("unknown command %s", argv[0]);
+ __builtin_unreachable();
}
diff --git a/adb/client/console.cpp b/adb/client/console.cpp
index 9563eac..4e8a3f8 100644
--- a/adb/client/console.cpp
+++ b/adb/client/console.cpp
@@ -135,6 +135,7 @@
// preventing the emulator from reading the command that adb has sent.
// https://code.google.com/p/android/issues/detail?id=21021
int result;
+ std::string emulator_output;
do {
char buf[BUFSIZ];
result = adb_read(fd, buf, sizeof(buf));
@@ -146,8 +147,37 @@
// appended above, and that causes the emulator to close the socket
// which should cause zero bytes (orderly/graceful shutdown) to be
// returned.
+ if (result > 0) emulator_output.append(buf, result);
} while (result > 0);
+ // Note: the following messages are expected to be quite stable from emulator.
+ //
+ // Emulator console will send the following message upon connection:
+ //
+ // Android Console: Authentication required
+ // Android Console: type 'auth <auth_token>' to authenticate
+ // Android Console: you can find your <auth_token> in
+ // '/<path-to-home>/.emulator_console_auth_token'
+ // OK\r\n
+ //
+ // and the following after authentication:
+ // Android Console: type 'help' for a list of commands
+ // OK\r\n
+ //
+ // So try search and skip first two "OK\r\n", print the rest.
+ //
+ const std::string delims = "OK\r\n";
+ size_t found = 0;
+ for (int i = 0; i < 2; ++i) {
+ const size_t result = emulator_output.find(delims, found);
+ if (result == std::string::npos) {
+ break;
+ } else {
+ found = result + delims.size();
+ }
+ }
+
+ printf("%s", emulator_output.c_str() + found);
adb_close(fd);
return 0;
diff --git a/adb/client/fastdeploy.cpp b/adb/client/fastdeploy.cpp
index fda3889..f4e8664 100644
--- a/adb/client/fastdeploy.cpp
+++ b/adb/client/fastdeploy.cpp
@@ -14,26 +14,35 @@
* limitations under the License.
*/
-#include <androidfw/ResourceTypes.h>
-#include <androidfw/ZipFileRO.h>
-#include <libgen.h>
-#include <algorithm>
+#include "fastdeploy.h"
+#include <string.h>
+#include <algorithm>
+#include <array>
+#include <memory>
+
+#include "android-base/file.h"
+#include "android-base/strings.h"
+#include "androidfw/ResourceTypes.h"
+#include "androidfw/ZipFileRO.h"
#include "client/file_sync_client.h"
#include "commandline.h"
-#include "fastdeploy.h"
#include "fastdeploycallbacks.h"
-#include "utils/String16.h"
+#include "sysdeps.h"
-const long kRequiredAgentVersion = 0x00000001;
+#include "adb_utils.h"
-const char* kDeviceAgentPath = "/data/local/tmp/";
+static constexpr long kRequiredAgentVersion = 0x00000002;
+
+static constexpr const char* kDeviceAgentPath = "/data/local/tmp/";
+
+static bool g_use_localagent = false;
long get_agent_version() {
std::vector<char> versionOutputBuffer;
std::vector<char> versionErrorBuffer;
- int statusCode = capture_shell_command("/data/local/tmp/deployagent.sh version",
+ int statusCode = capture_shell_command("/data/local/tmp/deployagent version",
&versionOutputBuffer, &versionErrorBuffer);
long version = -1;
@@ -58,75 +67,63 @@
return api_level;
}
-// local_path - must start with a '/' and be relative to $ANDROID_PRODUCT_OUT
-static bool get_agent_component_host_path(bool use_localagent, const char* adb_path,
- const char* local_path, const char* sdk_path,
- std::string* output_path) {
- std::string mutable_adb_path = adb_path;
- const char* adb_dir = dirname(&mutable_adb_path[0]);
- if (adb_dir == nullptr) {
- return false;
- }
-
- if (use_localagent) {
- const char* product_out = getenv("ANDROID_PRODUCT_OUT");
- if (product_out == nullptr) {
- return false;
- }
- *output_path = android::base::StringPrintf("%s%s", product_out, local_path);
- return true;
- } else {
- *output_path = android::base::StringPrintf("%s%s", adb_dir, sdk_path);
- return true;
- }
- return false;
+void fastdeploy_set_local_agent(bool use_localagent) {
+ g_use_localagent = use_localagent;
}
-static bool deploy_agent(bool checkTimeStamps, bool use_localagent, const char* adb_path) {
+// 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) {
std::vector<const char*> srcs;
-
- std::string agent_jar_path;
- if (get_agent_component_host_path(use_localagent, adb_path, "/system/framework/deployagent.jar",
- "/deployagent.jar", &agent_jar_path)) {
- srcs.push_back(agent_jar_path.c_str());
- } else {
- return false;
- }
-
- std::string agent_sh_path;
- if (get_agent_component_host_path(use_localagent, adb_path, "/system/bin/deployagent.sh",
- "/deployagent.sh", &agent_sh_path)) {
- srcs.push_back(agent_sh_path.c_str());
- } else {
- return false;
- }
+ 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());
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.sh";
+ const char* kChmodCommandPattern = "chmod 777 %sdeployagent";
std::string chmodCommand =
android::base::StringPrintf(kChmodCommandPattern, kDeviceAgentPath);
int ret = send_shell_command(chmodCommand);
- return (ret == 0);
+ if (ret != 0) {
+ error_exit("Error executing %s returncode: %d", chmodCommand.c_str(), ret);
+ }
} else {
- return false;
+ error_exit("Error pushing agent files to device");
}
+
+ return true;
}
-bool update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy, bool use_localagent,
- const char* adb_path) {
+void update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy) {
long agent_version = get_agent_version();
switch (agentUpdateStrategy) {
case FastDeploy_AgentUpdateAlways:
- if (deploy_agent(false, use_localagent, adb_path) == false) {
- return false;
- }
+ deploy_agent(false);
break;
case FastDeploy_AgentUpdateNewerTimeStamp:
- if (deploy_agent(true, use_localagent, adb_path) == false) {
- return false;
- }
+ deploy_agent(true);
break;
case FastDeploy_AgentUpdateDifferentVersion:
if (agent_version != kRequiredAgentVersion) {
@@ -136,15 +133,16 @@
printf("Device agent version is (%ld), (%ld) is required, re-deploying\n",
agent_version, kRequiredAgentVersion);
}
- if (deploy_agent(false, use_localagent, adb_path) == false) {
- return false;
- }
+ deploy_agent(false);
}
break;
}
agent_version = get_agent_version();
- return (agent_version == kRequiredAgentVersion);
+ 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) {
@@ -152,57 +150,49 @@
if (utf8_length <= 0) {
return {};
}
-
std::string utf8;
utf8.resize(utf8_length);
utf16_to_utf8(input, input_len, &*utf8.begin(), utf8_length + 1);
return utf8;
}
-// output is required to point to a valid output string (non-null)
-static bool get_packagename_from_apk(const char* apkPath, std::string* output) {
- using namespace android;
-
- ZipFileRO* zipFile = ZipFileRO::open(apkPath);
+static std::string get_packagename_from_apk(const char* apkPath) {
+#undef open
+ std::unique_ptr<android::ZipFileRO> zipFile(android::ZipFileRO::open(apkPath));
+#define open ___xxx_unix_open
if (zipFile == nullptr) {
- return false;
+ perror_exit("Could not open %s", apkPath);
}
-
- ZipEntryRO entry = zipFile->findEntryByName("AndroidManifest.xml");
+ android::ZipEntryRO entry = zipFile->findEntryByName("AndroidManifest.xml");
if (entry == nullptr) {
- return false;
+ error_exit("Could not find AndroidManifest.xml inside %s", apkPath);
}
-
uint32_t manifest_len = 0;
if (!zipFile->getEntryInfo(entry, NULL, &manifest_len, NULL, NULL, NULL, NULL)) {
- return false;
+ error_exit("Could not read AndroidManifest.xml inside %s", apkPath);
}
-
std::vector<char> manifest_data(manifest_len);
if (!zipFile->uncompressEntry(entry, manifest_data.data(), manifest_len)) {
- return false;
+ error_exit("Could not uncompress AndroidManifest.xml inside %s", apkPath);
}
-
- ResXMLTree tree;
- status_t setto_status = tree.setTo(manifest_data.data(), manifest_len, true);
- if (setto_status != NO_ERROR) {
- return false;
+ 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);
}
-
- ResXMLParser::event_code_t code;
- while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT &&
- code != ResXMLParser::END_DOCUMENT) {
+ android::ResXMLParser::event_code_t code;
+ while ((code = tree.next()) != android::ResXMLParser::BAD_DOCUMENT &&
+ code != android::ResXMLParser::END_DOCUMENT) {
switch (code) {
- case ResXMLParser::START_TAG: {
+ case android::ResXMLParser::START_TAG: {
size_t element_name_length;
const char16_t* element_name = tree.getElementName(&element_name_length);
if (element_name == nullptr) {
continue;
}
-
std::u16string element_name_string(element_name, element_name_length);
if (element_name_string == u"manifest") {
- for (int i = 0; i < (int)tree.getAttributeCount(); i++) {
+ for (size_t i = 0; i < tree.getAttributeCount(); i++) {
size_t attribute_name_length;
const char16_t* attribute_name_text =
tree.getAttributeName(i, &attribute_name_length);
@@ -211,7 +201,6 @@
}
std::u16string attribute_name_string(attribute_name_text,
attribute_name_length);
-
if (attribute_name_string == u"package") {
size_t attribute_value_length;
const char16_t* attribute_value_text =
@@ -219,9 +208,8 @@
if (attribute_value_text == nullptr) {
continue;
}
- *output = get_string_from_utf16(attribute_value_text,
- attribute_value_length);
- return true;
+ return get_string_from_utf16(attribute_value_text,
+ attribute_value_length);
}
}
}
@@ -231,135 +219,124 @@
break;
}
}
-
- return false;
+ error_exit("Could not find package name tag in AndroidManifest.xml inside %s", apkPath);
}
-int extract_metadata(const char* apkPath, FILE* outputFp) {
- std::string packageName;
- if (get_packagename_from_apk(apkPath, &packageName) == false) {
- return -1;
- }
-
- const char* kAgentExtractCommandPattern = "/data/local/tmp/deployagent.sh extract %s";
+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());
std::vector<char> extractErrorBuffer;
- int statusCode;
- DeployAgentFileCallback cb(outputFp, &extractErrorBuffer, &statusCode);
- int ret = send_shell_command(extractCommand, false, &cb);
-
- if (ret == 0) {
- return cb.getBytesWritten();
+ DeployAgentFileCallback cb(outputFp, &extractErrorBuffer);
+ int returnCode = send_shell_command(extractCommand, false, &cb);
+ if (returnCode != 0) {
+ fprintf(stderr, "Executing %s returned %d\n", extractCommand.c_str(), returnCode);
+ fprintf(stderr, "%*s\n", int(extractErrorBuffer.size()), extractErrorBuffer.data());
+ error_exit("Aborting");
}
-
- return ret;
}
-// output is required to point to a valid output string (non-null)
-static bool patch_generator_command(bool use_localagent, const char* adb_path,
- std::string* output) {
- if (use_localagent) {
+static std::string get_patch_generator_command() {
+ if (g_use_localagent) {
// This should never happen on a Windows machine
- const char* kGeneratorCommandPattern = "java -jar %s/framework/deploypatchgenerator.jar";
const char* host_out = getenv("ANDROID_HOST_OUT");
if (host_out == nullptr) {
- return false;
+ error_exit(
+ "Could not locate deploypatchgenerator.jar because $ANDROID_HOST_OUT "
+ "is not defined");
}
- *output = android::base::StringPrintf(kGeneratorCommandPattern, host_out, host_out);
- return true;
- } else {
- const char* kGeneratorCommandPattern = R"(java -jar "%s/deploypatchgenerator.jar")";
- std::string mutable_adb_path = adb_path;
- const char* adb_dir = dirname(&mutable_adb_path[0]);
- if (adb_dir == nullptr) {
- return false;
- }
-
- *output = android::base::StringPrintf(kGeneratorCommandPattern, adb_dir, adb_dir);
- return true;
+ return android::base::StringPrintf("java -jar %s/framework/deploypatchgenerator.jar",
+ host_out);
}
- return false;
+
+ 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());
}
-int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath,
- bool use_localagent, const char* adb_path) {
- const char* kGeneratePatchCommandPattern = R"(%s "%s" "%s" > "%s")";
- std::string patch_generator_command_string;
- if (patch_generator_command(use_localagent, adb_path, &patch_generator_command_string) ==
- false) {
- return 1;
- }
+void create_patch(const char* apkPath, const char* metadataPath, const char* patchPath) {
std::string generatePatchCommand = android::base::StringPrintf(
- kGeneratePatchCommandPattern, patch_generator_command_string.c_str(), apkPath,
- metadataPath, patchPath);
- return system(generatePatchCommand.c_str());
+ 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;
- if (get_packagename_from_apk(apkPath, &packageName) == false) {
- return "";
- }
+ std::string packageName = get_packagename_from_apk(apkPath);
std::string patchDevicePath =
android::base::StringPrintf("%s%s.patch", kDeviceAgentPath, packageName.c_str());
return patchDevicePath;
}
-int apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath) {
- const std::string kAgentApplyCommandPattern =
- "/data/local/tmp/deployagent.sh apply %s %s -o %s";
-
- std::string packageName;
- if (get_packagename_from_apk(apkPath, &packageName) == false) {
- return -1;
- }
+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) {
- return -1;
+ 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);
- return send_shell_command(applyPatchCommand);
+
+ int returnCode = send_shell_command(applyPatchCommand);
+ if (returnCode != 0) {
+ error_exit("Executing %s returned %d", applyPatchCommand.c_str(), returnCode);
+ }
}
-int install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv) {
- const std::string kAgentApplyCommandPattern =
- "/data/local/tmp/deployagent.sh apply %s %s -pm %s";
+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 packageName;
- if (get_packagename_from_apk(apkPath, &packageName) == false) {
- return -1;
- }
-
- std::vector<const char*> srcs;
std::string patchDevicePath =
android::base::StringPrintf("%s%s.patch", kDeviceAgentPath, packageName.c_str());
- srcs.push_back(patchPath);
- bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
+ std::vector<const char*> srcs{patchPath};
+ bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
if (!push_ok) {
- return -1;
+ error_exit("Error pushing %s to %s returned", patchPath, patchDevicePath.c_str());
}
std::vector<unsigned char> applyOutputBuffer;
std::vector<unsigned char> applyErrorBuffer;
std::string argsString;
+ bool rSwitchPresent = false;
for (int i = 0; i < argc; i++) {
argsString.append(argv[i]);
argsString.append(" ");
+ if (!strcmp(argv[i], "-r")) {
+ rSwitchPresent = true;
+ }
+ }
+ if (!rSwitchPresent) {
+ argsString.append("-r");
}
std::string applyPatchCommand =
android::base::StringPrintf(kAgentApplyCommandPattern.c_str(), packageName.c_str(),
patchDevicePath.c_str(), argsString.c_str());
- return send_shell_command(applyPatchCommand);
+ int returnCode = send_shell_command(applyPatchCommand);
+ if (returnCode != 0) {
+ error_exit("Executing %s returned %d", applyPatchCommand.c_str(), returnCode);
+ }
+}
+
+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);
}
diff --git a/adb/client/fastdeploy.h b/adb/client/fastdeploy.h
index d8acd30..7b7f2ec 100644
--- a/adb/client/fastdeploy.h
+++ b/adb/client/fastdeploy.h
@@ -16,22 +16,20 @@
#pragma once
-#include "adb.h"
+#include <string>
-typedef enum EFastDeploy_AgentUpdateStrategy {
+enum FastDeploy_AgentUpdateStrategy {
FastDeploy_AgentUpdateAlways,
FastDeploy_AgentUpdateNewerTimeStamp,
FastDeploy_AgentUpdateDifferentVersion
-} FastDeploy_AgentUpdateStrategy;
+};
-static constexpr int kFastDeployMinApi = 24;
-
+void fastdeploy_set_local_agent(bool use_localagent);
int get_device_api_level();
-bool update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy, bool use_localagent,
- const char* adb_path);
-int extract_metadata(const char* apkPath, FILE* outputFp);
-int create_patch(const char* apkPath, const char* metadataPath, const char* patchPath,
- bool use_localagent, const char* adb_path);
-int apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath);
-int install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv);
+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);
diff --git a/adb/client/fastdeploycallbacks.cpp b/adb/client/fastdeploycallbacks.cpp
index 6c9a21f..23a0aca 100644
--- a/adb/client/fastdeploycallbacks.cpp
+++ b/adb/client/fastdeploycallbacks.cpp
@@ -35,8 +35,7 @@
class DeployAgentBufferCallback : public StandardStreamsCallbackInterface {
public:
- DeployAgentBufferCallback(std::vector<char>* outBuffer, std::vector<char>* errBuffer,
- int* statusCode);
+ DeployAgentBufferCallback(std::vector<char>* outBuffer, std::vector<char>* errBuffer);
virtual void OnStdout(const char* buffer, int length);
virtual void OnStderr(const char* buffer, int length);
@@ -45,27 +44,17 @@
private:
std::vector<char>* mpOutBuffer;
std::vector<char>* mpErrBuffer;
- int* mpStatusCode;
};
int capture_shell_command(const char* command, std::vector<char>* outBuffer,
std::vector<char>* errBuffer) {
- int statusCode;
- DeployAgentBufferCallback cb(outBuffer, errBuffer, &statusCode);
- int ret = send_shell_command(command, false, &cb);
-
- if (ret == 0) {
- return statusCode;
- } else {
- return ret;
- }
+ DeployAgentBufferCallback cb(outBuffer, errBuffer);
+ return send_shell_command(command, false, &cb);
}
-DeployAgentFileCallback::DeployAgentFileCallback(FILE* outputFile, std::vector<char>* errBuffer,
- int* statusCode) {
+DeployAgentFileCallback::DeployAgentFileCallback(FILE* outputFile, std::vector<char>* errBuffer) {
mpOutFile = outputFile;
mpErrBuffer = errBuffer;
- mpStatusCode = statusCode;
mBytesWritten = 0;
}
@@ -84,10 +73,7 @@
}
int DeployAgentFileCallback::Done(int status) {
- if (mpStatusCode != NULL) {
- *mpStatusCode = status;
- }
- return 0;
+ return status;
}
int DeployAgentFileCallback::getBytesWritten() {
@@ -95,11 +81,9 @@
}
DeployAgentBufferCallback::DeployAgentBufferCallback(std::vector<char>* outBuffer,
- std::vector<char>* errBuffer,
- int* statusCode) {
+ std::vector<char>* errBuffer) {
mpOutBuffer = outBuffer;
mpErrBuffer = errBuffer;
- mpStatusCode = statusCode;
}
void DeployAgentBufferCallback::OnStdout(const char* buffer, int length) {
@@ -111,8 +95,5 @@
}
int DeployAgentBufferCallback::Done(int status) {
- if (mpStatusCode != NULL) {
- *mpStatusCode = status;
- }
- return 0;
+ return status;
}
diff --git a/adb/client/fastdeploycallbacks.h b/adb/client/fastdeploycallbacks.h
index b428b50..7e049c5 100644
--- a/adb/client/fastdeploycallbacks.h
+++ b/adb/client/fastdeploycallbacks.h
@@ -21,7 +21,7 @@
class DeployAgentFileCallback : public StandardStreamsCallbackInterface {
public:
- DeployAgentFileCallback(FILE* outputFile, std::vector<char>* errBuffer, int* statusCode);
+ DeployAgentFileCallback(FILE* outputFile, std::vector<char>* errBuffer);
virtual void OnStdout(const char* buffer, int length);
virtual void OnStderr(const char* buffer, int length);
@@ -33,7 +33,6 @@
FILE* mpOutFile;
std::vector<char>* mpErrBuffer;
int mBytesWritten;
- int* mpStatusCode;
};
int capture_shell_command(const char* command, std::vector<char>* outBuffer,
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index cb9bcfa..f0f9a80 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -325,12 +325,12 @@
memset(st, 0, sizeof(*st));
if (have_stat_v2_) {
if (!ReadFdExactly(fd, &msg.stat_v2, sizeof(msg.stat_v2))) {
- fatal_errno("protocol fault: failed to read stat response");
+ PLOG(FATAL) << "protocol fault: failed to read stat response";
}
if (msg.stat_v2.id != ID_LSTAT_V2 && msg.stat_v2.id != ID_STAT_V2) {
- fatal_errno("protocol fault: stat response has wrong message id: %" PRIx32,
- msg.stat_v2.id);
+ PLOG(FATAL) << "protocol fault: stat response has wrong message id: "
+ << msg.stat_v2.id;
}
if (msg.stat_v2.error != 0) {
@@ -351,12 +351,12 @@
return true;
} else {
if (!ReadFdExactly(fd, &msg.stat_v1, sizeof(msg.stat_v1))) {
- fatal_errno("protocol fault: failed to read stat response");
+ PLOG(FATAL) << "protocol fault: failed to read stat response";
}
if (msg.stat_v1.id != ID_LSTAT_V1) {
- fatal_errno("protocol fault: stat response has wrong message id: %" PRIx32,
- msg.stat_v1.id);
+ PLOG(FATAL) << "protocol fault: stat response has wrong message id: "
+ << msg.stat_v1.id;
}
if (msg.stat_v1.mode == 0 && msg.stat_v1.size == 0 && msg.stat_v1.time == 0) {
@@ -894,7 +894,8 @@
//
// TODO(b/25457350): We don't preserve permissions on directories.
// TODO: Find all of the leaves and `mkdir -p` them instead?
- if (CanUseFeature(sc.Features(), kFeatureShell2)) {
+ if (!CanUseFeature(sc.Features(), kFeatureFixedPushMkdir) &&
+ CanUseFeature(sc.Features(), kFeatureShell2)) {
SilentStandardStreamsCallbackInterface cb;
std::string cmd = "mkdir";
for (const auto& dir : directory_list) {
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 095ad98..2ee81a9 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -40,15 +40,15 @@
static void setup_daemon_logging() {
const std::string log_file_path(GetLogFilePath());
- int fd = unix_open(log_file_path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0640);
+ int fd = unix_open(log_file_path, O_WRONLY | O_CREAT | O_APPEND, 0640);
if (fd == -1) {
- fatal("cannot open '%s': %s", log_file_path.c_str(), strerror(errno));
+ PLOG(FATAL) << "cannot open " << log_file_path;
}
if (dup2(fd, STDOUT_FILENO) == -1) {
- fatal("cannot redirect stdout: %s", strerror(errno));
+ PLOG(FATAL) << "cannot redirect stdout";
}
if (dup2(fd, STDERR_FILENO) == -1) {
- fatal("cannot redirect stderr: %s", strerror(errno));
+ PLOG(FATAL) << "cannot redirect stderr";
}
unix_close(fd);
@@ -56,15 +56,6 @@
LOG(INFO) << adb_version();
}
-#if defined(_WIN32)
-static BOOL WINAPI ctrlc_handler(DWORD type) {
- // TODO: Consider trying to kill a starting up adb server (if we're in
- // launch_server) by calling GenerateConsoleCtrlEvent().
- exit(STATUS_CONTROL_C_EXIT);
- return TRUE;
-}
-#endif
-
void adb_server_cleanup() {
// Upon exit, we want to clean up in the following order:
// 1. close_smartsockets, so that we don't get any new clients
@@ -90,19 +81,23 @@
// This also keeps stderr unbuffered when it is redirected to adb.log.
if (is_daemon) {
if (setvbuf(stdout, nullptr, _IONBF, 0) == -1) {
- fatal("cannot make stdout unbuffered: %s", strerror(errno));
+ PLOG(FATAL) << "cannot make stdout unbuffered";
}
if (setvbuf(stderr, nullptr, _IONBF, 0) == -1) {
- fatal("cannot make stderr unbuffered: %s", strerror(errno));
+ PLOG(FATAL) << "cannot make stderr unbuffered";
}
}
- SetConsoleCtrlHandler(ctrlc_handler, TRUE);
-#else
+ // TODO: On Ctrl-C, consider trying to kill a starting up adb server (if we're in
+ // launch_server) by calling GenerateConsoleCtrlEvent().
+
+ // On Windows, SIGBREAK is when Ctrl-Break is pressed or the console window is closed. It should
+ // act like Ctrl-C.
+ signal(SIGBREAK, [](int) { raise(SIGINT); });
+#endif
signal(SIGINT, [](int) {
fdevent_run_on_main_thread([]() { exit(0); });
});
-#endif
char* leak = getenv("ADB_LEAK");
if (leak && strcmp(leak, "1") == 0) {
@@ -142,7 +137,7 @@
while (install_listener(socket_spec, "*smartsocket*", nullptr, 0, nullptr, &error) !=
INSTALL_STATUS_OK) {
if (std::chrono::steady_clock::now() - start > 0.5s) {
- fatal("could not install *smartsocket* listener: %s", error.c_str());
+ LOG(FATAL) << "could not install *smartsocket* listener: " << error;
}
std::this_thread::sleep_for(100ms);
@@ -158,7 +153,7 @@
// setsid will fail with EPERM if it's already been a lead process of new session.
// Ignore such error.
if (setsid() == -1 && errno != EPERM) {
- fatal("setsid() failed: %s", strerror(errno));
+ PLOG(FATAL) << "setsid() failed";
}
#endif
@@ -176,19 +171,19 @@
const DWORD bytes_to_write = arraysize(ack) - 1;
DWORD written = 0;
if (!WriteFile(ack_reply_handle, ack, bytes_to_write, &written, NULL)) {
- fatal("adb: cannot write ACK to handle 0x%p: %s", ack_reply_handle,
- android::base::SystemErrorCodeToString(GetLastError()).c_str());
+ LOG(FATAL) << "cannot write ACK to handle " << ack_reply_handle
+ << android::base::SystemErrorCodeToString(GetLastError());
}
if (written != bytes_to_write) {
- fatal("adb: cannot write %lu bytes of ACK: only wrote %lu bytes", bytes_to_write,
- written);
+ LOG(FATAL) << "cannot write " << bytes_to_write << " bytes of ACK: only wrote "
+ << written << " bytes";
}
CloseHandle(ack_reply_handle);
#else
// TODO(danalbert): Can't use SendOkay because we're sending "OK\n", not
// "OKAY".
if (!android::base::WriteStringToFd("OK\n", ack_reply_fd)) {
- fatal_errno("error writing ACK to fd %d", ack_reply_fd);
+ PLOG(FATAL) << "error writing ACK to fd " << ack_reply_fd;
}
unix_close(ack_reply_fd);
#endif
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index 10b6090..f2ca63b 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -332,13 +332,6 @@
return;
}
- rc = libusb_set_interface_alt_setting(handle.get(), interface_num, 0);
- if (rc != 0) {
- LOG(WARNING) << "failed to set interface alt setting for device '" << device_serial
- << "'" << libusb_error_name(rc);
- return;
- }
-
for (uint8_t endpoint : {bulk_in, bulk_out}) {
rc = libusb_clear_halt(handle.get(), endpoint);
if (rc != 0) {
diff --git a/adb/client/usb_linux.cpp b/adb/client/usb_linux.cpp
index f1bf559..1168958 100644
--- a/adb/client/usb_linux.cpp
+++ b/adb/client/usb_linux.cpp
@@ -39,6 +39,7 @@
#include <list>
#include <mutex>
#include <string>
+#include <string_view>
#include <thread>
#include <android-base/file.h>
@@ -90,7 +91,7 @@
static auto& g_usb_handles_mutex = *new std::mutex();
static auto& g_usb_handles = *new std::list<usb_handle*>();
-static int is_known_device(const char* dev_name) {
+static int is_known_device(std::string_view dev_name) {
std::lock_guard<std::mutex> lock(g_usb_handles_mutex);
for (usb_handle* usb : g_usb_handles) {
if (usb->path == dev_name) {
@@ -152,11 +153,11 @@
if (contains_non_digit(de->d_name)) continue;
std::string dev_name = bus_name + "/" + de->d_name;
- if (is_known_device(dev_name.c_str())) {
+ if (is_known_device(dev_name)) {
continue;
}
- int fd = unix_open(dev_name.c_str(), O_RDONLY | O_CLOEXEC);
+ int fd = unix_open(dev_name, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
continue;
}
@@ -535,10 +536,10 @@
// Initialize mark so we don't get garbage collected after the device scan.
usb->mark = true;
- usb->fd = unix_open(usb->path.c_str(), O_RDWR | O_CLOEXEC);
+ usb->fd = unix_open(usb->path, O_RDWR | O_CLOEXEC);
if (usb->fd == -1) {
// Opening RW failed, so see if we have RO access.
- usb->fd = unix_open(usb->path.c_str(), O_RDONLY | O_CLOEXEC);
+ usb->fd = unix_open(usb->path, O_RDONLY | O_CLOEXEC);
if (usb->fd == -1) {
D("[ usb open %s failed: %s]", usb->path.c_str(), strerror(errno));
return;
diff --git a/adb/client/usb_osx.cpp b/adb/client/usb_osx.cpp
index 49baf36..e380c84 100644
--- a/adb/client/usb_osx.cpp
+++ b/adb/client/usb_osx.cpp
@@ -136,8 +136,8 @@
io_service_t usbDevice;
io_service_t usbInterface;
IOCFPlugInInterface **plugInInterface = NULL;
- IOUSBInterfaceInterface220 **iface = NULL;
- IOUSBDeviceInterface197 **dev = NULL;
+ IOUSBInterfaceInterface500 **iface = NULL;
+ IOUSBDeviceInterface500 **dev = NULL;
HRESULT result;
SInt32 score;
uint32_t locationId;
@@ -163,7 +163,7 @@
//* This gets us the interface object
result = (*plugInInterface)->QueryInterface(
plugInInterface,
- CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID*)&iface);
+ CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID500), (LPVOID*)&iface);
//* We only needed the plugin to get the interface, so discard it
(*plugInInterface)->Release(plugInInterface);
if (result || !iface) {
@@ -209,7 +209,7 @@
}
result = (*plugInInterface)->QueryInterface(plugInInterface,
- CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*)&dev);
+ CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID500), (LPVOID*)&dev);
//* only needed this to query the plugin
(*plugInInterface)->Release(plugInInterface);
if (result || !dev) {
diff --git a/adb/client/usb_windows.cpp b/adb/client/usb_windows.cpp
index 00aeb9b..cfa5cf4 100644
--- a/adb/client/usb_windows.cpp
+++ b/adb/client/usb_windows.cpp
@@ -212,8 +212,8 @@
const HINSTANCE instance = GetModuleHandleW(nullptr);
if (!instance) {
// This is such a common API call that this should never fail.
- fatal("GetModuleHandleW failed: %s",
- android::base::SystemErrorCodeToString(GetLastError()).c_str());
+ LOG(FATAL) << "GetModuleHandleW failed: "
+ << android::base::SystemErrorCodeToString(GetLastError());
}
WNDCLASSEXW wndclass;
@@ -223,15 +223,15 @@
wndclass.hInstance = instance;
wndclass.lpszClassName = kPowerNotificationWindowClassName;
if (!RegisterClassExW(&wndclass)) {
- fatal("RegisterClassExW failed: %s",
- android::base::SystemErrorCodeToString(GetLastError()).c_str());
+ LOG(FATAL) << "RegisterClassExW failed: "
+ << android::base::SystemErrorCodeToString(GetLastError());
}
if (!CreateWindowExW(WS_EX_NOACTIVATE, kPowerNotificationWindowClassName,
L"ADB Power Notification Window", WS_POPUP, 0, 0, 0, 0, nullptr, nullptr,
instance, nullptr)) {
- fatal("CreateWindowExW failed: %s",
- android::base::SystemErrorCodeToString(GetLastError()).c_str());
+ LOG(FATAL) << "CreateWindowExW failed: "
+ << android::base::SystemErrorCodeToString(GetLastError());
}
MSG msg;
diff --git a/adb/daemon/abb.cpp b/adb/daemon/abb.cpp
new file mode 100644
index 0000000..f69babe
--- /dev/null
+++ b/adb/daemon/abb.cpp
@@ -0,0 +1,92 @@
+/*
+ * 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 "adb.h"
+#include "adb_io.h"
+#include "shell_service.h"
+
+#include "cmd.h"
+
+#include <sys/wait.h>
+
+namespace {
+
+class AdbFdTextOutput : public android::TextOutput {
+ public:
+ explicit AdbFdTextOutput(int fd) : mFD(fd) {}
+
+ private:
+ android::status_t print(const char* txt, size_t len) override {
+ return WriteFdExactly(mFD, txt, len) ? android::OK : -errno;
+ }
+ void moveIndent(int delta) override { /*not implemented*/
+ }
+
+ void pushBundle() override { /*not implemented*/
+ }
+ void popBundle() override { /*not implemented*/
+ }
+
+ private:
+ int mFD;
+};
+
+std::vector<std::string_view> parseCmdArgs(std::string_view args) {
+ std::vector<std::string_view> argv;
+
+ char delim = ABB_ARG_DELIMETER;
+ size_t size = args.size();
+ size_t base = 0;
+ while (base < size) {
+ size_t found;
+ for (found = base; found < size && args[found] && args[found] != delim; ++found)
+ ;
+ if (found > base) {
+ argv.emplace_back(args.substr(base, found - base));
+ }
+ base = found + 1;
+ }
+
+ return argv;
+}
+
+} // namespace
+
+static int execCmd(std::string_view args, int in, int out, int err) {
+ AdbFdTextOutput oin(out);
+ AdbFdTextOutput oerr(err);
+ return cmdMain(parseCmdArgs(args), oin, oerr, in, out, err, RunMode::kLibrary);
+}
+
+int main(int argc, char* const argv[]) {
+ signal(SIGPIPE, SIG_IGN);
+
+ int fd = STDIN_FILENO;
+ std::string data;
+ while (true) {
+ std::string error;
+ if (!ReadProtocolString(fd, &data, &error)) {
+ PLOG(ERROR) << "Failed to read message: " << error;
+ break;
+ }
+
+ auto result = StartCommandInProcess(std::move(data), &execCmd);
+ if (!SendFileDescriptor(fd, result)) {
+ 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
new file mode 100644
index 0000000..817aea1
--- /dev/null
+++ b/adb/daemon/abb_service.cpp
@@ -0,0 +1,88 @@
+/*
+ * 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 "adb.h"
+#include "adb_io.h"
+#include "adb_unique_fd.h"
+#include "adb_utils.h"
+#include "shell_service.h"
+
+namespace {
+
+struct AbbProcess;
+static auto& abbp = *new std::unique_ptr<AbbProcess>(std::make_unique<AbbProcess>());
+
+struct AbbProcess {
+ unique_fd sendCommand(std::string_view command);
+
+ private:
+ static unique_fd startAbbProcess(unique_fd* error_fd);
+
+ static constexpr auto kRetries = 2;
+ static constexpr auto kErrorProtocol = SubprocessProtocol::kShell;
+
+ std::mutex locker_;
+ unique_fd socket_fd_;
+};
+
+unique_fd AbbProcess::sendCommand(std::string_view command) {
+ std::unique_lock lock{locker_};
+
+ for (int i = 0; i < kRetries; ++i) {
+ unique_fd error_fd;
+ if (socket_fd_ == -1) {
+ socket_fd_ = startAbbProcess(&error_fd);
+ }
+ if (socket_fd_ == -1) {
+ LOG(ERROR) << "failed to start abb process";
+ return error_fd;
+ }
+
+ if (!SendProtocolString(socket_fd_, std::string(command))) {
+ PLOG(ERROR) << "failed to send command to abb";
+ socket_fd_.reset();
+ continue;
+ }
+
+ unique_fd fd;
+ std::string error;
+ if (!ReceiveFileDescriptor(socket_fd_, &fd, &error)) {
+ LOG(ERROR) << "failed to receive FD from abb: " << error;
+ socket_fd_.reset();
+ continue;
+ }
+
+ return fd;
+ }
+
+ LOG(ERROR) << "abb is unavailable";
+ socket_fd_.reset();
+ return ReportError(kErrorProtocol, "abb is unavailable");
+}
+
+unique_fd AbbProcess::startAbbProcess(unique_fd* error_fd) {
+ constexpr auto abb_process_type = SubprocessType::kRaw;
+ constexpr auto abb_protocol = SubprocessProtocol::kNone;
+ constexpr auto make_pty_raw = false;
+ return StartSubprocess("abb", "dumb", abb_process_type, abb_protocol, make_pty_raw,
+ kErrorProtocol, error_fd);
+}
+
+} // namespace
+
+unique_fd execute_binder_command(std::string_view command) {
+ return abbp->sendCommand(command);
+}
diff --git a/adb/daemon/file_sync_service.cpp b/adb/daemon/file_sync_service.cpp
index 8c39a20..d55096a 100644
--- a/adb/daemon/file_sync_service.cpp
+++ b/adb/daemon/file_sync_service.cpp
@@ -32,6 +32,10 @@
#include <unistd.h>
#include <utime.h>
+#include <memory>
+#include <string>
+#include <vector>
+
#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -47,6 +51,7 @@
#include "security_log_tags.h"
#include "sysdeps/errno.h"
+using android::base::Dirname;
using android::base::StringPrintf;
static bool should_use_fs_config(const std::string& path) {
@@ -219,7 +224,7 @@
}
if (fd < 0 && errno == ENOENT) {
- if (!secure_mkdirs(android::base::Dirname(path))) {
+ if (!secure_mkdirs(Dirname(path))) {
SendSyncFailErrno(s, "secure_mkdirs failed");
goto fail;
}
@@ -327,8 +332,6 @@
#else
static bool handle_send_link(int s, const std::string& path, std::vector<char>& buffer) {
syncmsg msg;
- unsigned int len;
- int ret;
if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
@@ -337,24 +340,28 @@
return false;
}
- len = msg.data.size;
+ unsigned int len = msg.data.size;
if (len > buffer.size()) { // TODO: resize buffer?
SendSyncFail(s, "oversize data message");
return false;
}
if (!ReadFdExactly(s, &buffer[0], len)) return false;
- ret = symlink(&buffer[0], path.c_str());
- if (ret && errno == ENOENT) {
- if (!secure_mkdirs(android::base::Dirname(path))) {
- SendSyncFailErrno(s, "secure_mkdirs failed");
+ std::string buf_link;
+ if (!android::base::Readlink(path, &buf_link) || (buf_link != &buffer[0])) {
+ adb_unlink(path.c_str());
+ auto ret = symlink(&buffer[0], path.c_str());
+ if (ret && errno == ENOENT) {
+ if (!secure_mkdirs(Dirname(path))) {
+ SendSyncFailErrno(s, "secure_mkdirs failed");
+ return false;
+ }
+ ret = symlink(&buffer[0], path.c_str());
+ }
+ if (ret) {
+ SendSyncFailErrno(s, "symlink failed");
return false;
}
- ret = symlink(&buffer[0], path.c_str());
- }
- if (ret) {
- SendSyncFailErrno(s, "symlink failed");
- return false;
}
if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
@@ -391,7 +398,8 @@
// Don't delete files before copying if they are not "regular" or symlinks.
struct stat st;
- bool do_unlink = (lstat(path.c_str(), &st) == -1) || S_ISREG(st.st_mode) || S_ISLNK(st.st_mode);
+ bool do_unlink = (lstat(path.c_str(), &st) == -1) || S_ISREG(st.st_mode) ||
+ (S_ISLNK(st.st_mode) && !S_ISLNK(mode));
if (do_unlink) {
adb_unlink(path.c_str());
}
diff --git a/adb/daemon/framebuffer_service.cpp b/adb/daemon/framebuffer_service.cpp
index 8d28c49..2a6418a 100644
--- a/adb/daemon/framebuffer_service.cpp
+++ b/adb/daemon/framebuffer_service.cpp
@@ -32,6 +32,7 @@
#include "adb.h"
#include "adb_io.h"
+#include "adb_utils.h"
#include "fdevent.h"
/* TODO:
@@ -78,7 +79,7 @@
const char* command = "screencap";
const char *args[2] = {command, nullptr};
execvp(command, (char**)args);
- exit(1);
+ perror_exit("exec screencap failed");
}
adb_close(fds[1]);
diff --git a/adb/daemon/include/adbd/usb.h b/adb/daemon/include/adbd/usb.h
index 78e4cd5..3213f69 100644
--- a/adb/daemon/include/adbd/usb.h
+++ b/adb/daemon/include/adbd/usb.h
@@ -62,3 +62,5 @@
};
usb_handle *create_usb_handle(unsigned num_bufs, unsigned io_size);
+bool open_functionfs(android::base::unique_fd* control, android::base::unique_fd* bulk_out,
+ android::base::unique_fd* bulk_in);
diff --git a/adb/daemon/jdwp_service.cpp b/adb/daemon/jdwp_service.cpp
index b40faee..f02cc13 100644
--- a/adb/daemon/jdwp_service.cpp
+++ b/adb/daemon/jdwp_service.cpp
@@ -136,7 +136,7 @@
this->fde = fdevent_create(socket, jdwp_process_event, this);
if (!this->fde) {
- fatal("could not create fdevent for new JDWP process");
+ LOG(FATAL) << "could not create fdevent for new JDWP process";
}
/* start by waiting for the PID */
@@ -200,7 +200,7 @@
// Message is length-prefixed with 4 hex digits in ASCII.
static constexpr size_t header_len = 4;
if (bufferlen < header_len) {
- fatal("invalid JDWP process list buffer size: %zu", bufferlen);
+ LOG(FATAL) << "invalid JDWP process list buffer size: " << bufferlen;
}
char head[header_len + 1];
@@ -212,6 +212,7 @@
static void jdwp_process_event(int socket, unsigned events, void* _proc) {
JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
+ CHECK_EQ(socket, proc->socket);
if (events & FDE_READ) {
if (proc->pid < 0) {
@@ -225,82 +226,27 @@
D("Adding pid %d to jdwp process list", proc->pid);
jdwp_process_list_updated();
} else {
- /* the pid was read, if we get there it's probably because the connection
- * was closed (e.g. the JDWP process exited or crashed) */
- char buf[32];
-
- while (true) {
- int len = TEMP_FAILURE_RETRY(recv(socket, buf, sizeof(buf), 0));
-
- if (len == 0) {
- D("terminating JDWP %d connection: EOF", proc->pid);
- break;
- } else if (len < 0) {
- if (len < 0 && errno == EAGAIN) {
- return;
- }
-
- D("terminating JDWP %d connection: EOF", proc->pid);
- break;
- } else {
- D("ignoring unexpected JDWP %d control socket activity (%d bytes)", proc->pid,
- len);
- }
- }
-
+ // 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) {
D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
- if (!proc->out_fds.empty()) {
- int fd = proc->out_fds.back().get();
- struct cmsghdr* cmsg;
- struct msghdr msg;
- struct iovec iov;
- char dummy = '!';
- char buffer[sizeof(struct cmsghdr) + sizeof(int)];
+ CHECK(!proc->out_fds.empty());
- iov.iov_base = &dummy;
- iov.iov_len = 1;
- msg.msg_name = nullptr;
- msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_flags = 0;
- msg.msg_control = buffer;
- msg.msg_controllen = sizeof(buffer);
+ int fd = proc->out_fds.back().get();
+ if (!SendFileDescriptor(socket, fd)) {
+ D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno));
+ goto CloseProcess;
+ }
- cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_len = msg.msg_controllen;
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- ((int*)CMSG_DATA(cmsg))[0] = fd;
+ D("sent file descriptor %d to JDWP process %d", fd, proc->pid);
- if (!set_file_block_mode(proc->socket, true)) {
- VLOG(JDWP) << "failed to set blocking mode for fd " << proc->socket;
- goto CloseProcess;
- }
-
- int ret = TEMP_FAILURE_RETRY(sendmsg(proc->socket, &msg, 0));
- if (ret < 0) {
- D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno));
- goto CloseProcess;
- }
-
- D("sent file descriptor %d to JDWP process %d", fd, proc->pid);
-
- proc->out_fds.pop_back();
-
- if (!set_file_block_mode(proc->socket, false)) {
- VLOG(JDWP) << "failed to set non-blocking mode for fd " << proc->socket;
- goto CloseProcess;
- }
-
- if (proc->out_fds.empty()) {
- fdevent_del(proc->fde, FDE_WRITE);
- }
+ proc->out_fds.pop_back();
+ if (proc->out_fds.empty()) {
+ fdevent_del(proc->fde, FDE_WRITE);
}
}
@@ -406,9 +352,10 @@
return 0;
}
-static void jdwp_control_event(int s, unsigned events, void* _control) {
+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) {
@@ -425,7 +372,7 @@
auto proc = std::make_unique<JdwpProcess>(s);
if (!proc) {
- fatal("failed to allocate JdwpProcess");
+ LOG(FATAL) << "failed to allocate JdwpProcess";
}
_jdwp_list.emplace_back(std::move(proc));
@@ -484,7 +431,7 @@
JdwpSocket* s = new JdwpSocket();
if (!s) {
- fatal("failed to allocate JdwpSocket");
+ LOG(FATAL) << "failed to allocate JdwpSocket";
}
install_local_socket(s);
@@ -561,7 +508,7 @@
asocket* create_jdwp_tracker_service_socket(void) {
auto t = std::make_unique<JdwpTracker>();
if (!t) {
- fatal("failed to allocate JdwpTracker");
+ LOG(FATAL) << "failed to allocate JdwpTracker";
}
memset(t.get(), 0, sizeof(asocket));
diff --git a/adb/daemon/mdns.cpp b/adb/daemon/mdns.cpp
index 849378f..3530f48 100644
--- a/adb/daemon/mdns.cpp
+++ b/adb/daemon/mdns.cpp
@@ -74,7 +74,7 @@
if (error != kDNSServiceErr_NoError) {
LOG(ERROR) << "Could not register mDNS service (" << error << ").";
- mdns_registered = false;
+ return;
}
mdns_registered = true;
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
index ed5f944..3c9dd04 100644
--- a/adb/daemon/remount_service.cpp
+++ b/adb/daemon/remount_service.cpp
@@ -35,6 +35,7 @@
#include <string>
#include <vector>
+#include <android-base/file.h>
#include <android-base/properties.h>
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
@@ -47,6 +48,8 @@
#include "adb_utils.h"
#include "set_verity_enable_state_service.h"
+using android::base::Realpath;
+
// Returns the last device used to mount a directory in /proc/mounts.
// This will find overlayfs entry where upperdir=lowerdir, to make sure
// remount is associated with the correct directory.
@@ -55,9 +58,15 @@
std::string mnt_fsname;
if (!fp) return mnt_fsname;
+ // dir might be a symlink, e.g., /product -> /system/product in GSI.
+ std::string canonical_path;
+ if (!Realpath(dir, &canonical_path)) {
+ PLOG(ERROR) << "Realpath failed: " << dir;
+ }
+
mntent* e;
while ((e = getmntent(fp.get())) != nullptr) {
- if (strcmp(dir, e->mnt_dir) == 0) {
+ if (canonical_path == e->mnt_dir) {
mnt_fsname = e->mnt_fsname;
}
}
@@ -69,7 +78,13 @@
std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
fs_mgr_free_fstab);
struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab.get(), dir);
- return rec ? rec->blk_device : "";
+ if (!rec) {
+ return "";
+ }
+ if (fs_mgr_is_logical(rec)) {
+ fs_mgr_update_logical_partition(rec);
+ }
+ return rec->blk_device;
}
// The proc entry for / is full of lies, so check fstab instead.
@@ -78,13 +93,17 @@
if (is_root) {
return find_fstab_mount(dir);
} else {
- return find_proc_mount(dir);
+ return find_proc_mount(dir);
}
}
+bool dev_is_overlayfs(const std::string& dev) {
+ return (dev == "overlay") || (dev == "overlayfs");
+}
+
bool make_block_device_writable(const std::string& dev) {
- if ((dev == "overlay") || (dev == "overlayfs")) return true;
- int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC);
+ if (dev_is_overlayfs(dev)) return true;
+ int fd = unix_open(dev, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
return false;
}
@@ -146,7 +165,16 @@
return true;
}
bool is_root = strcmp(dir, "/") == 0;
+ if (is_root && dev_is_overlayfs(find_mount("/system", false))) {
+ dir = "/system";
+ is_root = false;
+ }
std::string dev = find_mount(dir, is_root);
+ if (is_root && dev.empty()) {
+ // The fstab entry will be /system if the device switched roots during
+ // first-stage init.
+ dev = find_mount("/system", true);
+ }
// Even if the device for the root is not found, we still try to remount it
// as rw. This typically only happens when running Android in a container:
// the root will almost always be in a loop device, which is dynamic, so
@@ -209,61 +237,60 @@
bool system_verified = !(android::base::GetProperty("partition.system.verified", "").empty());
bool vendor_verified = !(android::base::GetProperty("partition.vendor.verified", "").empty());
- std::vector<std::string> partitions = {"/odm", "/oem", "/product", "/vendor"};
- if (android::base::GetBoolProperty("ro.build.system_root_image", false)) {
- partitions.push_back("/");
- } else {
- partitions.push_back("/system");
- }
+ std::vector<std::string> partitions{"/", "/odm", "/oem", "/product_services",
+ "/product", "/vendor"};
- bool verity_enabled = (system_verified || vendor_verified);
+ if (system_verified || vendor_verified) {
+ // Disable verity automatically (reboot will be required).
+ set_verity_enabled_state_service(unique_fd(dup(fd.get())), false);
- // If we can use overlayfs, lets get it in place first
- // before we struggle with determining deduplication operations.
- if (!verity_enabled && fs_mgr_overlayfs_setup() && fs_mgr_overlayfs_mount_all()) {
- WriteFdExactly(fd.get(), "overlayfs mounted\n");
- }
-
- // Find partitions that are deduplicated, and can be un-deduplicated.
- std::set<std::string> dedup;
- for (const auto& partition : partitions) {
- std::string dev = find_mount(partition.c_str(), partition == "/");
- if (dev.empty() || !fs_mgr_has_shared_blocks(partition, dev)) {
- continue;
- }
- if (can_unshare_blocks(fd.get(), dev.c_str())) {
- dedup.emplace(partition);
- }
- }
-
- // Reboot now if the user requested it (and an operation needs a reboot).
- if (user_requested_reboot) {
- if (!dedup.empty() || verity_enabled) {
- if (verity_enabled) {
- set_verity_enabled_state_service(unique_fd(dup(fd.get())), false);
+ // If overlayfs is not supported, we try and remount or set up
+ // un-deduplication. If it is supported, we can go ahead and wait for
+ // a reboot.
+ if (fs_mgr_overlayfs_valid() != OverlayfsValidResult::kNotSupported) {
+ if (user_requested_reboot) {
+ if (android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot")) {
+ WriteFdExactly(fd.get(), "rebooting device\n");
+ } else {
+ WriteFdExactly(fd.get(), "reboot failed\n");
+ }
}
- reboot_for_remount(fd.get(), !dedup.empty());
return;
}
- WriteFdExactly(fd.get(), "No reboot needed, skipping -R.\n");
+ } else if (fs_mgr_overlayfs_setup()) {
+ // If we can use overlayfs, lets get it in place first before we
+ // struggle with determining deduplication operations.
+ Fstab fstab;
+ if (ReadDefaultFstab(&fstab) && fs_mgr_overlayfs_mount_all(&fstab)) {
+ WriteFdExactly(fd.get(), "overlayfs mounted\n");
+ }
}
- // If we need to disable-verity, but we also need to perform a recovery
- // fsck for deduplicated partitions, hold off on warning about verity. We
- // can handle both verity and the recovery fsck in the same reboot cycle.
- if (verity_enabled && dedup.empty()) {
- // Allow remount but warn of likely bad effects
- bool both = system_verified && vendor_verified;
- WriteFdFmt(fd.get(), "dm_verity is enabled on the %s%s%s partition%s.\n",
- system_verified ? "system" : "", both ? " and " : "",
- vendor_verified ? "vendor" : "", both ? "s" : "");
- WriteFdExactly(fd.get(),
- "Use \"adb disable-verity\" to disable verity.\n"
- "If you do not, remount may succeed, however, you will still "
- "not be able to write to these volumes.\n");
- WriteFdExactly(fd.get(),
- "Alternately, use \"adb remount -R\" to disable verity "
- "and automatically reboot.\n");
+ // If overlayfs is supported, we don't bother trying to un-deduplicate
+ // partitions.
+ std::set<std::string> dedup;
+ if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
+ // Find partitions that are deduplicated, and can be un-deduplicated.
+ for (const auto& part : partitions) {
+ auto partition = part;
+ if ((part == "/") && !find_mount("/system", false).empty()) partition = "/system";
+ std::string dev = find_mount(partition.c_str(), partition == "/");
+ if (dev.empty() || !fs_mgr_has_shared_blocks(partition, dev)) {
+ continue;
+ }
+ if (can_unshare_blocks(fd.get(), dev.c_str())) {
+ dedup.emplace(partition);
+ }
+ }
+
+ // Reboot now if the user requested it (and an operation needs a reboot).
+ if (user_requested_reboot) {
+ if (!dedup.empty()) {
+ reboot_for_remount(fd.get(), !dedup.empty());
+ return;
+ }
+ WriteFdExactly(fd.get(), "No reboot needed, skipping -R.\n");
+ }
}
bool success = true;
diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp
index 8417690..5ae210f 100644
--- a/adb/daemon/services.cpp
+++ b/adb/daemon/services.cpp
@@ -33,6 +33,7 @@
#include <thread>
#include <android-base/file.h>
+#include <android-base/parseint.h>
#include <android-base/parsenetaddress.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
@@ -103,7 +104,9 @@
if (reboot_arg.empty()) reboot_arg = "adb";
std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg.c_str());
- if (reboot_arg == "fastboot" && access("/dev/socket/recovery", F_OK) == 0) {
+ 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
@@ -148,14 +151,17 @@
kick_transport(t);
}
-unique_fd reverse_service(const char* command, atransport* transport) {
+unique_fd reverse_service(std::string_view command, atransport* transport) {
+ // TODO: Switch handle_forward_request to std::string_view.
+ std::string str(command);
+
int s[2];
if (adb_socketpair(s)) {
PLOG(ERROR) << "cannot create service socket pair.";
return unique_fd{};
}
VLOG(SERVICES) << "service socketpair: " << s[0] << ", " << s[1];
- if (!handle_forward_request(command, transport, s[1])) {
+ if (!handle_forward_request(str.c_str(), transport, s[1])) {
SendFail(s[1], "not a reverse forwarding command");
}
adb_close(s[1]);
@@ -164,15 +170,16 @@
// Shell service string can look like:
// shell[,arg1,arg2,...]:[command]
-unique_fd ShellService(const std::string& args, const atransport* transport) {
+unique_fd ShellService(std::string_view args, const atransport* transport) {
size_t delimiter_index = args.find(':');
if (delimiter_index == std::string::npos) {
LOG(ERROR) << "No ':' found in shell service arguments: " << args;
return unique_fd{};
}
- const std::string service_args = args.substr(0, delimiter_index);
- const std::string command = args.substr(delimiter_index + 1);
+ // TODO: android::base::Split(const std::string_view&, ...)
+ std::string service_args(args.substr(0, delimiter_index));
+ std::string command(args.substr(delimiter_index + 1));
// Defaults:
// PTY for interactive, raw for non-interactive.
@@ -189,69 +196,210 @@
type = SubprocessType::kPty;
} else if (arg == kShellServiceArgShellProtocol) {
protocol = SubprocessProtocol::kShell;
- } else if (android::base::StartsWith(arg, "TERM=")) {
- terminal_type = arg.substr(5);
+ } else if (arg.starts_with("TERM=")) {
+ terminal_type = arg.substr(strlen("TERM="));
} else if (!arg.empty()) {
// This is not an error to allow for future expansion.
LOG(WARNING) << "Ignoring unknown shell service argument: " << arg;
}
}
- return StartSubprocess(command.c_str(), terminal_type.c_str(), type, protocol);
+ return StartSubprocess(command, terminal_type.c_str(), type, protocol);
}
-unique_fd daemon_service_to_fd(const char* name, atransport* transport) {
- if (!strncmp("dev:", name, 4)) {
- return unique_fd{unix_open(name + 4, O_RDWR | O_CLOEXEC)};
- } else if (!strncmp(name, "framebuffer:", 12)) {
+static void spin_service(unique_fd fd) {
+ if (!__android_log_is_debuggable()) {
+ WriteFdExactly(fd.get(), "refusing to spin on non-debuggable build\n");
+ return;
+ }
+
+ // A service that creates an fdevent that's always pending, and then ignores it.
+ unique_fd pipe_read, pipe_write;
+ if (!Pipe(&pipe_read, &pipe_write)) {
+ WriteFdExactly(fd.get(), "failed to create pipe\n");
+ return;
+ }
+
+ fdevent_run_on_main_thread([fd = pipe_read.release()]() {
+ fdevent* fde = fdevent_create(fd, [](int, unsigned, void*) {}, nullptr);
+ fdevent_add(fde, FDE_READ);
+ });
+
+ WriteFdExactly(fd.get(), "spinning\n");
+}
+
+struct ServiceSocket : public asocket {
+ ServiceSocket() {
+ install_local_socket(this);
+ this->enqueue = [](asocket* self, apacket::payload_type data) {
+ return static_cast<ServiceSocket*>(self)->Enqueue(std::move(data));
+ };
+ this->ready = [](asocket* self) { return static_cast<ServiceSocket*>(self)->Ready(); };
+ this->close = [](asocket* self) { return static_cast<ServiceSocket*>(self)->Close(); };
+ }
+ virtual ~ServiceSocket() = default;
+
+ virtual int Enqueue(apacket::payload_type data) { return -1; }
+ virtual void Ready() {}
+ virtual void Close() {
+ if (peer) {
+ peer->peer = nullptr;
+ if (peer->shutdown) {
+ peer->shutdown(peer);
+ }
+ peer->close(peer);
+ }
+
+ remove_socket(this);
+ delete this;
+ }
+};
+
+struct SinkSocket : public ServiceSocket {
+ explicit SinkSocket(size_t byte_count) {
+ LOG(INFO) << "Creating new SinkSocket with capacity " << byte_count;
+ bytes_left_ = byte_count;
+ }
+
+ virtual ~SinkSocket() { LOG(INFO) << "SinkSocket destroyed"; }
+
+ virtual int Enqueue(apacket::payload_type data) override final {
+ if (bytes_left_ <= data.size()) {
+ // Done reading.
+ Close();
+ return -1;
+ }
+
+ bytes_left_ -= data.size();
+ return 0;
+ }
+
+ size_t bytes_left_;
+};
+
+struct SourceSocket : public ServiceSocket {
+ explicit SourceSocket(size_t byte_count) {
+ LOG(INFO) << "Creating new SourceSocket with capacity " << byte_count;
+ bytes_left_ = byte_count;
+ }
+
+ virtual ~SourceSocket() { LOG(INFO) << "SourceSocket destroyed"; }
+
+ void Ready() {
+ size_t len = std::min(bytes_left_, get_max_payload());
+ if (len == 0) {
+ Close();
+ return;
+ }
+
+ Block block(len);
+ memset(block.data(), 0, block.size());
+ peer->enqueue(peer, std::move(block));
+ bytes_left_ -= len;
+ }
+
+ int Enqueue(apacket::payload_type data) { return -1; }
+
+ size_t bytes_left_;
+};
+
+asocket* daemon_service_to_socket(std::string_view name) {
+ if (name == "jdwp") {
+ return create_jdwp_service_socket();
+ } else if (name == "track-jdwp") {
+ return create_jdwp_tracker_service_socket();
+ } else if (name.starts_with("sink:")) {
+ name.remove_prefix(strlen("sink:"));
+ uint64_t byte_count = 0;
+ if (!android::base::ParseUint(name.data(), &byte_count)) {
+ return nullptr;
+ }
+ return new SinkSocket(byte_count);
+ } else if (name.starts_with("source:")) {
+ name.remove_prefix(strlen("source:"));
+ uint64_t byte_count = 0;
+ if (!android::base::ParseUint(name.data(), &byte_count)) {
+ return nullptr;
+ }
+ return new SourceSocket(byte_count);
+ }
+
+ return nullptr;
+}
+
+unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
+#ifndef __ANDROID_RECOVERY__
+ if (name.starts_with("abb:")) {
+ name.remove_prefix(strlen("abb:"));
+ return execute_binder_command(name);
+ }
+#endif
+
+ if (name.starts_with("dev:")) {
+ name.remove_prefix(strlen("dev:"));
+ return unique_fd{unix_open(name, O_RDWR | O_CLOEXEC)};
+ } else if (name.starts_with("framebuffer:")) {
return create_service_thread("fb", framebuffer_service);
- } else if (!strncmp(name, "jdwp:", 5)) {
- return create_jdwp_connection_fd(atoi(name + 5));
- } else if (!strncmp(name, "shell", 5)) {
- return ShellService(name + 5, transport);
- } else if (!strncmp(name, "exec:", 5)) {
- return StartSubprocess(name + 5, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
- } else if (!strncmp(name, "sync:", 5)) {
+ } else if (name.starts_with("jdwp:")) {
+ name.remove_prefix(strlen("jdwp:"));
+ std::string str(name);
+ return create_jdwp_connection_fd(atoi(str.c_str()));
+ } else if (name.starts_with("shell")) {
+ name.remove_prefix(strlen("shell"));
+ return ShellService(name, transport);
+ } else if (name.starts_with("exec:")) {
+ name.remove_prefix(strlen("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 (!strncmp(name, "remount:", 8)) {
- std::string options(name + strlen("remount:"));
+ } else if (name.starts_with("remount:")) {
+ std::string arg(name.begin() + strlen("remount:"), name.end());
return create_service_thread("remount",
- std::bind(remount_service, std::placeholders::_1, options));
- } else if (!strncmp(name, "reboot:", 7)) {
- std::string arg(name + strlen("reboot:"));
+ std::bind(remount_service, std::placeholders::_1, arg));
+ } else if (name.starts_with("reboot:")) {
+ std::string arg(name.begin() + strlen("reboot:"), name.end());
return create_service_thread("reboot",
std::bind(reboot_service, std::placeholders::_1, arg));
- } else if (!strncmp(name, "root:", 5)) {
+ } else if (name.starts_with("root:")) {
return create_service_thread("root", restart_root_service);
- } else if (!strncmp(name, "unroot:", 7)) {
+ } else if (name.starts_with("unroot:")) {
return create_service_thread("unroot", restart_unroot_service);
- } else if (!strncmp(name, "backup:", 7)) {
- return StartSubprocess(
- android::base::StringPrintf("/system/bin/bu backup %s", (name + 7)).c_str(),
- nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
- } else if (!strncmp(name, "restore:", 8)) {
+ } else if (name.starts_with("backup:")) {
+ name.remove_prefix(strlen("backup:"));
+ std::string cmd = "/system/bin/bu backup ";
+ cmd += name;
+ return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
+ } else if (name.starts_with("restore:")) {
return StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw,
SubprocessProtocol::kNone);
- } else if (!strncmp(name, "tcpip:", 6)) {
+ } else if (name.starts_with("tcpip:")) {
+ name.remove_prefix(strlen("tcpip:"));
+ std::string str(name);
+
int port;
- if (sscanf(name + 6, "%d", &port) != 1) {
+ if (sscanf(str.c_str(), "%d", &port) != 1) {
return unique_fd{};
}
return create_service_thread("tcp",
std::bind(restart_tcp_service, std::placeholders::_1, port));
- } else if (!strncmp(name, "usb:", 4)) {
+ } else if (name.starts_with("usb:")) {
return create_service_thread("usb", restart_usb_service);
- } else if (!strncmp(name, "reverse:", 8)) {
- return reverse_service(name + 8, transport);
- } else if (!strncmp(name, "disable-verity:", 15)) {
+ } else if (name.starts_with("reverse:")) {
+ name.remove_prefix(strlen("reverse:"));
+ return reverse_service(name, transport);
+ } else if (name.starts_with("disable-verity:")) {
return create_service_thread("verity-on", std::bind(set_verity_enabled_state_service,
std::placeholders::_1, false));
- } else if (!strncmp(name, "enable-verity:", 15)) {
+ } 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 (!strcmp(name, "reconnect")) {
+ } else if (name == "reconnect") {
return create_service_thread(
"reconnect", std::bind(reconnect_service, std::placeholders::_1, transport));
+ } else if (name == "spin") {
+ return create_service_thread("spin", spin_service);
}
+
return unique_fd{};
}
diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp
index 01097ac..455595f 100644
--- a/adb/daemon/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
@@ -140,8 +140,8 @@
class Subprocess {
public:
- Subprocess(const std::string& command, const char* terminal_type,
- SubprocessType type, SubprocessProtocol protocol);
+ Subprocess(std::string command, const char* terminal_type, SubprocessType type,
+ SubprocessProtocol protocol, bool make_pty_raw);
~Subprocess();
const std::string& command() const { return command_; }
@@ -154,6 +154,10 @@
// and exec's the child. Returns false and sets error on failure.
bool ForkAndExec(std::string* _Nonnull error);
+ // Sets up FDs, starts a thread executing command and the manager thread,
+ // Returns false and sets error on failure.
+ bool ExecInProcess(Command command, std::string* _Nonnull error);
+
// Start the subprocess manager thread. Consumes the subprocess, regardless of success.
// Returns false and sets error on failure.
static bool StartThread(std::unique_ptr<Subprocess> subprocess,
@@ -177,9 +181,9 @@
const std::string command_;
const std::string terminal_type_;
- bool make_pty_raw_ = false;
SubprocessType type_;
SubprocessProtocol protocol_;
+ bool make_pty_raw_;
pid_t pid_ = -1;
unique_fd local_socket_sfd_;
@@ -191,25 +195,13 @@
DISALLOW_COPY_AND_ASSIGN(Subprocess);
};
-Subprocess::Subprocess(const std::string& command, const char* terminal_type,
- SubprocessType type, SubprocessProtocol protocol)
- : command_(command),
+Subprocess::Subprocess(std::string command, const char* terminal_type, SubprocessType type,
+ SubprocessProtocol protocol, bool make_pty_raw)
+ : command_(std::move(command)),
terminal_type_(terminal_type ? terminal_type : ""),
type_(type),
- protocol_(protocol) {
- // If we aren't using the shell protocol we must allocate a PTY to properly close the
- // subprocess. PTYs automatically send SIGHUP to the slave-side process when the master side
- // of the PTY closes, which we rely on. If we use a raw pipe, processes that don't read/write,
- // e.g. screenrecord, will never notice the broken pipe and terminate.
- // The shell protocol doesn't require a PTY because it's always monitoring the local socket FD
- // with select() and will send SIGHUP manually to the child process.
- if (protocol_ == SubprocessProtocol::kNone && type_ == SubprocessType::kRaw) {
- // Disable PTY input/output processing since the client is expecting raw data.
- D("Can't create raw subprocess without shell protocol, using PTY in raw mode instead");
- type_ = SubprocessType::kPty;
- make_pty_raw_ = true;
- }
-}
+ protocol_(protocol),
+ make_pty_raw_(make_pty_raw) {}
Subprocess::~Subprocess() {
WaitForExit();
@@ -273,7 +265,7 @@
}
std::vector<std::string> joined_env;
- for (auto it : env) {
+ for (const auto& it : env) {
const char* key = it.first.c_str();
const char* value = it.second.c_str();
joined_env.push_back(android::base::StringPrintf("%s=%s", key, value));
@@ -430,6 +422,67 @@
return true;
}
+bool Subprocess::ExecInProcess(Command command, std::string* _Nonnull error) {
+ unique_fd child_stdinout_sfd, child_stderr_sfd;
+
+ CHECK(type_ == SubprocessType::kRaw);
+ CHECK(protocol_ == SubprocessProtocol::kShell);
+
+ __android_log_security_bswrite(SEC_TAG_ADB_SHELL_CMD, command_.c_str());
+
+ if (!CreateSocketpair(&stdinout_sfd_, &child_stdinout_sfd)) {
+ *error = android::base::StringPrintf("failed to create socketpair for stdin/out: %s",
+ strerror(errno));
+ return false;
+ }
+ // Raw subprocess + shell protocol allows for splitting stderr.
+ if (!CreateSocketpair(&stderr_sfd_, &child_stderr_sfd)) {
+ *error = android::base::StringPrintf("failed to create socketpair for stderr: %s",
+ strerror(errno));
+ return false;
+ }
+
+ D("execinprocess: stdin/stdout FD = %d, stderr FD = %d", stdinout_sfd_.get(),
+ stderr_sfd_.get());
+
+ // Required for shell protocol: create another socketpair to intercept data.
+ if (!CreateSocketpair(&protocol_sfd_, &local_socket_sfd_)) {
+ *error = android::base::StringPrintf("failed to create socketpair to intercept data: %s",
+ strerror(errno));
+ return false;
+ }
+ D("protocol FD = %d", protocol_sfd_.get());
+
+ input_ = std::make_unique<ShellProtocol>(protocol_sfd_);
+ output_ = std::make_unique<ShellProtocol>(protocol_sfd_);
+ if (!input_ || !output_) {
+ *error = "failed to allocate shell protocol objects";
+ return false;
+ }
+
+ // Don't let reads/writes to the subprocess block our thread. This isn't
+ // likely but could happen under unusual circumstances, such as if we
+ // write a ton of data to stdin but the subprocess never reads it and
+ // the pipe fills up.
+ for (int fd : {stdinout_sfd_.get(), stderr_sfd_.get()}) {
+ if (fd >= 0) {
+ if (!set_file_block_mode(fd, false)) {
+ *error = android::base::StringPrintf("failed to set non-blocking mode for fd %d",
+ fd);
+ return false;
+ }
+ }
+ }
+
+ std::thread([inout_sfd = std::move(child_stdinout_sfd), err_sfd = std::move(child_stderr_sfd),
+ command = std::move(command),
+ args = command_]() { command(args, inout_sfd, inout_sfd, err_sfd); })
+ .detach();
+
+ D("execinprocess: completed");
+ return true;
+}
+
bool Subprocess::StartThread(std::unique_ptr<Subprocess> subprocess, std::string* error) {
Subprocess* raw = subprocess.release();
std::thread(ThreadHandler, raw).detach();
@@ -512,7 +565,9 @@
// needed (e.g. SIGINT), pass those through the shell protocol
// and only fall back on this for unexpected closures.
D("protocol FD died, sending SIGHUP to pid %d", pid_);
- kill(pid_, SIGHUP);
+ if (pid_ != -1) {
+ kill(pid_, SIGHUP);
+ }
// We also need to close the pipes connected to the child process
// so that if it ignores SIGHUP and continues to write data it
@@ -682,7 +737,7 @@
int exit_code = 1;
D("waiting for pid %d", pid_);
- while (true) {
+ while (pid_ != -1) {
int status;
if (pid_ == waitpid(pid_, &status, 0)) {
D("post waitpid (pid=%d) status=%04x", pid_, status);
@@ -716,7 +771,7 @@
} // namespace
// Create a pipe containing the error.
-static unique_fd ReportError(SubprocessProtocol protocol, const std::string& message) {
+unique_fd ReportError(SubprocessProtocol protocol, const std::string& message) {
unique_fd read, write;
if (!Pipe(&read, &write)) {
PLOG(ERROR) << "failed to create pipe to report error";
@@ -745,23 +800,51 @@
return read;
}
-unique_fd StartSubprocess(const char* name, const char* terminal_type, SubprocessType type,
+unique_fd StartSubprocess(std::string name, const char* terminal_type, SubprocessType type,
SubprocessProtocol protocol) {
+ // If we aren't using the shell protocol we must allocate a PTY to properly close the
+ // subprocess. PTYs automatically send SIGHUP to the slave-side process when the master side
+ // of the PTY closes, which we rely on. If we use a raw pipe, processes that don't read/write,
+ // e.g. screenrecord, will never notice the broken pipe and terminate.
+ // The shell protocol doesn't require a PTY because it's always monitoring the local socket FD
+ // with select() and will send SIGHUP manually to the child process.
+ bool make_pty_raw = false;
+ if (protocol == SubprocessProtocol::kNone && type == SubprocessType::kRaw) {
+ // Disable PTY input/output processing since the client is expecting raw data.
+ D("Can't create raw subprocess without shell protocol, using PTY in raw mode instead");
+ type = SubprocessType::kPty;
+ make_pty_raw = true;
+ }
+
+ unique_fd error_fd;
+ unique_fd fd = StartSubprocess(std::move(name), terminal_type, type, protocol, make_pty_raw,
+ protocol, &error_fd);
+ if (fd == -1) {
+ return error_fd;
+ }
+ return fd;
+}
+
+unique_fd StartSubprocess(std::string name, const char* terminal_type, SubprocessType type,
+ SubprocessProtocol protocol, bool make_pty_raw,
+ SubprocessProtocol error_protocol, unique_fd* error_fd) {
D("starting %s subprocess (protocol=%s, TERM=%s): '%s'",
type == SubprocessType::kRaw ? "raw" : "PTY",
- protocol == SubprocessProtocol::kNone ? "none" : "shell",
- terminal_type, name);
+ protocol == SubprocessProtocol::kNone ? "none" : "shell", terminal_type, name.c_str());
- auto subprocess = std::make_unique<Subprocess>(name, terminal_type, type, protocol);
+ auto subprocess = std::make_unique<Subprocess>(std::move(name), terminal_type, type, protocol,
+ make_pty_raw);
if (!subprocess) {
LOG(ERROR) << "failed to allocate new subprocess";
- return ReportError(protocol, "failed to allocate new subprocess");
+ *error_fd = ReportError(error_protocol, "failed to allocate new subprocess");
+ return {};
}
std::string error;
if (!subprocess->ForkAndExec(&error)) {
LOG(ERROR) << "failed to start subprocess: " << error;
- return ReportError(protocol, error);
+ *error_fd = ReportError(error_protocol, error);
+ return {};
}
unique_fd local_socket(subprocess->ReleaseLocalSocket());
@@ -770,6 +853,40 @@
if (!Subprocess::StartThread(std::move(subprocess), &error)) {
LOG(ERROR) << "failed to start subprocess management thread: " << error;
+ *error_fd = ReportError(error_protocol, error);
+ return {};
+ }
+
+ return local_socket;
+}
+
+unique_fd StartCommandInProcess(std::string name, Command command) {
+ LOG(INFO) << "StartCommandInProcess(" << dump_hex(name.data(), name.size()) << ")";
+
+ constexpr auto terminal_type = "";
+ constexpr auto type = SubprocessType::kRaw;
+ constexpr auto protocol = SubprocessProtocol::kShell;
+ constexpr auto make_pty_raw = false;
+
+ auto subprocess = std::make_unique<Subprocess>(std::move(name), terminal_type, type, protocol,
+ make_pty_raw);
+ if (!subprocess) {
+ LOG(ERROR) << "failed to allocate new subprocess";
+ return ReportError(protocol, "failed to allocate new subprocess");
+ }
+
+ std::string error;
+ if (!subprocess->ExecInProcess(std::move(command), &error)) {
+ LOG(ERROR) << "failed to start subprocess: " << error;
+ return ReportError(protocol, error);
+ }
+
+ unique_fd local_socket(subprocess->ReleaseLocalSocket());
+ D("inprocess creation successful: local_socket_fd=%d, pid=%d", local_socket.get(),
+ subprocess->pid());
+
+ if (!Subprocess::StartThread(std::move(subprocess), &error)) {
+ LOG(ERROR) << "failed to start inprocess management thread: " << error;
return ReportError(protocol, error);
}
diff --git a/adb/daemon/shell_service.h b/adb/daemon/shell_service.h
index 2a48923..fc66377 100644
--- a/adb/daemon/shell_service.h
+++ b/adb/daemon/shell_service.h
@@ -16,8 +16,12 @@
#pragma once
+#include <string>
+
#include "adb_unique_fd.h"
+#include <string_view>
+
enum class SubprocessType {
kPty,
kRaw,
@@ -32,5 +36,20 @@
// shell is started, otherwise |name| is executed non-interactively.
//
// Returns an open FD connected to the subprocess or -1 on failure.
-unique_fd StartSubprocess(const char* name, const char* terminal_type, SubprocessType type,
+unique_fd StartSubprocess(std::string name, const char* terminal_type, SubprocessType type,
SubprocessProtocol protocol);
+
+// The same as above but with more fined grained control and custom error handling.
+unique_fd StartSubprocess(std::string name, const char* terminal_type, SubprocessType type,
+ SubprocessProtocol protocol, bool make_pty_raw,
+ SubprocessProtocol error_protocol, unique_fd* error_fd);
+
+// Executes |command| in a separate thread.
+// 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);
+unique_fd StartCommandInProcess(std::string name, Command command);
+
+// Create a pipe containing the error.
+unique_fd ReportError(SubprocessProtocol protocol, const std::string& message);
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index 9d495b0..f603d13 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * 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.
@@ -18,528 +18,568 @@
#include "sysdeps.h"
-#include <dirent.h>
#include <errno.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/functionfs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
-#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
-#include <algorithm>
-#include <atomic>
-#include <chrono>
-#include <condition_variable>
+#include <linux/usb/functionfs.h>
+#include <sys/eventfd.h>
+
+#include <array>
+#include <future>
+#include <memory>
#include <mutex>
-#include <thread>
+#include <optional>
+#include <vector>
+
+#include <asyncio/AsyncIO.h>
#include <android-base/logging.h>
+#include <android-base/macros.h>
#include <android-base/properties.h>
+#include <android-base/thread_annotations.h>
-#include "adb.h"
-#include "adbd/usb.h"
+#include <adbd/usb.h>
+
+#include "adb_unique_fd.h"
+#include "adb_utils.h"
+#include "sysdeps/chrono.h"
#include "transport.h"
+#include "types.h"
-using namespace std::chrono_literals;
+using android::base::StringPrintf;
-#define MAX_PACKET_SIZE_FS 64
-#define MAX_PACKET_SIZE_HS 512
-#define MAX_PACKET_SIZE_SS 1024
+static constexpr size_t kUsbReadQueueDepth = 16;
+static constexpr size_t kUsbReadSize = 16384;
-#define USB_FFS_BULK_SIZE 16384
+static constexpr size_t kUsbWriteQueueDepth = 16;
-// 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 cpu_to_le16(x) htole16(x)
-#define cpu_to_le32(x) htole32(x)
-
-static unique_fd& dummy_fd = *new unique_fd();
-
-struct func_desc {
- struct usb_interface_descriptor intf;
- struct usb_endpoint_descriptor_no_audio source;
- struct usb_endpoint_descriptor_no_audio sink;
-} __attribute__((packed));
-
-struct ss_func_desc {
- struct usb_interface_descriptor intf;
- struct usb_endpoint_descriptor_no_audio source;
- struct usb_ss_ep_comp_descriptor source_comp;
- struct usb_endpoint_descriptor_no_audio sink;
- struct usb_ss_ep_comp_descriptor sink_comp;
-} __attribute__((packed));
-
-struct desc_v1 {
- struct usb_functionfs_descs_head_v1 {
- __le32 magic;
- __le32 length;
- __le32 fs_count;
- __le32 hs_count;
- } __attribute__((packed)) header;
- struct func_desc fs_descs, hs_descs;
-} __attribute__((packed));
-
-struct desc_v2 {
- struct usb_functionfs_descs_head_v2 header;
- // The rest of the structure depends on the flags in the header.
- __le32 fs_count;
- __le32 hs_count;
- __le32 ss_count;
- __le32 os_count;
- struct func_desc fs_descs, hs_descs;
- struct ss_func_desc ss_descs;
- struct usb_os_desc_header os_header;
- struct usb_ext_compat_desc os_desc;
-} __attribute__((packed));
-
-static struct func_desc fs_descriptors = {
- .intf = {
- .bLength = sizeof(fs_descriptors.intf),
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = ADB_CLASS,
- .bInterfaceSubClass = ADB_SUBCLASS,
- .bInterfaceProtocol = ADB_PROTOCOL,
- .iInterface = 1, /* first string from the provided table */
- },
- .source = {
- .bLength = sizeof(fs_descriptors.source),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 1 | USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_FS,
- },
- .sink = {
- .bLength = sizeof(fs_descriptors.sink),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 2 | USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_FS,
- },
-};
-
-static struct func_desc hs_descriptors = {
- .intf = {
- .bLength = sizeof(hs_descriptors.intf),
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = ADB_CLASS,
- .bInterfaceSubClass = ADB_SUBCLASS,
- .bInterfaceProtocol = ADB_PROTOCOL,
- .iInterface = 1, /* first string from the provided table */
- },
- .source = {
- .bLength = sizeof(hs_descriptors.source),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 1 | USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_HS,
- },
- .sink = {
- .bLength = sizeof(hs_descriptors.sink),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 2 | USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_HS,
- },
-};
-
-static struct ss_func_desc ss_descriptors = {
- .intf = {
- .bLength = sizeof(ss_descriptors.intf),
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = ADB_CLASS,
- .bInterfaceSubClass = ADB_SUBCLASS,
- .bInterfaceProtocol = ADB_PROTOCOL,
- .iInterface = 1, /* first string from the provided table */
- },
- .source = {
- .bLength = sizeof(ss_descriptors.source),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 1 | USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_SS,
- },
- .source_comp = {
- .bLength = sizeof(ss_descriptors.source_comp),
- .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
- .bMaxBurst = 4,
- },
- .sink = {
- .bLength = sizeof(ss_descriptors.sink),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 2 | USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_SS,
- },
- .sink_comp = {
- .bLength = sizeof(ss_descriptors.sink_comp),
- .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
- .bMaxBurst = 4,
- },
-};
-
-struct usb_ext_compat_desc os_desc_compat = {
- .bFirstInterfaceNumber = 0,
- .Reserved1 = cpu_to_le32(1),
- .CompatibleID = {0},
- .SubCompatibleID = {0},
- .Reserved2 = {0},
-};
-
-static struct usb_os_desc_header os_desc_header = {
- .interface = cpu_to_le32(1),
- .dwLength = cpu_to_le32(sizeof(os_desc_header) + sizeof(os_desc_compat)),
- .bcdVersion = cpu_to_le32(1),
- .wIndex = cpu_to_le32(4),
- .bCount = cpu_to_le32(1),
- .Reserved = cpu_to_le32(0),
-};
-
-#define STR_INTERFACE_ "ADB Interface"
-
-static const struct {
- struct usb_functionfs_strings_head header;
- struct {
- __le16 code;
- const char str1[sizeof(STR_INTERFACE_)];
- } __attribute__((packed)) lang0;
-} __attribute__((packed)) strings = {
- .header = {
- .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
- .length = cpu_to_le32(sizeof(strings)),
- .str_count = cpu_to_le32(1),
- .lang_count = cpu_to_le32(1),
- },
- .lang0 = {
- cpu_to_le16(0x0409), /* en-us */
- STR_INTERFACE_,
- },
-};
-
-static void aio_block_init(aio_block* aiob, unsigned num_bufs) {
- aiob->iocb.resize(num_bufs);
- aiob->iocbs.resize(num_bufs);
- aiob->events.resize(num_bufs);
- aiob->num_submitted = 0;
- for (unsigned i = 0; i < num_bufs; i++) {
- aiob->iocbs[i] = &aiob->iocb[i];
- }
- memset(&aiob->ctx, 0, sizeof(aiob->ctx));
- if (io_setup(num_bufs, &aiob->ctx)) {
- D("[ aio: got error on io_setup (%d) ]", errno);
+static const char* to_string(enum usb_functionfs_event_type type) {
+ switch (type) {
+ case FUNCTIONFS_BIND:
+ return "FUNCTIONFS_BIND";
+ case FUNCTIONFS_UNBIND:
+ return "FUNCTIONFS_UNBIND";
+ case FUNCTIONFS_ENABLE:
+ return "FUNCTIONFS_ENABLE";
+ case FUNCTIONFS_DISABLE:
+ return "FUNCTIONFS_DISABLE";
+ case FUNCTIONFS_SETUP:
+ return "FUNCTIONFS_SETUP";
+ case FUNCTIONFS_SUSPEND:
+ return "FUNCTIONFS_SUSPEND";
+ case FUNCTIONFS_RESUME:
+ return "FUNCTIONFS_RESUME";
}
}
-static int getMaxPacketSize(int ffs_fd) {
- usb_endpoint_descriptor desc;
- if (ioctl(ffs_fd, FUNCTIONFS_ENDPOINT_DESC, reinterpret_cast<unsigned long>(&desc))) {
- D("[ could not get endpoint descriptor! (%d) ]", errno);
- return MAX_PACKET_SIZE_HS;
- } else {
- return desc.wMaxPacketSize;
+enum class TransferDirection : uint64_t {
+ READ = 0,
+ WRITE = 1,
+};
+
+struct TransferId {
+ TransferDirection direction : 1;
+ uint64_t id : 63;
+
+ TransferId() : TransferId(TransferDirection::READ, 0) {}
+
+ private:
+ TransferId(TransferDirection direction, uint64_t id) : direction(direction), id(id) {}
+
+ public:
+ explicit operator uint64_t() const {
+ uint64_t result;
+ static_assert(sizeof(*this) == sizeof(result));
+ memcpy(&result, this, sizeof(*this));
+ return result;
}
-}
-static bool init_functionfs(struct usb_handle* h) {
- LOG(INFO) << "initializing functionfs";
+ static TransferId read(uint64_t id) { return TransferId(TransferDirection::READ, id); }
+ static TransferId write(uint64_t id) { return TransferId(TransferDirection::WRITE, id); }
- ssize_t ret;
- struct desc_v1 v1_descriptor;
- struct desc_v2 v2_descriptor;
+ static TransferId from_value(uint64_t value) {
+ TransferId result;
+ memcpy(&result, &value, sizeof(value));
+ return result;
+ }
+};
- v2_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
- v2_descriptor.header.length = cpu_to_le32(sizeof(v2_descriptor));
- v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
- FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC;
- v2_descriptor.fs_count = 3;
- v2_descriptor.hs_count = 3;
- v2_descriptor.ss_count = 5;
- v2_descriptor.os_count = 1;
- 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;
+struct IoBlock {
+ bool pending;
+ struct iocb control;
+ Block payload;
- if (h->control < 0) { // might have already done this before
- LOG(INFO) << "opening control endpoint " << USB_FFS_ADB_EP0;
- h->control.reset(adb_open(USB_FFS_ADB_EP0, O_WRONLY));
- if (h->control < 0) {
- PLOG(ERROR) << "cannot open control endpoint " << USB_FFS_ADB_EP0;
- goto err;
+ TransferId id() const { return TransferId::from_value(control.aio_data); }
+};
+
+struct ScopedAioContext {
+ ScopedAioContext() = default;
+ ~ScopedAioContext() { reset(); }
+
+ ScopedAioContext(ScopedAioContext&& move) { reset(move.release()); }
+ ScopedAioContext(const ScopedAioContext& copy) = delete;
+
+ ScopedAioContext& operator=(ScopedAioContext&& move) {
+ reset(move.release());
+ return *this;
+ }
+ ScopedAioContext& operator=(const ScopedAioContext& copy) = delete;
+
+ static ScopedAioContext Create(size_t max_events) {
+ aio_context_t ctx = 0;
+ if (io_setup(max_events, &ctx) != 0) {
+ PLOG(FATAL) << "failed to create aio_context_t";
+ }
+ ScopedAioContext result;
+ result.reset(ctx);
+ return result;
+ }
+
+ aio_context_t release() {
+ aio_context_t result = context_;
+ context_ = 0;
+ return result;
+ }
+
+ void reset(aio_context_t new_context = 0) {
+ if (context_ != 0) {
+ io_destroy(context_);
}
- ret = adb_write(h->control.get(), &v2_descriptor, sizeof(v2_descriptor));
- if (ret < 0) {
- v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
- v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
- v1_descriptor.header.fs_count = 3;
- v1_descriptor.header.hs_count = 3;
- v1_descriptor.fs_descs = fs_descriptors;
- v1_descriptor.hs_descs = hs_descriptors;
- D("[ %s: Switching to V1_descriptor format errno=%d ]", USB_FFS_ADB_EP0, errno);
- ret = adb_write(h->control.get(), &v1_descriptor, sizeof(v1_descriptor));
- if (ret < 0) {
- D("[ %s: write descriptors failed: errno=%d ]", USB_FFS_ADB_EP0, errno);
- goto err;
+ context_ = new_context;
+ }
+
+ aio_context_t get() { return context_; }
+
+ private:
+ aio_context_t context_ = 0;
+};
+
+struct UsbFfsConnection : public Connection {
+ UsbFfsConnection(unique_fd control, unique_fd read, unique_fd write,
+ std::promise<void> destruction_notifier)
+ : stopped_(false),
+ destruction_notifier_(std::move(destruction_notifier)),
+ control_fd_(std::move(control)),
+ read_fd_(std::move(read)),
+ write_fd_(std::move(write)) {
+ LOG(INFO) << "UsbFfsConnection constructed";
+ event_fd_.reset(eventfd(0, EFD_CLOEXEC));
+ if (event_fd_ == -1) {
+ PLOG(FATAL) << "failed to create eventfd";
+ }
+
+ aio_context_ = ScopedAioContext::Create(kUsbReadQueueDepth + kUsbWriteQueueDepth);
+ }
+
+ ~UsbFfsConnection() {
+ LOG(INFO) << "UsbFfsConnection being destroyed";
+ Stop();
+ monitor_thread_.join();
+ destruction_notifier_.set_value();
+ }
+
+ 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));
+
+ std::lock_guard<std::mutex> lock(write_mutex_);
+ write_requests_.push_back(CreateWriteBlock(std::move(header), next_write_id_++));
+ if (!packet->payload.empty()) {
+ write_requests_.push_back(
+ CreateWriteBlock(std::move(packet->payload), next_write_id_++));
+ }
+ SubmitWrites();
+ return true;
+ }
+
+ virtual void Start() override final { StartMonitor(); }
+
+ virtual void Stop() override final {
+ if (stopped_.exchange(true)) {
+ return;
+ }
+ stopped_ = true;
+ uint64_t notify = 1;
+ ssize_t rc = adb_write(event_fd_.get(), ¬ify, sizeof(notify));
+ if (rc < 0) {
+ PLOG(FATAL) << "failed to notify eventfd to stop UsbFfsConnection";
+ }
+ CHECK_EQ(static_cast<size_t>(rc), sizeof(notify));
+ }
+
+ private:
+ void StartMonitor() {
+ // This is a bit of a mess.
+ // It's possible for io_submit to end up blocking, if we call it as the endpoint
+ // becomes disabled. Work around this by having a monitor thread to listen for functionfs
+ // lifecycle events. If we notice an error condition (either we've become disabled, or we
+ // were never enabled in the first place), we send interruption signals to the worker thread
+ // until it dies, and then report failure to the transport via HandleError, which will
+ // eventually result in the transport being destroyed, which will result in UsbFfsConnection
+ // being destroyed, which unblocks the open thread and restarts this entire process.
+ static constexpr int kInterruptionSignal = SIGUSR1;
+ static std::once_flag handler_once;
+ std::call_once(handler_once, []() { signal(kInterruptionSignal, [](int) {}); });
+
+ monitor_thread_ = std::thread([this]() {
+ adb_thread_setname("UsbFfs-monitor");
+
+ bool bound = false;
+ bool started = false;
+ bool running = true;
+ while (running) {
+ if (!bound || !started) {
+ adb_pollfd pfd = {.fd = control_fd_.get(), .events = POLLIN, .revents = 0};
+ int rc = TEMP_FAILURE_RETRY(adb_poll(&pfd, 1, 5000 /*ms*/));
+ if (rc == -1) {
+ PLOG(FATAL) << "poll on USB control fd failed";
+ } else if (rc == 0) {
+ // Something in the kernel presumably went wrong.
+ // Close our endpoints, wait for a bit, and then try again.
+ aio_context_.reset();
+ read_fd_.reset();
+ write_fd_.reset();
+ control_fd_.reset();
+ std::this_thread::sleep_for(5s);
+ HandleError("didn't receive FUNCTIONFS_ENABLE, retrying");
+ return;
+ }
+ }
+
+ struct usb_functionfs_event event;
+ if (TEMP_FAILURE_RETRY(adb_read(control_fd_.get(), &event, sizeof(event))) !=
+ sizeof(event)) {
+ PLOG(FATAL) << "failed to read functionfs event";
+ }
+
+ LOG(INFO) << "USB event: "
+ << to_string(static_cast<usb_functionfs_event_type>(event.type));
+
+ switch (event.type) {
+ case FUNCTIONFS_BIND:
+ CHECK(!started) << "received FUNCTIONFS_ENABLE while already bound?";
+ bound = true;
+ break;
+
+ case FUNCTIONFS_ENABLE:
+ CHECK(!started) << "received FUNCTIONFS_ENABLE while already running?";
+ started = true;
+ StartWorker();
+ break;
+
+ case FUNCTIONFS_DISABLE:
+ running = false;
+ break;
+ }
+ }
+
+ pthread_t worker_thread_handle = worker_thread_.native_handle();
+ while (true) {
+ int rc = pthread_kill(worker_thread_handle, kInterruptionSignal);
+ if (rc != 0) {
+ LOG(ERROR) << "failed to send interruption signal to worker: " << strerror(rc);
+ break;
+ }
+
+ std::this_thread::sleep_for(100ms);
+
+ rc = pthread_kill(worker_thread_handle, 0);
+ if (rc == 0) {
+ continue;
+ } else if (rc == ESRCH) {
+ break;
+ } else {
+ LOG(ERROR) << "failed to send interruption signal to worker: " << strerror(rc);
+ }
+ }
+
+ worker_thread_.join();
+
+ aio_context_.reset();
+ read_fd_.reset();
+ write_fd_.reset();
+ });
+ }
+
+ void StartWorker() {
+ worker_thread_ = std::thread([this]() {
+ adb_thread_setname("UsbFfs-worker");
+ for (size_t i = 0; i < kUsbReadQueueDepth; ++i) {
+ read_requests_[i] = CreateReadBlock(next_read_id_++);
+ SubmitRead(&read_requests_[i]);
+ }
+
+ while (!stopped_) {
+ uint64_t dummy;
+ ssize_t rc = adb_read(event_fd_.get(), &dummy, sizeof(dummy));
+ if (rc == -1) {
+ PLOG(FATAL) << "failed to read from eventfd";
+ } else if (rc == 0) {
+ LOG(FATAL) << "hit EOF on eventfd";
+ }
+
+ WaitForEvents();
+ }
+ });
+ }
+
+ void PrepareReadBlock(IoBlock* block, uint64_t id) {
+ block->pending = false;
+ block->payload.resize(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();
+ }
+
+ IoBlock CreateReadBlock(uint64_t id) {
+ IoBlock block;
+ PrepareReadBlock(&block, id);
+ block.control.aio_rw_flags = 0;
+ block.control.aio_lio_opcode = IOCB_CMD_PREAD;
+ block.control.aio_reqprio = 0;
+ block.control.aio_fildes = read_fd_.get();
+ block.control.aio_offset = 0;
+ block.control.aio_flags = IOCB_FLAG_RESFD;
+ block.control.aio_resfd = event_fd_.get();
+ return block;
+ }
+
+ void WaitForEvents() {
+ static constexpr size_t kMaxEvents = kUsbReadQueueDepth + kUsbWriteQueueDepth;
+ struct io_event events[kMaxEvents];
+ struct timespec timeout = {.tv_sec = 0, .tv_nsec = 0};
+ int rc = io_getevents(aio_context_.get(), 0, kMaxEvents, events, &timeout);
+ if (rc == -1) {
+ HandleError(StringPrintf("io_getevents failed while reading: %s", strerror(errno)));
+ return;
+ }
+
+ for (int event_idx = 0; event_idx < rc; ++event_idx) {
+ auto& event = events[event_idx];
+ TransferId id = TransferId::from_value(event.data);
+
+ if (event.res < 0) {
+ std::string error =
+ StringPrintf("%s %" PRIu64 " failed with error %s",
+ id.direction == TransferDirection::READ ? "read" : "write",
+ id.id, strerror(-event.res));
+ HandleError(error);
+ return;
+ }
+
+ if (id.direction == TransferDirection::READ) {
+ HandleRead(id, event.res);
+ } else {
+ HandleWrite(id);
+ }
+ }
+ }
+
+ void HandleRead(TransferId id, int64_t size) {
+ uint64_t read_idx = id.id % kUsbReadQueueDepth;
+ IoBlock* block = &read_requests_[read_idx];
+ block->pending = false;
+ block->payload.resize(size);
+
+ // Notification for completed reads can be received out of order.
+ if (block->id().id != needed_read_id_) {
+ LOG(VERBOSE) << "read " << block->id().id << " completed while waiting for "
+ << needed_read_id_;
+ return;
+ }
+
+ for (uint64_t id = needed_read_id_;; ++id) {
+ size_t read_idx = id % kUsbReadQueueDepth;
+ IoBlock* current_block = &read_requests_[read_idx];
+ if (current_block->pending) {
+ break;
+ }
+ ProcessRead(current_block);
+ ++needed_read_id_;
+ }
+ }
+
+ void ProcessRead(IoBlock* 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));
+ 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);
+ CHECK_LE(payload.size(), bytes_left);
+ incoming_payload_.append(std::make_unique<Block>(std::move(payload)));
+ }
+
+ if (incoming_header_->data_length == incoming_payload_.size()) {
+ auto packet = std::make_unique<apacket>();
+ packet->msg = *incoming_header_;
+
+ // TODO: Make apacket contain an IOVector so we don't have to coalesce.
+ packet->payload = incoming_payload_.coalesce();
+ read_callback_(this, std::move(packet));
+
+ incoming_header_.reset();
+ incoming_payload_.clear();
}
}
- ret = adb_write(h->control.get(), &strings, sizeof(strings));
- if (ret < 0) {
- D("[ %s: writing strings failed: errno=%d]", USB_FFS_ADB_EP0, errno);
- goto err;
+ PrepareReadBlock(block, block->id().id + kUsbReadQueueDepth);
+ SubmitRead(block);
+ }
+
+ void SubmitRead(IoBlock* block) {
+ block->pending = true;
+ struct iocb* iocb = &block->control;
+ if (io_submit(aio_context_.get(), 1, &iocb) != 1) {
+ HandleError(StringPrintf("failed to submit read: %s", strerror(errno)));
+ return;
}
- //Signal only when writing the descriptors to ffs
- android::base::SetProperty("sys.usb.ffs.ready", "1");
}
- h->bulk_out.reset(adb_open(USB_FFS_ADB_OUT, O_RDONLY));
- if (h->bulk_out < 0) {
- PLOG(ERROR) << "cannot open bulk-out endpoint " << USB_FFS_ADB_OUT;
- goto err;
+ void HandleWrite(TransferId id) {
+ 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);
+ });
+ CHECK(it != write_requests_.end());
+
+ write_requests_.erase(it);
+ size_t outstanding_writes = --writes_submitted_;
+ LOG(DEBUG) << "USB write: reaped, down to " << outstanding_writes;
+
+ SubmitWrites();
}
- h->bulk_in.reset(adb_open(USB_FFS_ADB_IN, O_WRONLY));
- if (h->bulk_in < 0) {
- PLOG(ERROR) << "cannot open bulk-in endpoint " << USB_FFS_ADB_IN;
- goto err;
+ std::unique_ptr<IoBlock> CreateWriteBlock(Block payload, 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());
+ block->control.aio_nbytes = block->payload.size();
+ block->control.aio_offset = 0;
+ block->control.aio_flags = IOCB_FLAG_RESFD;
+ block->control.aio_resfd = event_fd_.get();
+ return block;
}
- h->read_aiob.fd = h->bulk_out;
- h->write_aiob.fd = h->bulk_in;
- h->reads_zero_packets = true;
- return true;
+ void SubmitWrites() REQUIRES(write_mutex_) {
+ if (writes_submitted_ == kUsbWriteQueueDepth) {
+ return;
+ }
-err:
- h->bulk_in.reset();
- h->bulk_out.reset();
- h->control.reset();
- return false;
-}
+ ssize_t writes_to_submit = std::min(kUsbWriteQueueDepth - writes_submitted_,
+ write_requests_.size() - writes_submitted_);
+ CHECK_GE(writes_to_submit, 0);
+ if (writes_to_submit == 0) {
+ return;
+ }
-static void usb_ffs_open_thread(usb_handle *usb) {
+ 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;
+ LOG(VERBOSE) << "submitting write_request " << static_cast<void*>(iocbs[i]);
+ }
+
+ int rc = io_submit(aio_context_.get(), writes_to_submit, iocbs);
+ if (rc == -1) {
+ HandleError(StringPrintf("failed to submit write requests: %s", strerror(errno)));
+ return;
+ } else if (rc != writes_to_submit) {
+ LOG(FATAL) << "failed to submit all writes: wanted to submit " << writes_to_submit
+ << ", actually submitted " << rc;
+ }
+
+ writes_submitted_ += rc;
+ }
+
+ void HandleError(const std::string& error) {
+ std::call_once(error_flag_, [&]() {
+ error_callback_(this, error);
+ if (!stopped_) {
+ Stop();
+ }
+ });
+ }
+
+ std::thread monitor_thread_;
+ std::thread worker_thread_;
+
+ std::atomic<bool> stopped_;
+ std::promise<void> destruction_notifier_;
+ std::once_flag error_flag_;
+
+ unique_fd event_fd_;
+
+ ScopedAioContext aio_context_;
+ unique_fd control_fd_;
+ unique_fd read_fd_;
+ unique_fd write_fd_;
+
+ std::optional<amessage> incoming_header_;
+ IOVector incoming_payload_;
+
+ std::array<IoBlock, kUsbReadQueueDepth> read_requests_;
+ IOVector read_data_;
+
+ // ID of the next request that we're going to send out.
+ size_t next_read_id_ = 0;
+
+ // ID of the next packet we're waiting for.
+ size_t needed_read_id_ = 0;
+
+ std::mutex write_mutex_;
+ std::deque<std::unique_ptr<IoBlock>> 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;
+};
+
+static void usb_ffs_open_thread() {
adb_thread_setname("usb ffs open");
while (true) {
- // wait until the USB device needs opening
- std::unique_lock<std::mutex> lock(usb->lock);
- while (!usb->open_new_connection) {
- usb->notify.wait(lock);
- }
- usb->open_new_connection = false;
- lock.unlock();
-
- while (true) {
- if (init_functionfs(usb)) {
- LOG(INFO) << "functionfs successfully initialized";
- break;
- }
+ unique_fd control;
+ unique_fd bulk_out;
+ unique_fd bulk_in;
+ if (!open_functionfs(&control, &bulk_out, &bulk_in)) {
std::this_thread::sleep_for(1s);
- }
-
- LOG(INFO) << "registering usb transport";
- register_usb_transport(usb, nullptr, nullptr, 1);
- }
-
- // never gets here
- abort();
-}
-
-static int usb_ffs_write(usb_handle* h, const void* data, int len) {
- D("about to write (fd=%d, len=%d)", h->bulk_in.get(), len);
-
- const char* buf = static_cast<const char*>(data);
- int orig_len = len;
- while (len > 0) {
- int write_len = std::min(USB_FFS_BULK_SIZE, len);
- int n = adb_write(h->bulk_in, buf, write_len);
- if (n < 0) {
- D("ERROR: fd = %d, n = %d: %s", h->bulk_in.get(), n, strerror(errno));
- return -1;
- }
- buf += n;
- len -= n;
- }
-
- D("[ done fd=%d ]", h->bulk_in.get());
- return orig_len;
-}
-
-static int usb_ffs_read(usb_handle* h, void* data, int len) {
- D("about to read (fd=%d, len=%d)", h->bulk_out.get(), len);
-
- char* buf = static_cast<char*>(data);
- int orig_len = len;
- while (len > 0) {
- int read_len = std::min(USB_FFS_BULK_SIZE, len);
- int n = adb_read(h->bulk_out, buf, read_len);
- if (n < 0) {
- D("ERROR: fd = %d, n = %d: %s", h->bulk_out.get(), n, strerror(errno));
- return -1;
- }
- buf += n;
- len -= n;
- }
-
- D("[ done fd=%d ]", h->bulk_out.get());
- return orig_len;
-}
-
-static int usb_ffs_do_aio(usb_handle* h, const void* data, int len, bool read) {
- aio_block* aiob = read ? &h->read_aiob : &h->write_aiob;
- bool zero_packet = false;
-
- int num_bufs = len / h->io_size + (len % h->io_size == 0 ? 0 : 1);
- const char* cur_data = reinterpret_cast<const char*>(data);
- int packet_size = getMaxPacketSize(aiob->fd);
-
- if (posix_madvise(const_cast<void*>(data), len, POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED) <
- 0) {
- D("[ Failed to madvise: %d ]", errno);
- }
-
- for (int i = 0; i < num_bufs; i++) {
- int buf_len = std::min(len, static_cast<int>(h->io_size));
- io_prep(&aiob->iocb[i], aiob->fd, cur_data, buf_len, 0, read);
-
- len -= buf_len;
- cur_data += buf_len;
-
- if (len == 0 && buf_len % packet_size == 0 && read) {
- // adb does not expect the device to send a zero packet after data transfer,
- // but the host *does* send a zero packet for the device to read.
- zero_packet = h->reads_zero_packets;
- }
- }
- if (zero_packet) {
- io_prep(&aiob->iocb[num_bufs], aiob->fd, reinterpret_cast<const void*>(cur_data),
- packet_size, 0, read);
- num_bufs += 1;
- }
-
- while (true) {
- if (TEMP_FAILURE_RETRY(io_submit(aiob->ctx, num_bufs, aiob->iocbs.data())) < num_bufs) {
- PLOG(ERROR) << "aio: got error submitting " << (read ? "read" : "write");
- return -1;
- }
- if (TEMP_FAILURE_RETRY(io_getevents(aiob->ctx, num_bufs, num_bufs, aiob->events.data(),
- nullptr)) < num_bufs) {
- PLOG(ERROR) << "aio: got error waiting " << (read ? "read" : "write");
- return -1;
- }
- if (num_bufs == 1 && aiob->events[0].res == -EINTR) {
continue;
}
- int ret = 0;
- for (int i = 0; i < num_bufs; i++) {
- if (aiob->events[i].res < 0) {
- errno = -aiob->events[i].res;
- PLOG(ERROR) << "aio: got error event on " << (read ? "read" : "write")
- << " total bufs " << num_bufs;
- return -1;
- }
- ret += aiob->events[i].res;
- }
- return ret;
+
+ atransport* transport = new atransport();
+ transport->serial = "UsbFfs";
+ std::promise<void> destruction_notifier;
+ std::future<void> future = destruction_notifier.get_future();
+ transport->SetConnection(std::make_unique<UsbFfsConnection>(
+ std::move(control), std::move(bulk_out), std::move(bulk_in),
+ std::move(destruction_notifier)));
+ register_transport(transport);
+ future.wait();
}
}
-static int usb_ffs_aio_read(usb_handle* h, void* data, int len) {
- return usb_ffs_do_aio(h, data, len, true);
-}
-
-static int usb_ffs_aio_write(usb_handle* h, const void* data, int len) {
- return usb_ffs_do_aio(h, data, len, false);
-}
-
-static void usb_ffs_kick(usb_handle* h) {
- int err;
-
- err = ioctl(h->bulk_in.get(), FUNCTIONFS_CLEAR_HALT);
- if (err < 0) {
- D("[ kick: source (fd=%d) clear halt failed (%d) ]", h->bulk_in.get(), errno);
- }
-
- err = ioctl(h->bulk_out.get(), FUNCTIONFS_CLEAR_HALT);
- if (err < 0) {
- D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out.get(), errno);
- }
-
- // don't close ep0 here, since we may not need to reinitialize it with
- // the same descriptors again. if however ep1/ep2 fail to re-open in
- // init_functionfs, only then would we close and open ep0 again.
- // Ditto the comment in usb_adb_kick.
- h->kicked = true;
- TEMP_FAILURE_RETRY(dup2(dummy_fd.get(), h->bulk_out.get()));
- TEMP_FAILURE_RETRY(dup2(dummy_fd.get(), h->bulk_in.get()));
-}
-
-static void usb_ffs_close(usb_handle* h) {
- LOG(INFO) << "closing functionfs transport";
-
- h->kicked = false;
- h->bulk_out.reset();
- h->bulk_in.reset();
-
- // Notify usb_adb_open_thread to open a new connection.
- h->lock.lock();
- h->open_new_connection = true;
- h->lock.unlock();
- h->notify.notify_one();
-}
-
-usb_handle *create_usb_handle(unsigned num_bufs, unsigned io_size) {
- usb_handle* h = new usb_handle();
-
- if (android::base::GetBoolProperty("sys.usb.ffs.aio_compat", false)) {
- // Devices on older kernels (< 3.18) will not have aio support for ffs
- // unless backported. Fall back on the non-aio functions instead.
- h->write = usb_ffs_write;
- h->read = usb_ffs_read;
- } else {
- h->write = usb_ffs_aio_write;
- h->read = usb_ffs_aio_read;
- aio_block_init(&h->read_aiob, num_bufs);
- aio_block_init(&h->write_aiob, num_bufs);
- }
- h->io_size = io_size;
- h->kick = usb_ffs_kick;
- h->close = usb_ffs_close;
- return h;
-}
-
+void usb_init_legacy();
void usb_init() {
- D("[ usb_init - using FunctionFS ]");
- dummy_fd.reset(adb_open("/dev/null", O_WRONLY | O_CLOEXEC));
- CHECK_NE(-1, dummy_fd.get());
-
- std::thread(usb_ffs_open_thread, create_usb_handle(USB_FFS_NUM_BUFS, USB_FFS_BULK_SIZE)).detach();
-}
-
-int usb_write(usb_handle* h, const void* data, int len) {
- return h->write(h, data, len);
-}
-
-int usb_read(usb_handle* h, void* data, int len) {
- return h->read(h, data, len);
-}
-
-int usb_close(usb_handle* h) {
- h->close(h);
- return 0;
-}
-
-void usb_kick(usb_handle* h) {
- h->kick(h);
+ if (!android::base::GetBoolProperty("persist.adb.nonblocking_ffs", false)) {
+ usb_init_legacy();
+ } else {
+ std::thread(usb_ffs_open_thread).detach();
+ }
}
diff --git a/adb/daemon/usb_ffs.cpp b/adb/daemon/usb_ffs.cpp
new file mode 100644
index 0000000..07b4ba8
--- /dev/null
+++ b/adb/daemon/usb_ffs.cpp
@@ -0,0 +1,278 @@
+/*
+ * 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 USB
+
+#include "sysdeps.h"
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/functionfs.h>
+
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/unique_fd.h>
+
+#include "adb.h"
+#include "adbd/usb.h"
+
+#define MAX_PACKET_SIZE_FS 64
+#define MAX_PACKET_SIZE_HS 512
+#define MAX_PACKET_SIZE_SS 1024
+
+#define USB_FFS_BULK_SIZE 16384
+
+// 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 cpu_to_le16(x) htole16(x)
+#define cpu_to_le32(x) htole32(x)
+
+struct func_desc {
+ struct usb_interface_descriptor intf;
+ struct usb_endpoint_descriptor_no_audio source;
+ struct usb_endpoint_descriptor_no_audio sink;
+} __attribute__((packed));
+
+struct ss_func_desc {
+ struct usb_interface_descriptor intf;
+ struct usb_endpoint_descriptor_no_audio source;
+ struct usb_ss_ep_comp_descriptor source_comp;
+ struct usb_endpoint_descriptor_no_audio sink;
+ struct usb_ss_ep_comp_descriptor sink_comp;
+} __attribute__((packed));
+
+struct desc_v1 {
+ struct usb_functionfs_descs_head_v1 {
+ __le32 magic;
+ __le32 length;
+ __le32 fs_count;
+ __le32 hs_count;
+ } __attribute__((packed)) header;
+ struct func_desc fs_descs, hs_descs;
+} __attribute__((packed));
+
+struct desc_v2 {
+ struct usb_functionfs_descs_head_v2 header;
+ // The rest of the structure depends on the flags in the header.
+ __le32 fs_count;
+ __le32 hs_count;
+ __le32 ss_count;
+ __le32 os_count;
+ struct func_desc fs_descs, hs_descs;
+ struct ss_func_desc ss_descs;
+ struct usb_os_desc_header os_header;
+ struct usb_ext_compat_desc os_desc;
+} __attribute__((packed));
+
+// clang-format off
+static struct func_desc fs_descriptors = {
+ .intf = {
+ .bLength = sizeof(fs_descriptors.intf),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = ADB_CLASS,
+ .bInterfaceSubClass = ADB_SUBCLASS,
+ .bInterfaceProtocol = ADB_PROTOCOL,
+ .iInterface = 1, /* first string from the provided table */
+ },
+ .source = {
+ .bLength = sizeof(fs_descriptors.source),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 1 | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_FS,
+ },
+ .sink = {
+ .bLength = sizeof(fs_descriptors.sink),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 2 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_FS,
+ },
+};
+
+static struct func_desc hs_descriptors = {
+ .intf = {
+ .bLength = sizeof(hs_descriptors.intf),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = ADB_CLASS,
+ .bInterfaceSubClass = ADB_SUBCLASS,
+ .bInterfaceProtocol = ADB_PROTOCOL,
+ .iInterface = 1, /* first string from the provided table */
+ },
+ .source = {
+ .bLength = sizeof(hs_descriptors.source),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 1 | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_HS,
+ },
+ .sink = {
+ .bLength = sizeof(hs_descriptors.sink),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 2 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_HS,
+ },
+};
+
+static struct ss_func_desc ss_descriptors = {
+ .intf = {
+ .bLength = sizeof(ss_descriptors.intf),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = ADB_CLASS,
+ .bInterfaceSubClass = ADB_SUBCLASS,
+ .bInterfaceProtocol = ADB_PROTOCOL,
+ .iInterface = 1, /* first string from the provided table */
+ },
+ .source = {
+ .bLength = sizeof(ss_descriptors.source),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 1 | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_SS,
+ },
+ .source_comp = {
+ .bLength = sizeof(ss_descriptors.source_comp),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ .bMaxBurst = 4,
+ },
+ .sink = {
+ .bLength = sizeof(ss_descriptors.sink),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 2 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_SS,
+ },
+ .sink_comp = {
+ .bLength = sizeof(ss_descriptors.sink_comp),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ .bMaxBurst = 4,
+ },
+};
+
+struct usb_ext_compat_desc os_desc_compat = {
+ .bFirstInterfaceNumber = 0,
+ .Reserved1 = cpu_to_le32(1),
+ .CompatibleID = {0},
+ .SubCompatibleID = {0},
+ .Reserved2 = {0},
+};
+
+static struct usb_os_desc_header os_desc_header = {
+ .interface = cpu_to_le32(1),
+ .dwLength = cpu_to_le32(sizeof(os_desc_header) + sizeof(os_desc_compat)),
+ .bcdVersion = cpu_to_le32(1),
+ .wIndex = cpu_to_le32(4),
+ .bCount = cpu_to_le32(1),
+ .Reserved = cpu_to_le32(0),
+};
+
+#define STR_INTERFACE_ "ADB Interface"
+
+static const struct {
+ struct usb_functionfs_strings_head header;
+ struct {
+ __le16 code;
+ const char str1[sizeof(STR_INTERFACE_)];
+ } __attribute__((packed)) lang0;
+} __attribute__((packed)) strings = {
+ .header = {
+ .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
+ .length = cpu_to_le32(sizeof(strings)),
+ .str_count = cpu_to_le32(1),
+ .lang_count = cpu_to_le32(1),
+ },
+ .lang0 = {
+ cpu_to_le16(0x0409), /* en-us */
+ STR_INTERFACE_,
+ },
+};
+// clang-format on
+
+bool open_functionfs(android::base::unique_fd* out_control, android::base::unique_fd* out_bulk_out,
+ android::base::unique_fd* out_bulk_in) {
+ unique_fd control, bulk_out, bulk_in;
+ struct desc_v1 v1_descriptor = {};
+ struct desc_v2 v2_descriptor = {};
+
+ v2_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
+ v2_descriptor.header.length = cpu_to_le32(sizeof(v2_descriptor));
+ v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
+ FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC;
+ v2_descriptor.fs_count = 3;
+ v2_descriptor.hs_count = 3;
+ v2_descriptor.ss_count = 5;
+ v2_descriptor.os_count = 1;
+ 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;
+
+ if (out_control->get() < 0) { // might have already done this before
+ LOG(INFO) << "opening control endpoint " << USB_FFS_ADB_EP0;
+ control.reset(adb_open(USB_FFS_ADB_EP0, O_RDWR));
+ if (control < 0) {
+ PLOG(ERROR) << "cannot open control endpoint " << USB_FFS_ADB_EP0;
+ return false;
+ }
+
+ if (adb_write(control.get(), &v2_descriptor, sizeof(v2_descriptor)) < 0) {
+ D("[ %s: Switching to V1_descriptor format errno=%s ]", USB_FFS_ADB_EP0,
+ strerror(errno));
+ v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
+ v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
+ v1_descriptor.header.fs_count = 3;
+ v1_descriptor.header.hs_count = 3;
+ v1_descriptor.fs_descs = fs_descriptors;
+ v1_descriptor.hs_descs = hs_descriptors;
+ if (adb_write(control.get(), &v1_descriptor, sizeof(v1_descriptor)) < 0) {
+ PLOG(ERROR) << "failed to write USB descriptors";
+ return false;
+ }
+ }
+
+ if (adb_write(control.get(), &strings, sizeof(strings)) < 0) {
+ PLOG(ERROR) << "failed to write USB strings";
+ return false;
+ }
+ // Signal only when writing the descriptors to ffs
+ android::base::SetProperty("sys.usb.ffs.ready", "1");
+ }
+
+ bulk_out.reset(adb_open(USB_FFS_ADB_OUT, O_RDONLY));
+ if (bulk_out < 0) {
+ PLOG(ERROR) << "cannot open bulk-out endpoint " << USB_FFS_ADB_OUT;
+ return false;
+ }
+
+ bulk_in.reset(adb_open(USB_FFS_ADB_IN, O_WRONLY));
+ if (bulk_in < 0) {
+ PLOG(ERROR) << "cannot open bulk-in endpoint " << USB_FFS_ADB_IN;
+ return false;
+ }
+
+ *out_control = std::move(control);
+ *out_bulk_in = std::move(bulk_in);
+ *out_bulk_out = std::move(bulk_out);
+ return true;
+}
diff --git a/adb/daemon/usb_legacy.cpp b/adb/daemon/usb_legacy.cpp
new file mode 100644
index 0000000..7ace59d
--- /dev/null
+++ b/adb/daemon/usb_legacy.cpp
@@ -0,0 +1,312 @@
+/*
+ * 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.
+ */
+
+#define TRACE_TAG USB
+
+#include "sysdeps.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/functionfs.h>
+
+#include <algorithm>
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+
+#include "adb.h"
+#include "adbd/usb.h"
+#include "transport.h"
+
+using namespace std::chrono_literals;
+
+#define MAX_PACKET_SIZE_FS 64
+#define MAX_PACKET_SIZE_HS 512
+#define MAX_PACKET_SIZE_SS 1024
+
+#define USB_FFS_BULK_SIZE 16384
+
+// 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)
+
+static unique_fd& dummy_fd = *new unique_fd();
+
+static void aio_block_init(aio_block* aiob, unsigned num_bufs) {
+ aiob->iocb.resize(num_bufs);
+ aiob->iocbs.resize(num_bufs);
+ aiob->events.resize(num_bufs);
+ aiob->num_submitted = 0;
+ for (unsigned i = 0; i < num_bufs; i++) {
+ aiob->iocbs[i] = &aiob->iocb[i];
+ }
+ memset(&aiob->ctx, 0, sizeof(aiob->ctx));
+ if (io_setup(num_bufs, &aiob->ctx)) {
+ D("[ aio: got error on io_setup (%d) ]", errno);
+ }
+}
+
+static int getMaxPacketSize(int ffs_fd) {
+ usb_endpoint_descriptor desc;
+ if (ioctl(ffs_fd, FUNCTIONFS_ENDPOINT_DESC, reinterpret_cast<unsigned long>(&desc))) {
+ D("[ could not get endpoint descriptor! (%d) ]", errno);
+ return MAX_PACKET_SIZE_HS;
+ } else {
+ return desc.wMaxPacketSize;
+ }
+}
+
+static bool init_functionfs(struct usb_handle* h) {
+ LOG(INFO) << "initializing functionfs";
+ if (!open_functionfs(&h->control, &h->bulk_out, &h->bulk_in)) {
+ return false;
+ }
+
+ h->read_aiob.fd = h->bulk_out.get();
+ h->write_aiob.fd = h->bulk_in.get();
+ h->reads_zero_packets = true;
+ return true;
+}
+
+static void usb_legacy_ffs_open_thread(usb_handle* usb) {
+ adb_thread_setname("usb legacy ffs open");
+
+ while (true) {
+ // wait until the USB device needs opening
+ std::unique_lock<std::mutex> lock(usb->lock);
+ while (!usb->open_new_connection) {
+ usb->notify.wait(lock);
+ }
+ usb->open_new_connection = false;
+ lock.unlock();
+
+ while (true) {
+ if (init_functionfs(usb)) {
+ LOG(INFO) << "functionfs successfully initialized";
+ break;
+ }
+ std::this_thread::sleep_for(1s);
+ }
+
+ LOG(INFO) << "registering usb transport";
+ register_usb_transport(usb, nullptr, nullptr, 1);
+ }
+
+ // never gets here
+ abort();
+}
+
+static int usb_ffs_write(usb_handle* h, const void* data, int len) {
+ D("about to write (fd=%d, len=%d)", h->bulk_in.get(), len);
+
+ const char* buf = static_cast<const char*>(data);
+ int orig_len = len;
+ while (len > 0) {
+ int write_len = std::min(USB_FFS_BULK_SIZE, len);
+ int n = adb_write(h->bulk_in, buf, write_len);
+ if (n < 0) {
+ D("ERROR: fd = %d, n = %d: %s", h->bulk_in.get(), n, strerror(errno));
+ return -1;
+ }
+ buf += n;
+ len -= n;
+ }
+
+ D("[ done fd=%d ]", h->bulk_in.get());
+ return orig_len;
+}
+
+static int usb_ffs_read(usb_handle* h, void* data, int len) {
+ D("about to read (fd=%d, len=%d)", h->bulk_out.get(), len);
+
+ char* buf = static_cast<char*>(data);
+ int orig_len = len;
+ while (len > 0) {
+ int read_len = std::min(USB_FFS_BULK_SIZE, len);
+ int n = adb_read(h->bulk_out, buf, read_len);
+ if (n < 0) {
+ D("ERROR: fd = %d, n = %d: %s", h->bulk_out.get(), n, strerror(errno));
+ return -1;
+ }
+ buf += n;
+ len -= n;
+ }
+
+ D("[ done fd=%d ]", h->bulk_out.get());
+ return orig_len;
+}
+
+static int usb_ffs_do_aio(usb_handle* h, const void* data, int len, bool read) {
+ aio_block* aiob = read ? &h->read_aiob : &h->write_aiob;
+ bool zero_packet = false;
+
+ int num_bufs = len / h->io_size + (len % h->io_size == 0 ? 0 : 1);
+ const char* cur_data = reinterpret_cast<const char*>(data);
+ int packet_size = getMaxPacketSize(aiob->fd);
+
+ if (posix_madvise(const_cast<void*>(data), len, POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED) <
+ 0) {
+ D("[ Failed to madvise: %d ]", errno);
+ }
+
+ for (int i = 0; i < num_bufs; i++) {
+ int buf_len = std::min(len, static_cast<int>(h->io_size));
+ io_prep(&aiob->iocb[i], aiob->fd, cur_data, buf_len, 0, read);
+
+ len -= buf_len;
+ cur_data += buf_len;
+
+ if (len == 0 && buf_len % packet_size == 0 && read) {
+ // adb does not expect the device to send a zero packet after data transfer,
+ // but the host *does* send a zero packet for the device to read.
+ zero_packet = h->reads_zero_packets;
+ }
+ }
+ if (zero_packet) {
+ io_prep(&aiob->iocb[num_bufs], aiob->fd, reinterpret_cast<const void*>(cur_data),
+ packet_size, 0, read);
+ num_bufs += 1;
+ }
+
+ while (true) {
+ if (TEMP_FAILURE_RETRY(io_submit(aiob->ctx, num_bufs, aiob->iocbs.data())) < num_bufs) {
+ PLOG(ERROR) << "aio: got error submitting " << (read ? "read" : "write");
+ return -1;
+ }
+ if (TEMP_FAILURE_RETRY(io_getevents(aiob->ctx, num_bufs, num_bufs, aiob->events.data(),
+ nullptr)) < num_bufs) {
+ PLOG(ERROR) << "aio: got error waiting " << (read ? "read" : "write");
+ return -1;
+ }
+ if (num_bufs == 1 && aiob->events[0].res == -EINTR) {
+ continue;
+ }
+ int ret = 0;
+ for (int i = 0; i < num_bufs; i++) {
+ if (aiob->events[i].res < 0) {
+ errno = -aiob->events[i].res;
+ PLOG(ERROR) << "aio: got error event on " << (read ? "read" : "write")
+ << " total bufs " << num_bufs;
+ return -1;
+ }
+ ret += aiob->events[i].res;
+ }
+ return ret;
+ }
+}
+
+static int usb_ffs_aio_read(usb_handle* h, void* data, int len) {
+ return usb_ffs_do_aio(h, data, len, true);
+}
+
+static int usb_ffs_aio_write(usb_handle* h, const void* data, int len) {
+ return usb_ffs_do_aio(h, data, len, false);
+}
+
+static void usb_ffs_kick(usb_handle* h) {
+ int err;
+
+ err = ioctl(h->bulk_in.get(), FUNCTIONFS_CLEAR_HALT);
+ if (err < 0) {
+ D("[ kick: source (fd=%d) clear halt failed (%d) ]", h->bulk_in.get(), errno);
+ }
+
+ err = ioctl(h->bulk_out.get(), FUNCTIONFS_CLEAR_HALT);
+ if (err < 0) {
+ D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out.get(), errno);
+ }
+
+ // don't close ep0 here, since we may not need to reinitialize it with
+ // the same descriptors again. if however ep1/ep2 fail to re-open in
+ // init_functionfs, only then would we close and open ep0 again.
+ // Ditto the comment in usb_adb_kick.
+ h->kicked = true;
+ TEMP_FAILURE_RETRY(dup2(dummy_fd.get(), h->bulk_out.get()));
+ TEMP_FAILURE_RETRY(dup2(dummy_fd.get(), h->bulk_in.get()));
+}
+
+static void usb_ffs_close(usb_handle* h) {
+ LOG(INFO) << "closing functionfs transport";
+
+ h->kicked = false;
+ h->bulk_out.reset();
+ h->bulk_in.reset();
+
+ // Notify usb_adb_open_thread to open a new connection.
+ h->lock.lock();
+ h->open_new_connection = true;
+ h->lock.unlock();
+ h->notify.notify_one();
+}
+
+usb_handle* create_usb_handle(unsigned num_bufs, unsigned io_size) {
+ usb_handle* h = new usb_handle();
+
+ if (android::base::GetBoolProperty("sys.usb.ffs.aio_compat", false)) {
+ // Devices on older kernels (< 3.18) will not have aio support for ffs
+ // unless backported. Fall back on the non-aio functions instead.
+ h->write = usb_ffs_write;
+ h->read = usb_ffs_read;
+ } else {
+ h->write = usb_ffs_aio_write;
+ h->read = usb_ffs_aio_read;
+ aio_block_init(&h->read_aiob, num_bufs);
+ aio_block_init(&h->write_aiob, num_bufs);
+ }
+ h->io_size = io_size;
+ h->kick = usb_ffs_kick;
+ h->close = usb_ffs_close;
+ return h;
+}
+
+void usb_init_legacy() {
+ D("[ usb_init - using legacy FunctionFS ]");
+ dummy_fd.reset(adb_open("/dev/null", O_WRONLY | O_CLOEXEC));
+ CHECK_NE(-1, dummy_fd.get());
+
+ std::thread(usb_legacy_ffs_open_thread, create_usb_handle(USB_FFS_NUM_BUFS, USB_FFS_BULK_SIZE))
+ .detach();
+}
+
+int usb_write(usb_handle* h, const void* data, int len) {
+ return h->write(h, data, len);
+}
+
+int usb_read(usb_handle* h, void* data, int len) {
+ return h->read(h, data, len);
+}
+
+int usb_close(usb_handle* h) {
+ h->close(h);
+ return 0;
+}
+
+void usb_kick(usb_handle* h) {
+ h->kick(h);
+}
diff --git a/adb/fastdeploy/Android.bp b/adb/fastdeploy/Android.bp
index 30f4730..1ba0de0 100644
--- a/adb/fastdeploy/Android.bp
+++ b/adb/fastdeploy/Android.bp
@@ -14,24 +14,20 @@
// limitations under the License.
//
-java_library {
+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",
+ },
+ dex_preopt: {
+ enabled: false,
}
}
-cc_prebuilt_binary {
- name: "deployagent.sh",
-
- srcs: ["deployagent/deployagent.sh"],
- required: ["deployagent"],
- device_supported: true,
-}
-
java_binary_host {
name: "deploypatchgenerator",
srcs: ["deploypatchgenerator/src/**/*.java", "deploylib/src/**/*.java", "proto/**/*.proto"],
diff --git a/adb/fastdeploy/OWNERS b/adb/fastdeploy/OWNERS
new file mode 100644
index 0000000..d145834
--- /dev/null
+++ b/adb/fastdeploy/OWNERS
@@ -0,0 +1 @@
+idries@google.com
diff --git a/adb/fastdeploy/deployagent/src/com/android/fastdeploy/DeployAgent.java b/adb/fastdeploy/deployagent/src/com/android/fastdeploy/DeployAgent.java
index cd6f168..2d3b135 100644
--- a/adb/fastdeploy/deployagent/src/com/android/fastdeploy/DeployAgent.java
+++ b/adb/fastdeploy/deployagent/src/com/android/fastdeploy/DeployAgent.java
@@ -35,7 +35,7 @@
public final class DeployAgent {
private static final int BUFFER_SIZE = 128 * 1024;
- private static final int AGENT_VERSION = 0x00000001;
+ private static final int AGENT_VERSION = 0x00000002;
public static void main(String[] args) {
int exitCode = 0;
@@ -53,6 +53,15 @@
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);
@@ -112,6 +121,7 @@
"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" +
@@ -134,7 +144,7 @@
return null;
}
- private static File getFileFromPackageName(String packageName) throws IOException {
+ private static String getFilenameFromPackageName(String packageName) throws IOException {
StringBuilder commandBuilder = new StringBuilder();
commandBuilder.append("pm list packages -f " + packageName);
@@ -142,16 +152,32 @@
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String packagePrefix = "package:";
+ String packageSuffix = "=" + packageName;
String line = "";
while ((line = reader.readLine()) != null) {
- int packageIndex = line.indexOf(packagePrefix);
- int equalsIndex = line.indexOf("=" + packageName);
- return new File(line.substring(packageIndex + packagePrefix.length(), equalsIndex));
+ if (line.endsWith(packageSuffix)) {
+ int packageIndex = line.indexOf(packagePrefix);
+ if (packageIndex == -1) {
+ throw new IOException("error reading package list");
+ }
+ int equalsIndex = line.lastIndexOf(packageSuffix);
+ String fileName =
+ 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 extractMetaData(String packageName) throws IOException {
File apkFile = getFileFromPackageName(packageName);
APKMetaData apkMetaData = PatchUtils.getAPKMetaData(apkFile);
diff --git a/adb/fastdeploy/deploypatchgenerator/src/com/android/fastdeploy/DeployPatchGenerator.java b/adb/fastdeploy/deploypatchgenerator/src/com/android/fastdeploy/DeployPatchGenerator.java
index 5577364..24b2eab 100644
--- a/adb/fastdeploy/deploypatchgenerator/src/com/android/fastdeploy/DeployPatchGenerator.java
+++ b/adb/fastdeploy/deploypatchgenerator/src/com/android/fastdeploy/DeployPatchGenerator.java
@@ -61,22 +61,22 @@
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("Device Entries (" + deviceZipEntries.size() + ")");
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("Host Entries (" + hostFileEntries.size() + ")");
System.err.println(sb.toString());
}
@@ -130,7 +130,8 @@
for (APKEntry deviceZipEntry : deviceZipEntries) {
for (APKEntry hostZipEntry : hostZipEntries) {
- if (deviceZipEntry.getCrc32() == hostZipEntry.getCrc32()) {
+ if (deviceZipEntry.getCrc32() == hostZipEntry.getCrc32() &&
+ deviceZipEntry.getFileName().equals(hostZipEntry.getFileName())) {
identicalContents.add(new SimpleEntry(deviceZipEntry, hostZipEntry));
}
}
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index dee87bd..e096560 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -35,6 +35,8 @@
#include <unordered_map>
#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>
@@ -44,6 +46,7 @@
#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
@@ -147,24 +150,34 @@
return fde;
}
-void fdevent_destroy(fdevent* fde) {
+unique_fd fdevent_release(fdevent* fde) {
check_main_thread();
- if (fde == nullptr) return;
+ 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(fde->fd.get());
+ g_poll_node_map.erase(result.get());
+
if (fde->state & FDE_PENDING) {
g_pending_list.remove(fde);
}
- fde->fd.reset();
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) {
@@ -237,6 +250,7 @@
}
CHECK_GT(pollfds.size(), 0u);
D("poll(), pollfds = %s", dump_pollfds(pollfds).c_str());
+
int ret = adb_poll(&pollfds[0], pollfds.size(), -1);
if (ret == -1) {
PLOG(ERROR) << "poll(), ret = " << ret;
@@ -357,10 +371,66 @@
}
}
+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;
@@ -370,6 +440,8 @@
fdevent_process();
+ fdevent_check_spin(cycle++);
+
while (!g_pending_list.empty()) {
fdevent* fde = g_pending_list.front();
g_pending_list.pop_front();
diff --git a/adb/fdevent.h b/adb/fdevent.h
index d501b86..df2339a 100644
--- a/adb/fdevent.h
+++ b/adb/fdevent.h
@@ -50,11 +50,12 @@
*/
fdevent *fdevent_create(int fd, fd_func func, void *arg);
-/* Uninitialize and deallocate an fdevent object that was
-** created by fdevent_create()
-*/
+// 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);
diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp
index 0cb2439..816134f 100644
--- a/adb/fdevent_test.cpp
+++ b/adb/fdevent_test.cpp
@@ -19,6 +19,7 @@
#include <gtest/gtest.h>
#include <limits>
+#include <memory>
#include <queue>
#include <string>
#include <thread>
@@ -26,7 +27,6 @@
#include "adb_io.h"
#include "fdevent_test.h"
-#include "sysdeps/memory.h"
class FdHandler {
public:
diff --git a/adb/fdevent_test.h b/adb/fdevent_test.h
index 5a417e0..8d853c3 100644
--- a/adb/fdevent_test.h
+++ b/adb/fdevent_test.h
@@ -20,6 +20,7 @@
#include <mutex>
#include <thread>
+#include "adb_io.h"
#include "socket.h"
#include "sysdeps.h"
#include "sysdeps/chrono.h"
diff --git a/adb/services.cpp b/adb/services.cpp
index 4b033bd..73fed09 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -71,25 +71,24 @@
return unique_fd(s[0]);
}
-int service_to_fd(const char* name, atransport* transport) {
- int ret = -1;
+int service_to_fd(std::string_view name, atransport* transport) {
+ unique_fd ret;
if (is_socket_spec(name)) {
std::string error;
- ret = socket_spec_connect(name, &error);
- if (ret < 0) {
+ if (!socket_spec_connect(&ret, name, nullptr, nullptr, &error)) {
LOG(ERROR) << "failed to connect to socket '" << name << "': " << error;
}
} else {
#if !ADB_HOST
- ret = daemon_service_to_fd(name, transport).release();
+ ret = daemon_service_to_fd(name, transport);
#endif
}
if (ret >= 0) {
close_on_exec(ret);
}
- return ret;
+ return ret.release();
}
#if ADB_HOST
diff --git a/adb/socket.h b/adb/socket.h
index 0905aab..e7df991 100644
--- a/adb/socket.h
+++ b/adb/socket.h
@@ -103,17 +103,18 @@
void close_all_sockets(atransport *t);
asocket *create_local_socket(int fd);
-asocket* create_local_service_socket(const char* destination, atransport* transport);
+asocket* create_local_service_socket(std::string_view destination, atransport* transport);
asocket *create_remote_socket(unsigned id, atransport *t);
-void connect_to_remote(asocket *s, const char *destination);
+void connect_to_remote(asocket* s, std::string_view destination);
void connect_to_smartsocket(asocket *s);
// Internal functions that are only made available here for testing purposes.
namespace internal {
#if ADB_HOST
-char* skip_host_serial(char* service);
+bool parse_host_service(std::string_view* out_serial, std::string_view* out_command,
+ std::string_view service);
#endif
} // namespace internal
diff --git a/adb/socket_spec.cpp b/adb/socket_spec.cpp
index eb4df97..cc67b6b 100644
--- a/adb/socket_spec.cpp
+++ b/adb/socket_spec.cpp
@@ -17,6 +17,7 @@
#include "socket_spec.h"
#include <string>
+#include <string_view>
#include <unordered_map>
#include <vector>
@@ -29,7 +30,8 @@
#include "adb.h"
#include "sysdeps.h"
-using android::base::StartsWith;
+using namespace std::string_literals;
+
using android::base::StringPrintf;
#if defined(__linux__)
@@ -64,10 +66,11 @@
{ "localfilesystem", { ANDROID_SOCKET_NAMESPACE_FILESYSTEM, !ADB_WINDOWS } },
});
-bool parse_tcp_socket_spec(const std::string& spec, std::string* hostname, int* port,
- std::string* error) {
- if (!StartsWith(spec, "tcp:")) {
- *error = StringPrintf("specification is not tcp: '%s'", spec.c_str());
+bool parse_tcp_socket_spec(std::string_view spec, std::string* hostname, int* port,
+ std::string* serial, std::string* error) {
+ if (!spec.starts_with("tcp:")) {
+ *error = "specification is not tcp: ";
+ *error += spec;
return false;
}
@@ -84,17 +87,18 @@
return false;
}
} else {
- std::string addr = spec.substr(4);
+ std::string addr(spec.substr(4));
port_value = -1;
// FIXME: ParseNetAddress rejects port 0. This currently doesn't hurt, because listening
// on an address that isn't 'localhost' is unsupported.
- if (!android::base::ParseNetAddress(addr, &hostname_value, &port_value, nullptr, error)) {
+ if (!android::base::ParseNetAddress(addr, &hostname_value, &port_value, serial, error)) {
return false;
}
if (port_value == -1) {
- *error = StringPrintf("missing port in specification: '%s'", spec.c_str());
+ *error = "missing port in specification: ";
+ *error += spec;
return false;
}
}
@@ -110,87 +114,93 @@
return true;
}
-static bool tcp_host_is_local(const std::string& hostname) {
+static bool tcp_host_is_local(std::string_view hostname) {
// FIXME
return hostname.empty() || hostname == "localhost";
}
-bool is_socket_spec(const std::string& spec) {
+bool is_socket_spec(std::string_view spec) {
for (const auto& it : kLocalSocketTypes) {
std::string prefix = it.first + ":";
- if (StartsWith(spec, prefix)) {
+ if (spec.starts_with(prefix)) {
return true;
}
}
- return StartsWith(spec, "tcp:");
+ return spec.starts_with("tcp:");
}
-bool is_local_socket_spec(const std::string& spec) {
+bool is_local_socket_spec(std::string_view spec) {
for (const auto& it : kLocalSocketTypes) {
std::string prefix = it.first + ":";
- if (StartsWith(spec, prefix)) {
+ if (spec.starts_with(prefix)) {
return true;
}
}
std::string error;
std::string hostname;
- if (!parse_tcp_socket_spec(spec, &hostname, nullptr, &error)) {
+ if (!parse_tcp_socket_spec(spec, &hostname, nullptr, nullptr, &error)) {
return false;
}
return tcp_host_is_local(hostname);
}
-int socket_spec_connect(const std::string& spec, std::string* error) {
- if (StartsWith(spec, "tcp:")) {
+bool socket_spec_connect(unique_fd* fd, std::string_view address, int* port, std::string* serial,
+ std::string* error) {
+ if (address.starts_with("tcp:")) {
std::string hostname;
- int port;
- if (!parse_tcp_socket_spec(spec, &hostname, &port, error)) {
- return -1;
+ int port_value = port ? *port : 0;
+ if (!parse_tcp_socket_spec(address, &hostname, &port_value, serial, error)) {
+ return false;
}
- int result;
if (tcp_host_is_local(hostname)) {
- result = network_loopback_client(port, SOCK_STREAM, error);
+ fd->reset(network_loopback_client(port_value, SOCK_STREAM, error));
} else {
#if ADB_HOST
- result = network_connect(hostname, port, SOCK_STREAM, 0, error);
+ fd->reset(network_connect(hostname, port_value, SOCK_STREAM, 0, error));
#else
// Disallow arbitrary connections in adbd.
*error = "adbd does not support arbitrary tcp connections";
- return -1;
+ return false;
#endif
}
- if (result >= 0) {
- disable_tcp_nagle(result);
+ if (fd->get() > 0) {
+ disable_tcp_nagle(fd->get());
+ if (port) {
+ *port = port_value;
+ }
+ return true;
}
- return result;
+ return false;
}
for (const auto& it : kLocalSocketTypes) {
std::string prefix = it.first + ":";
- if (StartsWith(spec, prefix)) {
+ if (address.starts_with(prefix)) {
if (!it.second.available) {
*error = StringPrintf("socket type %s is unavailable on this platform",
it.first.c_str());
- return -1;
+ return false;
}
- return network_local_client(&spec[prefix.length()], it.second.socket_namespace,
- SOCK_STREAM, error);
+ fd->reset(network_local_client(&address[prefix.length()], it.second.socket_namespace,
+ SOCK_STREAM, error));
+ return true;
}
}
- *error = StringPrintf("unknown socket specification '%s'", spec.c_str());
- return -1;
+ *error = "unknown socket specification: ";
+ *error += address;
+ return false;
}
-int socket_spec_listen(const std::string& spec, std::string* error, int* resolved_tcp_port) {
- if (StartsWith(spec, "tcp:")) {
+int socket_spec_listen(std::string_view spec, std::string* error, int* resolved_tcp_port) {
+ if (spec.starts_with("tcp:")) {
std::string hostname;
int port;
- if (!parse_tcp_socket_spec(spec, &hostname, &port, error)) {
+ if (!parse_tcp_socket_spec(spec, &hostname, &port, nullptr, error)) {
return -1;
}
@@ -213,10 +223,10 @@
for (const auto& it : kLocalSocketTypes) {
std::string prefix = it.first + ":";
- if (StartsWith(spec, prefix)) {
+ if (spec.starts_with(prefix)) {
if (!it.second.available) {
- *error = StringPrintf("attempted to listen on unavailable socket type: '%s'",
- spec.c_str());
+ *error = "attempted to listen on unavailable socket type: ";
+ *error += spec;
return -1;
}
@@ -225,6 +235,7 @@
}
}
- *error = StringPrintf("unknown socket specification '%s'", spec.c_str());
+ *error = "unknown socket specification:";
+ *error += spec;
return -1;
}
diff --git a/adb/socket_spec.h b/adb/socket_spec.h
index 6920e91..687d751 100644
--- a/adb/socket_spec.h
+++ b/adb/socket_spec.h
@@ -17,15 +17,18 @@
#pragma once
#include <string>
+#include <tuple>
+
+#include "adb_unique_fd.h"
// Returns true if the argument starts with a plausible socket prefix.
-bool is_socket_spec(const std::string& spec);
-bool is_local_socket_spec(const std::string& spec);
+bool is_socket_spec(std::string_view spec);
+bool is_local_socket_spec(std::string_view spec);
-int socket_spec_connect(const std::string& spec, std::string* error);
-int socket_spec_listen(const std::string& spec, std::string* error,
- int* resolved_tcp_port = nullptr);
+bool socket_spec_connect(unique_fd* fd, std::string_view address, int* port, std::string* serial,
+ std::string* error);
+int socket_spec_listen(std::string_view spec, std::string* error, int* resolved_tcp_port = nullptr);
// Exposed for testing.
-bool parse_tcp_socket_spec(const std::string& spec, std::string* hostname, int* port,
- std::string* error);
+bool parse_tcp_socket_spec(std::string_view spec, std::string* hostname, int* port,
+ std::string* serial, std::string* error);
diff --git a/adb/socket_spec_test.cpp b/adb/socket_spec_test.cpp
index 40ce21c..f5ec0f1 100644
--- a/adb/socket_spec_test.cpp
+++ b/adb/socket_spec_test.cpp
@@ -21,34 +21,37 @@
#include <gtest/gtest.h>
TEST(socket_spec, parse_tcp_socket_spec) {
- std::string hostname, error;
+ std::string hostname, error, serial;
int port;
- EXPECT_TRUE(parse_tcp_socket_spec("tcp:5037", &hostname, &port, &error));
+ EXPECT_TRUE(parse_tcp_socket_spec("tcp:5037", &hostname, &port, &serial, &error));
EXPECT_EQ("", hostname);
EXPECT_EQ(5037, port);
+ EXPECT_EQ("", serial);
// Bad ports:
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:-1", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:65536", &hostname, &port, &error));
+ 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));
- EXPECT_TRUE(parse_tcp_socket_spec("tcp:localhost:1234", &hostname, &port, &error));
+ 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, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:-1", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:65536", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost", &hostname, &port, &serial, &error));
+ 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:
- EXPECT_TRUE(parse_tcp_socket_spec("tcp:[::1]:1234", &hostname, &port, &error));
+ 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);
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]:", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]:-1", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:::1", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:::1:1234", &hostname, &port, &error));
+ 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));
}
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index 04214a2..80f9430 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -34,6 +34,9 @@
#include "sysdeps.h"
#include "sysdeps/chrono.h"
+using namespace std::string_literals;
+using namespace std::string_view_literals;
+
struct ThreadArg {
int first_read_fd;
int last_write_fd;
@@ -303,56 +306,78 @@
#if ADB_HOST
-// Checks that skip_host_serial(serial) returns a pointer to the part of |serial| which matches
-// |expected|, otherwise logs the failure to gtest.
-void VerifySkipHostSerial(std::string serial, const char* expected) {
- char* result = internal::skip_host_serial(&serial[0]);
- if (expected == nullptr) {
- EXPECT_EQ(nullptr, result);
- } else {
- EXPECT_STREQ(expected, result);
- }
-}
+#define VerifyParseHostServiceFailed(s) \
+ do { \
+ std::string service(s); \
+ std::string_view serial, command; \
+ bool result = internal::parse_host_service(&serial, &command, service); \
+ EXPECT_FALSE(result); \
+ } while (0)
+
+#define VerifyParseHostService(s, expected_serial, expected_command) \
+ do { \
+ std::string service(s); \
+ std::string_view serial, command; \
+ bool result = internal::parse_host_service(&serial, &command, service); \
+ EXPECT_TRUE(result); \
+ EXPECT_EQ(std::string(expected_serial), std::string(serial)); \
+ EXPECT_EQ(std::string(expected_command), std::string(command)); \
+ } while (0);
// Check [tcp:|udp:]<serial>[:<port>]:<command> format.
-TEST(socket_test, test_skip_host_serial) {
+TEST(socket_test, test_parse_host_service) {
for (const std::string& protocol : {"", "tcp:", "udp:"}) {
- VerifySkipHostSerial(protocol, nullptr);
- VerifySkipHostSerial(protocol + "foo", nullptr);
+ VerifyParseHostServiceFailed(protocol);
+ VerifyParseHostServiceFailed(protocol + "foo");
- VerifySkipHostSerial(protocol + "foo:bar", ":bar");
- VerifySkipHostSerial(protocol + "foo:bar:baz", ":bar:baz");
+ {
+ std::string serial = protocol + "foo";
+ VerifyParseHostService(serial + ":bar", serial, "bar");
+ VerifyParseHostService(serial + " :bar:baz", serial, "bar:baz");
+ }
- VerifySkipHostSerial(protocol + "foo:123:bar", ":bar");
- VerifySkipHostSerial(protocol + "foo:123:456", ":456");
- VerifySkipHostSerial(protocol + "foo:123:bar:baz", ":bar:baz");
+ {
+ // With port.
+ std::string serial = protocol + "foo:123";
+ VerifyParseHostService(serial + ":bar", serial, "bar");
+ VerifyParseHostService(serial + ":456", serial, "456");
+ VerifyParseHostService(serial + ":bar:baz", serial, "bar:baz");
+ }
// Don't register a port unless it's all numbers and ends with ':'.
- VerifySkipHostSerial(protocol + "foo:123", ":123");
- VerifySkipHostSerial(protocol + "foo:123bar:baz", ":123bar:baz");
+ VerifyParseHostService(protocol + "foo:123", protocol + "foo", "123");
+ VerifyParseHostService(protocol + "foo:123bar:baz", protocol + "foo", "123bar:baz");
- VerifySkipHostSerial(protocol + "100.100.100.100:5555:foo", ":foo");
- VerifySkipHostSerial(protocol + "[0123:4567:89ab:CDEF:0:9:a:f]:5555:foo", ":foo");
- VerifySkipHostSerial(protocol + "[::1]:5555:foo", ":foo");
+ std::string addresses[] = {"100.100.100.100", "[0123:4567:89ab:CDEF:0:9:a:f]", "[::1]"};
+ for (const std::string& address : addresses) {
+ std::string serial = protocol + address;
+ std::string serial_with_port = protocol + address + ":5555";
+ VerifyParseHostService(serial + ":foo", serial, "foo");
+ VerifyParseHostService(serial_with_port + ":foo", serial_with_port, "foo");
+ }
// If we can't find both [] then treat it as a normal serial with [ in it.
- VerifySkipHostSerial(protocol + "[0123:foo", ":foo");
+ VerifyParseHostService(protocol + "[0123:foo", protocol + "[0123", "foo");
// Don't be fooled by random IPv6 addresses in the command string.
- VerifySkipHostSerial(protocol + "foo:ping [0123:4567:89ab:CDEF:0:9:a:f]:5555",
- ":ping [0123:4567:89ab:CDEF:0:9:a:f]:5555");
+ VerifyParseHostService(protocol + "foo:ping [0123:4567:89ab:CDEF:0:9:a:f]:5555",
+ protocol + "foo", "ping [0123:4567:89ab:CDEF:0:9:a:f]:5555");
+
+ // Handle embedded NULs properly.
+ VerifyParseHostService(protocol + "foo:echo foo\0bar"s, protocol + "foo",
+ "echo foo\0bar"sv);
}
}
// Check <prefix>:<serial>:<command> format.
-TEST(socket_test, test_skip_host_serial_prefix) {
+TEST(socket_test, test_parse_host_service_prefix) {
for (const std::string& prefix : {"usb:", "product:", "model:", "device:"}) {
- VerifySkipHostSerial(prefix, nullptr);
- VerifySkipHostSerial(prefix + "foo", nullptr);
+ VerifyParseHostServiceFailed(prefix);
+ VerifyParseHostServiceFailed(prefix + "foo");
- VerifySkipHostSerial(prefix + "foo:bar", ":bar");
- VerifySkipHostSerial(prefix + "foo:bar:baz", ":bar:baz");
- VerifySkipHostSerial(prefix + "foo:123:bar", ":123:bar");
+ VerifyParseHostService(prefix + "foo:bar", prefix + "foo", "bar");
+ VerifyParseHostService(prefix + "foo:bar:baz", prefix + "foo", "bar:baz");
+ VerifyParseHostService(prefix + "foo:123:bar", prefix + "foo", "123:bar");
}
}
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 1534792..47ae883 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -37,6 +37,7 @@
#include "adb.h"
#include "adb_io.h"
+#include "adb_utils.h"
#include "transport.h"
#include "types.h"
@@ -78,7 +79,7 @@
// Socket ids should never be 0.
if (local_socket_next_id == 0) {
- fatal("local socket id overflow");
+ LOG(FATAL) << "local socket id overflow";
}
local_socket_list.push_back(s);
@@ -346,13 +347,10 @@
return s;
}
-asocket* create_local_service_socket(const char* name, atransport* transport) {
+asocket* create_local_service_socket(std::string_view name, atransport* transport) {
#if !ADB_HOST
- if (!strcmp(name, "jdwp")) {
- return create_jdwp_service_socket();
- }
- if (!strcmp(name, "track-jdwp")) {
- return create_jdwp_tracker_service_socket();
+ if (asocket* s = daemon_service_to_socket(name); s) {
+ return s;
}
#endif
int fd = service_to_fd(name, transport);
@@ -361,13 +359,12 @@
}
asocket* s = create_local_socket(fd);
- D("LS(%d): bound to '%s' via %d", s->id, name, fd);
+ LOG(VERBOSE) << "LS(" << s->id << "): bound to '" << name << "' via " << fd;
#if !ADB_HOST
- if ((!strncmp(name, "root:", 5) && getuid() != 0 && __android_log_is_debuggable()) ||
- (!strncmp(name, "unroot:", 7) && getuid() == 0) ||
- !strncmp(name, "usb:", 4) ||
- !strncmp(name, "tcpip:", 6)) {
+ if ((name.starts_with("root:") && getuid() != 0 && __android_log_is_debuggable()) ||
+ (name.starts_with("unroot:") && getuid() == 0) || name.starts_with("usb:") ||
+ name.starts_with("tcpip:")) {
D("LS(%d): enabling exit_on_close", s->id);
s->exit_on_close = 1;
}
@@ -451,7 +448,7 @@
// Returns a new non-NULL asocket handle.
asocket* create_remote_socket(unsigned id, atransport* t) {
if (id == 0) {
- fatal("invalid remote socket id (0)");
+ LOG(FATAL) << "invalid remote socket id (0)";
}
asocket* s = new asocket();
s->id = id;
@@ -465,21 +462,22 @@
return s;
}
-void connect_to_remote(asocket* s, const char* destination) {
+void connect_to_remote(asocket* s, std::string_view destination) {
D("Connect_to_remote call RS(%d) fd=%d", s->id, s->fd);
apacket* p = get_apacket();
- D("LS(%d): connect('%s')", s->id, destination);
+ LOG(VERBOSE) << "LS(" << s->id << ": connect(" << destination << ")";
p->msg.command = A_OPEN;
p->msg.arg0 = s->id;
- // adbd expects a null-terminated string.
- p->payload.assign(destination, destination + strlen(destination) + 1);
+ // adbd used to expect a null-terminated string.
+ // Keep doing so to maintain backward compatibility.
+ p->payload.resize(destination.size() + 1);
+ memcpy(p->payload.data(), destination.data(), destination.size());
+ p->payload[destination.size()] = '\0';
p->msg.data_length = p->payload.size();
- if (p->msg.data_length > s->get_max_payload()) {
- fatal("destination oversized");
- }
+ CHECK_LE(p->msg.data_length, s->get_max_payload());
send_packet(p, s->transport);
}
@@ -552,57 +550,119 @@
namespace internal {
-// Returns the position in |service| following the target serial parameter. Serial format can be
-// any of:
+// Parses a host service string of the following format:
// * [tcp:|udp:]<serial>[:<port>]:<command>
// * <prefix>:<serial>:<command>
// Where <port> must be a base-10 number and <prefix> may be any of {usb,product,model,device}.
-//
-// The returned pointer will point to the ':' just before <command>, or nullptr if not found.
-char* skip_host_serial(char* service) {
- static const std::vector<std::string>& prefixes =
- *(new std::vector<std::string>{"usb:", "product:", "model:", "device:"});
+bool parse_host_service(std::string_view* out_serial, std::string_view* out_command,
+ std::string_view full_service) {
+ if (full_service.empty()) {
+ return false;
+ }
- for (const std::string& prefix : prefixes) {
- if (!strncmp(service, prefix.c_str(), prefix.length())) {
- return strchr(service + prefix.length(), ':');
+ std::string_view serial;
+ std::string_view command = full_service;
+ // Remove |count| bytes from the beginning of command and add them to |serial|.
+ auto consume = [&full_service, &serial, &command](size_t count) {
+ CHECK_LE(count, command.size());
+ if (!serial.empty()) {
+ CHECK_EQ(serial.data() + serial.size(), command.data());
+ }
+
+ serial = full_service.substr(0, serial.size() + count);
+ command.remove_prefix(count);
+ };
+
+ // Remove the trailing : from serial, and assign the values to the output parameters.
+ auto finish = [out_serial, out_command, &serial, &command] {
+ if (serial.empty() || command.empty()) {
+ return false;
+ }
+
+ CHECK_EQ(':', serial.back());
+ serial.remove_suffix(1);
+
+ *out_serial = serial;
+ *out_command = command;
+ return true;
+ };
+
+ static constexpr std::string_view prefixes[] = {"usb:", "product:", "model:", "device:"};
+ for (std::string_view prefix : prefixes) {
+ if (command.starts_with(prefix)) {
+ consume(prefix.size());
+
+ size_t offset = command.find_first_of(':');
+ if (offset == std::string::npos) {
+ return false;
+ }
+ consume(offset + 1);
+ return finish();
}
}
// For fastboot compatibility, ignore protocol prefixes.
- if (!strncmp(service, "tcp:", 4) || !strncmp(service, "udp:", 4)) {
- service += 4;
- }
-
- // Check for an IPv6 address. `adb connect` creates the serial number from the canonical
- // network address so it will always have the [] delimiters.
- if (service[0] == '[') {
- char* ipv6_end = strchr(service, ']');
- if (ipv6_end != nullptr) {
- service = ipv6_end;
+ if (command.starts_with("tcp:") || command.starts_with("udp:")) {
+ consume(4);
+ if (command.empty()) {
+ return false;
}
}
- // The next colon we find must either begin the port field or the command field.
- char* colon_ptr = strchr(service, ':');
- if (!colon_ptr) {
- // No colon in service string.
- return nullptr;
+ bool found_address = false;
+ if (command[0] == '[') {
+ // Read an IPv6 address. `adb connect` creates the serial number from the canonical
+ // network address so it will always have the [] delimiters.
+ size_t ipv6_end = command.find_first_of(']');
+ if (ipv6_end != std::string::npos) {
+ consume(ipv6_end + 1);
+ if (command.empty()) {
+ // Nothing after the IPv6 address.
+ return false;
+ } else if (command[0] != ':') {
+ // Garbage after the IPv6 address.
+ return false;
+ }
+ consume(1);
+ found_address = true;
+ }
}
- // If the next field is only decimal digits and ends with another colon, it's a port.
- char* serial_end = colon_ptr;
- if (isdigit(serial_end[1])) {
- serial_end++;
- while (*serial_end && isdigit(*serial_end)) {
- serial_end++;
+ if (!found_address) {
+ // Scan ahead to the next colon.
+ size_t offset = command.find_first_of(':');
+ if (offset == std::string::npos) {
+ return false;
}
- if (*serial_end != ':') {
- // Something other than "<port>:" was found, this must be the command field instead.
- serial_end = colon_ptr;
+ consume(offset + 1);
+ }
+
+ // We're either at the beginning of a port, or the command itself.
+ // Look for a port in between colons.
+ size_t next_colon = command.find_first_of(':');
+ if (next_colon == std::string::npos) {
+ // No colon, we must be at the command.
+ return finish();
+ }
+
+ bool port_valid = true;
+ if (command.size() <= next_colon) {
+ return false;
+ }
+
+ std::string_view port = command.substr(0, next_colon);
+ for (auto digit : port) {
+ if (!isdigit(digit)) {
+ // Port isn't a number.
+ port_valid = false;
+ break;
}
}
- return serial_end;
+
+ if (port_valid) {
+ consume(next_colon + 1);
+ }
+ return finish();
}
} // namespace internal
@@ -611,8 +671,8 @@
static int smart_socket_enqueue(asocket* s, apacket::payload_type data) {
#if ADB_HOST
- char* service = nullptr;
- char* serial = nullptr;
+ std::string_view service;
+ std::string_view serial;
TransportId transport_id = 0;
TransportType type = kTransportAny;
#endif
@@ -649,49 +709,52 @@
D("SS(%d): '%s'", s->id, (char*)(s->smart_socket_data.data() + 4));
#if ADB_HOST
- service = &s->smart_socket_data[4];
- if (!strncmp(service, "host-serial:", strlen("host-serial:"))) {
- char* serial_end;
- service += strlen("host-serial:");
+ service = std::string_view(s->smart_socket_data).substr(4);
+ if (service.starts_with("host-serial:")) {
+ service.remove_prefix(strlen("host-serial:"));
// serial number should follow "host:" and could be a host:port string.
- serial_end = internal::skip_host_serial(service);
- if (serial_end) {
- *serial_end = 0; // terminate string
- serial = service;
- service = serial_end + 1;
+ if (!internal::parse_host_service(&serial, &service, service)) {
+ LOG(ERROR) << "SS(" << s->id << "): failed to parse host service: " << service;
+ goto fail;
}
- } else if (!strncmp(service, "host-transport-id:", strlen("host-transport-id:"))) {
- service += strlen("host-transport-id:");
- transport_id = strtoll(service, &service, 10);
-
- if (*service != ':') {
+ } else if (service.starts_with("host-transport-id:")) {
+ service.remove_prefix(strlen("host-transport-id:"));
+ if (!ParseUint(&transport_id, service, &service)) {
+ LOG(ERROR) << "SS(" << s->id << "): failed to parse host transport id: " << service;
return -1;
}
- service++;
- } else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) {
+ if (!service.starts_with(":")) {
+ LOG(ERROR) << "SS(" << s->id << "): host-transport-id without command";
+ return -1;
+ }
+ service.remove_prefix(1);
+ } else if (service.starts_with("host-usb:")) {
type = kTransportUsb;
- service += strlen("host-usb:");
- } else if (!strncmp(service, "host-local:", strlen("host-local:"))) {
+ service.remove_prefix(strlen("host-usb:"));
+ } else if (service.starts_with("host-local:")) {
type = kTransportLocal;
- service += strlen("host-local:");
- } else if (!strncmp(service, "host:", strlen("host:"))) {
+ service.remove_prefix(strlen("host-local:"));
+ } else if (service.starts_with("host:")) {
type = kTransportAny;
- service += strlen("host:");
+ service.remove_prefix(strlen("host:"));
} else {
- service = nullptr;
+ service = std::string_view{};
}
- if (service) {
+ if (!service.empty()) {
asocket* s2;
// Some requests are handled immediately -- in that case the handle_host_request() routine
// has sent the OKAY or FAIL message and all we have to do is clean up.
- if (handle_host_request(service, type, serial, transport_id, s->peer->fd, s)) {
- D("SS(%d): handled host service '%s'", s->id, service);
+ // TODO: Convert to string_view.
+ if (handle_host_request(std::string(service).c_str(), type,
+ serial.empty() ? nullptr : std::string(serial).c_str(),
+ transport_id, s->peer->fd, s)) {
+ LOG(VERBOSE) << "SS(" << s->id << "): handled host service '" << service << "'";
goto fail;
}
- if (!strncmp(service, "transport", strlen("transport"))) {
+ if (service.starts_with("transport")) {
D("SS(%d): okay transport", s->id);
s->smart_socket_data.clear();
return 0;
@@ -701,9 +764,11 @@
** if no such service exists, we'll fail out
** and tear down here.
*/
- s2 = create_host_service_socket(service, serial, transport_id);
+ // TODO: Convert to string_view.
+ s2 = create_host_service_socket(std::string(service).c_str(), std::string(serial).c_str(),
+ transport_id);
if (s2 == nullptr) {
- D("SS(%d): couldn't create host service '%s'", s->id, service);
+ LOG(VERBOSE) << "SS(" << s->id << "): couldn't create host service '" << service << "'";
SendFail(s->peer->fd, "unknown host service");
goto fail;
}
@@ -764,7 +829,7 @@
/* give him our transport and upref it */
s->peer->transport = s->transport;
- connect_to_remote(s->peer, s->smart_socket_data.data() + 4);
+ connect_to_remote(s->peer, std::string_view(s->smart_socket_data).substr(4));
s->peer = nullptr;
s->close(s);
return 1;
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 0c2e45c..15247e7 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -27,6 +27,7 @@
#include <errno.h>
#include <string>
+#include <string_view>
#include <vector>
// Include this before open/close/unlink are defined as macros below.
@@ -52,10 +53,11 @@
#include <fcntl.h>
#include <io.h>
#include <process.h>
+#include <stdint.h>
#include <sys/stat.h>
#include <utime.h>
-#include <winsock2.h>
#include <windows.h>
+#include <winsock2.h>
#include <ws2tcpip.h>
#include <memory> // unique_ptr
@@ -72,12 +74,7 @@
return c == '\\' || c == '/';
}
-static __inline__ int adb_thread_setname(const std::string& name) {
- // TODO: See https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx for how to set
- // the thread name in Windows. Unfortunately, it only works during debugging, but
- // our build process doesn't generate PDB files needed for debugging.
- return 0;
-}
+extern int adb_thread_setname(const std::string& name);
static __inline__ void close_on_exec(int fd)
{
@@ -97,7 +94,7 @@
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 int adb_lseek(int fd, int pos, int where);
+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_close(int fd);
extern int adb_register_socket(SOCKET s);
@@ -129,6 +126,13 @@
#undef write
#define write ___xxx_write
+// 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);
+}
+#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)
{
@@ -136,7 +140,7 @@
}
// See the comments for the !defined(_WIN32) version of unix_open().
-extern int unix_open(const char* path, int options, ...);
+extern int unix_open(std::string_view path, int options, ...);
#define open ___xxx_unix_open
// Checks if |fd| corresponds to a console.
@@ -313,25 +317,24 @@
#else /* !_WIN32 a.k.a. Unix */
-#include <cutils/sockets.h>
#include <fcntl.h>
-#include <poll.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-
-#include <pthread.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdarg.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
+#include <poll.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdint.h>
#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
#include <unistd.h>
#include <string>
+#include <cutils/sockets.h>
+
#define OS_PATH_SEPARATORS "/"
#define OS_PATH_SEPARATOR '/'
#define OS_PATH_SEPARATOR_STR "/"
@@ -355,20 +358,17 @@
// by unix_read(), unix_write(), unix_close()). Also, the C Runtime has
// configurable CR/LF translation which defaults to text mode, but is settable
// with _setmode().
-static __inline__ int unix_open(const char* path, int options,...)
-{
- if ((options & O_CREAT) == 0)
- {
- return TEMP_FAILURE_RETRY( open(path, options) );
- }
- else
- {
- int mode;
- va_list args;
- va_start( args, options );
- mode = va_arg( args, int );
- va_end( args );
- return TEMP_FAILURE_RETRY( open( path, options, mode ) );
+static __inline__ int unix_open(std::string_view path, int options, ...) {
+ std::string zero_terminated(path.begin(), path.end());
+ if ((options & O_CREAT) == 0) {
+ return TEMP_FAILURE_RETRY(open(zero_terminated.c_str(), options));
+ } else {
+ int mode;
+ va_list args;
+ va_start(args, options);
+ mode = va_arg(args, int);
+ va_end(args);
+ return TEMP_FAILURE_RETRY(open(zero_terminated.c_str(), options, mode));
}
}
@@ -441,12 +441,15 @@
#undef write
#define write ___xxx_write
-static __inline__ int adb_lseek(int fd, int pos, int where)
-{
+static __inline__ int64_t adb_lseek(int fd, int64_t pos, int where) {
+#if defined(__APPLE__)
return lseek(fd, pos, where);
+#else
+ return lseek64(fd, pos, where);
+#endif
}
-#undef lseek
-#define lseek ___xxx_lseek
+#undef lseek
+#define lseek ___xxx_lseek
static __inline__ int adb_unlink(const char* path)
{
@@ -523,6 +526,7 @@
// via _setmode()).
#define unix_read adb_read
#define unix_write adb_write
+#define unix_lseek adb_lseek
#define unix_close adb_close
static __inline__ int adb_thread_setname(const std::string& name) {
diff --git a/adb/sysdeps/errno.cpp b/adb/sysdeps/errno.cpp
index 6869947..9a37ea2 100644
--- a/adb/sysdeps/errno.cpp
+++ b/adb/sysdeps/errno.cpp
@@ -24,10 +24,6 @@
#include "adb.h"
-#if defined(_WIN32)
-#define ETXTBSY EBUSY
-#endif
-
// Use the linux asm-generic values for errno (which are used on all android archs but mips).
#define ERRNO_VALUES() \
ERRNO_VALUE(EACCES, 13); \
diff --git a/adb/sysdeps/memory.h b/adb/sysdeps/memory.h
deleted file mode 100644
index 4108aff..0000000
--- a/adb/sysdeps/memory.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#pragma once
-
-/*
- * 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 <memory>
-#include <type_traits>
-
-#if defined(_WIN32)
-// We don't have C++14 on Windows yet.
-// Reimplement std::make_unique ourselves until we do.
-
-namespace internal {
-
-template <typename T>
-struct array_known_bounds;
-
-template <typename T>
-struct array_known_bounds<T[]> {
- constexpr static bool value = false;
-};
-
-template <typename T, size_t N>
-struct array_known_bounds<T[N]> {
- constexpr static bool value = true;
-};
-
-} // namespace internal
-
-namespace std {
-
-template <typename T, typename... Args>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type make_unique(
- Args&&... args) {
- return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
-}
-
-template <typename T>
-typename std::enable_if<std::is_array<T>::value && !internal::array_known_bounds<T>::value,
- std::unique_ptr<T>>::type
-make_unique(std::size_t size) {
- return std::unique_ptr<T>(new typename std::remove_extent<T>::type[size]());
-}
-
-template <typename T, typename... Args>
-typename std::enable_if<std::is_array<T>::value && internal::array_known_bounds<T>::value,
- std::unique_ptr<T>>::type
-make_unique(Args&&... args) = delete;
-
-} // namespace std
-
-#endif
diff --git a/adb/sysdeps/stat_test.cpp b/adb/sysdeps/stat_test.cpp
index 2c2e0ee..67155d9 100644
--- a/adb/sysdeps/stat_test.cpp
+++ b/adb/sysdeps/stat_test.cpp
@@ -16,7 +16,7 @@
#include <string>
-#include <android-base/test_utils.h>
+#include <android-base/file.h>
#include <gtest/gtest.h>
#include "adb_utils.h"
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index c94d13f..dbc8920 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -29,12 +29,14 @@
#include <memory>
#include <mutex>
#include <string>
+#include <string_view>
#include <unordered_map>
#include <vector>
#include <cutils/sockets.h>
#include <android-base/errors.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
@@ -46,18 +48,15 @@
#include "sysdeps/uio.h"
-extern void fatal(const char *fmt, ...);
-
/* forward declarations */
typedef const struct FHClassRec_* FHClass;
typedef struct FHRec_* FH;
-typedef struct EventHookRec_* EventHook;
typedef struct FHClassRec_ {
void (*_fh_init)(FH);
int (*_fh_close)(FH);
- int (*_fh_lseek)(FH, int, int);
+ int64_t (*_fh_lseek)(FH, int64_t, int);
int (*_fh_read)(FH, void*, int);
int (*_fh_write)(FH, const void*, int);
int (*_fh_writev)(FH, const adb_iovec*, int);
@@ -65,7 +64,7 @@
static void _fh_file_init(FH);
static int _fh_file_close(FH);
-static int _fh_file_lseek(FH, int, int);
+static int64_t _fh_file_lseek(FH, int64_t, int);
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);
@@ -81,7 +80,7 @@
static void _fh_socket_init(FH);
static int _fh_socket_close(FH);
-static int _fh_socket_lseek(FH, int, int);
+static int64_t _fh_socket_lseek(FH, int64_t, int);
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);
@@ -95,10 +94,9 @@
_fh_socket_writev,
};
-#define assert(cond) \
- do { \
- if (!(cond)) fatal("assertion failed '%s' on %s:%d\n", #cond, __FILE__, __LINE__); \
- } while (0)
+#if defined(assert)
+#undef assert
+#endif
void handle_deleter::operator()(HANDLE h) {
// CreateFile() is documented to return INVALID_HANDLE_FILE on error,
@@ -318,10 +316,8 @@
return wrote_bytes;
}
-static int _fh_file_lseek(FH f, int pos, int origin) {
+static int64_t _fh_file_lseek(FH f, int64_t pos, int origin) {
DWORD method;
- DWORD result;
-
switch (origin) {
case SEEK_SET:
method = FILE_BEGIN;
@@ -337,14 +333,13 @@
return -1;
}
- result = SetFilePointer(f->fh_handle, pos, nullptr, method);
- if (result == INVALID_SET_FILE_POINTER) {
+ LARGE_INTEGER li = {.QuadPart = pos};
+ if (!SetFilePointerEx(f->fh_handle, li, &li, method)) {
errno = EIO;
return -1;
- } else {
- f->eof = 0;
}
- return (int)result;
+ f->eof = 0;
+ return li.QuadPart;
}
/**************************************************************************/
@@ -491,14 +486,12 @@
return f->clazz->_fh_writev(f, iov, iovcnt);
}
-int adb_lseek(int fd, int pos, int where) {
+int64_t adb_lseek(int fd, int64_t pos, int where) {
FH f = _fh_from_int(fd, __func__);
-
if (!f) {
errno = EBADF;
return -1;
}
-
return f->clazz->_fh_lseek(f, pos, where);
}
@@ -644,7 +637,7 @@
return 0;
}
-static int _fh_socket_lseek(FH f, int pos, int origin) {
+static int64_t _fh_socket_lseek(FH f, int64_t pos, int origin) {
errno = EPIPE;
return -1;
}
@@ -732,8 +725,8 @@
WSADATA wsaData;
int rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (rc != 0) {
- fatal("adb: could not initialize Winsock: %s",
- android::base::SystemErrorCodeToString(rc).c_str());
+ LOG(FATAL) << "could not initialize Winsock: "
+ << android::base::SystemErrorCodeToString(rc);
}
// Note that we do not call atexit() to register WSACleanup to be called
@@ -1289,11 +1282,11 @@
}
if (read_count == 0) { // should be impossible
- fatal("ReadConsoleInputA returned 0");
+ LOG(FATAL) << "ReadConsoleInputA returned 0";
}
if (read_count != 1) { // should be impossible
- fatal("ReadConsoleInputA did not return one input record");
+ LOG(FATAL) << "ReadConsoleInputA did not return one input record";
}
// If the console window is resized, emulate SIGWINCH by breaking out
@@ -1311,8 +1304,7 @@
if ((input_record->EventType == KEY_EVENT) &&
(input_record->Event.KeyEvent.bKeyDown)) {
if (input_record->Event.KeyEvent.wRepeatCount == 0) {
- fatal("ReadConsoleInputA returned a key event with zero repeat"
- " count");
+ LOG(FATAL) << "ReadConsoleInputA returned a key event with zero repeat count";
}
// Got an interesting INPUT_RECORD, so return
@@ -2195,7 +2187,7 @@
for (int i = 0; i < argc; ++i) {
std::string arg_narrow;
if (!android::base::WideToUTF8(argv[i], &arg_narrow)) {
- fatal_errno("cannot convert argument from UTF-16 to UTF-8");
+ PLOG(FATAL) << "cannot convert argument from UTF-16 to UTF-8";
}
narrow_args[i] = strdup(arg_narrow.c_str());
}
@@ -2212,15 +2204,15 @@
}
}
-int unix_open(const char* path, int options, ...) {
+int unix_open(std::string_view path, int options, ...) {
std::wstring path_wide;
- if (!android::base::UTF8ToWide(path, &path_wide)) {
+ if (!android::base::UTF8ToWide(path.data(), path.size(), &path_wide)) {
return -1;
}
if ((options & O_CREAT) == 0) {
return _wopen(path_wide.c_str(), options);
} else {
- int mode;
+ int mode;
va_list args;
va_start(args, options);
mode = va_arg(args, int);
@@ -2646,7 +2638,7 @@
// If _wenviron is null, then -municode probably wasn't used. That
// linker flag will cause the entry point to setup _wenviron. It will
// also require an implementation of wmain() (which we provide above).
- fatal("_wenviron is not set, did you link with -municode?");
+ LOG(FATAL) << "_wenviron is not set, did you link with -municode?";
}
// Read name/value pairs from UTF-16 _wenviron and write new name/value
@@ -2742,3 +2734,26 @@
return buf;
}
+
+// The SetThreadDescription API was brought in version 1607 of Windows 10.
+typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription);
+
+// Based on PlatformThread::SetName() from
+// https://cs.chromium.org/chromium/src/base/threading/platform_thread_win.cc
+int adb_thread_setname(const std::string& name) {
+ // The SetThreadDescription API works even if no debugger is attached.
+ auto set_thread_description_func = reinterpret_cast<SetThreadDescription>(
+ ::GetProcAddress(::GetModuleHandleW(L"Kernel32.dll"), "SetThreadDescription"));
+ if (set_thread_description_func) {
+ std::wstring name_wide;
+ if (!android::base::UTF8ToWide(name.c_str(), &name_wide)) {
+ return errno;
+ }
+ set_thread_description_func(::GetCurrentThread(), name_wide.c_str());
+ }
+
+ // Don't use the thread naming SEH exception because we're compiled with -fno-exceptions.
+ // https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code?view=vs-2017
+
+ return 0;
+}
diff --git a/adb/sysdeps_win32_test.cpp b/adb/sysdeps_win32_test.cpp
index 529b212..183cd5b 100644
--- a/adb/sysdeps_win32_test.cpp
+++ b/adb/sysdeps_win32_test.cpp
@@ -18,7 +18,7 @@
#include "sysdeps.h"
-#include <android-base/test_utils.h>
+#include <android-base/file.h>
TEST(sysdeps_win32, adb_getenv) {
// Insert all test env vars before first call to adb_getenv() which will
diff --git a/adb/test_adb.py b/adb/test_adb.py
index cde2b22..430fc3d 100755
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -31,6 +31,7 @@
import threading
import time
import unittest
+import warnings
@contextlib.contextmanager
@@ -229,6 +230,10 @@
stderr=subprocess.STDOUT)
try:
+ # We get warnings for unclosed files for the subprocess's pipes,
+ # and it's somewhat cumbersome to close them, so just ignore this.
+ warnings.simplefilter("ignore", ResourceWarning)
+
# Run the adb client and have it start the adb server.
proc = subprocess.Popen(["adb", "-P", str(port), "start-server"],
stdin=subprocess.PIPE,
@@ -490,6 +495,58 @@
self.assertEqual(_devices(server_port), [])
+@unittest.skipUnless(sys.platform == "win32", "requires Windows")
+class PowerTest(unittest.TestCase):
+ def test_resume_usb_kick(self):
+ """Resuming from sleep/hibernate should kick USB devices."""
+ try:
+ usb_serial = subprocess.check_output(["adb", "-d", "get-serialno"]).strip()
+ except subprocess.CalledProcessError:
+ # If there are multiple USB devices, we don't have a way to check whether the selected
+ # device is USB.
+ raise unittest.SkipTest('requires single USB device')
+
+ try:
+ serial = subprocess.check_output(["adb", "get-serialno"]).strip()
+ except subprocess.CalledProcessError:
+ # Did you forget to select a device with $ANDROID_SERIAL?
+ raise unittest.SkipTest('requires $ANDROID_SERIAL set to a USB device')
+
+ # Test only works with USB devices because adb _power_notification_thread does not kick
+ # non-USB devices on resume event.
+ if serial != usb_serial:
+ raise unittest.SkipTest('requires USB device')
+
+ # Run an adb shell command in the background that takes a while to complete.
+ proc = subprocess.Popen(['adb', 'shell', 'sleep', '5'])
+
+ # Wait for startup of adb server's _power_notification_thread.
+ time.sleep(0.1)
+
+ # Simulate resuming from sleep/hibernation by sending Windows message.
+ import ctypes
+ from ctypes import wintypes
+ HWND_BROADCAST = 0xffff
+ WM_POWERBROADCAST = 0x218
+ PBT_APMRESUMEAUTOMATIC = 0x12
+
+ PostMessageW = ctypes.windll.user32.PostMessageW
+ PostMessageW.restype = wintypes.BOOL
+ PostMessageW.argtypes = (wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM)
+ result = PostMessageW(HWND_BROADCAST, WM_POWERBROADCAST, PBT_APMRESUMEAUTOMATIC, 0)
+ if not result:
+ raise ctypes.WinError()
+
+ # Wait for connection to adb shell to be broken by _power_notification_thread detecting the
+ # Windows message.
+ start = time.time()
+ proc.wait()
+ end = time.time()
+
+ # If the power event was detected, the adb shell command should be broken very quickly.
+ self.assertLess(end - start, 2)
+
+
def main():
"""Main entrypoint."""
random.seed(0)
diff --git a/adb/test_device.py b/adb/test_device.py
old mode 100644
new mode 100755
index 20f224a..34f8fd9
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -750,8 +750,8 @@
if host_dir is not None:
shutil.rmtree(host_dir)
- def test_push_empty(self):
- """Push a directory containing an empty directory to the device."""
+ def disabled_test_push_empty(self):
+ """Push an empty directory to the device."""
self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
self.device.shell(['mkdir', self.DEVICE_TEMP_DIR])
@@ -767,9 +767,10 @@
self.device.push(empty_dir_path, self.DEVICE_TEMP_DIR)
- test_empty_cmd = ['[', '-d',
- os.path.join(self.DEVICE_TEMP_DIR, 'empty')]
+ remote_path = os.path.join(self.DEVICE_TEMP_DIR, "empty")
+ test_empty_cmd = ["[", "-d", remote_path, "]"]
rc, _, _ = self.device.shell_nocheck(test_empty_cmd)
+
self.assertEqual(rc, 0)
self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
finally:
@@ -1334,6 +1335,206 @@
self.device.forward_remove("tcp:{}".format(local_port))
+if sys.platform == "win32":
+ # From https://stackoverflow.com/a/38749458
+ import os
+ import contextlib
+ import msvcrt
+ import ctypes
+ from ctypes import wintypes
+
+ kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
+
+ GENERIC_READ = 0x80000000
+ GENERIC_WRITE = 0x40000000
+ FILE_SHARE_READ = 1
+ FILE_SHARE_WRITE = 2
+ CONSOLE_TEXTMODE_BUFFER = 1
+ INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value
+ STD_OUTPUT_HANDLE = wintypes.DWORD(-11)
+ STD_ERROR_HANDLE = wintypes.DWORD(-12)
+
+ def _check_zero(result, func, args):
+ if not result:
+ raise ctypes.WinError(ctypes.get_last_error())
+ return args
+
+ def _check_invalid(result, func, args):
+ if result == INVALID_HANDLE_VALUE:
+ raise ctypes.WinError(ctypes.get_last_error())
+ return args
+
+ if not hasattr(wintypes, 'LPDWORD'): # Python 2
+ wintypes.LPDWORD = ctypes.POINTER(wintypes.DWORD)
+ wintypes.PSMALL_RECT = ctypes.POINTER(wintypes.SMALL_RECT)
+
+ class COORD(ctypes.Structure):
+ _fields_ = (('X', wintypes.SHORT),
+ ('Y', wintypes.SHORT))
+
+ class CONSOLE_SCREEN_BUFFER_INFOEX(ctypes.Structure):
+ _fields_ = (('cbSize', wintypes.ULONG),
+ ('dwSize', COORD),
+ ('dwCursorPosition', COORD),
+ ('wAttributes', wintypes.WORD),
+ ('srWindow', wintypes.SMALL_RECT),
+ ('dwMaximumWindowSize', COORD),
+ ('wPopupAttributes', wintypes.WORD),
+ ('bFullscreenSupported', wintypes.BOOL),
+ ('ColorTable', wintypes.DWORD * 16))
+ def __init__(self, *args, **kwds):
+ super(CONSOLE_SCREEN_BUFFER_INFOEX, self).__init__(
+ *args, **kwds)
+ self.cbSize = ctypes.sizeof(self)
+
+ PCONSOLE_SCREEN_BUFFER_INFOEX = ctypes.POINTER(
+ CONSOLE_SCREEN_BUFFER_INFOEX)
+ LPSECURITY_ATTRIBUTES = wintypes.LPVOID
+
+ kernel32.GetStdHandle.errcheck = _check_invalid
+ kernel32.GetStdHandle.restype = wintypes.HANDLE
+ kernel32.GetStdHandle.argtypes = (
+ wintypes.DWORD,) # _In_ nStdHandle
+
+ kernel32.CreateConsoleScreenBuffer.errcheck = _check_invalid
+ kernel32.CreateConsoleScreenBuffer.restype = wintypes.HANDLE
+ kernel32.CreateConsoleScreenBuffer.argtypes = (
+ wintypes.DWORD, # _In_ dwDesiredAccess
+ wintypes.DWORD, # _In_ dwShareMode
+ LPSECURITY_ATTRIBUTES, # _In_opt_ lpSecurityAttributes
+ wintypes.DWORD, # _In_ dwFlags
+ wintypes.LPVOID) # _Reserved_ lpScreenBufferData
+
+ kernel32.GetConsoleScreenBufferInfoEx.errcheck = _check_zero
+ kernel32.GetConsoleScreenBufferInfoEx.argtypes = (
+ wintypes.HANDLE, # _In_ hConsoleOutput
+ PCONSOLE_SCREEN_BUFFER_INFOEX) # _Out_ lpConsoleScreenBufferInfo
+
+ kernel32.SetConsoleScreenBufferInfoEx.errcheck = _check_zero
+ kernel32.SetConsoleScreenBufferInfoEx.argtypes = (
+ wintypes.HANDLE, # _In_ hConsoleOutput
+ PCONSOLE_SCREEN_BUFFER_INFOEX) # _In_ lpConsoleScreenBufferInfo
+
+ kernel32.SetConsoleWindowInfo.errcheck = _check_zero
+ kernel32.SetConsoleWindowInfo.argtypes = (
+ wintypes.HANDLE, # _In_ hConsoleOutput
+ wintypes.BOOL, # _In_ bAbsolute
+ wintypes.PSMALL_RECT) # _In_ lpConsoleWindow
+
+ kernel32.FillConsoleOutputCharacterW.errcheck = _check_zero
+ kernel32.FillConsoleOutputCharacterW.argtypes = (
+ wintypes.HANDLE, # _In_ hConsoleOutput
+ wintypes.WCHAR, # _In_ cCharacter
+ wintypes.DWORD, # _In_ nLength
+ COORD, # _In_ dwWriteCoord
+ wintypes.LPDWORD) # _Out_ lpNumberOfCharsWritten
+
+ kernel32.ReadConsoleOutputCharacterW.errcheck = _check_zero
+ kernel32.ReadConsoleOutputCharacterW.argtypes = (
+ wintypes.HANDLE, # _In_ hConsoleOutput
+ wintypes.LPWSTR, # _Out_ lpCharacter
+ wintypes.DWORD, # _In_ nLength
+ COORD, # _In_ dwReadCoord
+ wintypes.LPDWORD) # _Out_ lpNumberOfCharsRead
+
+ @contextlib.contextmanager
+ def allocate_console():
+ allocated = kernel32.AllocConsole()
+ try:
+ yield allocated
+ finally:
+ if allocated:
+ kernel32.FreeConsole()
+
+ @contextlib.contextmanager
+ def console_screen(ncols=None, nrows=None):
+ info = CONSOLE_SCREEN_BUFFER_INFOEX()
+ new_info = CONSOLE_SCREEN_BUFFER_INFOEX()
+ nwritten = (wintypes.DWORD * 1)()
+ hStdOut = kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
+ kernel32.GetConsoleScreenBufferInfoEx(
+ hStdOut, ctypes.byref(info))
+ if ncols is None:
+ ncols = info.dwSize.X
+ if nrows is None:
+ nrows = info.dwSize.Y
+ elif nrows > 9999:
+ raise ValueError('nrows must be 9999 or less')
+ fd_screen = None
+ hScreen = kernel32.CreateConsoleScreenBuffer(
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ None, CONSOLE_TEXTMODE_BUFFER, None)
+ try:
+ fd_screen = msvcrt.open_osfhandle(
+ hScreen, os.O_RDWR | os.O_BINARY)
+ kernel32.GetConsoleScreenBufferInfoEx(
+ hScreen, ctypes.byref(new_info))
+ new_info.dwSize = COORD(ncols, nrows)
+ new_info.srWindow = wintypes.SMALL_RECT(
+ Left=0, Top=0, Right=(ncols - 1),
+ Bottom=(info.srWindow.Bottom - info.srWindow.Top))
+ kernel32.SetConsoleScreenBufferInfoEx(
+ hScreen, ctypes.byref(new_info))
+ kernel32.SetConsoleWindowInfo(hScreen, True,
+ ctypes.byref(new_info.srWindow))
+ kernel32.FillConsoleOutputCharacterW(
+ hScreen, u'\0', ncols * nrows, COORD(0,0), nwritten)
+ kernel32.SetConsoleActiveScreenBuffer(hScreen)
+ try:
+ yield fd_screen
+ finally:
+ kernel32.SetConsoleScreenBufferInfoEx(
+ hStdOut, ctypes.byref(info))
+ kernel32.SetConsoleWindowInfo(hStdOut, True,
+ ctypes.byref(info.srWindow))
+ kernel32.SetConsoleActiveScreenBuffer(hStdOut)
+ finally:
+ if fd_screen is not None:
+ os.close(fd_screen)
+ else:
+ kernel32.CloseHandle(hScreen)
+
+ def read_screen(fd):
+ hScreen = msvcrt.get_osfhandle(fd)
+ csbi = CONSOLE_SCREEN_BUFFER_INFOEX()
+ kernel32.GetConsoleScreenBufferInfoEx(
+ hScreen, ctypes.byref(csbi))
+ ncols = csbi.dwSize.X
+ pos = csbi.dwCursorPosition
+ length = ncols * pos.Y + pos.X + 1
+ buf = (ctypes.c_wchar * length)()
+ n = (wintypes.DWORD * 1)()
+ kernel32.ReadConsoleOutputCharacterW(
+ hScreen, buf, length, COORD(0,0), n)
+ lines = [buf[i:i+ncols].rstrip(u'\0')
+ for i in range(0, n[0], ncols)]
+ return u'\n'.join(lines)
+
+@unittest.skipUnless(sys.platform == "win32", "requires Windows")
+class WindowsConsoleTest(DeviceTest):
+ def test_unicode_output(self):
+ """Test Unicode command line parameters and Unicode console window output.
+
+ Bug: https://issuetracker.google.com/issues/111972753
+ """
+ # If we don't have a console window, allocate one. This isn't necessary if we're already
+ # being run from a console window, which is typical.
+ with allocate_console() as allocated_console:
+ # Create a temporary console buffer and switch to it. We could also pass a parameter of
+ # ncols=len(unicode_string), but it causes the window to flash as it is resized and
+ # likely unnecessary given the typical console window size.
+ with console_screen(nrows=1000) as screen:
+ unicode_string = u'로보카 폴리'
+ # Run adb and allow it to detect that stdout is a console, not a pipe, by using
+ # device.shell_popen() which does not use a pipe, unlike device.shell().
+ process = self.device.shell_popen(['echo', '"' + unicode_string + '"'])
+ process.wait()
+ # Read what was written by adb to the temporary console buffer.
+ console_output = read_screen(screen)
+ self.assertEqual(unicode_string, console_output)
+
+
def main():
random.seed(0)
if len(adb.get_devices()) > 0:
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 239403a..ae53597 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -17,7 +17,6 @@
#define TRACE_TAG TRANSPORT
#include "sysdeps.h"
-#include "sysdeps/memory.h"
#include "transport.h"
@@ -32,6 +31,7 @@
#include <algorithm>
#include <deque>
#include <list>
+#include <memory>
#include <mutex>
#include <set>
#include <thread>
@@ -52,7 +52,6 @@
#include "fdevent.h"
#include "sysdeps/chrono.h"
-static void register_transport(atransport* transport);
static void remove_transport(atransport* transport);
static void transport_unref(atransport* transport);
@@ -67,6 +66,9 @@
const char* const kFeatureStat2 = "stat_v2";
const char* const kFeatureLibusb = "libusb";
const char* const kFeaturePushSync = "push_sync";
+const char* const kFeatureApex = "apex";
+const char* const kFeatureFixedPushMkdir = "fixed_push_mkdir";
+const char* const kFeatureAbb = "abb";
namespace {
@@ -408,42 +410,6 @@
fd_.reset();
}
-static std::string dump_packet(const char* name, const char* func, apacket* p) {
- unsigned command = p->msg.command;
- int len = p->msg.data_length;
- char cmd[9];
- char arg0[12], arg1[12];
- int n;
-
- for (n = 0; n < 4; n++) {
- int b = (command >> (n * 8)) & 255;
- if (b < 32 || b >= 127) break;
- cmd[n] = (char)b;
- }
- if (n == 4) {
- cmd[4] = 0;
- } else {
- /* There is some non-ASCII name in the command, so dump
- * the hexadecimal value instead */
- snprintf(cmd, sizeof cmd, "%08x", command);
- }
-
- if (p->msg.arg0 < 256U)
- snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
- else
- snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
-
- if (p->msg.arg1 < 256U)
- snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
- else
- snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
-
- std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ", name,
- func, cmd, arg0, arg1, len);
- result += dump_hex(p->payload.data(), p->payload.size());
- return result;
-}
-
void send_packet(apacket* p, atransport* t) {
p->msg.magic = p->msg.command ^ 0xffffffff;
// compute a checksum for connection/auth packets for compatibility reasons
@@ -456,7 +422,7 @@
VLOG(TRANSPORT) << dump_packet(t->serial.c_str(), "to remote", p);
if (t == nullptr) {
- fatal("Transport is null");
+ LOG(FATAL) << "Transport is null";
}
if (t->Write(p) != 0) {
@@ -562,7 +528,7 @@
asocket* create_device_tracker(bool long_output) {
device_tracker* tracker = new device_tracker();
- if (tracker == nullptr) fatal("cannot allocate device tracker");
+ if (tracker == nullptr) LOG(FATAL) << "cannot allocate device tracker";
D("device tracker %p created", tracker);
@@ -668,7 +634,7 @@
}
if (transport_read_action(_fd, &m)) {
- fatal_errno("cannot read transport registration socket");
+ PLOG(FATAL) << "cannot read transport registration socket";
}
t = m.transport;
@@ -707,7 +673,7 @@
return true;
});
t->connection()->SetErrorCallback([t](Connection*, const std::string& error) {
- D("%s: connection terminated: %s", t->serial.c_str(), error.c_str());
+ LOG(INFO) << t->serial_name() << ": connection terminated: " << error;
fdevent_run_on_main_thread([t]() {
handle_offline(t);
transport_unref(t);
@@ -742,7 +708,7 @@
int s[2];
if (adb_socketpair(s)) {
- fatal_errno("cannot open transport registration socketpair");
+ PLOG(FATAL) << "cannot open transport registration socketpair";
}
D("socketpair: (%d,%d)", s[0], s[1]);
@@ -766,13 +732,13 @@
}
/* the fdevent select pump is single threaded */
-static void register_transport(atransport* transport) {
+void register_transport(atransport* transport) {
tmsg m;
m.transport = transport;
m.action = 1;
D("transport: %s registered", transport->serial.c_str());
if (transport_write_action(transport_registration_send, &m)) {
- fatal_errno("cannot write transport registration socket\n");
+ PLOG(FATAL) << "cannot write transport registration socket";
}
}
@@ -782,7 +748,7 @@
m.action = 0;
D("transport: %s removed", transport->serial.c_str());
if (transport_write_action(transport_registration_send, &m)) {
- fatal_errno("cannot write transport registration socket\n");
+ PLOG(FATAL) << "cannot write transport registration socket";
}
}
@@ -794,10 +760,15 @@
CHECK_GT(t->ref_count, 0u);
t->ref_count--;
if (t->ref_count == 0) {
+ 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());
+
+ // 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());
@@ -1040,26 +1011,22 @@
return max_payload;
}
-namespace {
-
-constexpr char kFeatureStringDelimiter = ',';
-
-} // namespace
-
const FeatureSet& supported_features() {
// Local static allocation to avoid global non-POD variables.
static const FeatureSet* features = new FeatureSet{
- kFeatureShell2, kFeatureCmd, kFeatureStat2,
- // Increment ADB_SERVER_VERSION whenever the feature list changes to
- // make sure that the adb client and server features stay in sync
- // (http://b/24370690).
+ kFeatureShell2, kFeatureCmd, kFeatureStat2,
+ kFeatureFixedPushMkdir, kFeatureApex, kFeatureAbb,
+ // 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.
+ // (http://b/24370690)
};
return *features;
}
std::string FeatureSetToString(const FeatureSet& features) {
- return android::base::Join(features, kFeatureStringDelimiter);
+ return android::base::Join(features, ',');
}
FeatureSet StringToFeatureSet(const std::string& features_string) {
@@ -1067,7 +1034,7 @@
return FeatureSet();
}
- auto names = android::base::Split(features_string, {kFeatureStringDelimiter});
+ auto names = android::base::Split(features_string, ",");
return FeatureSet(names.begin(), names.end());
}
@@ -1335,17 +1302,15 @@
register_transport(t);
}
+#if ADB_HOST
// This should only be used for transports with connection_state == kCsNoPerm.
void unregister_usb_transport(usb_handle* usb) {
std::lock_guard<std::recursive_mutex> lock(transport_lock);
transport_list.remove_if([usb](atransport* t) {
- auto connection = t->connection();
- if (auto usb_connection = dynamic_cast<UsbConnection*>(connection.get())) {
- return usb_connection->handle_ == usb && t->GetConnectionState() == kCsNoPerm;
- }
- return false;
+ return t->GetUsbHandle() == usb && t->GetConnectionState() == kCsNoPerm;
});
}
+#endif
bool check_header(apacket* p, atransport* t) {
if (p->msg.magic != (p->msg.command ^ 0xffffffff)) {
@@ -1365,10 +1330,20 @@
#if ADB_HOST
std::shared_ptr<RSA> atransport::NextKey() {
- if (keys_.empty()) keys_ = adb_auth_get_private_keys();
+ if (keys_.empty()) {
+ LOG(INFO) << "fetching keys for transport " << this->serial_name();
+ keys_ = adb_auth_get_private_keys();
+
+ // We should have gotten at least one key: the one that's automatically generated.
+ CHECK(!keys_.empty());
+ }
std::shared_ptr<RSA> result = keys_[0];
keys_.pop_front();
return result;
}
+
+void atransport::ResetKeys() {
+ keys_.clear();
+}
#endif
diff --git a/adb/transport.h b/adb/transport.h
index f854ce5..6f53e6ec 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -37,6 +37,7 @@
#include "adb.h"
#include "adb_unique_fd.h"
+#include "usb.h"
typedef std::unordered_set<std::string> FeatureSet;
@@ -57,8 +58,14 @@
extern const char* const kFeatureStat2;
// The server is running with libusb enabled.
extern const char* const kFeatureLibusb;
-// The server supports `push --sync`.
+// adbd supports `push --sync`.
extern const char* const kFeaturePushSync;
+// adbd supports installing .apex packages.
+extern const char* const kFeatureApex;
+// adbd has b/110953234 fixed.
+extern const char* const kFeatureFixedPushMkdir;
+// adbd supports android binder bridge (abb).
+extern const char* const kFeatureAbb;
TransportId NextTransportId();
@@ -238,6 +245,9 @@
return connection_;
}
+ void SetUsbHandle(usb_handle* h) { usb_handle_ = h; }
+ usb_handle* GetUsbHandle() { return usb_handle_; }
+
const TransportId id;
size_t ref_count = 0;
bool online = false;
@@ -254,6 +264,7 @@
#if ADB_HOST
std::shared_ptr<RSA> NextKey();
+ void ResetKeys();
#endif
char token[TOKEN_SIZE] = {};
@@ -328,6 +339,9 @@
// The underlying connection object.
std::shared_ptr<Connection> connection_ GUARDED_BY(mutex_);
+ // USB handle for the connection, if available.
+ usb_handle* usb_handle_ = nullptr;
+
// A callback that will be invoked when the atransport needs to reconnect.
ReconnectCallback reconnect_;
@@ -362,6 +376,7 @@
void kick_all_tcp_devices();
void kick_all_transports();
+void register_transport(atransport* transport);
void register_usb_transport(usb_handle* h, const char* serial,
const char* devpath, unsigned writeable);
diff --git a/adb/transport_fd.cpp b/adb/transport_fd.cpp
index 85f3c52..a93e68a 100644
--- a/adb/transport_fd.cpp
+++ b/adb/transport_fd.cpp
@@ -17,6 +17,7 @@
#include <stdint.h>
#include <deque>
+#include <memory>
#include <mutex>
#include <string>
#include <thread>
@@ -28,7 +29,6 @@
#include "adb_unique_fd.h"
#include "adb_utils.h"
#include "sysdeps.h"
-#include "sysdeps/memory.h"
#include "transport.h"
#include "types.h"
@@ -85,18 +85,9 @@
if (pfds[0].revents) {
if ((pfds[0].revents & POLLOUT)) {
std::lock_guard<std::mutex> lock(this->write_mutex_);
- WriteResult result = DispatchWrites();
- switch (result) {
- case WriteResult::Error:
- *error = "write failed";
- return;
-
- case WriteResult::Completed:
- writable_ = true;
- break;
-
- case WriteResult::TryAgain:
- break;
+ if (DispatchWrites() == WriteResult::Error) {
+ *error = "write failed";
+ return;
}
}
@@ -179,13 +170,14 @@
WriteResult DispatchWrites() REQUIRES(write_mutex_) {
CHECK(!write_buffer_.empty());
- if (!writable_) {
- return WriteResult::TryAgain;
- }
-
auto iovs = write_buffer_.iovecs();
ssize_t rc = adb_writev(fd_.get(), iovs.data(), iovs.size());
if (rc == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ writable_ = false;
+ return WriteResult::TryAgain;
+ }
+
return WriteResult::Error;
} else if (rc == 0) {
errno = 0;
@@ -194,6 +186,7 @@
// TODO: Implement a more efficient drop_front?
write_buffer_.take_front(rc);
+ writable_ = write_buffer_.empty();
if (write_buffer_.empty()) {
return WriteResult::Completed;
}
@@ -211,7 +204,12 @@
if (!packet->payload.empty()) {
write_buffer_.append(std::make_unique<IOVector::block_type>(std::move(packet->payload)));
}
- return DispatchWrites() != WriteResult::Error;
+
+ WriteResult result = DispatchWrites();
+ if (result == WriteResult::TryAgain) {
+ WakeThread();
+ }
+ return result != WriteResult::Error;
}
std::thread thread_;
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 4fd483b..b384085 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <condition_variable>
+#include <memory>
#include <mutex>
#include <thread>
#include <unordered_map>
@@ -44,8 +45,8 @@
#include "adb_io.h"
#include "adb_unique_fd.h"
#include "adb_utils.h"
+#include "socket_spec.h"
#include "sysdeps/chrono.h"
-#include "sysdeps/memory.h"
#if ADB_HOST
@@ -70,32 +71,17 @@
std::tuple<unique_fd, int, std::string> tcp_connect(const std::string& address,
std::string* response) {
- std::string serial;
- std::string host;
+ unique_fd fd;
int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
- if (!android::base::ParseNetAddress(address, &host, &port, &serial, response)) {
- D("failed to parse address: '%s'", address.c_str());
- return std::make_tuple(unique_fd(), port, serial);
- }
-
- std::string error;
- unique_fd fd(network_connect(host.c_str(), port, SOCK_STREAM, 10, &error));
- if (fd == -1) {
- *response = android::base::StringPrintf("unable to connect to %s: %s",
- serial.c_str(), error.c_str());
+ std::string serial;
+ if (socket_spec_connect(&fd, "tcp:" + address, &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);
}
-
- D("client: connected %s remote on fd %d", serial.c_str(), fd.get());
- close_on_exec(fd);
- disable_tcp_nagle(fd);
-
- // Send a TCP keepalive ping to the device every second so we can detect disconnects.
- 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, "");
}
void connect_device(const std::string& address, std::string* response) {
@@ -187,8 +173,8 @@
}
// Retry the disconnected local port for 60 times, and sleep 1 second between two retries.
-constexpr uint32_t LOCAL_PORT_RETRY_COUNT = 60;
-constexpr auto LOCAL_PORT_RETRY_INTERVAL = 1s;
+static constexpr uint32_t LOCAL_PORT_RETRY_COUNT = 60;
+static constexpr auto LOCAL_PORT_RETRY_INTERVAL = 1s;
struct RetryPort {
int port;
@@ -251,8 +237,9 @@
adb_thread_setname("server socket");
D("transport: server_socket_thread() starting");
while (serverfd == -1) {
+ std::string spec = android::base::StringPrintf("tcp:%d", port);
std::string error;
- serverfd.reset(network_inaddr_any_server(port, SOCK_STREAM, &error));
+ serverfd.reset(socket_spec_listen(spec, &error));
if (serverfd < 0) {
D("server: cannot bind socket yet: %s", error.c_str());
std::this_thread::sleep_for(1s);
diff --git a/adb/transport_test.cpp b/adb/transport_test.cpp
index 8c628d8..b66f8fa 100644
--- a/adb/transport_test.cpp
+++ b/adb/transport_test.cpp
@@ -19,13 +19,16 @@
#include <gtest/gtest.h>
#include "adb.h"
+#include "fdevent_test.h"
+
+struct TransportTest : public FdeventTest {};
static void DisconnectFunc(void* arg, atransport*) {
int* count = reinterpret_cast<int*>(arg);
++*count;
}
-TEST(transport, RunDisconnects) {
+TEST_F(TransportTest, RunDisconnects) {
atransport t;
// RunDisconnects() can be called with an empty atransport.
t.RunDisconnects();
@@ -49,7 +52,7 @@
ASSERT_EQ(0, count);
}
-TEST(transport, SetFeatures) {
+TEST_F(TransportTest, SetFeatures) {
atransport t;
ASSERT_EQ(0U, t.features().size());
@@ -77,8 +80,7 @@
ASSERT_EQ(0U, t.features().size());
}
-TEST(transport, parse_banner_no_features) {
- set_main_thread();
+TEST_F(TransportTest, parse_banner_no_features) {
atransport t;
parse_banner("host::", &t);
@@ -91,7 +93,7 @@
ASSERT_EQ(std::string(), t.device);
}
-TEST(transport, parse_banner_product_features) {
+TEST_F(TransportTest, parse_banner_product_features) {
atransport t;
const char banner[] =
@@ -107,9 +109,8 @@
ASSERT_EQ(std::string("baz"), t.device);
}
-TEST(transport, parse_banner_features) {
+TEST_F(TransportTest, parse_banner_features) {
atransport t;
-
const char banner[] =
"host::ro.product.name=foo;ro.product.model=bar;ro.product.device=baz;"
"features=woodly,doodly";
@@ -126,7 +127,7 @@
ASSERT_EQ(std::string("baz"), t.device);
}
-TEST(transport, test_matches_target) {
+TEST_F(TransportTest, test_matches_target) {
std::string serial = "foo";
std::string devpath = "/path/to/bar";
std::string product = "test_product";
@@ -157,7 +158,7 @@
}
}
-TEST(transport, test_matches_target_local) {
+TEST_F(TransportTest, test_matches_target_local) {
std::string serial = "100.100.100.100:5555";
atransport t;
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 602970c..2e5918a 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -16,8 +16,9 @@
#define TRACE_TAG TRANSPORT
+#include <memory>
+
#include "sysdeps.h"
-#include "sysdeps/memory.h"
#include "transport.h"
#include <stdio.h>
@@ -179,6 +180,7 @@
auto connection = std::make_unique<UsbConnection>(h);
t->SetConnection(std::make_unique<BlockingConnectionAdapter>(std::move(connection)));
t->type = kTransportUsb;
+ t->SetUsbHandle(h);
}
int is_adb_interface(int usb_class, int usb_subclass, int usb_protocol) {
diff --git a/adb/types.h b/adb/types.h
index a3e5d48..0090c98 100644
--- a/adb/types.h
+++ b/adb/types.h
@@ -25,7 +25,6 @@
#include <android-base/logging.h>
-#include "sysdeps/memory.h"
#include "sysdeps/uio.h"
// Essentially std::vector<char>, except without zero initialization or reallocation.
@@ -42,14 +41,14 @@
}
Block(const Block& copy) = delete;
- Block(Block&& move) {
+ Block(Block&& move) noexcept {
std::swap(data_, move.data_);
std::swap(capacity_, move.capacity_);
std::swap(size_, move.size_);
}
Block& operator=(const Block& copy) = delete;
- Block& operator=(Block&& move) {
+ Block& operator=(Block&& move) noexcept {
clear();
std::swap(data_, move.data_);
@@ -109,7 +108,10 @@
CHECK_EQ(0ULL, capacity_);
CHECK_EQ(0ULL, size_);
if (size != 0) {
- data_ = std::make_unique<char[]>(size);
+ // This isn't std::make_unique because that's equivalent to `new char[size]()`, which
+ // value-initializes the array instead of leaving it uninitialized. As an optimization,
+ // call new without parentheses to avoid this costly initialization.
+ data_.reset(new char[size]);
capacity_ = size;
size_ = size;
}
@@ -147,12 +149,10 @@
}
IOVector(const IOVector& copy) = delete;
- IOVector(IOVector&& move) : IOVector() {
- *this = std::move(move);
- }
+ IOVector(IOVector&& move) noexcept : IOVector() { *this = std::move(move); }
IOVector& operator=(const IOVector& copy) = delete;
- IOVector& operator=(IOVector&& move) {
+ IOVector& operator=(IOVector&& move) noexcept {
chain_ = std::move(move.chain_);
chain_length_ = move.chain_length_;
begin_offset_ = move.begin_offset_;
diff --git a/adb/types_test.cpp b/adb/types_test.cpp
index 31ab90a..1fbd2ca 100644
--- a/adb/types_test.cpp
+++ b/adb/types_test.cpp
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
-#include "sysdeps/memory.h"
+#include <memory>
#include "types.h"
static std::unique_ptr<IOVector::block_type> create_block(const std::string& string) {
diff --git a/base/Android.bp b/base/Android.bp
index 3d80d97..b0181aa 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -20,6 +20,7 @@
"-Wall",
"-Werror",
"-Wextra",
+ "-D_FILE_OFFSET_BITS=64",
],
}
@@ -47,6 +48,7 @@
"chrono_utils.cpp",
"file.cpp",
"logging.cpp",
+ "mapped_file.cpp",
"parsenetaddress.cpp",
"properties.cpp",
"quick_exit.cpp",
@@ -56,6 +58,7 @@
"test_utils.cpp",
],
+ cppflags: ["-Wexit-time-destructors"],
shared_libs: ["liblog"],
target: {
android: {
@@ -68,13 +71,11 @@
srcs: [
"errors_unix.cpp",
],
- cppflags: ["-Wexit-time-destructors"],
},
darwin: {
srcs: [
"errors_unix.cpp",
],
- cppflags: ["-Wexit-time-destructors"],
},
linux_bionic: {
enabled: true,
@@ -125,6 +126,7 @@
"file_test.cpp",
"logging_test.cpp",
"macros_test.cpp",
+ "mapped_file_test.cpp",
"parsedouble_test.cpp",
"parseint_test.cpp",
"parsenetaddress_test.cpp",
diff --git a/base/file.cpp b/base/file.cpp
index d6fe753..2f4a517 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -18,7 +18,11 @@
#include <errno.h>
#include <fcntl.h>
+#include <ftw.h>
#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -28,20 +32,144 @@
#include <string>
#include <vector>
-#include "android-base/logging.h"
-#include "android-base/macros.h" // For TEMP_FAILURE_RETRY on Darwin.
-#include "android-base/unique_fd.h"
-#include "android-base/utf8.h"
-
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#endif
#if defined(_WIN32)
+#include <direct.h>
#include <windows.h>
-#define O_CLOEXEC O_NOINHERIT
#define O_NOFOLLOW 0
+#define OS_PATH_SEPARATOR '\\'
+#else
+#define OS_PATH_SEPARATOR '/'
#endif
+#include "android-base/logging.h" // and must be after windows.h for ERROR
+#include "android-base/macros.h" // For TEMP_FAILURE_RETRY on Darwin.
+#include "android-base/unique_fd.h"
+#include "android-base/utf8.h"
+
+#ifdef _WIN32
+int mkstemp(char* template_name) {
+ if (_mktemp(template_name) == nullptr) {
+ 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);
+}
+
+char* mkdtemp(char* template_name) {
+ if (_mktemp(template_name) == nullptr) {
+ return nullptr;
+ }
+ if (_mkdir(template_name) == -1) {
+ return nullptr;
+ }
+ return template_name;
+}
+#endif
+
+namespace {
+
+std::string GetSystemTempDir() {
+#if defined(__ANDROID__)
+ const auto* tmpdir = getenv("TMPDIR");
+ if (tmpdir == nullptr) tmpdir = "/data/local/tmp";
+ if (access(tmpdir, R_OK | W_OK | X_OK) == 0) {
+ return tmpdir;
+ }
+ // Tests running in app context can't access /data/local/tmp,
+ // 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;
+
+ // 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';
+ return tmp_dir;
+#else
+ const auto* tmpdir = getenv("TMPDIR");
+ if (tmpdir == nullptr) tmpdir = "/tmp";
+ return tmpdir;
+#endif
+}
+
+} // namespace
+
+TemporaryFile::TemporaryFile() {
+ init(GetSystemTempDir());
+}
+
+TemporaryFile::TemporaryFile(const std::string& tmp_dir) {
+ init(tmp_dir);
+}
+
+TemporaryFile::~TemporaryFile() {
+ if (fd != -1) {
+ close(fd);
+ }
+ if (remove_file_) {
+ unlink(path);
+ }
+}
+
+int TemporaryFile::release() {
+ int result = fd;
+ fd = -1;
+ return result;
+}
+
+void TemporaryFile::init(const std::string& tmp_dir) {
+ snprintf(path, sizeof(path), "%s%cTemporaryFile-XXXXXX", tmp_dir.c_str(), OS_PATH_SEPARATOR);
+ fd = mkstemp(path);
+}
+
+TemporaryDir::TemporaryDir() {
+ init(GetSystemTempDir());
+}
+
+TemporaryDir::~TemporaryDir() {
+ if (!remove_dir_and_contents_) return;
+
+ auto callback = [](const char* child, const struct stat*, int file_type, struct FTW*) -> int {
+ switch (file_type) {
+ case FTW_D:
+ case FTW_DP:
+ case FTW_DNR:
+ if (rmdir(child) == -1) {
+ PLOG(ERROR) << "rmdir " << child;
+ }
+ break;
+ case FTW_NS:
+ default:
+ if (rmdir(child) != -1) break;
+ // FALLTHRU (for gcc, lint, pcc, etc; and following for clang)
+ FALLTHROUGH_INTENDED;
+ case FTW_F:
+ case FTW_SL:
+ case FTW_SLN:
+ if (unlink(child) == -1) {
+ PLOG(ERROR) << "unlink " << child;
+ }
+ break;
+ }
+ return 0;
+ };
+
+ nftw(path, callback, 128, FTW_DEPTH | FTW_MOUNT | FTW_PHYS);
+}
+
+bool TemporaryDir::init(const std::string& tmp_dir) {
+ snprintf(path, sizeof(path), "%s%cTemporaryDir-XXXXXX", tmp_dir.c_str(), OS_PATH_SEPARATOR);
+ return (mkdtemp(path) != nullptr);
+}
+
namespace android {
namespace base {
diff --git a/base/file_test.cpp b/base/file_test.cpp
index 6794652..f64e81c 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -24,8 +24,6 @@
#include <string>
-#include "android-base/test_utils.h"
-
#if !defined(_WIN32)
#include <pwd.h>
#endif
diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h
index 908690b..f8748b5 100644
--- a/base/include/android-base/file.h
+++ b/base/include/android-base/file.h
@@ -18,17 +18,62 @@
#include <sys/stat.h>
#include <sys/types.h>
+
#include <string>
+#include <android-base/macros.h>
+#include "android-base/off64_t.h"
+
#if !defined(_WIN32) && !defined(O_BINARY)
+/** Windows needs O_BINARY, but Unix never mangles line endings. */
#define O_BINARY 0
#endif
-#if defined(__APPLE__)
-/* Mac OS has always had a 64-bit off_t, so it doesn't have off64_t. */
-typedef off_t off64_t;
+#if defined(_WIN32) && !defined(O_CLOEXEC)
+/** Windows has O_CLOEXEC but calls it O_NOINHERIT for some reason. */
+#define O_CLOEXEC O_NOINHERIT
#endif
+class TemporaryFile {
+ public:
+ TemporaryFile();
+ explicit TemporaryFile(const std::string& tmp_dir);
+ ~TemporaryFile();
+
+ // Release the ownership of fd, caller is reponsible for closing the
+ // fd or stream properly.
+ int release();
+ // Don't remove the temporary file in the destructor.
+ void DoNotRemove() { remove_file_ = false; }
+
+ int fd;
+ char path[1024];
+
+ private:
+ void init(const std::string& tmp_dir);
+
+ bool remove_file_ = true;
+
+ DISALLOW_COPY_AND_ASSIGN(TemporaryFile);
+};
+
+class TemporaryDir {
+ public:
+ TemporaryDir();
+ ~TemporaryDir();
+ // Don't remove the temporary dir in the destructor.
+ void DoNotRemove() { remove_dir_and_contents_ = false; }
+
+ char path[1024];
+
+ private:
+ bool init(const std::string& tmp_dir);
+
+ bool remove_dir_and_contents_ = true;
+
+ DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
+};
+
namespace android {
namespace base {
diff --git a/base/include/android-base/macros.h b/base/include/android-base/macros.h
index 49cc0c9..5abf514 100644
--- a/base/include/android-base/macros.h
+++ b/base/include/android-base/macros.h
@@ -75,46 +75,6 @@
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
-// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize,
-// but can be used on anonymous types or types defined inside
-// functions. It's less safe than arraysize as it accepts some
-// (although not all) pointers. Therefore, you should use arraysize
-// whenever possible.
-//
-// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type
-// size_t.
-//
-// ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error
-//
-// "warning: division by zero in ..."
-//
-// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer.
-// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays.
-//
-// The following comments are on the implementation details, and can
-// be ignored by the users.
-//
-// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in
-// the array) and sizeof(*(arr)) (the # of bytes in one array
-// element). If the former is divisible by the latter, perhaps arr is
-// indeed an array, in which case the division result is the # of
-// elements in the array. Otherwise, arr cannot possibly be an array,
-// and we generate a compiler error to prevent the code from
-// compiling.
-//
-// Since the size of bool is implementation-defined, we need to cast
-// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
-// result has type size_t.
-//
-// This macro is not perfect as it wrongfully accepts certain
-// pointers, namely where the pointer size is divisible by the pointee
-// size. Since all our code has to go through a 32-bit compiler,
-// where a pointer is 4 bytes, this means all pointers to a type whose
-// size is 3 or greater than 4 will be (righteously) rejected.
-#define ARRAYSIZE_UNSAFE(a) \
- ((sizeof(a) / sizeof(*(a))) / \
- static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
-
#define SIZEOF_MEMBER(t, f) sizeof(std::declval<t>().f)
// Changing this definition will cause you a lot of pain. A majority of
@@ -153,24 +113,26 @@
// case 42:
// ...
//
-// As shown in the example above, the FALLTHROUGH_INTENDED macro should be
-// followed by a semicolon. It is designed to mimic control-flow statements
-// like 'break;', so it can be placed in most places where 'break;' can, but
-// only if there are no statements on the execution path between it and the
-// next switch label.
+// As shown in the example above, the FALLTHROUGH_INTENDED macro should be
+// followed by a semicolon. It is designed to mimic control-flow statements
+// like 'break;', so it can be placed in most places where 'break;' can, but
+// only if there are no statements on the execution path between it and the
+// next switch label.
//
-// When compiled with clang, the FALLTHROUGH_INTENDED macro is expanded to
-// [[clang::fallthrough]] attribute, which is analysed when performing switch
-// labels fall-through diagnostic ('-Wimplicit-fallthrough'). See clang
-// documentation on language extensions for details:
-// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
+// When compiled with clang, the FALLTHROUGH_INTENDED macro is expanded to
+// [[clang::fallthrough]] attribute, which is analysed when performing switch
+// labels fall-through diagnostic ('-Wimplicit-fallthrough'). See clang
+// documentation on language extensions for details:
+// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
//
-// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
-// effect on diagnostics.
+// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
+// effect on diagnostics.
//
-// In either case this macro has no effect on runtime behavior and performance
-// of code.
+// In either case this macro has no effect on runtime behavior and performance
+// of code.
+#ifndef FALLTHROUGH_INTENDED
#define FALLTHROUGH_INTENDED [[clang::fallthrough]] // NOLINT
+#endif
// Current ABI string
#if defined(__arm__)
diff --git a/base/include/android-base/mapped_file.h b/base/include/android-base/mapped_file.h
new file mode 100644
index 0000000..80513b1
--- /dev/null
+++ b/base/include/android-base/mapped_file.h
@@ -0,0 +1,75 @@
+/*
+ * 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 "android-base/macros.h"
+#include "android-base/off64_t.h"
+
+#include <sys/types.h>
+
+#include <memory>
+
+#if defined(_WIN32)
+#include <windows.h>
+#define PROT_READ 1
+#define PROT_WRITE 2
+#else
+#include <sys/mman.h>
+#endif
+
+namespace android {
+namespace base {
+
+/**
+ * A region of a file mapped into memory.
+ */
+class MappedFile {
+ public:
+ /**
+ * Creates a new mapping of the file pointed to by `fd`. Unlike the underlying OS primitives,
+ * `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);
+
+ /**
+ * Removes the mapping.
+ */
+ ~MappedFile();
+
+ char* data() { return base_ + offset_; }
+ size_t size() { return size_; }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MappedFile);
+
+ char* base_;
+ size_t size_;
+
+ size_t offset_;
+
+#if defined(_WIN32)
+ MappedFile(char* base, size_t size, size_t offset, HANDLE handle)
+ : base_(base), size_(size), offset_(offset), handle_(handle) {}
+ HANDLE handle_;
+#else
+ MappedFile(char* base, size_t size, size_t offset) : base_(base), size_(size), offset_(offset) {}
+#endif
+};
+
+} // namespace base
+} // namespace android
diff --git a/libbacktrace/GetPss.h b/base/include/android-base/off64_t.h
similarity index 74%
copy from libbacktrace/GetPss.h
copy to base/include/android-base/off64_t.h
index 787c33d..e6b71b8 100644
--- a/libbacktrace/GetPss.h
+++ b/base/include/android-base/off64_t.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#ifndef _LIBBACKTRACE_GET_PSS_H
-#define _LIBBACKTRACE_GET_PSS_H
+#pragma once
-size_t GetPssBytes();
-
-#endif // _LIBBACKTRACE_GET_PSS_H
+#if defined(__APPLE__)
+/** Mac OS has always had a 64-bit off_t, so it doesn't have off64_t. */
+typedef off_t off64_t;
+#endif
diff --git a/base/include/android-base/parseint.h b/base/include/android-base/parseint.h
index 9444fdd..be8b97b 100644
--- a/base/include/android-base/parseint.h
+++ b/base/include/android-base/parseint.h
@@ -22,6 +22,7 @@
#include <limits>
#include <string>
+#include <type_traits>
namespace android {
namespace base {
@@ -33,6 +34,7 @@
template <typename T>
bool ParseUint(const char* s, T* out, T max = std::numeric_limits<T>::max(),
bool allow_suffixes = false) {
+ static_assert(std::is_unsigned<T>::value, "ParseUint can only be used with unsigned types");
while (isspace(*s)) {
s++;
}
@@ -96,6 +98,7 @@
bool ParseInt(const char* s, T* out,
T min = std::numeric_limits<T>::min(),
T max = std::numeric_limits<T>::max()) {
+ static_assert(std::is_signed<T>::value, "ParseInt can only be used with signed types");
while (isspace(*s)) {
s++;
}
diff --git a/base/include/android-base/scopeguard.h b/base/include/android-base/scopeguard.h
index e6a9d10..5a224d6 100644
--- a/base/include/android-base/scopeguard.h
+++ b/base/include/android-base/scopeguard.h
@@ -28,7 +28,7 @@
public:
ScopeGuard(F&& f) : f_(std::forward<F>(f)), active_(true) {}
- ScopeGuard(ScopeGuard&& that) : f_(std::move(that.f_)), active_(that.active_) {
+ ScopeGuard(ScopeGuard&& that) noexcept : f_(std::move(that.f_)), active_(that.active_) {
that.active_ = false;
}
diff --git a/base/include/android-base/strings.h b/base/include/android-base/strings.h
index 9c35560..fc5c1ce 100644
--- a/base/include/android-base/strings.h
+++ b/base/include/android-base/strings.h
@@ -61,6 +61,7 @@
bool StartsWithIgnoreCase(const std::string& s, const char* prefix);
bool StartsWith(const std::string& s, const std::string& prefix);
bool StartsWithIgnoreCase(const std::string& s, const std::string& prefix);
+bool StartsWith(const std::string& s, char prefix);
// Tests whether 's' ends with 'suffix'.
// TODO: string_view
@@ -68,6 +69,7 @@
bool EndsWithIgnoreCase(const std::string& s, const char* suffix);
bool EndsWith(const std::string& s, const std::string& suffix);
bool EndsWithIgnoreCase(const std::string& s, const std::string& suffix);
+bool EndsWith(const std::string& s, char suffix);
// Tests whether 'lhs' equals 'rhs', ignoring case.
bool EqualsIgnoreCase(const std::string& lhs, const std::string& rhs);
diff --git a/base/include/android-base/test_utils.h b/base/include/android-base/test_utils.h
index 9e2ea97..b20f278 100644
--- a/base/include/android-base/test_utils.h
+++ b/base/include/android-base/test_utils.h
@@ -19,59 +19,26 @@
#include <regex>
#include <string>
+#include <android-base/file.h>
#include <android-base/macros.h>
-class TemporaryFile {
- public:
- TemporaryFile();
- explicit TemporaryFile(const std::string& tmp_dir);
- ~TemporaryFile();
-
- // Release the ownership of fd, caller is reponsible for closing the
- // fd or stream properly.
- int release();
- // Don't remove the temporary file in the destructor.
- void DoNotRemove() { remove_file_ = false; }
-
- int fd;
- char path[1024];
-
- private:
- void init(const std::string& tmp_dir);
-
- bool remove_file_ = true;
-
- DISALLOW_COPY_AND_ASSIGN(TemporaryFile);
-};
-
-class TemporaryDir {
- public:
- TemporaryDir();
- ~TemporaryDir();
-
- char path[1024];
-
- private:
- bool init(const std::string& tmp_dir);
-
- DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
-};
-
class CapturedStdFd {
public:
CapturedStdFd(int std_fd);
~CapturedStdFd();
- int fd() const;
std::string str();
- private:
- void Init();
+ void Start();
+ void Stop();
void Reset();
+ private:
+ int fd() const;
+
TemporaryFile temp_file_;
int std_fd_;
- int old_fd_;
+ int old_fd_ = -1;
DISALLOW_COPY_AND_ASSIGN(CapturedStdFd);
};
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index c6936f1..2c890b4 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -16,12 +16,15 @@
#pragma once
+#include <dirent.h>
#include <fcntl.h>
#if !defined(_WIN32)
+#include <dirent.h>
#include <sys/socket.h>
#endif
+#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
@@ -89,8 +92,8 @@
explicit unique_fd_impl(int fd) { reset(fd); }
~unique_fd_impl() { reset(); }
- unique_fd_impl(unique_fd_impl&& other) { reset(other.release()); }
- unique_fd_impl& operator=(unique_fd_impl&& s) {
+ unique_fd_impl(unique_fd_impl&& other) noexcept { reset(other.release()); }
+ unique_fd_impl& operator=(unique_fd_impl&& s) noexcept {
int fd = s.fd_;
s.fd_ = -1;
reset(fd, &s);
@@ -100,7 +103,7 @@
void reset(int new_value = -1) { reset(new_value, nullptr); }
int get() const { return fd_; }
- operator int() const { return get(); }
+ operator int() const { return get(); } // NOLINT
int release() __attribute__((warn_unused_result)) {
tag(fd_, this, nullptr);
@@ -158,22 +161,35 @@
// Inline functions, so that they can be used header-only.
template <typename Closer>
-inline bool Pipe(unique_fd_impl<Closer>* read, unique_fd_impl<Closer>* write) {
+inline bool Pipe(unique_fd_impl<Closer>* read, unique_fd_impl<Closer>* write,
+ int flags = O_CLOEXEC) {
int pipefd[2];
#if defined(__linux__)
- if (pipe2(pipefd, O_CLOEXEC) != 0) {
+ if (pipe2(pipefd, flags) != 0) {
return false;
}
#else // defined(__APPLE__)
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK)) {
+ return false;
+ }
if (pipe(pipefd) != 0) {
return false;
}
- if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) != 0 || fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) != 0) {
- close(pipefd[0]);
- close(pipefd[1]);
- return false;
+ if (flags & O_CLOEXEC) {
+ if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) != 0 || fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) != 0) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return false;
+ }
+ }
+ if (flags & O_NONBLOCK) {
+ if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) != 0 || fcntl(pipefd[1], F_SETFL, O_NONBLOCK) != 0) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return false;
+ }
}
#endif
@@ -199,6 +215,28 @@
return Socketpair(AF_UNIX, type, 0, left, right);
}
+// Using fdopen with unique_fd correctly is more annoying than it should be,
+// because fdopen doesn't close the file descriptor received upon failure.
+inline FILE* Fdopen(unique_fd&& ufd, const char* mode) {
+ int fd = ufd.release();
+ FILE* file = fdopen(fd, mode);
+ if (!file) {
+ close(fd);
+ }
+ return file;
+}
+
+// Using fdopendir with unique_fd correctly is more annoying than it should be,
+// because fdopen doesn't close the file descriptor received upon failure.
+inline DIR* Fdopendir(unique_fd&& ufd) {
+ int fd = ufd.release();
+ DIR* dir = fdopendir(fd);
+ if (dir == nullptr) {
+ close(fd);
+ }
+ return dir;
+}
+
#endif // !defined(_WIN32)
} // namespace base
@@ -207,3 +245,13 @@
template <typename T>
int close(const android::base::unique_fd_impl<T>&)
__attribute__((__unavailable__("close called on unique_fd")));
+
+template <typename T>
+FILE* fdopen(const android::base::unique_fd_impl<T>&, const char* mode)
+ __attribute__((__unavailable__("fdopen takes ownership of the fd passed in; either dup the "
+ "unique_fd, or use android::base::Fdopen to pass ownership")));
+
+template <typename T>
+DIR* fdopendir(const android::base::unique_fd_impl<T>&) __attribute__((
+ __unavailable__("fdopendir takes ownership of the fd passed in; either dup the "
+ "unique_fd, or use android::base::Fdopendir to pass ownership")));
diff --git a/base/include/android-base/utf8.h b/base/include/android-base/utf8.h
index 4b91623..1a414ec 100644
--- a/base/include/android-base/utf8.h
+++ b/base/include/android-base/utf8.h
@@ -17,6 +17,7 @@
#pragma once
#ifdef _WIN32
+#include <sys/types.h>
#include <string>
#else
// Bring in prototypes for standard APIs so that we can import them into the utf8 namespace.
diff --git a/base/logging.cpp b/base/logging.cpp
index d60d91d..f89168c 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -53,6 +53,7 @@
#include <unistd.h>
#endif
+#include <android-base/file.h>
#include <android-base/macros.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
@@ -71,14 +72,8 @@
static char progname[MAX_PATH] = {};
if (first) {
- CHAR longname[MAX_PATH];
- DWORD nchars = GetModuleFileNameA(nullptr, longname, arraysize(longname));
- if ((nchars >= arraysize(longname)) || (nchars == 0)) {
- // String truncation or some other error.
- strcpy(progname, "<unknown>");
- } else {
- strcpy(progname, basename(longname));
- }
+ snprintf(progname, sizeof(progname), "%s",
+ android::base::Basename(android::base::GetExecutablePath()).c_str());
first = false;
}
@@ -422,6 +417,14 @@
}
std::string msg(data_->ToString());
+ if (data_->GetSeverity() == FATAL) {
+#ifdef __ANDROID__
+ // Set the bionic abort message early to avoid liblog doing it
+ // with the individual lines, so that we get the whole message.
+ android_set_abort_message(msg.c_str());
+#endif
+ }
+
{
// Do the actual logging with the lock held.
std::lock_guard<std::mutex> lock(LoggingLock());
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 75b4ea0..3113fb4 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -206,10 +206,8 @@
}
#endif
-static void CheckMessage(CapturedStderr& cap, android::base::LogSeverity severity,
+static void CheckMessage(const std::string& output, android::base::LogSeverity severity,
const char* expected, const char* expected_tag = nullptr) {
- std::string output = cap.str();
-
// We can't usefully check the output of any of these on Windows because we
// don't have std::regex, but we can at least make sure we printed at least as
// many characters are in the log message.
@@ -231,20 +229,28 @@
#endif
}
+static void CheckMessage(CapturedStderr& cap, android::base::LogSeverity severity,
+ const char* expected, const char* expected_tag = nullptr) {
+ cap.Stop();
+ std::string output = cap.str();
+ return CheckMessage(output, severity, expected, expected_tag);
+}
-#define CHECK_LOG_STREAM_DISABLED(severity) \
- { \
+#define CHECK_LOG_STREAM_DISABLED(severity) \
+ { \
android::base::ScopedLogSeverity sls1(android::base::FATAL); \
- CapturedStderr cap1; \
- LOG_STREAM(severity) << "foo bar"; \
- ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
- } \
- { \
+ CapturedStderr cap1; \
+ LOG_STREAM(severity) << "foo bar"; \
+ cap1.Stop(); \
+ ASSERT_EQ("", cap1.str()); \
+ } \
+ { \
android::base::ScopedLogSeverity sls1(android::base::FATAL); \
- CapturedStderr cap1; \
- LOG_STREAM(::android::base::severity) << "foo bar"; \
- ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
- } \
+ CapturedStderr cap1; \
+ LOG_STREAM(::android::base::severity) << "foo bar"; \
+ cap1.Stop(); \
+ ASSERT_EQ("", cap1.str()); \
+ }
#define CHECK_LOG_STREAM_ENABLED(severity) \
{ \
@@ -265,7 +271,7 @@
}
TEST(logging, LOG_STREAM_FATAL_WITHOUT_ABORT_enabled) {
- CHECK_LOG_STREAM_ENABLED(FATAL_WITHOUT_ABORT);
+ ASSERT_NO_FATAL_FAILURE(CHECK_LOG_STREAM_ENABLED(FATAL_WITHOUT_ABORT));
}
TEST(logging, LOG_STREAM_ERROR_disabled) {
@@ -273,7 +279,7 @@
}
TEST(logging, LOG_STREAM_ERROR_enabled) {
- CHECK_LOG_STREAM_ENABLED(ERROR);
+ ASSERT_NO_FATAL_FAILURE(CHECK_LOG_STREAM_ENABLED(ERROR));
}
TEST(logging, LOG_STREAM_WARNING_disabled) {
@@ -281,7 +287,7 @@
}
TEST(logging, LOG_STREAM_WARNING_enabled) {
- CHECK_LOG_STREAM_ENABLED(WARNING);
+ ASSERT_NO_FATAL_FAILURE(CHECK_LOG_STREAM_ENABLED(WARNING));
}
TEST(logging, LOG_STREAM_INFO_disabled) {
@@ -289,7 +295,7 @@
}
TEST(logging, LOG_STREAM_INFO_enabled) {
- CHECK_LOG_STREAM_ENABLED(INFO);
+ ASSERT_NO_FATAL_FAILURE(CHECK_LOG_STREAM_ENABLED(INFO));
}
TEST(logging, LOG_STREAM_DEBUG_disabled) {
@@ -297,7 +303,7 @@
}
TEST(logging, LOG_STREAM_DEBUG_enabled) {
- CHECK_LOG_STREAM_ENABLED(DEBUG);
+ ASSERT_NO_FATAL_FAILURE(CHECK_LOG_STREAM_ENABLED(DEBUG));
}
TEST(logging, LOG_STREAM_VERBOSE_disabled) {
@@ -305,26 +311,27 @@
}
TEST(logging, LOG_STREAM_VERBOSE_enabled) {
- CHECK_LOG_STREAM_ENABLED(VERBOSE);
+ ASSERT_NO_FATAL_FAILURE(CHECK_LOG_STREAM_ENABLED(VERBOSE));
}
#undef CHECK_LOG_STREAM_DISABLED
#undef CHECK_LOG_STREAM_ENABLED
-
-#define CHECK_LOG_DISABLED(severity) \
- { \
+#define CHECK_LOG_DISABLED(severity) \
+ { \
android::base::ScopedLogSeverity sls1(android::base::FATAL); \
- CapturedStderr cap1; \
- LOG(severity) << "foo bar"; \
- ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
- } \
- { \
+ CapturedStderr cap1; \
+ LOG(severity) << "foo bar"; \
+ cap1.Stop(); \
+ ASSERT_EQ("", cap1.str()); \
+ } \
+ { \
android::base::ScopedLogSeverity sls1(android::base::FATAL); \
- CapturedStderr cap1; \
- LOG(::android::base::severity) << "foo bar"; \
- ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
- } \
+ CapturedStderr cap1; \
+ LOG(::android::base::severity) << "foo bar"; \
+ cap1.Stop(); \
+ ASSERT_EQ("", cap1.str()); \
+ }
#define CHECK_LOG_ENABLED(severity) \
{ \
@@ -350,7 +357,7 @@
}
TEST(logging, LOG_FATAL_WITHOUT_ABORT_enabled) {
- CHECK_LOG_ENABLED(FATAL_WITHOUT_ABORT);
+ ASSERT_NO_FATAL_FAILURE(CHECK_LOG_ENABLED(FATAL_WITHOUT_ABORT));
}
TEST(logging, LOG_ERROR_disabled) {
@@ -358,7 +365,7 @@
}
TEST(logging, LOG_ERROR_enabled) {
- CHECK_LOG_ENABLED(ERROR);
+ ASSERT_NO_FATAL_FAILURE(CHECK_LOG_ENABLED(ERROR));
}
TEST(logging, LOG_WARNING_disabled) {
@@ -366,7 +373,7 @@
}
TEST(logging, LOG_WARNING_enabled) {
- CHECK_LOG_ENABLED(WARNING);
+ ASSERT_NO_FATAL_FAILURE(CHECK_LOG_ENABLED(WARNING));
}
TEST(logging, LOG_INFO_disabled) {
@@ -374,7 +381,7 @@
}
TEST(logging, LOG_INFO_enabled) {
- CHECK_LOG_ENABLED(INFO);
+ ASSERT_NO_FATAL_FAILURE(CHECK_LOG_ENABLED(INFO));
}
TEST(logging, LOG_DEBUG_disabled) {
@@ -382,7 +389,7 @@
}
TEST(logging, LOG_DEBUG_enabled) {
- CHECK_LOG_ENABLED(DEBUG);
+ ASSERT_NO_FATAL_FAILURE(CHECK_LOG_ENABLED(DEBUG));
}
TEST(logging, LOG_VERBOSE_disabled) {
@@ -390,28 +397,28 @@
}
TEST(logging, LOG_VERBOSE_enabled) {
- CHECK_LOG_ENABLED(VERBOSE);
+ ASSERT_NO_FATAL_FAILURE(CHECK_LOG_ENABLED(VERBOSE));
}
#undef CHECK_LOG_DISABLED
#undef CHECK_LOG_ENABLED
-
TEST(logging, LOG_complex_param) {
-#define CHECK_LOG_COMBINATION(use_scoped_log_severity_info, use_logging_severity_info) \
- { \
- android::base::ScopedLogSeverity sls( \
- (use_scoped_log_severity_info) ? ::android::base::INFO : ::android::base::WARNING); \
- CapturedStderr cap; \
- LOG((use_logging_severity_info) ? ::android::base::INFO : ::android::base::WARNING) \
- << "foobar"; \
- if ((use_scoped_log_severity_info) || !(use_logging_severity_info)) { \
- CheckMessage(cap, \
- (use_logging_severity_info) ? ::android::base::INFO : ::android::base::WARNING, \
- "foobar"); \
- } else { \
- ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_CUR)); \
- } \
+#define CHECK_LOG_COMBINATION(use_scoped_log_severity_info, use_logging_severity_info) \
+ { \
+ android::base::ScopedLogSeverity sls( \
+ (use_scoped_log_severity_info) ? ::android::base::INFO : ::android::base::WARNING); \
+ CapturedStderr cap; \
+ LOG((use_logging_severity_info) ? ::android::base::INFO : ::android::base::WARNING) \
+ << "foobar"; \
+ if ((use_scoped_log_severity_info) || !(use_logging_severity_info)) { \
+ ASSERT_NO_FATAL_FAILURE(CheckMessage( \
+ cap, (use_logging_severity_info) ? ::android::base::INFO : ::android::base::WARNING, \
+ "foobar")); \
+ } else { \
+ cap.Stop(); \
+ ASSERT_EQ("", cap.str()); \
+ } \
}
CHECK_LOG_COMBINATION(false,false);
@@ -429,7 +436,7 @@
LOG(INFO) << (errno = 67890);
EXPECT_EQ(12345, errno) << "errno was not restored";
- CheckMessage(cap, android::base::INFO, "67890");
+ ASSERT_NO_FATAL_FAILURE(CheckMessage(cap, android::base::INFO, "67890"));
}
TEST(logging, PLOG_does_not_clobber_errno) {
@@ -438,7 +445,7 @@
PLOG(INFO) << (errno = 67890);
EXPECT_EQ(12345, errno) << "errno was not restored";
- CheckMessage(cap, android::base::INFO, "67890");
+ ASSERT_NO_FATAL_FAILURE(CheckMessage(cap, android::base::INFO, "67890"));
}
TEST(logging, LOG_does_not_have_dangling_if) {
@@ -464,19 +471,21 @@
EXPECT_FALSE(flag) << "LOG macro probably has a dangling if with no else";
}
-#define CHECK_PLOG_DISABLED(severity) \
- { \
+#define CHECK_PLOG_DISABLED(severity) \
+ { \
android::base::ScopedLogSeverity sls1(android::base::FATAL); \
- CapturedStderr cap1; \
- PLOG(severity) << "foo bar"; \
- ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
- } \
- { \
+ CapturedStderr cap1; \
+ PLOG(severity) << "foo bar"; \
+ cap1.Stop(); \
+ ASSERT_EQ("", cap1.str()); \
+ } \
+ { \
android::base::ScopedLogSeverity sls1(android::base::FATAL); \
- CapturedStderr cap1; \
- PLOG(severity) << "foo bar"; \
- ASSERT_EQ(0, lseek(cap1.fd(), 0, SEEK_CUR)); \
- } \
+ CapturedStderr cap1; \
+ PLOG(severity) << "foo bar"; \
+ cap1.Stop(); \
+ ASSERT_EQ("", cap1.str()); \
+ }
#define CHECK_PLOG_ENABLED(severity) \
{ \
@@ -504,7 +513,7 @@
}
TEST(logging, PLOG_FATAL_WITHOUT_ABORT_enabled) {
- CHECK_PLOG_ENABLED(FATAL_WITHOUT_ABORT);
+ ASSERT_NO_FATAL_FAILURE(CHECK_PLOG_ENABLED(FATAL_WITHOUT_ABORT));
}
TEST(logging, PLOG_ERROR_disabled) {
@@ -512,7 +521,7 @@
}
TEST(logging, PLOG_ERROR_enabled) {
- CHECK_PLOG_ENABLED(ERROR);
+ ASSERT_NO_FATAL_FAILURE(CHECK_PLOG_ENABLED(ERROR));
}
TEST(logging, PLOG_WARNING_disabled) {
@@ -520,7 +529,7 @@
}
TEST(logging, PLOG_WARNING_enabled) {
- CHECK_PLOG_ENABLED(WARNING);
+ ASSERT_NO_FATAL_FAILURE(CHECK_PLOG_ENABLED(WARNING));
}
TEST(logging, PLOG_INFO_disabled) {
@@ -528,7 +537,7 @@
}
TEST(logging, PLOG_INFO_enabled) {
- CHECK_PLOG_ENABLED(INFO);
+ ASSERT_NO_FATAL_FAILURE(CHECK_PLOG_ENABLED(INFO));
}
TEST(logging, PLOG_DEBUG_disabled) {
@@ -536,7 +545,7 @@
}
TEST(logging, PLOG_DEBUG_enabled) {
- CHECK_PLOG_ENABLED(DEBUG);
+ ASSERT_NO_FATAL_FAILURE(CHECK_PLOG_ENABLED(DEBUG));
}
TEST(logging, PLOG_VERBOSE_disabled) {
@@ -544,7 +553,7 @@
}
TEST(logging, PLOG_VERBOSE_enabled) {
- CHECK_PLOG_ENABLED(VERBOSE);
+ ASSERT_NO_FATAL_FAILURE(CHECK_PLOG_ENABLED(VERBOSE));
}
#undef CHECK_PLOG_DISABLED
@@ -557,7 +566,7 @@
CapturedStderr cap;
errno = ENOENT;
UNIMPLEMENTED(ERROR);
- CheckMessage(cap, android::base::ERROR, expected.c_str());
+ ASSERT_NO_FATAL_FAILURE(CheckMessage(cap, android::base::ERROR, expected.c_str()));
}
static void NoopAborter(const char* msg ATTRIBUTE_UNUSED) {
@@ -565,17 +574,19 @@
}
TEST(logging, LOG_FATAL_NOOP_ABORTER) {
+ CapturedStderr cap;
{
android::base::SetAborter(NoopAborter);
android::base::ScopedLogSeverity sls(android::base::ERROR);
- CapturedStderr cap;
LOG(FATAL) << "foobar";
- CheckMessage(cap, android::base::FATAL, "foobar");
- CheckMessage(cap, android::base::ERROR, "called noop");
+ cap.Stop();
android::base::SetAborter(android::base::DefaultAborter);
}
+ std::string output = cap.str();
+ ASSERT_NO_FATAL_FAILURE(CheckMessage(output, android::base::FATAL, "foobar"));
+ ASSERT_NO_FATAL_FAILURE(CheckMessage(output, android::base::ERROR, "called noop"));
ASSERT_DEATH({SuppressAbortUI(); LOG(FATAL) << "foobar";}, "foobar");
}
@@ -619,25 +630,21 @@
LOG(INFO) << expected_msg;
android::base::SetDefaultTag(old_default_tag);
}
- CheckMessage(cap, android::base::LogSeverity::INFO, expected_msg, expected_tag);
+ ASSERT_NO_FATAL_FAILURE(
+ CheckMessage(cap, android::base::LogSeverity::INFO, expected_msg, expected_tag));
}
TEST(logging, StdioLogger) {
- std::string err_str;
- std::string out_str;
- {
- CapturedStderr cap_err;
- CapturedStdout cap_out;
- android::base::SetLogger(android::base::StdioLogger);
- LOG(INFO) << "out";
- LOG(ERROR) << "err";
- err_str = cap_err.str();
- out_str = cap_out.str();
- }
+ CapturedStderr cap_err;
+ CapturedStdout cap_out;
+ android::base::SetLogger(android::base::StdioLogger);
+ LOG(INFO) << "out";
+ LOG(ERROR) << "err";
+ cap_err.Stop();
+ cap_out.Stop();
// For INFO we expect just the literal "out\n".
- ASSERT_EQ("out\n", out_str) << out_str;
+ ASSERT_EQ("out\n", cap_out.str());
// Whereas ERROR logging includes the program name.
- ASSERT_EQ(android::base::Basename(android::base::GetExecutablePath()) + ": err\n", err_str)
- << err_str;
+ ASSERT_EQ(android::base::Basename(android::base::GetExecutablePath()) + ": err\n", cap_err.str());
}
diff --git a/base/mapped_file.cpp b/base/mapped_file.cpp
new file mode 100644
index 0000000..f7901af
--- /dev/null
+++ b/base/mapped_file.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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/mapped_file.h"
+
+namespace android {
+namespace base {
+
+static off64_t InitPageSize() {
+#if defined(_WIN32)
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return si.dwAllocationGranularity;
+#else
+ return sysconf(_SC_PAGE_SIZE);
+#endif
+}
+
+std::unique_ptr<MappedFile> MappedFile::FromFd(int fd, off64_t offset, size_t length, int prot) {
+ static 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);
+ if (handle == nullptr) return nullptr;
+ void* base = MapViewOfFile(handle, (prot & PROT_WRITE) ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ, 0,
+ file_offset, file_length);
+ if (base == nullptr) {
+ CloseHandle(handle);
+ return nullptr;
+ }
+ return std::unique_ptr<MappedFile>(
+ new MappedFile{static_cast<char*>(base), length, slop, handle});
+#else
+ void* base = mmap(nullptr, file_length, prot, MAP_SHARED, fd, file_offset);
+ if (base == MAP_FAILED) return nullptr;
+ return std::unique_ptr<MappedFile>(new MappedFile{static_cast<char*>(base), length, slop});
+#endif
+}
+
+MappedFile::~MappedFile() {
+#if defined(_WIN32)
+ if (base_ != nullptr) UnmapViewOfFile(base_);
+ if (handle_ != nullptr) CloseHandle(handle_);
+#else
+ if (base_ != nullptr) munmap(base_, size_);
+#endif
+
+ base_ = nullptr;
+ offset_ = size_ = 0;
+}
+
+} // namespace base
+} // namespace android
diff --git a/base/mapped_file_test.cpp b/base/mapped_file_test.cpp
new file mode 100644
index 0000000..7e89723
--- /dev/null
+++ b/base/mapped_file_test.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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/mapped_file.h"
+
+#include <gtest/gtest.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "android-base/file.h"
+#include "android-base/unique_fd.h"
+
+TEST(mapped_file, smoke) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ ASSERT_TRUE(android::base::WriteStringToFd("hello world", tf.fd));
+
+ auto m = android::base::MappedFile::FromFd(tf.fd, 3, 2, PROT_READ);
+ ASSERT_EQ(2u, m->size());
+ ASSERT_EQ('l', m->data()[0]);
+ ASSERT_EQ('o', m->data()[1]);
+}
diff --git a/base/strings.cpp b/base/strings.cpp
index a8bb2a9..2d6eef0 100644
--- a/base/strings.cpp
+++ b/base/strings.cpp
@@ -95,6 +95,10 @@
return strncmp(s.c_str(), prefix.c_str(), prefix.size()) == 0;
}
+bool StartsWith(const std::string& s, char prefix) {
+ return *s.c_str() == prefix; // Use c_str() to guarantee there is at least a '\0'.
+}
+
bool StartsWithIgnoreCase(const std::string& s, const char* prefix) {
return strncasecmp(s.c_str(), prefix, strlen(prefix)) == 0;
}
@@ -121,6 +125,10 @@
return EndsWith(s, suffix.c_str(), suffix.size(), true);
}
+bool EndsWith(const std::string& s, char suffix) {
+ return EndsWith(s, &suffix, 1, true);
+}
+
bool EndsWithIgnoreCase(const std::string& s, const char* suffix) {
return EndsWith(s, suffix, strlen(suffix), false);
}
diff --git a/base/strings_test.cpp b/base/strings_test.cpp
index b8639ea..9d74094 100644
--- a/base/strings_test.cpp
+++ b/base/strings_test.cpp
@@ -198,6 +198,12 @@
ASSERT_FALSE(android::base::StartsWithIgnoreCase("foobar", "BAR"));
}
+TEST(strings, StartsWith_char) {
+ ASSERT_FALSE(android::base::StartsWith("", 'f'));
+ ASSERT_TRUE(android::base::StartsWith("foo", 'f'));
+ ASSERT_FALSE(android::base::StartsWith("foo", 'o'));
+}
+
TEST(strings, EndsWith_empty) {
ASSERT_FALSE(android::base::EndsWith("", "foo"));
ASSERT_TRUE(android::base::EndsWith("", ""));
@@ -273,6 +279,12 @@
ASSERT_FALSE(android::base::EndsWithIgnoreCase("GoOdByE", std::string{"lo"}));
}
+TEST(strings, EndsWith_char) {
+ ASSERT_FALSE(android::base::EndsWith("", 'o'));
+ ASSERT_TRUE(android::base::EndsWith("foo", 'o'));
+ ASSERT_FALSE(android::base::EndsWith("foo", "f"));
+}
+
TEST(strings, EqualsIgnoreCase) {
ASSERT_TRUE(android::base::EqualsIgnoreCase("foo", "FOO"));
ASSERT_TRUE(android::base::EqualsIgnoreCase("FOO", "foo"));
diff --git a/base/test_utils.cpp b/base/test_utils.cpp
index 5096369..36b4cdf 100644
--- a/base/test_utils.cpp
+++ b/base/test_utils.cpp
@@ -22,115 +22,19 @@
#include <sys/stat.h>
#include <unistd.h>
-#if defined(_WIN32)
-#include <windows.h>
-#include <direct.h>
-#define OS_PATH_SEPARATOR '\\'
-#else
-#define OS_PATH_SEPARATOR '/'
-#endif
-
#include <string>
#include <android-base/file.h>
#include <android-base/logging.h>
-#ifdef _WIN32
-int mkstemp(char* template_name) {
- if (_mktemp(template_name) == nullptr) {
- 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);
-}
-
-char* mkdtemp(char* template_name) {
- if (_mktemp(template_name) == nullptr) {
- return nullptr;
- }
- if (_mkdir(template_name) == -1) {
- return nullptr;
- }
- return template_name;
-}
-#endif
-
-static std::string GetSystemTempDir() {
-#if defined(__ANDROID__)
- const char* tmpdir = "/data/local/tmp";
- if (access(tmpdir, R_OK | W_OK | X_OK) == 0) {
- return tmpdir;
- }
- // Tests running in app context can't access /data/local/tmp,
- // 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);
- CHECK_NE(result, 0ul) << "GetTempPathA failed, error: " << GetLastError();
- CHECK_LT(result, sizeof(tmp_dir)) << "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';
- return tmp_dir;
-#else
- return "/tmp";
-#endif
-}
-
-TemporaryFile::TemporaryFile() {
- init(GetSystemTempDir());
-}
-
-TemporaryFile::TemporaryFile(const std::string& tmp_dir) {
- init(tmp_dir);
-}
-
-TemporaryFile::~TemporaryFile() {
- if (fd != -1) {
- close(fd);
- }
- if (remove_file_) {
- unlink(path);
- }
-}
-
-int TemporaryFile::release() {
- int result = fd;
- fd = -1;
- return result;
-}
-
-void TemporaryFile::init(const std::string& tmp_dir) {
- snprintf(path, sizeof(path), "%s%cTemporaryFile-XXXXXX", tmp_dir.c_str(),
- OS_PATH_SEPARATOR);
- fd = mkstemp(path);
-}
-
-TemporaryDir::TemporaryDir() {
- init(GetSystemTempDir());
-}
-
-TemporaryDir::~TemporaryDir() {
- rmdir(path);
-}
-
-bool TemporaryDir::init(const std::string& tmp_dir) {
- snprintf(path, sizeof(path), "%s%cTemporaryDir-XXXXXX", tmp_dir.c_str(),
- OS_PATH_SEPARATOR);
- return (mkdtemp(path) != nullptr);
-}
-
CapturedStdFd::CapturedStdFd(int std_fd) : std_fd_(std_fd), old_fd_(-1) {
- Init();
+ Start();
}
CapturedStdFd::~CapturedStdFd() {
- Reset();
+ if (old_fd_ != -1) {
+ Stop();
+ }
}
int CapturedStdFd::fd() const {
@@ -144,19 +48,28 @@
return result;
}
-void CapturedStdFd::Init() {
+void CapturedStdFd::Reset() {
+ // Do not reset while capturing.
+ CHECK_EQ(-1, old_fd_);
+ CHECK_EQ(0, TEMP_FAILURE_RETRY(lseek(fd(), 0, SEEK_SET)));
+ CHECK_EQ(0, ftruncate(fd(), 0));
+}
+
+void CapturedStdFd::Start() {
#if defined(_WIN32)
// On Windows, stderr is often buffered, so make sure it is unbuffered so
// that we can immediately read back what was written to stderr.
- if (std_fd_ == STDERR_FILENO) CHECK_EQ(0, setvbuf(stderr, NULL, _IONBF, 0));
+ if (std_fd_ == STDERR_FILENO) CHECK_EQ(0, setvbuf(stderr, nullptr, _IONBF, 0));
#endif
old_fd_ = dup(std_fd_);
CHECK_NE(-1, old_fd_);
CHECK_NE(-1, dup2(fd(), std_fd_));
}
-void CapturedStdFd::Reset() {
+void CapturedStdFd::Stop() {
+ CHECK_NE(-1, old_fd_);
CHECK_NE(-1, dup2(old_fd_, std_fd_));
- CHECK_EQ(0, close(old_fd_));
+ close(old_fd_);
+ old_fd_ = -1;
// Note: cannot restore prior setvbuf() setting.
}
diff --git a/base/test_utils_test.cpp b/base/test_utils_test.cpp
index 597271a..15a79dd 100644
--- a/base/test_utils_test.cpp
+++ b/base/test_utils_test.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <stdio.h>
+
#include "android-base/test_utils.h"
#include <gtest/gtest-spi.h>
@@ -42,5 +44,43 @@
EXPECT_NONFATAL_FAILURE(EXPECT_NOT_MATCH("foobar", R"(foobar)"), "regex mismatch");
}
+TEST(TestUtilsTest, CaptureStdout_smoke) {
+ CapturedStdout cap;
+ printf("This should be captured.\n");
+ cap.Stop();
+ printf("This will not be captured.\n");
+ ASSERT_EQ("This should be captured.\n", cap.str());
+
+ cap.Start();
+ printf("And this text should be captured too.\n");
+ cap.Stop();
+ ASSERT_EQ("This should be captured.\nAnd this text should be captured too.\n", cap.str());
+
+ printf("Still not going to be captured.\n");
+ cap.Reset();
+ cap.Start();
+ printf("Only this will be captured.\n");
+ ASSERT_EQ("Only this will be captured.\n", cap.str());
+}
+
+TEST(TestUtilsTest, CaptureStderr_smoke) {
+ CapturedStderr cap;
+ fprintf(stderr, "This should be captured.\n");
+ cap.Stop();
+ fprintf(stderr, "This will not be captured.\n");
+ ASSERT_EQ("This should be captured.\n", cap.str());
+
+ cap.Start();
+ fprintf(stderr, "And this text should be captured too.\n");
+ cap.Stop();
+ ASSERT_EQ("This should be captured.\nAnd this text should be captured too.\n", cap.str());
+
+ fprintf(stderr, "Still not going to be captured.\n");
+ cap.Reset();
+ cap.Start();
+ fprintf(stderr, "Only this will be captured.\n");
+ ASSERT_EQ("Only this will be captured.\n", cap.str());
+}
+
} // namespace base
} // namespace android
diff --git a/base/utf8_test.cpp b/base/utf8_test.cpp
index fcb25c3..472e82c 100644
--- a/base/utf8_test.cpp
+++ b/base/utf8_test.cpp
@@ -21,8 +21,8 @@
#include <fcntl.h>
#include <stdlib.h>
+#include "android-base/file.h"
#include "android-base/macros.h"
-#include "android-base/test_utils.h"
#include "android-base/unique_fd.h"
namespace android {
diff --git a/bootstat/boot_event_record_store_test.cpp b/bootstat/boot_event_record_store_test.cpp
index 4b7ab36..5ca9b09 100644
--- a/bootstat/boot_event_record_store_test.cpp
+++ b/bootstat/boot_event_record_store_test.cpp
@@ -29,7 +29,6 @@
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
-#include <android-base/test_utils.h>
#include <android-base/unique_fd.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index c17e00f..6700b6c 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -236,7 +236,7 @@
{"reboot,rescueparty", 90},
{"charge", 91},
{"oem_tz_crash", 92},
- {"uvlo", 93},
+ {"uvlo", 93}, // aliasReasons converts to reboot,undervoltage
{"oem_ps_hold", 94},
{"abnormal_reset", 95},
{"oemerr_unknown", 96},
@@ -248,9 +248,9 @@
{"watchdog_nonsec", 102},
{"watchdog_apps_bark", 103},
{"reboot_dmverity_corrupted", 104},
- {"reboot_smpl", 105},
+ {"reboot_smpl", 105}, // aliasReasons converts to reboot,powerloss
{"watchdog_sdi_apps_reset", 106},
- {"smpl", 107},
+ {"smpl", 107}, // aliasReasons converts to reboot,powerloss
{"oem_modem_failed_to_powerup", 108},
{"reboot_normal", 109},
{"oem_lpass_cfg", 110},
@@ -262,8 +262,8 @@
{"oem_rpm_undef_error", 116},
{"oem_crash_on_the_lk", 117},
{"oem_rpm_reset", 118},
- {"REUSE1", 119}, // Former dupe, can be re-used
- {"REUSE2", 120}, // Former dupe, can be re-used
+ {"reboot,powerloss", 119},
+ {"reboot,undervoltage", 120},
{"factory_cable", 121},
{"oem_ar6320_failed_to_powerup", 122},
{"watchdog_rpm_bite", 123},
@@ -840,6 +840,8 @@
{"reboot,tool", "tool_by_pass_pwk"},
{"!reboot,longkey", "reboot_longkey"},
{"!reboot,longkey", "kpdpwr"},
+ {"!reboot,undervoltage", "uvlo"},
+ {"!reboot,powerloss", "smpl"},
{"bootloader", ""},
};
diff --git a/cpio/Android.bp b/cpio/Android.bp
new file mode 100644
index 0000000..baa0319
--- /dev/null
+++ b/cpio/Android.bp
@@ -0,0 +1,11 @@
+// Copyright 2005 The Android Open Source Project
+
+cc_binary_host {
+ name: "mkbootfs",
+ srcs: ["mkbootfs.c"],
+ cflags: ["-Werror"],
+ shared_libs: ["libcutils"],
+ dist: {
+ targets: ["dist_files"],
+ },
+}
diff --git a/cpio/Android.mk b/cpio/Android.mk
deleted file mode 100644
index 2aa7297..0000000
--- a/cpio/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- mkbootfs.c
-
-LOCAL_MODULE := mkbootfs
-
-LOCAL_CFLAGS := -Werror
-
-LOCAL_SHARED_LIBRARIES := libcutils
-
-include $(BUILD_HOST_EXECUTABLE)
-
-$(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE))
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 03b3287..10f52f4 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -9,7 +9,6 @@
"-Wno-nullability-completeness",
"-Os",
],
- cpp_std: "gnu++17",
local_include_dirs: ["include"],
}
@@ -117,14 +116,21 @@
"libdebuggerd",
"libbacktrace",
"libunwindstack",
- "libdexfile",
+ "libdexfile", // libunwindstack dependency
+ "libdexfile_external", // libunwindstack dependency
+ "libdexfile_support", // libunwindstack dependency
"liblzma",
"libcutils",
],
target: {
recovery: {
cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
- exclude_static_libs: ["libdexfile"],
+ exclude_static_libs: [
+ "libartbase",
+ "libdexfile",
+ "libdexfile_external",
+ "libdexfile_support",
+ ],
},
},
@@ -144,6 +150,7 @@
shared_libs: [
"libbase",
"libcutils",
+ "libprocinfo",
],
export_header_lib_headers: ["libdebuggerd_common_headers"],
@@ -171,12 +178,22 @@
static_libs: [
"libbacktrace",
+ "libdexfile_external", // libunwindstack dependency
+ "libdexfile_support", // libunwindstack dependency
"libunwindstack",
"liblzma",
"libbase",
"libcutils",
"liblog",
],
+ target: {
+ recovery: {
+ exclude_static_libs: [
+ "libdexfile_external",
+ "libdexfile_support",
+ ],
+ },
+ },
}
cc_test {
@@ -217,6 +234,8 @@
static_libs: [
"libdebuggerd",
+ "libdexfile_external", // libunwindstack dependency
+ "libdexfile_support", // libunwindstack dependency
"libunwindstack",
],
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index cb7cbbe..610b96b 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -33,6 +33,7 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <cutils/sockets.h>
+#include <procinfo/process.h>
#include "debuggerd/handler.h"
#include "protocol.h"
@@ -62,8 +63,20 @@
tv->tv_usec = static_cast<long>(microseconds.count());
}
-bool debuggerd_trigger_dump(pid_t pid, DebuggerdDumpType dump_type, unsigned int timeout_ms,
+bool debuggerd_trigger_dump(pid_t tid, DebuggerdDumpType dump_type, unsigned int timeout_ms,
unique_fd output_fd) {
+ pid_t pid = tid;
+ if (dump_type == kDebuggerdJavaBacktrace) {
+ // Java dumps always get sent to the tgid, so we need to resolve our tid to a tgid.
+ android::procinfo::ProcessInfo procinfo;
+ std::string error;
+ if (!android::procinfo::GetProcessInfo(tid, &procinfo, &error)) {
+ LOG(ERROR) << "libdebugged_client: failed to get process info: " << error;
+ return false;
+ }
+ pid = procinfo.pid;
+ }
+
LOG(INFO) << "libdebuggerd_client: started dumping process " << pid;
unique_fd sockfd;
const auto end = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeout_ms);
@@ -143,12 +156,16 @@
ssize_t rc =
TEMP_FAILURE_RETRY(recv(set_timeout(sockfd.get()), &response, sizeof(response), MSG_TRUNC));
if (rc == 0) {
- LOG(ERROR) << "libdebuggerd_client: failed to read response from tombstoned: timeout reached?";
+ LOG(ERROR) << "libdebuggerd_client: failed to read initial response from tombstoned: "
+ << "timeout reached?";
+ return false;
+ } else if (rc == -1) {
+ PLOG(ERROR) << "libdebuggerd_client: failed to read initial response from tombstoned";
return false;
} else if (rc != sizeof(response)) {
- LOG(ERROR)
- << "libdebuggerd_client: received packet of unexpected length from tombstoned: expected "
- << sizeof(response) << ", received " << rc;
+ LOG(ERROR) << "libdebuggerd_client: received packet of unexpected length from tombstoned while "
+ "reading initial response: expected "
+ << sizeof(response) << ", received " << rc;
return false;
}
@@ -158,18 +175,22 @@
return false;
}
- if (!send_signal(pid, dump_type)) {
+ if (!send_signal(tid, dump_type)) {
return false;
}
rc = TEMP_FAILURE_RETRY(recv(set_timeout(sockfd.get()), &response, sizeof(response), MSG_TRUNC));
if (rc == 0) {
- LOG(ERROR) << "libdebuggerd_client: failed to read response from tombstoned: timeout reached?";
+ LOG(ERROR) << "libdebuggerd_client: failed to read status response from tombstoned: "
+ "timeout reached?";
+ return false;
+ } else if (rc == -1) {
+ PLOG(ERROR) << "libdebuggerd_client: failed to read status response from tombstoned";
return false;
} else if (rc != sizeof(response)) {
- LOG(ERROR)
- << "libdebuggerd_client: received packet of unexpected length from tombstoned: expected "
- << sizeof(response) << ", received " << rc;
+ LOG(ERROR) << "libdebuggerd_client: received packet of unexpected length from tombstoned while "
+ "reading confirmation response: expected "
+ << sizeof(response) << ", received " << rc;
return false;
}
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 93f7572..d79d20b 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -34,6 +34,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/macros.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
@@ -282,6 +283,7 @@
switch (crash_info->header.version) {
case 2:
*fdsan_table_address = crash_info->data.v2.fdsan_table_address;
+ FALLTHROUGH_INTENDED;
case 1:
*abort_msg_address = crash_info->data.v1.abort_msg_address;
*siginfo = crash_info->data.v1.siginfo;
@@ -346,8 +348,16 @@
return vm_pid;
}
+static void InstallSigPipeHandler() {
+ struct sigaction action = {};
+ action.sa_handler = SIG_IGN;
+ action.sa_flags = SA_RESTART;
+ sigaction(SIGPIPE, &action, nullptr);
+}
+
int main(int argc, char** argv) {
DefuseSignalHandlers();
+ InstallSigPipeHandler();
atrace_begin(ATRACE_TAG, "before reparent");
pid_t target_process = getppid();
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index f0fe1d0..f0bdfbf 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -224,7 +224,7 @@
// Prefixes.
if (!strncmp(arg, "wait-", strlen("wait-"))) {
char buf[1];
- TEMP_FAILURE_RETRY(read(STDIN_FILENO, buf, sizeof(buf)));
+ UNUSED(TEMP_FAILURE_RETRY(read(STDIN_FILENO, buf, sizeof(buf))));
return do_action(arg + strlen("wait-"));
} else if (!strncmp(arg, "exhaustfd-", strlen("exhaustfd-"))) {
errno = 0;
@@ -258,10 +258,14 @@
__assert("some_file.c", 123, "false");
} else if (!strcasecmp(arg, "assert2")) {
__assert2("some_file.c", 123, "some_function", "false");
+#if !defined(__clang_analyzer__)
} else if (!strcasecmp(arg, "fortify")) {
+ // FORTIFY is disabled when running clang-tidy and other tools, so this
+ // shouldn't depend on internal implementation details of it.
char buf[10];
__read_chk(-1, buf, 32, 10);
while (true) pause();
+#endif
} else if (!strcasecmp(arg, "fdsan_file")) {
FILE* f = fopen("/dev/null", "r");
close(fileno(f));
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index e2ea480..bea8b43 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -37,6 +37,7 @@
#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 <android-base/test_utils.h>
#include <android-base/unique_fd.h>
@@ -587,9 +588,28 @@
"/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy";
static pid_t seccomp_fork_impl(void (*prejail)()) {
- unique_fd policy_fd(open(kDebuggerdSeccompPolicy, O_RDONLY | O_CLOEXEC));
- if (policy_fd == -1) {
- LOG(FATAL) << "failed to open policy " << kDebuggerdSeccompPolicy;
+ std::string policy;
+ if (!android::base::ReadFileToString(kDebuggerdSeccompPolicy, &policy)) {
+ PLOG(FATAL) << "failed to read policy file";
+ }
+
+ // Allow a bunch of syscalls used by the tests.
+ policy += "\nclone: 1";
+ policy += "\nsigaltstack: 1";
+ policy += "\nnanosleep: 1";
+
+ FILE* tmp_file = tmpfile();
+ if (!tmp_file) {
+ PLOG(FATAL) << "tmpfile failed";
+ }
+
+ unique_fd tmp_fd(dup(fileno(tmp_file)));
+ if (!android::base::WriteStringToFd(policy, tmp_fd.get())) {
+ PLOG(FATAL) << "failed to write policy to tmpfile";
+ }
+
+ if (lseek(tmp_fd.get(), 0, SEEK_SET) != 0) {
+ PLOG(FATAL) << "failed to seek tmp_fd";
}
ScopedMinijail jail{minijail_new()};
@@ -600,7 +620,7 @@
minijail_no_new_privs(jail.get());
minijail_log_seccomp_filter_failures(jail.get());
minijail_use_seccomp_filter(jail.get());
- minijail_parse_seccomp_filters_from_fd(jail.get(), policy_fd.release());
+ minijail_parse_seccomp_filters_from_fd(jail.get(), tmp_fd.release());
pid_t result = fork();
if (result == -1) {
@@ -735,6 +755,16 @@
ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
}
+extern "C" void foo() {
+ LOG(INFO) << "foo";
+ std::this_thread::sleep_for(1s);
+}
+
+extern "C" void bar() {
+ LOG(INFO) << "bar";
+ std::this_thread::sleep_for(1s);
+}
+
TEST_F(CrasherTest, seccomp_backtrace) {
int intercept_result;
unique_fd output_fd;
@@ -742,6 +772,11 @@
static const auto dump_type = kDebuggerdNativeBacktrace;
StartProcess(
[]() {
+ std::thread a(foo);
+ std::thread b(bar);
+
+ std::this_thread::sleep_for(100ms);
+
raise_debugger_signal(dump_type);
_exit(0);
},
@@ -756,6 +791,8 @@
std::string result;
ConsumeFd(std::move(output_fd), &result);
ASSERT_BACKTRACE_FRAME(result, "raise_debugger_signal");
+ ASSERT_BACKTRACE_FRAME(result, "foo");
+ ASSERT_BACKTRACE_FRAME(result, "bar");
}
TEST_F(CrasherTest, seccomp_crash_logcat) {
@@ -1017,3 +1054,42 @@
ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf)));
ASSERT_STREQ("any", outbuf);
}
+
+TEST(tombstoned, interceptless_backtrace) {
+ // Generate 50 backtraces, and then check to see that we haven't created 50 new tombstones.
+ auto get_tombstone_timestamps = []() -> std::map<int, time_t> {
+ std::map<int, time_t> result;
+ for (int i = 0; i < 99; ++i) {
+ std::string path = android::base::StringPrintf("/data/tombstones/tombstone_%02d", i);
+ struct stat st;
+ if (stat(path.c_str(), &st) == 0) {
+ result[i] = st.st_mtim.tv_sec;
+ }
+ }
+ return result;
+ };
+
+ auto before = get_tombstone_timestamps();
+ for (int i = 0; i < 50; ++i) {
+ raise_debugger_signal(kDebuggerdNativeBacktrace);
+ }
+ auto after = get_tombstone_timestamps();
+
+ int diff = 0;
+ for (int i = 0; i < 99; ++i) {
+ if (after.count(i) == 0) {
+ continue;
+ }
+ if (before.count(i) == 0) {
+ ++diff;
+ continue;
+ }
+ if (before[i] != after[i]) {
+ ++diff;
+ }
+ }
+
+ // We can't be sure that nothing's crash looping in the background.
+ // This should be good enough, though...
+ ASSERT_LT(diff, 10) << "too many new tombstones; is something crashing in the background?";
+}
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index 079a574..15c0265 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -47,6 +47,7 @@
#include <unwindstack/Regs.h>
#include "debuggerd/handler.h"
+#include "handler/fallback.h"
#include "tombstoned/tombstoned.h"
#include "util.h"
@@ -187,7 +188,7 @@
static void trace_handler(siginfo_t* info, ucontext_t* ucontext) {
static std::atomic<uint64_t> trace_output(pack_thread_fd(-1, -1));
- if (info->si_value.sival_int == ~0) {
+ if (info->si_value.sival_ptr == kDebuggerdFallbackSivalPtrRequestDump) {
// Asked to dump by the original signal recipient.
uint64_t val = trace_output.load();
auto [tid, fd] = unpack_thread_fd(val);
@@ -249,17 +250,18 @@
}
uint64_t expected = pack_thread_fd(-1, -1);
- if (!trace_output.compare_exchange_strong(expected,
- pack_thread_fd(tid, pipe_write.release()))) {
+ int sent_fd = pipe_write.release();
+ if (!trace_output.compare_exchange_strong(expected, pack_thread_fd(tid, sent_fd))) {
auto [tid, fd] = unpack_thread_fd(expected);
async_safe_format_log(ANDROID_LOG_ERROR, "libc",
"thread %d is already outputting to fd %d?", tid, fd);
+ close(sent_fd);
return false;
}
siginfo_t siginfo = {};
siginfo.si_code = SI_QUEUE;
- siginfo.si_value.sival_int = ~0;
+ siginfo.si_value.sival_ptr = kDebuggerdFallbackSivalPtrRequestDump;
siginfo.si_pid = getpid();
siginfo.si_uid = getuid();
@@ -331,7 +333,7 @@
extern "C" void debuggerd_fallback_handler(siginfo_t* info, ucontext_t* ucontext,
void* abort_message) {
- if (info->si_signo == DEBUGGER_SIGNAL && info->si_value.sival_int != 0) {
+ if (info->si_signo == DEBUGGER_SIGNAL && info->si_value.sival_ptr != nullptr) {
return trace_handler(info, ucontext);
} else {
return crash_handler(info, ucontext, abort_message);
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 15557b6..a064ca0 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -58,6 +58,8 @@
#include "dump_type.h"
#include "protocol.h"
+#include "handler/fallback.h"
+
using android::base::Pipe;
// We muck with our fds in a 'thread' that doesn't share the same fd table.
@@ -473,13 +475,15 @@
}
void* abort_message = nullptr;
+ uintptr_t si_val = reinterpret_cast<uintptr_t>(info->si_ptr);
if (signal_number == DEBUGGER_SIGNAL) {
if (info->si_code == SI_QUEUE && info->si_pid == __getpid()) {
// Allow for the abort message to be explicitly specified via the sigqueue value.
// Keep the bottom bit intact for representing whether we want a backtrace or a tombstone.
- uintptr_t value = reinterpret_cast<uintptr_t>(info->si_ptr);
- abort_message = reinterpret_cast<void*>(value & ~1);
- info->si_ptr = reinterpret_cast<void*>(value & 1);
+ if (si_val != kDebuggerdFallbackSivalUintptrRequestDump) {
+ abort_message = reinterpret_cast<void*>(si_val & ~1);
+ info->si_ptr = reinterpret_cast<void*>(si_val & 1);
+ }
}
} else {
if (g_callbacks.get_abort_message) {
@@ -492,7 +496,8 @@
// of a specific thread. It is possible that the prctl call might return 1,
// then return 0 in subsequent calls, so check the sival_int to determine if
// the fallback handler should be called first.
- if (info->si_value.sival_int == ~0 || prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) == 1) {
+ if (si_val == kDebuggerdFallbackSivalUintptrRequestDump ||
+ prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) == 1) {
// This check might be racy if another thread sets NO_NEW_PRIVS, but this should be unlikely,
// you can only set NO_NEW_PRIVS to 1, and the effect should be at worst a single missing
// ANR trace.
diff --git a/libbacktrace/GetPss.h b/debuggerd/handler/fallback.h
similarity index 63%
copy from libbacktrace/GetPss.h
copy to debuggerd/handler/fallback.h
index 787c33d..597f582 100644
--- a/libbacktrace/GetPss.h
+++ b/debuggerd/handler/fallback.h
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#ifndef _LIBBACKTRACE_GET_PSS_H
-#define _LIBBACKTRACE_GET_PSS_H
+#pragma once
-size_t GetPssBytes();
+#include <stdint.h>
-#endif // _LIBBACKTRACE_GET_PSS_H
+static void* const kDebuggerdFallbackSivalPtrRequestDump = reinterpret_cast<void*>(~0UL);
+static const uintptr_t kDebuggerdFallbackSivalUintptrRequestDump = ~0UL;
diff --git a/debuggerd/libdebuggerd/test/open_files_list_test.cpp b/debuggerd/libdebuggerd/test/open_files_list_test.cpp
index d7036fd..3e920eb 100644
--- a/debuggerd/libdebuggerd/test/open_files_list_test.cpp
+++ b/debuggerd/libdebuggerd/test/open_files_list_test.cpp
@@ -20,10 +20,9 @@
#include <string>
+#include <android-base/file.h>
#include <gtest/gtest.h>
-#include "android-base/test_utils.h"
-
#include "libdebuggerd/open_files_list.h"
// Check that we can produce a list of open files for the current process, and
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index 421ce43..d24c887 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -15,6 +15,7 @@
*/
#include <stdlib.h>
+#include <time.h>
#include <memory>
#include <string>
@@ -494,3 +495,10 @@
expected += android::base::StringPrintf("ABI: '%s'\n", ABI_STRING);
ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
}
+
+TEST_F(TombstoneTest, dump_timestamp) {
+ setenv("TZ", "UTC", 1);
+ tzset();
+ dump_timestamp(&log_, 0);
+ ASSERT_STREQ("Timestamp: 1970-01-01 00:00:00+0000\n", amfd_data_.c_str());
+}
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 0b8a936..b20014f 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -78,7 +78,16 @@
_LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING);
}
-static void dump_probable_cause(log_t* log, const siginfo_t* si) {
+static void dump_timestamp(log_t* log, time_t time) {
+ struct tm tm;
+ localtime_r(&time, &tm);
+
+ char buf[strlen("1970-01-01 00:00:00+0830") + 1];
+ strftime(buf, sizeof(buf), "%F %T%z", &tm);
+ _LOG(log, logtype::HEADER, "Timestamp: %s\n", buf);
+}
+
+static void dump_probable_cause(log_t* log, const siginfo_t* si, BacktraceMap* map) {
std::string cause;
if (si->si_signo == SIGSEGV && si->si_code == SEGV_MAPERR) {
if (si->si_addr < reinterpret_cast<void*>(4096)) {
@@ -94,6 +103,14 @@
} else if (si->si_addr == reinterpret_cast<void*>(0xffff0f60)) {
cause = "call to kuser_cmpxchg64";
}
+ } else if (si->si_signo == SIGSEGV && si->si_code == SEGV_ACCERR) {
+ for (auto it = map->begin(); it != map->end(); ++it) {
+ const backtrace_map_t* entry = *it;
+ if (si->si_addr >= reinterpret_cast<void*>(entry->start) &&
+ si->si_addr < reinterpret_cast<void*>(entry->end) && entry->flags == PROT_EXEC) {
+ cause = "execute-only (no-read) memory access error; likely due to data in .text.";
+ }
+ }
} else if (si->si_signo == SIGSYS && si->si_code == SYS_SECCOMP) {
cause = StringPrintf("seccomp prevented call to disallowed %s system call %d", ABI_STRING,
si->si_syscall);
@@ -125,8 +142,6 @@
_LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s%s), fault addr %s\n",
thread_info.siginfo->si_signo, get_signame(thread_info.siginfo),
thread_info.siginfo->si_code, get_sigcode(thread_info.siginfo), sender_desc, addr_desc);
-
- dump_probable_cause(log, thread_info.siginfo);
}
static void dump_thread_info(log_t* log, const ThreadInfo& thread_info) {
@@ -426,6 +441,7 @@
if (thread_info.siginfo) {
dump_signal_info(log, thread_info, process_memory);
+ dump_probable_cause(log, thread_info.siginfo, map);
}
if (primary_thread) {
@@ -647,6 +663,7 @@
_LOG(&log, logtype::HEADER, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
dump_header_info(&log);
+ dump_timestamp(&log, time(nullptr));
auto it = threads.find(target_thread);
if (it == threads.end()) {
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 8bdc02f..d0c5234 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -382,6 +382,8 @@
case TRAP_TRACE: return "TRAP_TRACE";
case TRAP_BRANCH: return "TRAP_BRANCH";
case TRAP_HWBKPT: return "TRAP_HWBKPT";
+ case TRAP_UNK:
+ return "TRAP_UNDIAGNOSED";
}
if ((si->si_code & 0xff) == SIGTRAP) {
switch ((si->si_code >> 8) & 0xff) {
@@ -403,7 +405,7 @@
return "PTRACE_EVENT_STOP";
}
}
- static_assert(NSIGTRAP == TRAP_HWBKPT, "missing TRAP_* si_code");
+ static_assert(NSIGTRAP == TRAP_UNK, "missing TRAP_* si_code");
break;
}
// Then the other codes...
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 15ae406..ad92067 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -212,8 +212,13 @@
bool intercepted =
intercept_manager->GetIntercept(crash->crash_pid, crash->crash_type, &output_fd);
if (!intercepted) {
- std::tie(crash->crash_tombstone_path, output_fd) = CrashQueue::for_crash(crash)->get_output();
- crash->crash_tombstone_fd.reset(dup(output_fd.get()));
+ if (crash->crash_type == kDebuggerdNativeBacktrace) {
+ // Don't generate tombstones for native backtrace requests.
+ output_fd.reset(open("/dev/null", O_WRONLY | O_CLOEXEC));
+ } else {
+ std::tie(crash->crash_tombstone_path, output_fd) = CrashQueue::for_crash(crash)->get_output();
+ crash->crash_tombstone_fd.reset(dup(output_fd.get()));
+ }
}
TombstonedCrashPacket response = {
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index 3b91ddd..716fe95 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -43,6 +43,7 @@
"libgtest_main",
"libbase",
"libadb_host",
+ "liblp",
],
header_libs: [
@@ -121,6 +122,8 @@
shared_libs: [
"android.hardware.boot@1.0",
+ "android.hardware.fastboot@1.0",
+ "android.hardware.health@2.0",
"libadbd",
"libasyncio",
"libbase",
@@ -129,6 +132,7 @@
"libext2_uuid",
"libext4_utils",
"libfs_mgr",
+ "libgsi",
"libhidlbase",
"libhidltransport",
"libhwbinder",
@@ -138,7 +142,9 @@
"libutils",
],
- cpp_std: "c++17",
+ static_libs: [
+ "libhealthhalutils",
+ ],
}
cc_defaults {
@@ -167,6 +173,11 @@
host_ldlibs: ["-lws2_32"],
},
+ not_windows: {
+ static_libs: [
+ "libext4_utils",
+ ],
+ },
},
stl: "libc++_static",
@@ -187,6 +198,8 @@
"libbase",
"libcutils",
"libgtest_host",
+ "liblp",
+ "libcrypto",
],
}
@@ -198,10 +211,8 @@
name: "libfastboot",
defaults: ["fastboot_host_defaults"],
- cpp_std: "c++17",
srcs: [
"bootimg_utils.cpp",
- "engine.cpp",
"fastboot.cpp",
"fs.cpp",
"socket.cpp",
@@ -247,6 +258,13 @@
"mke2fs",
"make_f2fs",
],
+ dist: {
+ targets: [
+ "dist_files",
+ "sdk",
+ "win_sdk",
+ ],
+ },
target: {
not_windows: {
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index e4c1317..17ec392 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -18,13 +18,9 @@
# Package fastboot-related executables.
#
-my_dist_files := $(HOST_OUT_EXECUTABLES)/fastboot
-my_dist_files += $(HOST_OUT_EXECUTABLES)/mke2fs
+my_dist_files := $(HOST_OUT_EXECUTABLES)/mke2fs
my_dist_files += $(HOST_OUT_EXECUTABLES)/e2fsdroid
my_dist_files += $(HOST_OUT_EXECUTABLES)/make_f2fs
my_dist_files += $(HOST_OUT_EXECUTABLES)/sload_f2fs
$(call dist-for-goals,dist_files sdk win_sdk,$(my_dist_files))
-ifdef HOST_CROSS_OS
-$(call dist-for-goals,dist_files sdk win_sdk,$(ALL_MODULES.host_cross_fastboot.BUILT))
-endif
my_dist_files :=
diff --git a/fastboot/bootimg_utils.cpp b/fastboot/bootimg_utils.cpp
index 1152007..e433787 100644
--- a/fastboot/bootimg_utils.cpp
+++ b/fastboot/bootimg_utils.cpp
@@ -39,27 +39,27 @@
strcpy(reinterpret_cast<char*>(h->cmdline), cmdline.c_str());
}
-boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, void* ramdisk, int64_t ramdisk_size,
- void* second, int64_t second_size, size_t base,
- const boot_img_hdr_v1& src, int64_t* bootimg_size) {
+boot_img_hdr_v1* mkbootimg(const std::vector<char>& kernel, const std::vector<char>& ramdisk,
+ const std::vector<char>& second, size_t base, const boot_img_hdr_v1& src,
+ std::vector<char>* out) {
const size_t page_mask = src.page_size - 1;
int64_t header_actual = (sizeof(boot_img_hdr_v1) + page_mask) & (~page_mask);
- int64_t kernel_actual = (kernel_size + page_mask) & (~page_mask);
- int64_t ramdisk_actual = (ramdisk_size + page_mask) & (~page_mask);
- int64_t second_actual = (second_size + page_mask) & (~page_mask);
+ int64_t kernel_actual = (kernel.size() + page_mask) & (~page_mask);
+ int64_t ramdisk_actual = (ramdisk.size() + page_mask) & (~page_mask);
+ int64_t second_actual = (second.size() + page_mask) & (~page_mask);
- *bootimg_size = header_actual + kernel_actual + ramdisk_actual + second_actual;
+ int64_t bootimg_size = header_actual + kernel_actual + ramdisk_actual + second_actual;
+ out->resize(bootimg_size);
- boot_img_hdr_v1* hdr = reinterpret_cast<boot_img_hdr_v1*>(calloc(*bootimg_size, 1));
- if (hdr == nullptr) die("couldn't allocate boot image: %" PRId64 " bytes", *bootimg_size);
+ boot_img_hdr_v1* hdr = reinterpret_cast<boot_img_hdr_v1*>(out->data());
*hdr = src;
memcpy(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
- hdr->kernel_size = kernel_size;
- hdr->ramdisk_size = ramdisk_size;
- hdr->second_size = second_size;
+ hdr->kernel_size = kernel.size();
+ hdr->ramdisk_size = ramdisk.size();
+ hdr->second_size = second.size();
hdr->kernel_addr += base;
hdr->ramdisk_addr += base;
@@ -70,8 +70,9 @@
hdr->header_size = sizeof(boot_img_hdr_v1);
}
- memcpy(hdr->magic + hdr->page_size, kernel, kernel_size);
- memcpy(hdr->magic + hdr->page_size + kernel_actual, ramdisk, ramdisk_size);
- memcpy(hdr->magic + hdr->page_size + kernel_actual + ramdisk_actual, second, second_size);
+ memcpy(hdr->magic + hdr->page_size, kernel.data(), kernel.size());
+ memcpy(hdr->magic + hdr->page_size + kernel_actual, ramdisk.data(), ramdisk.size());
+ memcpy(hdr->magic + hdr->page_size + kernel_actual + ramdisk_actual, second.data(),
+ second.size());
return hdr;
}
diff --git a/fastboot/bootimg_utils.h b/fastboot/bootimg_utils.h
index fe805b0..a4e8870 100644
--- a/fastboot/bootimg_utils.h
+++ b/fastboot/bootimg_utils.h
@@ -33,8 +33,9 @@
#include <sys/types.h>
#include <string>
+#include <vector>
-boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, void* ramdisk, int64_t ramdisk_size,
- void* second, int64_t second_size, size_t base,
- const boot_img_hdr_v1& src, int64_t* bootimg_size);
+boot_img_hdr_v1* mkbootimg(const std::vector<char>& kernel, const std::vector<char>& ramdisk,
+ const std::vector<char>& second, size_t base, const boot_img_hdr_v1& src,
+ std::vector<char>* out);
void bootimg_set_cmdline(boot_img_hdr_v1* h, const std::string& cmdline);
diff --git a/fastboot/constants.h b/fastboot/constants.h
index 063cd40..8a72627 100644
--- a/fastboot/constants.h
+++ b/fastboot/constants.h
@@ -32,6 +32,8 @@
#define FB_CMD_DELETE_PARTITION "delete-logical-partition"
#define FB_CMD_RESIZE_PARTITION "resize-logical-partition"
#define FB_CMD_UPDATE_SUPER "update-super"
+#define FB_CMD_OEM "oem"
+#define FB_CMD_GSI "gsi"
#define RESPONSE_OKAY "OKAY"
#define RESPONSE_FAIL "FAIL"
@@ -53,7 +55,14 @@
#define FB_VAR_HAS_SLOT "has-slot"
#define FB_VAR_SLOT_COUNT "slot-count"
#define FB_VAR_PARTITION_SIZE "partition-size"
+#define FB_VAR_PARTITION_TYPE "partition-type"
#define FB_VAR_SLOT_SUCCESSFUL "slot-successful"
#define FB_VAR_SLOT_UNBOOTABLE "slot-unbootable"
#define FB_VAR_IS_LOGICAL "is-logical"
#define FB_VAR_IS_USERSPACE "is-userspace"
+#define FB_VAR_HW_REVISION "hw-revision"
+#define FB_VAR_VARIANT "variant"
+#define FB_VAR_OFF_MODE_CHARGE_STATE "off-mode-charge"
+#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"
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 1e853bf..a2336bf 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -27,6 +27,8 @@
#include <android-base/unique_fd.h>
#include <cutils/android_reboot.h>
#include <ext4_utils/wipe.h>
+#include <fs_mgr.h>
+#include <libgsi/libgsi.h>
#include <liblp/builder.h>
#include <liblp/liblp.h>
#include <uuid/uuid.h>
@@ -40,42 +42,102 @@
using ::android::hardware::boot::V1_0::BoolResult;
using ::android::hardware::boot::V1_0::CommandResult;
using ::android::hardware::boot::V1_0::Slot;
+using ::android::hardware::fastboot::V1_0::Result;
+using ::android::hardware::fastboot::V1_0::Status;
+
using namespace android::fs_mgr;
+struct VariableHandlers {
+ // Callback to retrieve the value of a single variable.
+ std::function<bool(FastbootDevice*, const std::vector<std::string>&, std::string*)> get;
+ // Callback to retrieve all possible argument combinations, for getvar all.
+ std::function<std::vector<std::vector<std::string>>(FastbootDevice*)> get_all_args;
+};
+
+static void GetAllVars(FastbootDevice* device, const std::string& name,
+ const VariableHandlers& handlers) {
+ if (!handlers.get_all_args) {
+ std::string message;
+ if (!handlers.get(device, std::vector<std::string>(), &message)) {
+ return;
+ }
+ device->WriteInfo(android::base::StringPrintf("%s:%s", name.c_str(), message.c_str()));
+ return;
+ }
+
+ auto all_args = handlers.get_all_args(device);
+ for (const auto& args : all_args) {
+ std::string message;
+ if (!handlers.get(device, args, &message)) {
+ continue;
+ }
+ std::string arg_string = android::base::Join(args, ":");
+ device->WriteInfo(android::base::StringPrintf("%s:%s:%s", name.c_str(), arg_string.c_str(),
+ message.c_str()));
+ }
+}
+
bool GetVarHandler(FastbootDevice* device, const std::vector<std::string>& args) {
- using VariableHandler = std::function<bool(FastbootDevice*, const std::vector<std::string>&)>;
- const std::unordered_map<std::string, VariableHandler> kVariableMap = {
- {FB_VAR_VERSION, GetVersion},
- {FB_VAR_VERSION_BOOTLOADER, GetBootloaderVersion},
- {FB_VAR_VERSION_BASEBAND, GetBasebandVersion},
- {FB_VAR_PRODUCT, GetProduct},
- {FB_VAR_SERIALNO, GetSerial},
- {FB_VAR_SECURE, GetSecure},
- {FB_VAR_UNLOCKED, GetUnlocked},
- {FB_VAR_MAX_DOWNLOAD_SIZE, GetMaxDownloadSize},
- {FB_VAR_CURRENT_SLOT, ::GetCurrentSlot},
- {FB_VAR_SLOT_COUNT, GetSlotCount},
- {FB_VAR_HAS_SLOT, GetHasSlot},
- {FB_VAR_SLOT_SUCCESSFUL, GetSlotSuccessful},
- {FB_VAR_SLOT_UNBOOTABLE, GetSlotUnbootable},
- {FB_VAR_PARTITION_SIZE, GetPartitionSize},
- {FB_VAR_IS_LOGICAL, GetPartitionIsLogical},
- {FB_VAR_IS_USERSPACE, GetIsUserspace}};
+ const std::unordered_map<std::string, VariableHandlers> kVariableMap = {
+ {FB_VAR_VERSION, {GetVersion, nullptr}},
+ {FB_VAR_VERSION_BOOTLOADER, {GetBootloaderVersion, nullptr}},
+ {FB_VAR_VERSION_BASEBAND, {GetBasebandVersion, nullptr}},
+ {FB_VAR_PRODUCT, {GetProduct, nullptr}},
+ {FB_VAR_SERIALNO, {GetSerial, nullptr}},
+ {FB_VAR_VARIANT, {GetVariant, nullptr}},
+ {FB_VAR_SECURE, {GetSecure, nullptr}},
+ {FB_VAR_UNLOCKED, {GetUnlocked, nullptr}},
+ {FB_VAR_MAX_DOWNLOAD_SIZE, {GetMaxDownloadSize, nullptr}},
+ {FB_VAR_CURRENT_SLOT, {::GetCurrentSlot, nullptr}},
+ {FB_VAR_SLOT_COUNT, {GetSlotCount, nullptr}},
+ {FB_VAR_HAS_SLOT, {GetHasSlot, GetAllPartitionArgsNoSlot}},
+ {FB_VAR_SLOT_SUCCESSFUL, {GetSlotSuccessful, nullptr}},
+ {FB_VAR_SLOT_UNBOOTABLE, {GetSlotUnbootable, nullptr}},
+ {FB_VAR_PARTITION_SIZE, {GetPartitionSize, GetAllPartitionArgsWithSlot}},
+ {FB_VAR_PARTITION_TYPE, {GetPartitionType, GetAllPartitionArgsWithSlot}},
+ {FB_VAR_IS_LOGICAL, {GetPartitionIsLogical, GetAllPartitionArgsWithSlot}},
+ {FB_VAR_IS_USERSPACE, {GetIsUserspace, nullptr}},
+ {FB_VAR_OFF_MODE_CHARGE_STATE, {GetOffModeChargeState, nullptr}},
+ {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}}};
+
+ if (args.size() < 2) {
+ return device->WriteFail("Missing argument");
+ }
+
+ // Special case: return all variables that we can.
+ if (args[1] == "all") {
+ for (const auto& [name, handlers] : kVariableMap) {
+ GetAllVars(device, name, handlers);
+ }
+ return device->WriteOkay("");
+ }
// args[0] is command name, args[1] is variable.
auto found_variable = kVariableMap.find(args[1]);
if (found_variable == kVariableMap.end()) {
- return device->WriteStatus(FastbootResult::FAIL, "Unknown variable");
+ return device->WriteFail("Unknown variable");
}
+ std::string message;
std::vector<std::string> getvar_args(args.begin() + 2, args.end());
- return found_variable->second(device, getvar_args);
+ if (!found_variable->second.get(device, getvar_args, &message)) {
+ return device->WriteFail(message);
+ }
+ return device->WriteOkay(message);
}
bool EraseHandler(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, "Erase is not allowed on locked devices");
+ }
+
PartitionHandle handle;
if (!OpenPartition(device, args[1], &handle)) {
return device->WriteStatus(FastbootResult::FAIL, "Partition doesn't exist");
@@ -86,13 +148,37 @@
return device->WriteStatus(FastbootResult::FAIL, "Erasing failed");
}
+bool OemCmdHandler(FastbootDevice* device, const std::vector<std::string>& args) {
+ auto fastboot_hal = device->fastboot_hal();
+ if (!fastboot_hal) {
+ return device->WriteStatus(FastbootResult::FAIL, "Unable to open fastboot HAL");
+ }
+
+ Result ret;
+ auto ret_val = fastboot_hal->doOemCommand(args[0], [&](Result result) { ret = result; });
+ if (!ret_val.isOk()) {
+ return device->WriteStatus(FastbootResult::FAIL, "Unable to do OEM command");
+ }
+ if (ret.status != Status::SUCCESS) {
+ return device->WriteStatus(FastbootResult::FAIL, ret.message);
+ }
+
+ return device->WriteStatus(FastbootResult::OKAY, ret.message);
+}
+
bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& args) {
if (args.size() < 2) {
return device->WriteStatus(FastbootResult::FAIL, "size argument unspecified");
}
+
+ if (GetDeviceLockStatus()) {
+ return device->WriteStatus(FastbootResult::FAIL,
+ "Download is not allowed on locked devices");
+ }
+
// arg[0] is the command name, arg[1] contains size of data to be downloaded
unsigned int size;
- if (!android::base::ParseUint("0x" + args[1], &size, UINT_MAX)) {
+ if (!android::base::ParseUint("0x" + args[1], &size, kMaxDownloadSizeDefault)) {
return device->WriteStatus(FastbootResult::FAIL, "Invalid size");
}
device->download_data().resize(size);
@@ -112,6 +198,12 @@
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));
@@ -124,6 +216,11 @@
return device->WriteStatus(FastbootResult::FAIL, "Missing slot argument");
}
+ if (GetDeviceLockStatus()) {
+ return device->WriteStatus(FastbootResult::FAIL,
+ "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)) {
@@ -142,7 +239,13 @@
CommandResult ret;
auto cb = [&ret](CommandResult result) { ret = result; };
auto result = boot_control_hal->setActiveBootSlot(slot, cb);
- if (result.isOk() && ret.success) return device->WriteStatus(FastbootResult::OKAY, "");
+ if (result.isOk() && ret.success) {
+ // Save as slot suffix to match the suffix format as returned from
+ // the boot control HAL.
+ auto current_slot = "_" + args[1];
+ device->set_active_slot(current_slot);
+ return device->WriteStatus(FastbootResult::OKAY, "");
+ }
return device->WriteStatus(FastbootResult::FAIL, "Unable to set slot");
}
@@ -220,27 +323,28 @@
// partition table to the same place it was read.
class PartitionBuilder {
public:
- explicit PartitionBuilder(FastbootDevice* device);
+ explicit PartitionBuilder(FastbootDevice* device, const std::string& partition_name);
bool Write();
bool Valid() const { return !!builder_; }
MetadataBuilder* operator->() const { return builder_.get(); }
private:
+ FastbootDevice* device_;
std::string super_device_;
uint32_t slot_number_;
std::unique_ptr<MetadataBuilder> builder_;
};
-PartitionBuilder::PartitionBuilder(FastbootDevice* device) {
- auto super_device = FindPhysicalPartition(LP_METADATA_PARTITION_NAME);
+PartitionBuilder::PartitionBuilder(FastbootDevice* device, const std::string& partition_name)
+ : device_(device) {
+ std::string slot_suffix = GetSuperSlotSuffix(device, partition_name);
+ slot_number_ = SlotNumberForSlotSuffix(slot_suffix);
+ auto super_device = FindPhysicalPartition(fs_mgr_get_super_partition_name(slot_number_));
if (!super_device) {
return;
}
super_device_ = *super_device;
-
- std::string slot = device->GetCurrentSlot();
- slot_number_ = SlotNumberForSlotSuffix(slot);
builder_ = MetadataBuilder::New(super_device_, slot_number_);
}
@@ -249,7 +353,7 @@
if (!metadata) {
return false;
}
- return UpdatePartitionTable(super_device_, *metadata.get(), slot_number_);
+ return UpdateAllPartitionMetadata(device_, super_device_, *metadata.get());
}
bool CreatePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
@@ -257,13 +361,17 @@
return device->WriteFail("Invalid partition name and size");
}
+ if (GetDeviceLockStatus()) {
+ return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
+ }
+
uint64_t partition_size;
std::string partition_name = args[1];
if (!android::base::ParseUint(args[2].c_str(), &partition_size)) {
return device->WriteFail("Invalid partition size");
}
- PartitionBuilder builder(device);
+ PartitionBuilder builder(device, partition_name);
if (!builder.Valid()) {
return device->WriteFail("Could not open super partition");
}
@@ -272,13 +380,7 @@
return device->WriteFail("Partition already exists");
}
- // Make a random UUID, since they're not currently used.
- uuid_t uuid;
- char uuid_str[37];
- uuid_generate_random(uuid);
- uuid_unparse(uuid, uuid_str);
-
- Partition* partition = builder->AddPartition(partition_name, uuid_str, 0);
+ Partition* partition = builder->AddPartition(partition_name, 0);
if (!partition) {
return device->WriteFail("Failed to add partition");
}
@@ -297,11 +399,17 @@
return device->WriteFail("Invalid partition name and size");
}
- PartitionBuilder builder(device);
+ if (GetDeviceLockStatus()) {
+ return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
+ }
+
+ std::string partition_name = args[1];
+
+ PartitionBuilder builder(device, partition_name);
if (!builder.Valid()) {
return device->WriteFail("Could not open super partition");
}
- builder->RemovePartition(args[1]);
+ builder->RemovePartition(partition_name);
if (!builder.Write()) {
return device->WriteFail("Failed to write partition table");
}
@@ -313,13 +421,17 @@
return device->WriteFail("Invalid partition name and size");
}
+ if (GetDeviceLockStatus()) {
+ return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
+ }
+
uint64_t partition_size;
std::string partition_name = args[1];
if (!android::base::ParseUint(args[2].c_str(), &partition_size)) {
return device->WriteFail("Invalid partition size");
}
- PartitionBuilder builder(device);
+ PartitionBuilder builder(device, partition_name);
if (!builder.Valid()) {
return device->WriteFail("Could not open super partition");
}
@@ -341,6 +453,30 @@
if (args.size() < 2) {
return device->WriteFail("Invalid arguments");
}
+
+ if (GetDeviceLockStatus()) {
+ return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
+ }
+
bool wipe = (args.size() >= 3 && args[2] == "wipe");
return UpdateSuper(device, args[1], wipe);
}
+
+bool GsiHandler(FastbootDevice* device, const std::vector<std::string>& args) {
+ if (!android::gsi::IsGsiInstalled()) {
+ return device->WriteStatus(FastbootResult::FAIL, "No GSI is installed");
+ }
+ if (args.size() != 2) {
+ return device->WriteFail("Invalid arguments");
+ }
+ if (args[1] == "wipe") {
+ if (!android::gsi::UninstallGsi()) {
+ return device->WriteStatus(FastbootResult::FAIL, strerror(errno));
+ }
+ } else if (args[1] == "disable") {
+ if (!android::gsi::DisableGsi()) {
+ return device->WriteStatus(FastbootResult::FAIL, strerror(errno));
+ }
+ }
+ return device->WriteStatus(FastbootResult::OKAY, "Success");
+}
diff --git a/fastboot/device/commands.h b/fastboot/device/commands.h
index 4778d23..afd6d08 100644
--- a/fastboot/device/commands.h
+++ b/fastboot/device/commands.h
@@ -19,6 +19,8 @@
#include <string>
#include <vector>
+constexpr unsigned int kMaxDownloadSizeDefault = 0x20000000;
+
class FastbootDevice;
enum class FastbootResult {
@@ -45,3 +47,5 @@
bool DeletePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args);
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);
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index 6ed6d32..56fafab 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -19,6 +19,8 @@
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <android/hardware/boot/1.0/IBootControl.h>
+#include <android/hardware/fastboot/1.0/IFastboot.h>
+#include <healthhalutils/HealthHalUtils.h>
#include <algorithm>
@@ -29,6 +31,9 @@
using ::android::hardware::hidl_string;
using ::android::hardware::boot::V1_0::IBootControl;
using ::android::hardware::boot::V1_0::Slot;
+using ::android::hardware::fastboot::V1_0::IFastboot;
+using ::android::hardware::health::V2_0::get_health_service;
+
namespace sph = std::placeholders;
FastbootDevice::FastbootDevice()
@@ -47,9 +52,14 @@
{FB_CMD_DELETE_PARTITION, DeletePartitionHandler},
{FB_CMD_RESIZE_PARTITION, ResizePartitionHandler},
{FB_CMD_UPDATE_SUPER, UpdateSuperHandler},
+ {FB_CMD_OEM, OemCmdHandler},
+ {FB_CMD_GSI, GsiHandler},
}),
transport_(std::make_unique<ClientUsbTransport>()),
- boot_control_hal_(IBootControl::getService()) {}
+ boot_control_hal_(IBootControl::getService()),
+ health_hal_(get_health_service()),
+ fastboot_hal_(IFastboot::getService()),
+ active_slot_("") {}
FastbootDevice::~FastbootDevice() {
CloseDevice();
@@ -60,6 +70,11 @@
}
std::string FastbootDevice::GetCurrentSlot() {
+ // Check if a set_active ccommand was issued earlier since the boot control HAL
+ // returns the slot that is currently booted into.
+ if (!active_slot_.empty()) {
+ return active_slot_;
+ }
// Non-A/B devices must not have boot control HALs.
if (!boot_control_hal_) {
return "";
@@ -118,10 +133,20 @@
command[bytes_read] = '\0';
LOG(INFO) << "Fastboot command: " << command;
- auto args = android::base::Split(command, ":");
- auto found_command = kCommandMap.find(args[0]);
+
+ std::vector<std::string> args;
+ std::string cmd_name;
+ if (android::base::StartsWith(command, "oem ")) {
+ args = {command};
+ cmd_name = FB_CMD_OEM;
+ } else {
+ args = android::base::Split(command, ":");
+ cmd_name = args[0];
+ }
+
+ auto found_command = kCommandMap.find(cmd_name);
if (found_command == kCommandMap.end()) {
- WriteStatus(FastbootResult::FAIL, "Unrecognized command");
+ WriteStatus(FastbootResult::FAIL, "Unrecognized command " + args[0]);
continue;
}
if (!found_command->second(this, args)) {
@@ -137,3 +162,7 @@
bool FastbootDevice::WriteFail(const std::string& message) {
return WriteStatus(FastbootResult::FAIL, message);
}
+
+bool FastbootDevice::WriteInfo(const std::string& message) {
+ return WriteStatus(FastbootResult::INFO, message);
+}
diff --git a/fastboot/device/fastboot_device.h b/fastboot/device/fastboot_device.h
index addc2ef..091aadf 100644
--- a/fastboot/device/fastboot_device.h
+++ b/fastboot/device/fastboot_device.h
@@ -23,6 +23,8 @@
#include <vector>
#include <android/hardware/boot/1.0/IBootControl.h>
+#include <android/hardware/fastboot/1.0/IFastboot.h>
+#include <android/hardware/health/2.0/IHealth.h>
#include "commands.h"
#include "transport.h"
@@ -39,20 +41,30 @@
bool HandleData(bool read, std::vector<char>* data);
std::string GetCurrentSlot();
- // Shortcuts for writing OKAY and FAIL status results.
+ // Shortcuts for writing status results.
bool WriteOkay(const std::string& message);
bool WriteFail(const std::string& message);
+ bool WriteInfo(const std::string& message);
std::vector<char>& download_data() { return download_data_; }
Transport* get_transport() { return transport_.get(); }
android::sp<android::hardware::boot::V1_0::IBootControl> boot_control_hal() {
return boot_control_hal_;
}
+ android::sp<android::hardware::fastboot::V1_0::IFastboot> fastboot_hal() {
+ return fastboot_hal_;
+ }
+ android::sp<android::hardware::health::V2_0::IHealth> health_hal() { return health_hal_; }
+
+ void set_active_slot(const std::string& active_slot) { active_slot_ = active_slot; }
private:
const std::unordered_map<std::string, CommandHandler> kCommandMap;
std::unique_ptr<Transport> transport_;
android::sp<android::hardware::boot::V1_0::IBootControl> boot_control_hal_;
+ 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_;
+ std::string active_slot_;
};
diff --git a/fastboot/device/flashing.cpp b/fastboot/device/flashing.cpp
index e3efbcb..f737405 100644
--- a/fastboot/device/flashing.cpp
+++ b/fastboot/device/flashing.cpp
@@ -21,10 +21,15 @@
#include <algorithm>
#include <memory>
+#include <set>
+#include <string>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <ext4_utils/ext4_utils.h>
+#include <fs_mgr_overlayfs.h>
+#include <fstab/fstab.h>
#include <liblp/builder.h>
#include <liblp/liblp.h>
#include <sparse/sparse.h>
@@ -32,13 +37,35 @@
#include "fastboot_device.h"
#include "utility.h"
+using namespace android::fs_mgr;
+using namespace std::literals;
+
namespace {
constexpr uint32_t SPARSE_HEADER_MAGIC = 0xed26ff3a;
-} // namespace
+void WipeOverlayfsForPartition(FastbootDevice* device, const std::string& partition_name) {
+ // May be called, in the case of sparse data, multiple times so cache/skip.
+ static std::set<std::string> wiped;
+ if (wiped.find(partition_name) != wiped.end()) return;
+ wiped.insert(partition_name);
+ // Following appears to have a first time 2% impact on flashing speeds.
-using namespace android::fs_mgr;
+ // Convert partition_name to a validated mount point and wipe.
+ std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
+ fs_mgr_free_fstab);
+ for (auto i = 0; i < fstab->num_entries; i++) {
+ const auto mount_point = fstab->recs[i].mount_point;
+ if (!mount_point) continue;
+ auto partition = android::base::Basename(mount_point);
+ if ("/"s == mount_point) partition = "system";
+ if ((partition + device->GetCurrentSlot()) == partition_name) {
+ fs_mgr_overlayfs_teardown(mount_point);
+ }
+ }
+}
+
+} // namespace
int FlashRawDataChunk(int fd, const char* data, size_t len) {
size_t ret = 0;
@@ -101,15 +128,11 @@
} else if (data.size() > get_block_device_size(handle.fd())) {
return -EOVERFLOW;
}
+ WipeOverlayfsForPartition(device, partition_name);
return FlashBlockDevice(handle.fd(), data);
}
-bool UpdateSuper(FastbootDevice* device, const std::string& partition_name, bool wipe) {
- std::optional<std::string> super = FindPhysicalPartition(partition_name);
- if (!super) {
- return device->WriteFail("Could not find partition: " + partition_name);
- }
-
+bool UpdateSuper(FastbootDevice* device, const std::string& super_name, bool wipe) {
std::vector<char> data = std::move(device->download_data());
if (data.empty()) {
return device->WriteFail("No data available");
@@ -120,57 +143,55 @@
return device->WriteFail("Data is not a valid logical partition metadata image");
}
+ if (!FindPhysicalPartition(super_name)) {
+ return device->WriteFail("Cannot find " + super_name +
+ ", build may be missing broken or missing boot_devices");
+ }
+
// If we are unable to read the existing metadata, then the super partition
// is corrupt. In this case we reflash the whole thing using the provided
// image.
std::string slot_suffix = device->GetCurrentSlot();
uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
- std::unique_ptr<LpMetadata> metadata = ReadMetadata(super->c_str(), slot_number);
- if (!metadata || wipe) {
- if (!FlashPartitionTable(super.value(), *new_metadata.get())) {
+ std::unique_ptr<LpMetadata> old_metadata = ReadMetadata(super_name, slot_number);
+ if (wipe || !old_metadata) {
+ if (!FlashPartitionTable(super_name, *new_metadata.get())) {
return device->WriteFail("Unable to flash new partition table");
}
+ fs_mgr_overlayfs_teardown();
return device->WriteOkay("Successfully flashed partition table");
}
- // There's a working super partition, and we don't want to wipe it - it may
- // may contain partitions created for the user. Instead, we create a zero-
- // sized partition for each entry in the new partition table. It is then
- // the host's responsibility to size it correctly via resize-logical-partition.
- std::unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(*metadata.get());
- if (!builder) {
- return device->WriteFail("Unable to create a metadata builder");
- }
- for (const auto& partition : new_metadata->partitions) {
- std::string name = GetPartitionName(partition);
- if (builder->FindPartition(name)) {
+ std::set<std::string> partitions_to_keep;
+ for (const auto& partition : old_metadata->partitions) {
+ // Preserve partitions in the other slot, but not the current slot.
+ std::string partition_name = GetPartitionName(partition);
+ if (!slot_suffix.empty() && GetPartitionSlotSuffix(partition_name) == slot_suffix) {
continue;
}
- std::string guid = GetPartitionGuid(partition);
- if (!builder->AddPartition(name, guid, partition.attributes)) {
- return device->WriteFail("Unable to add partition: " + name);
- }
+ partitions_to_keep.emplace(partition_name);
}
- // The scratch partition may exist as temporary storage, created for
- // use by adb remount for overlayfs. If we're performing a flashall
- // operation then we want to start over with a clean slate, so we
- // remove the scratch partition until it is requested again.
- builder->RemovePartition("scratch");
+ // Do not preserve the scratch partition.
+ partitions_to_keep.erase("scratch");
- new_metadata = builder->Export();
- if (!new_metadata) {
- return device->WriteFail("Unable to export new partition table");
+ if (!partitions_to_keep.empty()) {
+ std::unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(*new_metadata.get());
+ if (!builder->ImportPartitions(*old_metadata.get(), partitions_to_keep)) {
+ return device->WriteFail(
+ "Old partitions are not compatible with the new super layout; wipe needed");
+ }
+
+ new_metadata = builder->Export();
+ if (!new_metadata) {
+ return device->WriteFail("Unable to build new partition table; wipe needed");
+ }
}
// Write the new table to every metadata slot.
- bool ok = true;
- for (size_t i = 0; i < new_metadata->geometry.metadata_slot_count; i++) {
- ok &= UpdatePartitionTable(super.value(), *new_metadata.get(), i);
- }
-
- if (!ok) {
+ if (!UpdateAllPartitionMetadata(device, super_name, *new_metadata.get())) {
return device->WriteFail("Unable to write new partition table");
}
+ fs_mgr_overlayfs_teardown();
return device->WriteOkay("Successfully updated partition table");
}
diff --git a/fastboot/device/flashing.h b/fastboot/device/flashing.h
index 89e20fc..b15f28b 100644
--- a/fastboot/device/flashing.h
+++ b/fastboot/device/flashing.h
@@ -22,4 +22,4 @@
class FastbootDevice;
int Flash(FastbootDevice* device, const std::string& partition_name);
-bool UpdateSuper(FastbootDevice* device, const std::string& partition_name, bool wipe);
+bool UpdateSuper(FastbootDevice* device, const std::string& super_name, bool wipe);
diff --git a/fastboot/device/utility.cpp b/fastboot/device/utility.cpp
index ec84576..2ebd57d 100644
--- a/fastboot/device/utility.cpp
+++ b/fastboot/device/utility.cpp
@@ -16,17 +16,30 @@
#include "utility.h"
+#include <dirent.h>
+#include <sys/stat.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/strings.h>
+#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
+#include <liblp/builder.h>
#include <liblp/liblp.h>
#include "fastboot_device.h"
using namespace android::fs_mgr;
+using namespace std::chrono_literals;
using android::base::unique_fd;
using android::hardware::boot::V1_0::Slot;
-static bool OpenPhysicalPartition(const std::string& name, PartitionHandle* handle) {
+namespace {
+
+bool OpenPhysicalPartition(const std::string& name, PartitionHandle* handle) {
std::optional<std::string> path = FindPhysicalPartition(name);
if (!path) {
return false;
@@ -35,28 +48,31 @@
return true;
}
-static bool OpenLogicalPartition(const std::string& name, const std::string& slot,
- PartitionHandle* handle) {
- std::optional<std::string> path = FindPhysicalPartition(LP_METADATA_PARTITION_NAME);
+bool OpenLogicalPartition(FastbootDevice* device, const std::string& partition_name,
+ PartitionHandle* handle) {
+ std::string slot_suffix = GetSuperSlotSuffix(device, partition_name);
+ uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
+ auto path = FindPhysicalPartition(fs_mgr_get_super_partition_name(slot_number));
if (!path) {
return false;
}
- uint32_t slot_number = SlotNumberForSlotSuffix(slot);
std::string dm_path;
- if (!CreateLogicalPartition(path->c_str(), slot_number, name, true, &dm_path)) {
- LOG(ERROR) << "Could not map partition: " << name;
+ if (!CreateLogicalPartition(path->c_str(), slot_number, partition_name, true, 5s, &dm_path)) {
+ LOG(ERROR) << "Could not map partition: " << partition_name;
return false;
}
- auto closer = [name]() -> void { DestroyLogicalPartition(name); };
+ auto closer = [partition_name]() -> void { DestroyLogicalPartition(partition_name, 5s); };
*handle = PartitionHandle(dm_path, std::move(closer));
return true;
}
+} // namespace
+
bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHandle* handle) {
// We prioritize logical partitions over physical ones, and do this
// consistently for other partition operations (like getvar:partition-size).
- if (LogicalPartitionExists(name, device->GetCurrentSlot())) {
- if (!OpenLogicalPartition(name, device->GetCurrentSlot(), handle)) {
+ if (LogicalPartitionExists(device, name)) {
+ if (!OpenLogicalPartition(device, name, handle)) {
return false;
}
} else if (!OpenPhysicalPartition(name, handle)) {
@@ -74,8 +90,12 @@
}
std::optional<std::string> FindPhysicalPartition(const std::string& name) {
+ // Check for an invalid file name
+ if (android::base::StartsWith(name, "../") || name.find("/../") != std::string::npos) {
+ return {};
+ }
std::string path = "/dev/block/by-name/" + name;
- if (access(path.c_str(), R_OK | W_OK) < 0) {
+ if (access(path.c_str(), W_OK) < 0) {
return {};
}
return path;
@@ -91,14 +111,14 @@
return nullptr;
}
-bool LogicalPartitionExists(const std::string& name, const std::string& slot_suffix,
- bool* is_zero_length) {
- auto path = FindPhysicalPartition(LP_METADATA_PARTITION_NAME);
+bool LogicalPartitionExists(FastbootDevice* device, const std::string& name, bool* is_zero_length) {
+ std::string slot_suffix = GetSuperSlotSuffix(device, name);
+ uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
+ auto path = FindPhysicalPartition(fs_mgr_get_super_partition_name(slot_number));
if (!path) {
return false;
}
- uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
std::unique_ptr<LpMetadata> metadata = ReadMetadata(path->c_str(), slot_number);
if (!metadata) {
return false;
@@ -123,3 +143,92 @@
*number = slot[0] - 'a';
return true;
}
+
+std::vector<std::string> ListPartitions(FastbootDevice* device) {
+ std::vector<std::string> partitions;
+
+ // First get physical partitions.
+ struct dirent* de;
+ std::unique_ptr<DIR, decltype(&closedir)> by_name(opendir("/dev/block/by-name"), closedir);
+ while ((de = readdir(by_name.get())) != nullptr) {
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
+ continue;
+ }
+ struct stat s;
+ std::string path = "/dev/block/by-name/" + std::string(de->d_name);
+ if (!stat(path.c_str(), &s) && S_ISBLK(s.st_mode)) {
+ partitions.emplace_back(de->d_name);
+ }
+ }
+
+ // Find metadata in each super partition (on retrofit devices, there will
+ // be two).
+ std::vector<std::unique_ptr<LpMetadata>> metadata_list;
+
+ uint32_t current_slot = SlotNumberForSlotSuffix(device->GetCurrentSlot());
+ std::string super_name = fs_mgr_get_super_partition_name(current_slot);
+ if (auto metadata = ReadMetadata(super_name, current_slot)) {
+ metadata_list.emplace_back(std::move(metadata));
+ }
+
+ uint32_t other_slot = (current_slot == 0) ? 1 : 0;
+ std::string other_super = fs_mgr_get_super_partition_name(other_slot);
+ if (super_name != other_super) {
+ if (auto metadata = ReadMetadata(other_super, other_slot)) {
+ metadata_list.emplace_back(std::move(metadata));
+ }
+ }
+
+ for (const auto& metadata : metadata_list) {
+ for (const auto& partition : metadata->partitions) {
+ std::string partition_name = GetPartitionName(partition);
+ if (std::find(partitions.begin(), partitions.end(), partition_name) ==
+ partitions.end()) {
+ partitions.emplace_back(partition_name);
+ }
+ }
+ }
+ return partitions;
+}
+
+bool GetDeviceLockStatus() {
+ std::string cmdline;
+ // Return lock status true if unable to read kernel command line.
+ if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) {
+ return true;
+ }
+ return cmdline.find("androidboot.verifiedbootstate=orange") == std::string::npos;
+}
+
+bool UpdateAllPartitionMetadata(FastbootDevice* device, const std::string& super_name,
+ const android::fs_mgr::LpMetadata& metadata) {
+ size_t num_slots = 1;
+ auto boot_control_hal = device->boot_control_hal();
+ if (boot_control_hal) {
+ num_slots = boot_control_hal->getNumberSlots();
+ }
+
+ bool ok = true;
+ for (size_t i = 0; i < num_slots; i++) {
+ ok &= UpdatePartitionTable(super_name, metadata, i);
+ }
+ return ok;
+}
+
+std::string GetSuperSlotSuffix(FastbootDevice* device, const std::string& partition_name) {
+ // If the super partition does not have a slot suffix, this is not a
+ // retrofit device, and we should take the current slot.
+ std::string current_slot_suffix = device->GetCurrentSlot();
+ uint32_t current_slot_number = SlotNumberForSlotSuffix(current_slot_suffix);
+ std::string super_partition = fs_mgr_get_super_partition_name(current_slot_number);
+ if (GetPartitionSlotSuffix(super_partition).empty()) {
+ return current_slot_suffix;
+ }
+
+ // Otherwise, infer the slot from the partition name.
+ std::string slot_suffix = GetPartitionSlotSuffix(partition_name);
+ if (!slot_suffix.empty()) {
+ return slot_suffix;
+ }
+ return current_slot_suffix;
+}
diff --git a/fastboot/device/utility.h b/fastboot/device/utility.h
index 0931fc3..bfeeb74 100644
--- a/fastboot/device/utility.h
+++ b/fastboot/device/utility.h
@@ -20,6 +20,7 @@
#include <android-base/unique_fd.h>
#include <android/hardware/boot/1.0/IBootControl.h>
+#include <liblp/liblp.h>
// Logical partitions are only mapped to a block device as needed, and
// immediately unmapped when no longer needed. In order to enforce this we
@@ -52,9 +53,20 @@
class FastbootDevice;
+// On normal devices, the super partition is always named "super". On retrofit
+// devices, the name must be derived from the partition name or current slot.
+// This helper assists in choosing the correct super for a given partition
+// name.
+std::string GetSuperSlotSuffix(FastbootDevice* device, const std::string& partition_name);
+
std::optional<std::string> FindPhysicalPartition(const std::string& name);
-bool LogicalPartitionExists(const std::string& name, const std::string& slot_suffix,
+bool LogicalPartitionExists(FastbootDevice* device, const std::string& name,
bool* is_zero_length = nullptr);
bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHandle* handle);
-
bool GetSlotNumber(const std::string& slot, android::hardware::boot::V1_0::Slot* number);
+std::vector<std::string> ListPartitions(FastbootDevice* device);
+bool GetDeviceLockStatus();
+
+// Update all copies of metadata.
+bool UpdateAllPartitionMetadata(FastbootDevice* device, const std::string& super_name,
+ const android::fs_mgr::LpMetadata& metadata);
diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp
index 65cfea3..130a3cf 100644
--- a/fastboot/device/variables.cpp
+++ b/fastboot/device/variables.cpp
@@ -24,6 +24,9 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <ext4_utils/ext4_utils.h>
+#include <fs_mgr.h>
+#include <healthhalutils/HealthHalUtils.h>
+#include <liblp/liblp.h>
#include "fastboot_device.h"
#include "flashing.h"
@@ -31,145 +34,393 @@
using ::android::hardware::boot::V1_0::BoolResult;
using ::android::hardware::boot::V1_0::Slot;
+using ::android::hardware::fastboot::V1_0::FileSystemType;
+using ::android::hardware::fastboot::V1_0::Result;
+using ::android::hardware::fastboot::V1_0::Status;
+using namespace android::fs_mgr;
-constexpr int kMaxDownloadSizeDefault = 0x20000000;
constexpr char kFastbootProtocolVersion[] = "0.4";
-bool GetVersion(FastbootDevice* device, const std::vector<std::string>& /* args */) {
- return device->WriteOkay(kFastbootProtocolVersion);
+bool GetVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ *message = kFastbootProtocolVersion;
+ return true;
}
-bool GetBootloaderVersion(FastbootDevice* device, const std::vector<std::string>& /* args */) {
- return device->WriteOkay(android::base::GetProperty("ro.bootloader", ""));
+bool GetBootloaderVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ *message = android::base::GetProperty("ro.bootloader", "");
+ return true;
}
-bool GetBasebandVersion(FastbootDevice* device, const std::vector<std::string>& /* args */) {
- return device->WriteOkay(android::base::GetProperty("ro.build.expect.baseband", ""));
+bool GetBasebandVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ *message = android::base::GetProperty("ro.build.expect.baseband", "");
+ return true;
}
-bool GetProduct(FastbootDevice* device, const std::vector<std::string>& /* args */) {
- return device->WriteOkay(android::base::GetProperty("ro.product.device", ""));
+bool GetProduct(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ *message = android::base::GetProperty("ro.product.device", "");
+ return true;
}
-bool GetSerial(FastbootDevice* device, const std::vector<std::string>& /* args */) {
- return device->WriteOkay(android::base::GetProperty("ro.serialno", ""));
+bool GetSerial(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ *message = android::base::GetProperty("ro.serialno", "");
+ return true;
}
-bool GetSecure(FastbootDevice* device, const std::vector<std::string>& /* args */) {
- return device->WriteOkay(android::base::GetBoolProperty("ro.secure", "") ? "yes" : "no");
+bool GetSecure(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ *message = android::base::GetBoolProperty("ro.secure", "") ? "yes" : "no";
+ return true;
}
-bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& /* args */) {
+bool GetVariant(FastbootDevice* device, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ auto fastboot_hal = device->fastboot_hal();
+ if (!fastboot_hal) {
+ *message = "Fastboot HAL not found";
+ return false;
+ }
+
+ Result ret;
+ auto ret_val = fastboot_hal->getVariant([&](std::string device_variant, Result result) {
+ *message = device_variant;
+ ret = result;
+ });
+ if (!ret_val.isOk() || ret.status != Status::SUCCESS) {
+ *message = "Unable to get device variant";
+ return false;
+ }
+
+ return true;
+}
+
+bool GetBatteryVoltageHelper(FastbootDevice* device, int32_t* battery_voltage) {
+ using android::hardware::health::V2_0::HealthInfo;
+ using android::hardware::health::V2_0::Result;
+
+ auto health_hal = device->health_hal();
+ if (!health_hal) {
+ return false;
+ }
+
+ Result ret;
+ auto ret_val = health_hal->getHealthInfo([&](Result result, HealthInfo info) {
+ *battery_voltage = info.legacy.batteryVoltage;
+ ret = result;
+ });
+ if (!ret_val.isOk() || (ret != Result::SUCCESS)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool GetBatterySoCOk(FastbootDevice* device, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ int32_t battery_voltage = 0;
+ if (!GetBatteryVoltageHelper(device, &battery_voltage)) {
+ *message = "Unable to read battery voltage";
+ return false;
+ }
+
+ auto fastboot_hal = device->fastboot_hal();
+ if (!fastboot_hal) {
+ *message = "Fastboot HAL not found";
+ return false;
+ }
+
+ Result ret;
+ auto ret_val = fastboot_hal->getBatteryVoltageFlashingThreshold(
+ [&](int32_t voltage_threshold, Result result) {
+ *message = battery_voltage >= voltage_threshold ? "yes" : "no";
+ ret = result;
+ });
+
+ if (!ret_val.isOk() || ret.status != Status::SUCCESS) {
+ *message = "Unable to get battery voltage flashing threshold";
+ return false;
+ }
+
+ return true;
+}
+
+bool GetOffModeChargeState(FastbootDevice* device, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ auto fastboot_hal = device->fastboot_hal();
+ if (!fastboot_hal) {
+ *message = "Fastboot HAL not found";
+ return false;
+ }
+
+ Result ret;
+ auto ret_val =
+ fastboot_hal->getOffModeChargeState([&](bool off_mode_charging_state, Result result) {
+ *message = off_mode_charging_state ? "1" : "0";
+ ret = result;
+ });
+ if (!ret_val.isOk() || (ret.status != Status::SUCCESS)) {
+ *message = "Unable to get off mode charge state";
+ return false;
+ }
+
+ return true;
+}
+
+bool GetBatteryVoltage(FastbootDevice* device, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ int32_t battery_voltage = 0;
+ if (GetBatteryVoltageHelper(device, &battery_voltage)) {
+ *message = std::to_string(battery_voltage);
+ return true;
+ }
+ *message = "Unable to get battery voltage";
+ return false;
+}
+
+bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& /* args */,
+ std::string* message) {
std::string suffix = device->GetCurrentSlot();
- std::string slot = suffix.size() == 2 ? suffix.substr(1) : suffix;
- return device->WriteOkay(slot);
+ *message = suffix.size() == 2 ? suffix.substr(1) : suffix;
+ return true;
}
-bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& /* args */) {
+bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& /* args */,
+ std::string* message) {
auto boot_control_hal = device->boot_control_hal();
if (!boot_control_hal) {
- return "0";
+ *message = "0";
+ } else {
+ *message = std::to_string(boot_control_hal->getNumberSlots());
}
- return device->WriteOkay(std::to_string(boot_control_hal->getNumberSlots()));
+ return true;
}
-bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args) {
+bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message) {
if (args.empty()) {
- return device->WriteFail("Missing argument");
+ *message = "Missing argument";
+ return false;
}
Slot slot;
if (!GetSlotNumber(args[0], &slot)) {
- return device->WriteFail("Invalid slot");
+ *message = "Invalid slot";
+ return false;
}
auto boot_control_hal = device->boot_control_hal();
if (!boot_control_hal) {
- return device->WriteFail("Device has no slots");
+ *message = "Device has no slots";
+ return false;
}
if (boot_control_hal->isSlotMarkedSuccessful(slot) != BoolResult::TRUE) {
- return device->WriteOkay("no");
+ *message = "no";
+ } else {
+ *message = "yes";
}
- return device->WriteOkay("yes");
+ return true;
}
-bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args) {
+bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message) {
if (args.empty()) {
- return device->WriteFail("Missing argument");
+ *message = "Missing argument";
+ return false;
}
Slot slot;
if (!GetSlotNumber(args[0], &slot)) {
- return device->WriteFail("Invalid slot");
+ *message = "Invalid slot";
+ return false;
}
auto boot_control_hal = device->boot_control_hal();
if (!boot_control_hal) {
- return device->WriteFail("Device has no slots");
+ *message = "Device has no slots";
+ return false;
}
if (boot_control_hal->isSlotBootable(slot) != BoolResult::TRUE) {
- return device->WriteOkay("yes");
+ *message = "yes";
+ } else {
+ *message = "no";
}
- return device->WriteOkay("no");
+ return true;
}
-bool GetMaxDownloadSize(FastbootDevice* device, const std::vector<std::string>& /* args */) {
- return device->WriteOkay(std::to_string(kMaxDownloadSizeDefault));
+bool GetMaxDownloadSize(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ *message = android::base::StringPrintf("0x%X", kMaxDownloadSizeDefault);
+ return true;
}
-bool GetUnlocked(FastbootDevice* device, const std::vector<std::string>& /* args */) {
- return device->WriteOkay("yes");
+bool GetUnlocked(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ *message = GetDeviceLockStatus() ? "no" : "yes";
+ return true;
}
-bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args) {
+bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message) {
if (args.empty()) {
- return device->WriteFail("Missing argument");
+ *message = "Missing argument";
+ return false;
}
std::string slot_suffix = device->GetCurrentSlot();
if (slot_suffix.empty()) {
- return device->WriteOkay("no");
+ *message = "no";
+ return true;
}
std::string partition_name = args[0] + slot_suffix;
- if (FindPhysicalPartition(partition_name) ||
- LogicalPartitionExists(partition_name, slot_suffix)) {
- return device->WriteOkay("yes");
+ if (FindPhysicalPartition(partition_name) || LogicalPartitionExists(device, partition_name)) {
+ *message = "yes";
+ } else {
+ *message = "no";
}
- return device->WriteOkay("no");
+ return true;
}
-bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args) {
+bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message) {
if (args.size() < 1) {
- return device->WriteFail("Missing argument");
+ *message = "Missing argument";
+ return false;
}
// Zero-length partitions cannot be created through device-mapper, so we
// special case them here.
bool is_zero_length;
- if (LogicalPartitionExists(args[0], device->GetCurrentSlot(), &is_zero_length) &&
- is_zero_length) {
- return device->WriteOkay("0");
+ if (LogicalPartitionExists(device, args[0], &is_zero_length) && is_zero_length) {
+ *message = "0x0";
+ return true;
}
// Otherwise, open the partition as normal.
PartitionHandle handle;
if (!OpenPartition(device, args[0], &handle)) {
- return device->WriteFail("Could not open partition");
+ *message = "Could not open partition";
+ return false;
}
uint64_t size = get_block_device_size(handle.fd());
- return device->WriteOkay(android::base::StringPrintf("%" PRIX64, size));
+ *message = android::base::StringPrintf("0x%" PRIX64, size);
+ return true;
}
-bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args) {
+bool GetPartitionType(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message) {
if (args.size() < 1) {
- return device->WriteFail("Missing argument");
+ *message = "Missing argument";
+ return false;
+ }
+
+ std::string partition_name = args[0];
+ if (!FindPhysicalPartition(partition_name) && !LogicalPartitionExists(device, partition_name)) {
+ *message = "Invalid partition";
+ return false;
+ }
+
+ auto fastboot_hal = device->fastboot_hal();
+ if (!fastboot_hal) {
+ *message = "Fastboot HAL not found";
+ return false;
+ }
+
+ FileSystemType type;
+ Result ret;
+ auto ret_val =
+ fastboot_hal->getPartitionType(args[0], [&](FileSystemType fs_type, Result result) {
+ type = fs_type;
+ ret = result;
+ });
+ if (!ret_val.isOk() || (ret.status != Status::SUCCESS)) {
+ *message = "Unable to retrieve partition type";
+ } else {
+ switch (type) {
+ case FileSystemType::RAW:
+ *message = "raw";
+ return true;
+ case FileSystemType::EXT4:
+ *message = "ext4";
+ return true;
+ case FileSystemType::F2FS:
+ *message = "f2fs";
+ return true;
+ default:
+ *message = "Unknown file system type";
+ }
+ }
+
+ return false;
+}
+
+bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message) {
+ if (args.size() < 1) {
+ *message = "Missing argument";
+ return false;
}
// Note: if a partition name is in both the GPT and the super partition, we
// return "true", to be consistent with prefering to flash logical partitions
// over physical ones.
std::string partition_name = args[0];
- if (LogicalPartitionExists(partition_name, device->GetCurrentSlot())) {
- return device->WriteOkay("yes");
+ if (LogicalPartitionExists(device, partition_name)) {
+ *message = "yes";
+ return true;
}
if (FindPhysicalPartition(partition_name)) {
- return device->WriteOkay("no");
+ *message = "no";
+ return true;
}
- return device->WriteFail("Partition not found");
+ *message = "Partition not found";
+ return false;
}
-bool GetIsUserspace(FastbootDevice* device, const std::vector<std::string>& /* args */) {
- return device->WriteOkay("yes");
+bool GetIsUserspace(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ *message = "yes";
+ return true;
+}
+
+std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device) {
+ std::vector<std::vector<std::string>> args;
+ auto partitions = ListPartitions(device);
+ for (const auto& partition : partitions) {
+ args.emplace_back(std::initializer_list<std::string>{partition});
+ }
+ return args;
+}
+
+std::vector<std::vector<std::string>> GetAllPartitionArgsNoSlot(FastbootDevice* device) {
+ auto partitions = ListPartitions(device);
+
+ std::string slot_suffix = device->GetCurrentSlot();
+ if (!slot_suffix.empty()) {
+ auto names = std::move(partitions);
+ for (const auto& name : names) {
+ std::string slotless_name = name;
+ if (android::base::EndsWith(name, "_a") || android::base::EndsWith(name, "_b")) {
+ slotless_name = name.substr(0, name.rfind("_"));
+ }
+ if (std::find(partitions.begin(), partitions.end(), slotless_name) ==
+ partitions.end()) {
+ partitions.emplace_back(slotless_name);
+ }
+ }
+ }
+
+ std::vector<std::vector<std::string>> args;
+ for (const auto& partition : partitions) {
+ args.emplace_back(std::initializer_list<std::string>{partition});
+ }
+ return args;
+}
+
+bool GetHardwareRevision(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ *message = android::base::GetProperty("ro.revision", "");
+ return true;
+}
+
+bool GetSuperPartitionName(FastbootDevice* device, const std::vector<std::string>& /* args */,
+ std::string* message) {
+ uint32_t slot_number = SlotNumberForSlotSuffix(device->GetCurrentSlot());
+ *message = fs_mgr_get_super_partition_name(slot_number);
+ return true;
}
diff --git a/fastboot/device/variables.h b/fastboot/device/variables.h
index 554a080..015a4c5 100644
--- a/fastboot/device/variables.h
+++ b/fastboot/device/variables.h
@@ -21,19 +21,47 @@
class FastbootDevice;
-bool GetVersion(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetBootloaderVersion(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetBasebandVersion(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetProduct(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetSerial(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetSecure(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetMaxDownloadSize(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetUnlocked(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args);
-bool GetIsUserspace(FastbootDevice* device, const std::vector<std::string>& args);
+bool GetVersion(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
+bool GetBootloaderVersion(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetBasebandVersion(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetProduct(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
+bool GetSerial(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
+bool GetSecure(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
+bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetMaxDownloadSize(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetUnlocked(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
+bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetPartitionType(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetIsUserspace(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetHardwareRevision(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetVariant(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
+bool GetOffModeChargeState(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetBatteryVoltage(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetBatterySoCOk(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+bool GetSuperPartitionName(FastbootDevice* device, const std::vector<std::string>& args,
+ std::string* message);
+
+// Helpers for getvar all.
+std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device);
+std::vector<std::vector<std::string>> GetAllPartitionArgsNoSlot(FastbootDevice* device);
diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp
deleted file mode 100644
index 6a52b12..0000000
--- a/fastboot/engine.cpp
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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 COPYRIGHT HOLDERS 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
- * COPYRIGHT OWNER 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.
- */
-#include "engine.h"
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-#include <vector>
-
-#include <android-base/stringprintf.h>
-
-#include "constants.h"
-#include "transport.h"
-
-enum Op {
- OP_DOWNLOAD,
- OP_COMMAND,
- OP_QUERY,
- OP_NOTICE,
- OP_DOWNLOAD_SPARSE,
- OP_WAIT_FOR_DISCONNECT,
- OP_DOWNLOAD_FD,
- OP_UPLOAD,
-};
-
-struct Action {
- Action(Op op, const std::string& cmd) : op(op), cmd(cmd) {}
-
- Op op;
- std::string cmd;
- std::string msg;
-
- std::string product;
-
- void* data = nullptr;
- // The protocol only supports 32-bit sizes, so you'll have to break
- // anything larger into multiple chunks.
- uint32_t size = 0;
-
- int fd = -1;
-
- int (*func)(Action& a, int status, const char* resp) = nullptr;
-
- double start = -1;
-};
-
-static std::vector<std::unique_ptr<Action>> action_list;
-static fastboot::FastBootDriver* fb = nullptr;
-
-static constexpr char kStatusFormat[] = "%-50s ";
-
-void fb_init(fastboot::FastBootDriver& fbi) {
- fb = &fbi;
- auto cb = [](std::string& info) { fprintf(stderr, "(bootloader) %s\n", info.c_str()); };
- fb->SetInfoCallback(cb);
-}
-
-void fb_reinit(Transport* transport) {
- fb->set_transport(transport);
-}
-
-const std::string fb_get_error() {
- return fb->Error();
-}
-
-bool fb_getvar(const std::string& key, std::string* value) {
- return !fb->GetVar(key, value);
-}
-
-static int cb_default(Action& a, int status, const char* resp) {
- if (status) {
- fprintf(stderr,"FAILED (%s)\n", resp);
- } else {
- double split = now();
- fprintf(stderr, "OKAY [%7.3fs]\n", (split - a.start));
- a.start = split;
- }
- return status;
-}
-
-static Action& queue_action(Op op, const std::string& cmd) {
- std::unique_ptr<Action> a{new Action(op, cmd)};
- a->func = cb_default;
-
- action_list.push_back(std::move(a));
- return *action_list.back();
-}
-
-void fb_set_active(const std::string& slot) {
- Action& a = queue_action(OP_COMMAND, FB_CMD_SET_ACTIVE ":" + slot);
- a.msg = "Setting current slot to '" + slot + "'";
-}
-
-void fb_queue_erase(const std::string& partition) {
- Action& a = queue_action(OP_COMMAND, FB_CMD_ERASE ":" + partition);
- a.msg = "Erasing '" + partition + "'";
-}
-
-void fb_queue_flash_fd(const std::string& partition, int fd, uint32_t sz) {
- Action& a = queue_action(OP_DOWNLOAD_FD, "");
- a.fd = fd;
- a.size = sz;
- a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024);
-
- Action& b = queue_action(OP_COMMAND, FB_CMD_FLASH ":" + partition);
- b.msg = "Writing '" + partition + "'";
-}
-
-void fb_queue_flash(const std::string& partition, void* data, uint32_t sz) {
- Action& a = queue_action(OP_DOWNLOAD, "");
- a.data = data;
- a.size = sz;
- a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024);
-
- Action& b = queue_action(OP_COMMAND, FB_CMD_FLASH ":" + partition);
- b.msg = "Writing '" + partition + "'";
-}
-
-void fb_queue_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
- size_t current, size_t total) {
- Action& a = queue_action(OP_DOWNLOAD_SPARSE, "");
- a.data = s;
- a.size = 0;
- a.msg = android::base::StringPrintf("Sending sparse '%s' %zu/%zu (%u KB)", partition.c_str(),
- current, total, sz / 1024);
-
- Action& b = queue_action(OP_COMMAND, FB_CMD_FLASH ":" + partition);
- b.msg = android::base::StringPrintf("Writing sparse '%s' %zu/%zu", partition.c_str(), current,
- total);
-}
-
-void fb_queue_create_partition(const std::string& partition, const std::string& size) {
- Action& a = queue_action(OP_COMMAND, FB_CMD_CREATE_PARTITION ":" + partition + ":" + size);
- a.msg = "Creating '" + partition + "'";
-}
-
-void fb_queue_delete_partition(const std::string& partition) {
- Action& a = queue_action(OP_COMMAND, FB_CMD_DELETE_PARTITION ":" + partition);
- a.msg = "Deleting '" + partition + "'";
-}
-
-void fb_queue_resize_partition(const std::string& partition, const std::string& size) {
- Action& a = queue_action(OP_COMMAND, FB_CMD_RESIZE_PARTITION ":" + partition + ":" + size);
- a.msg = "Resizing '" + partition + "'";
-}
-
-static int match(const char* str, const char** value, unsigned count) {
- unsigned n;
-
- for (n = 0; n < count; n++) {
- const char *val = value[n];
- int len = strlen(val);
- int match;
-
- if ((len > 1) && (val[len-1] == '*')) {
- len--;
- match = !strncmp(val, str, len);
- } else {
- match = !strcmp(val, str);
- }
-
- if (match) return 1;
- }
-
- return 0;
-}
-
-static int cb_check(Action& a, int status, const char* resp, int invert) {
- const char** value = reinterpret_cast<const char**>(a.data);
- unsigned count = a.size;
- unsigned n;
-
- if (status) {
- fprintf(stderr,"FAILED (%s)\n", resp);
- return status;
- }
-
- if (!a.product.empty()) {
- if (a.product != cur_product) {
- double split = now();
- fprintf(stderr, "IGNORE, product is %s required only for %s [%7.3fs]\n", cur_product,
- a.product.c_str(), (split - a.start));
- a.start = split;
- return 0;
- }
- }
-
- int yes = match(resp, value, count);
- if (invert) yes = !yes;
-
- if (yes) {
- double split = now();
- fprintf(stderr, "OKAY [%7.3fs]\n", (split - a.start));
- a.start = split;
- return 0;
- }
-
- fprintf(stderr, "FAILED\n\n");
- fprintf(stderr, "Device %s is '%s'.\n", a.cmd.c_str() + 7, resp);
- fprintf(stderr, "Update %s '%s'", invert ? "rejects" : "requires", value[0]);
- for (n = 1; n < count; n++) {
- fprintf(stderr, " or '%s'", value[n]);
- }
- fprintf(stderr, ".\n\n");
- return -1;
-}
-
-static int cb_require(Action& a, int status, const char* resp) {
- return cb_check(a, status, resp, 0);
-}
-
-static int cb_reject(Action& a, int status, const char* resp) {
- return cb_check(a, status, resp, 1);
-}
-
-void fb_queue_require(const std::string& product, const std::string& var, bool invert,
- size_t nvalues, const char** values) {
- Action& a = queue_action(OP_QUERY, FB_CMD_GETVAR ":" + var);
- a.product = product;
- a.data = values;
- a.size = nvalues;
- a.msg = "Checking " + var;
- a.func = invert ? cb_reject : cb_require;
- if (a.data == nullptr) die("out of memory");
-}
-
-static int cb_display(Action& a, int status, const char* resp) {
- if (status) {
- fprintf(stderr, "%s FAILED (%s)\n", a.cmd.c_str(), resp);
- return status;
- }
- fprintf(stderr, "%s: %s\n", static_cast<const char*>(a.data), resp);
- free(static_cast<char*>(a.data));
- return 0;
-}
-
-void fb_queue_display(const std::string& label, const std::string& var) {
- Action& a = queue_action(OP_QUERY, FB_CMD_GETVAR ":" + var);
- a.data = xstrdup(label.c_str());
- a.func = cb_display;
-}
-
-static int cb_save(Action& a, int status, const char* resp) {
- if (status) {
- fprintf(stderr, "%s FAILED (%s)\n", a.cmd.c_str(), resp);
- return status;
- }
- strncpy(reinterpret_cast<char*>(a.data), resp, a.size);
- return 0;
-}
-
-void fb_queue_query_save(const std::string& var, char* dest, uint32_t dest_size) {
- Action& a = queue_action(OP_QUERY, FB_CMD_GETVAR ":" + var);
- a.data = dest;
- a.size = dest_size;
- a.func = cb_save;
-}
-
-static int cb_do_nothing(Action&, int, const char*) {
- fprintf(stderr, "\n");
- return 0;
-}
-
-void fb_queue_reboot() {
- Action& a = queue_action(OP_COMMAND, FB_CMD_REBOOT);
- a.func = cb_do_nothing;
- a.msg = "Rebooting";
-}
-
-void fb_queue_command(const std::string& cmd, const std::string& msg) {
- Action& a = queue_action(OP_COMMAND, cmd);
- a.msg = msg;
-}
-
-void fb_queue_download(const std::string& name, void* data, uint32_t size) {
- Action& a = queue_action(OP_DOWNLOAD, "");
- a.data = data;
- a.size = size;
- a.msg = "Downloading '" + name + "'";
-}
-
-void fb_queue_download_fd(const std::string& name, int fd, uint32_t sz) {
- Action& a = queue_action(OP_DOWNLOAD_FD, "");
- a.fd = fd;
- a.size = sz;
- a.msg = android::base::StringPrintf("Sending '%s' (%u KB)", name.c_str(), sz / 1024);
-}
-
-void fb_queue_upload(const std::string& outfile) {
- Action& a = queue_action(OP_UPLOAD, "");
- a.data = xstrdup(outfile.c_str());
- a.msg = "Uploading '" + outfile + "'";
-}
-
-void fb_queue_notice(const std::string& notice) {
- Action& a = queue_action(OP_NOTICE, "");
- a.msg = notice;
-}
-
-void fb_queue_wait_for_disconnect() {
- queue_action(OP_WAIT_FOR_DISCONNECT, "");
-}
-
-int64_t fb_execute_queue() {
- int64_t status = 0;
- for (auto& a : action_list) {
- a->start = now();
- if (!a->msg.empty()) {
- fprintf(stderr, kStatusFormat, a->msg.c_str());
- verbose("\n");
- }
- if (a->op == OP_DOWNLOAD) {
- char* cbuf = static_cast<char*>(a->data);
- status = fb->Download(cbuf, a->size);
- status = a->func(*a, status, status ? fb_get_error().c_str() : "");
- if (status) break;
- } else if (a->op == OP_DOWNLOAD_FD) {
- status = fb->Download(a->fd, a->size);
- status = a->func(*a, status, status ? fb_get_error().c_str() : "");
- if (status) break;
- } else if (a->op == OP_COMMAND) {
- status = fb->RawCommand(a->cmd);
- status = a->func(*a, status, status ? fb_get_error().c_str() : "");
- if (status) break;
- } else if (a->op == OP_QUERY) {
- std::string resp;
- status = fb->RawCommand(a->cmd, &resp);
- status = a->func(*a, status, status ? fb_get_error().c_str() : resp.c_str());
- if (status) break;
- } else if (a->op == OP_NOTICE) {
- // We already showed the notice because it's in `Action::msg`.
- fprintf(stderr, "\n");
- } else if (a->op == OP_DOWNLOAD_SPARSE) {
- status = fb->Download(reinterpret_cast<sparse_file*>(a->data));
- status = a->func(*a, status, status ? fb_get_error().c_str() : "");
- if (status) break;
- } else if (a->op == OP_WAIT_FOR_DISCONNECT) {
- fb->WaitForDisconnect();
- } else if (a->op == OP_UPLOAD) {
- status = fb->Upload(reinterpret_cast<const char*>(a->data));
- status = a->func(*a, status, status ? fb_get_error().c_str() : "");
- } else {
- die("unknown action: %d", a->op);
- }
- }
- action_list.clear();
- return status;
-}
-
-bool fb_reboot_to_userspace() {
- // First ensure that the queue is flushed.
- fb_execute_queue();
-
- fprintf(stderr, kStatusFormat, "Rebooting to userspace fastboot");
- verbose("\n");
-
- if (fb->RebootTo("fastboot") != fastboot::RetCode::SUCCESS) {
- fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
- return false;
- }
- fprintf(stderr, "OKAY\n");
-
- fb->set_transport(nullptr);
- return true;
-}
diff --git a/fastboot/engine.h b/fastboot/engine.h
deleted file mode 100644
index f098ca7..0000000
--- a/fastboot/engine.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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 COPYRIGHT HOLDERS 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
- * COPYRIGHT OWNER 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.
- */
-
-#pragma once
-
-#include <inttypes.h>
-#include <stdlib.h>
-
-#include <string>
-
-#include <bootimg.h>
-#include "fastboot_driver.h"
-#include "util.h"
-
-#include "constants.h"
-
-class Transport;
-struct sparse_file;
-
-const std::string fb_get_error();
-
-//#define FB_COMMAND_SZ (fastboot::FB_COMMAND_SZ)
-//#define FB_RESPONSE_SZ (fastboot::FB_RESPONSE_SZ)
-
-/* engine.c - high level command queue engine */
-
-void fb_init(fastboot::FastBootDriver& fbi);
-void fb_reinit(Transport* transport);
-
-bool fb_getvar(const std::string& key, std::string* value);
-void fb_queue_flash(const std::string& partition, void* data, uint32_t sz);
-void fb_queue_flash_fd(const std::string& partition, int fd, uint32_t sz);
-void fb_queue_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz,
- size_t current, size_t total);
-void fb_queue_erase(const std::string& partition);
-void fb_queue_format(const std::string& partition, int skip_if_not_supported, int32_t max_chunk_sz);
-void fb_queue_require(const std::string& prod, const std::string& var, bool invert, size_t nvalues,
- const char** values);
-void fb_queue_display(const std::string& label, const std::string& var);
-void fb_queue_query_save(const std::string& var, char* dest, uint32_t dest_size);
-void fb_queue_reboot(void);
-void fb_queue_command(const std::string& cmd, const std::string& msg);
-void fb_queue_download(const std::string& name, void* data, uint32_t size);
-void fb_queue_download_fd(const std::string& name, int fd, uint32_t sz);
-void fb_queue_upload(const std::string& outfile);
-void fb_queue_notice(const std::string& notice);
-void fb_queue_wait_for_disconnect(void);
-void fb_queue_create_partition(const std::string& partition, const std::string& size);
-void fb_queue_delete_partition(const std::string& partition);
-void fb_queue_resize_partition(const std::string& partition, const std::string& size);
-int64_t fb_execute_queue();
-void fb_set_active(const std::string& slot);
-bool fb_reboot_to_userspace();
-
-/* Current product */
-extern char cur_product[FB_RESPONSE_SZ + 1];
-
-class FastBootTool {
- public:
- int Main(int argc, char* argv[]);
-
- void ParseOsPatchLevel(boot_img_hdr_v1*, const char*);
- void ParseOsVersion(boot_img_hdr_v1*, const char*);
-};
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 2887d3b..d753f0f 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -26,6 +26,8 @@
* SUCH DAMAGE.
*/
+#include "fastboot.h"
+
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -43,6 +45,8 @@
#include <chrono>
#include <functional>
+#include <regex>
+#include <string>
#include <thread>
#include <utility>
#include <vector>
@@ -53,29 +57,29 @@
#include <android-base/parsenetaddress.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <android-base/test_utils.h>
#include <android-base/unique_fd.h>
#include <build/version.h>
+#include <liblp/liblp.h>
#include <platform_tools_version.h>
#include <sparse/sparse.h>
#include <ziparchive/zip_archive.h>
#include "bootimg_utils.h"
+#include "constants.h"
#include "diagnose_usb.h"
-#include "engine.h"
+#include "fastboot_driver.h"
#include "fs.h"
#include "tcp.h"
#include "transport.h"
#include "udp.h"
#include "usb.h"
+#include "util.h"
+using android::base::ReadFully;
+using android::base::Split;
+using android::base::Trim;
using android::base::unique_fd;
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-char cur_product[FB_RESPONSE_SZ + 1];
+using namespace std::string_literals;
static const char* serial = nullptr;
@@ -96,6 +100,8 @@
static const std::string convert_fbe_marker_filename("convert_fbe");
+fastboot::FastBootDriver* fb = nullptr;
+
enum fb_buffer_type {
FB_BUFFER_FD,
FB_BUFFER_SPARSE,
@@ -148,14 +154,27 @@
{ 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 },
+ { "vbmeta_system",
+ "vbmeta_system.img",
+ "vbmeta_system.sig",
+ "vbmeta_system",
+ true, ImageType::BootCritical },
{ "vendor", "vendor.img", "vendor.sig", "vendor", true, ImageType::Normal },
{ nullptr, "vendor_other.img", "vendor.sig", "vendor", true, ImageType::Normal },
// clang-format on
};
-static std::string find_item_given_name(const std::string& img_name) {
+static char* get_android_product_out() {
char* dir = getenv("ANDROID_PRODUCT_OUT");
if (dir == nullptr || dir[0] == '\0') {
+ return nullptr;
+ }
+ return dir;
+}
+
+static std::string find_item_given_name(const std::string& img_name) {
+ char* dir = get_android_product_out();
+ if (!dir) {
die("ANDROID_PRODUCT_OUT not set");
}
return std::string(dir) + "/" + img_name;
@@ -172,40 +191,46 @@
return "";
}
+double last_start_time;
+
+static void Status(const std::string& message) {
+ static constexpr char kStatusFormat[] = "%-50s ";
+ fprintf(stderr, kStatusFormat, message.c_str());
+ last_start_time = now();
+}
+
+static void Epilog(int status) {
+ if (status) {
+ fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
+ die("Command failed");
+ } else {
+ double split = now();
+ fprintf(stderr, "OKAY [%7.3fs]\n", (split - last_start_time));
+ }
+}
+
+static void InfoMessage(const std::string& info) {
+ fprintf(stderr, "(bootloader) %s\n", info.c_str());
+}
+
static int64_t get_file_size(int fd) {
struct stat sb;
- return fstat(fd, &sb) == -1 ? -1 : sb.st_size;
+ if (fstat(fd, &sb) == -1) {
+ die("could not get file size");
+ }
+ return sb.st_size;
}
-static void* load_fd(int fd, int64_t* sz) {
- int errno_tmp;
- char* data = nullptr;
+bool ReadFileToVector(const std::string& file, std::vector<char>* out) {
+ out->clear();
- *sz = get_file_size(fd);
- if (*sz < 0) {
- goto oops;
+ unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY)));
+ if (fd == -1) {
+ return false;
}
- data = (char*) malloc(*sz);
- if (data == nullptr) goto oops;
-
- if(read(fd, data, *sz) != *sz) goto oops;
- close(fd);
-
- return data;
-
-oops:
- errno_tmp = errno;
- close(fd);
- if(data != 0) free(data);
- errno = errno_tmp;
- return 0;
-}
-
-static void* load_file(const std::string& path, int64_t* sz) {
- int fd = open(path.c_str(), O_RDONLY | O_BINARY);
- if (fd == -1) return nullptr;
- return load_fd(fd, sz);
+ out->resize(get_file_size(fd));
+ return ReadFully(fd, out->data(), out->size());
}
static int match_fastboot_with_serial(usb_ifc_info* info, const char* local_serial) {
@@ -362,6 +387,7 @@
" Format a flash partition.\n"
" 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"
"\n"
"boot image:\n"
" boot KERNEL [RAMDISK [SECOND]]\n"
@@ -393,6 +419,7 @@
" -s SERIAL Specify a USB device.\n"
" -s tcp|udp:HOST[:PORT] Specify a network device.\n"
" -S SIZE[K|M|G] Break into sparse files no larger than SIZE.\n"
+ " --force Force a flash operation that may be unsafe.\n"
" --slot SLOT Use SLOT; 'all' for both slots, 'other' for\n"
" non-current slot (default: current active slot).\n"
" --set-active[=SLOT] Sets the active slot before rebooting.\n"
@@ -413,70 +440,71 @@
return 0;
}
-static void* load_bootable_image(const std::string& kernel, const std::string& ramdisk,
- const std::string& second_stage, int64_t* sz) {
- int64_t ksize;
- void* kdata = load_file(kernel.c_str(), &ksize);
- if (kdata == nullptr) die("cannot load '%s': %s", kernel.c_str(), strerror(errno));
+static std::vector<char> LoadBootableImage(const std::string& kernel, const std::string& ramdisk,
+ const std::string& second_stage) {
+ std::vector<char> kernel_data;
+ if (!ReadFileToVector(kernel, &kernel_data)) {
+ die("cannot load '%s': %s", kernel.c_str(), strerror(errno));
+ }
// Is this actually a boot image?
- if (ksize < static_cast<int64_t>(sizeof(boot_img_hdr_v1))) {
+ if (kernel_data.size() < sizeof(boot_img_hdr_v1)) {
die("cannot load '%s': too short", kernel.c_str());
}
- if (!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
+ if (!memcmp(kernel_data.data(), BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
if (!g_cmdline.empty()) {
- bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v1*>(kdata), g_cmdline);
+ bootimg_set_cmdline(reinterpret_cast<boot_img_hdr_v1*>(kernel_data.data()), g_cmdline);
}
if (!ramdisk.empty()) die("cannot boot a boot.img *and* ramdisk");
- *sz = ksize;
- return kdata;
+ return kernel_data;
}
- void* rdata = nullptr;
- int64_t rsize = 0;
+ std::vector<char> ramdisk_data;
if (!ramdisk.empty()) {
- rdata = load_file(ramdisk.c_str(), &rsize);
- if (rdata == nullptr) die("cannot load '%s': %s", ramdisk.c_str(), strerror(errno));
+ if (!ReadFileToVector(ramdisk, &ramdisk_data)) {
+ die("cannot load '%s': %s", ramdisk.c_str(), strerror(errno));
+ }
}
- void* sdata = nullptr;
- int64_t ssize = 0;
+ std::vector<char> second_stage_data;
if (!second_stage.empty()) {
- sdata = load_file(second_stage.c_str(), &ssize);
- if (sdata == nullptr) die("cannot load '%s': %s", second_stage.c_str(), strerror(errno));
+ if (!ReadFileToVector(second_stage, &second_stage_data)) {
+ die("cannot load '%s': %s", second_stage.c_str(), strerror(errno));
+ }
}
-
fprintf(stderr,"creating boot image...\n");
- boot_img_hdr_v1* bdata = mkbootimg(kdata, ksize, rdata, rsize, sdata, ssize,
- g_base_addr, g_boot_img_hdr, sz);
- if (bdata == nullptr) die("failed to create boot.img");
- if (!g_cmdline.empty()) bootimg_set_cmdline(bdata, g_cmdline);
- fprintf(stderr, "creating boot image - %" PRId64 " bytes\n", *sz);
+ std::vector<char> out;
+ boot_img_hdr_v1* boot_image_data = mkbootimg(kernel_data, ramdisk_data, second_stage_data,
+ g_base_addr, g_boot_img_hdr, &out);
- return bdata;
+ if (!g_cmdline.empty()) bootimg_set_cmdline(boot_image_data, g_cmdline);
+ fprintf(stderr, "creating boot image - %zu bytes\n", out.size());
+
+ return out;
}
-static void* unzip_to_memory(ZipArchiveHandle zip, const char* entry_name, int64_t* sz) {
- ZipString zip_entry_name(entry_name);
+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) {
- fprintf(stderr, "archive does not contain '%s'\n", entry_name);
- return nullptr;
+ fprintf(stderr, "archive does not contain '%s'\n", entry_name.c_str());
+ return false;
}
- *sz = zip_entry.uncompressed_length;
+ out->resize(zip_entry.uncompressed_length);
- fprintf(stderr, "extracting %s (%" PRId64 " MB) to RAM...\n", entry_name, *sz / 1024 / 1024);
- uint8_t* data = reinterpret_cast<uint8_t*>(malloc(zip_entry.uncompressed_length));
- if (data == nullptr) die("failed to allocate %" PRId64 " bytes for '%s'", *sz, entry_name);
+ fprintf(stderr, "extracting %s (%zu MB) to RAM...\n", entry_name.c_str(),
+ out->size() / 1024 / 1024);
- int error = ExtractToMemory(zip, &zip_entry, data, zip_entry.uncompressed_length);
- if (error != 0) die("failed to extract '%s': %s", entry_name, ErrorCodeString(error));
+ int error = ExtractToMemory(zip, &zip_entry, reinterpret_cast<uint8_t*>(out->data()),
+ out->size());
+ if (error != 0) die("failed to extract '%s': %s", entry_name.c_str(), ErrorCodeString(error));
- return data;
+ return true;
}
#if defined(_WIN32)
@@ -597,120 +625,168 @@
return fd.release();
}
-static char* strip(char* s) {
- while (*s && isspace(*s)) s++;
+static void CheckRequirement(const std::string& cur_product, const std::string& var,
+ const std::string& product, bool invert,
+ const std::vector<std::string>& options) {
+ Status("Checking '" + var + "'");
- int n = strlen(s);
- while (n-- > 0) {
- if (!isspace(s[n])) break;
- s[n] = 0;
+ double start = now();
+
+ if (!product.empty()) {
+ if (product != cur_product) {
+ double split = now();
+ fprintf(stderr, "IGNORE, product is %s required only for %s [%7.3fs]\n",
+ cur_product.c_str(), product.c_str(), (split - start));
+ return;
+ }
}
- return s;
+
+ std::string var_value;
+ if (fb->GetVar(var, &var_value) != fastboot::SUCCESS) {
+ fprintf(stderr, "FAILED\n\n");
+ fprintf(stderr, "Could not getvar for '%s' (%s)\n\n", var.c_str(),
+ fb->Error().c_str());
+ die("requirements not met!");
+ }
+
+ bool match = false;
+ for (const auto& option : options) {
+ if (option == var_value || (option.back() == '*' &&
+ !var_value.compare(0, option.length() - 1, option, 0,
+ option.length() - 1))) {
+ match = true;
+ break;
+ }
+ }
+
+ if (invert) {
+ match = !match;
+ }
+
+ if (match) {
+ double split = now();
+ fprintf(stderr, "OKAY [%7.3fs]\n", (split - start));
+ return;
+ }
+
+ fprintf(stderr, "FAILED\n\n");
+ fprintf(stderr, "Device %s is '%s'.\n", var.c_str(), var_value.c_str());
+ fprintf(stderr, "Update %s '%s'", invert ? "rejects" : "requires", options[0].c_str());
+ for (auto it = std::next(options.begin()); it != options.end(); ++it) {
+ fprintf(stderr, " or '%s'", it->c_str());
+ }
+ fprintf(stderr, ".\n\n");
+ die("requirements not met!");
}
-#define MAX_OPTIONS 32
-static void check_requirement(char* line) {
- char *val[MAX_OPTIONS];
- unsigned count;
- char *x;
- int invert = 0;
-
+bool ParseRequirementLine(const std::string& line, std::string* name, std::string* product,
+ bool* invert, std::vector<std::string>* options) {
// "require product=alpha|beta|gamma"
// "require version-bootloader=1234"
// "require-for-product:gamma version-bootloader=istanbul|constantinople"
// "require partition-exists=vendor"
+ *product = "";
+ *invert = false;
- char* name = line;
- const char* product = "";
- if (!strncmp(name, "reject ", 7)) {
- name += 7;
- invert = 1;
- } else if (!strncmp(name, "require ", 8)) {
- name += 8;
- invert = 0;
- } else if (!strncmp(name, "require-for-product:", 20)) {
- // Get the product and point name past it
- product = name + 20;
- name = strchr(name, ' ');
- if (!name) die("android-info.txt syntax error: %s", line);
- *name = 0;
- name += 1;
- invert = 0;
+ auto require_reject_regex = std::regex{"(require\\s+|reject\\s+)?\\s*(\\S+)\\s*=\\s*(.*)"};
+ auto require_product_regex =
+ std::regex{"require-for-product:\\s*(\\S+)\\s+(\\S+)\\s*=\\s*(.*)"};
+ std::smatch match_results;
+
+ if (std::regex_match(line, match_results, require_reject_regex)) {
+ *invert = Trim(match_results[1]) == "reject";
+ } else if (std::regex_match(line, match_results, require_product_regex)) {
+ *product = match_results[1];
+ } else {
+ return false;
}
- x = strchr(name, '=');
- if (x == 0) return;
- *x = 0;
- val[0] = x + 1;
+ *name = match_results[2];
+ // Work around an unfortunate name mismatch.
+ if (*name == "board") {
+ *name = "product";
+ }
- name = strip(name);
+ auto raw_options = Split(match_results[3], "|");
+ for (const auto& option : raw_options) {
+ auto trimmed_option = Trim(option);
+ options->emplace_back(trimmed_option);
+ }
- // "require partition-exists=x" is a special case, added because of the trouble we had when
- // Pixel 2 shipped with new partitions and users used old versions of fastboot to flash them,
- // missing out new partitions. A device with new partitions can use "partition-exists" to
- // override the fields `optional_if_no_image` in the `images` array.
- if (!strcmp(name, "partition-exists")) {
- const char* partition_name = val[0];
- std::string has_slot;
- if (!fb_getvar(std::string("has-slot:") + partition_name, &has_slot) ||
- (has_slot != "yes" && has_slot != "no")) {
- die("device doesn't have required partition %s!", partition_name);
+ return true;
+}
+
+// "require partition-exists=x" is a special case, added because of the trouble we had when
+// Pixel 2 shipped with new partitions and users used old versions of fastboot to flash them,
+// missing out new partitions. A device with new partitions can use "partition-exists" to
+// override the fields `optional_if_no_image` in the `images` array.
+static void HandlePartitionExists(const std::vector<std::string>& options) {
+ const std::string& partition_name = options[0];
+ std::string has_slot;
+ if (fb->GetVar("has-slot:" + partition_name, &has_slot) != fastboot::SUCCESS ||
+ (has_slot != "yes" && has_slot != "no")) {
+ die("device doesn't have required partition %s!", partition_name.c_str());
+ }
+ bool known_partition = false;
+ for (size_t i = 0; i < arraysize(images); ++i) {
+ if (images[i].nickname && images[i].nickname == partition_name) {
+ images[i].optional_if_no_image = false;
+ known_partition = true;
}
- bool known_partition = false;
- for (size_t i = 0; i < arraysize(images); ++i) {
- if (images[i].nickname && !strcmp(images[i].nickname, partition_name)) {
- images[i].optional_if_no_image = false;
- known_partition = true;
- }
+ }
+ if (!known_partition) {
+ die("device requires partition %s which is not known to this version of fastboot",
+ partition_name.c_str());
+ }
+}
+
+static void CheckRequirements(const std::string& data) {
+ std::string cur_product;
+ if (fb->GetVar("product", &cur_product) != fastboot::SUCCESS) {
+ fprintf(stderr, "getvar:product FAILED (%s)\n", fb->Error().c_str());
+ }
+
+ auto lines = Split(data, "\n");
+ for (const auto& line : lines) {
+ if (line.empty()) {
+ continue;
}
- if (!known_partition) {
- die("device requires partition %s which is not known to this version of fastboot",
- partition_name);
+
+ std::string name;
+ std::string product;
+ bool invert;
+ std::vector<std::string> options;
+
+ if (!ParseRequirementLine(line, &name, &product, &invert, &options)) {
+ fprintf(stderr, "android-info.txt syntax error: %s\n", line.c_str());
+ continue;
}
+ if (name == "partition-exists") {
+ HandlePartitionExists(options);
+ } else {
+ CheckRequirement(cur_product, name, product, invert, options);
+ }
+ }
+}
+
+static void DisplayVarOrError(const std::string& label, const std::string& var) {
+ std::string value;
+
+ if (fb->GetVar(var, &value) != fastboot::SUCCESS) {
+ Status("getvar:" + var);
+ fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
return;
}
-
- for(count = 1; count < MAX_OPTIONS; count++) {
- x = strchr(val[count - 1],'|');
- if (x == 0) break;
- *x = 0;
- val[count] = x + 1;
- }
-
- // Work around an unfortunate name mismatch.
- const char* var = name;
- if (!strcmp(name, "board")) var = "product";
-
- const char** out = reinterpret_cast<const char**>(malloc(sizeof(char*) * count));
- if (out == nullptr) die("out of memory");
-
- for (size_t i = 0; i < count; ++i) {
- out[i] = xstrdup(strip(val[i]));
- }
-
- fb_queue_require(product, var, invert, count, out);
+ fprintf(stderr, "%s: %s\n", label.c_str(), value.c_str());
}
-static void check_requirements(char* data, int64_t sz) {
- char* s = data;
- while (sz-- > 0) {
- if (*s == '\n') {
- *s++ = 0;
- check_requirement(data);
- data = s;
- } else {
- s++;
- }
- }
- if (fb_execute_queue()) die("requirements not met!");
-}
+static void DumpInfo() {
+ fprintf(stderr, "--------------------------------------------\n");
+ DisplayVarOrError("Bootloader Version...", "version-bootloader");
+ DisplayVarOrError("Baseband Version.....", "version-baseband");
+ DisplayVarOrError("Serial Number........", "serialno");
+ fprintf(stderr, "--------------------------------------------\n");
-static void queue_info_dump() {
- fb_queue_notice("--------------------------------------------");
- fb_queue_display("Bootloader Version...", "version-bootloader");
- fb_queue_display("Baseband Version.....", "version-baseband");
- fb_queue_display("Serial Number........", "serialno");
- fb_queue_notice("--------------------------------------------");
}
static struct sparse_file** load_sparse_files(int fd, int64_t max_size) {
@@ -735,7 +811,7 @@
static int64_t get_target_sparse_limit() {
std::string max_download_size;
- if (!fb_getvar("max-download-size", &max_download_size) ||
+ if (fb->GetVar("max-download-size", &max_download_size) != fastboot::SUCCESS ||
max_download_size.empty()) {
verbose("target didn't report max-download-size");
return 0;
@@ -788,7 +864,7 @@
buf->image_size = sz;
}
- lseek64(fd, 0, SEEK_SET);
+ lseek(fd, 0, SEEK_SET);
int64_t limit = get_sparse_limit(sz);
if (limit) {
sparse_file** s = load_sparse_files(fd, limit);
@@ -883,12 +959,12 @@
for (size_t i = 0; i < sparse_files.size(); ++i) {
const auto& pair = sparse_files[i];
- fb_queue_flash_sparse(partition, pair.first, pair.second, i + 1, sparse_files.size());
+ fb->FlashPartition(partition, pair.first, pair.second, i + 1, sparse_files.size());
}
break;
}
case FB_BUFFER_FD:
- fb_queue_flash_fd(partition, buf->fd, buf->sz);
+ fb->FlashPartition(partition, buf->fd, buf->sz);
break;
default:
die("unknown buffer type: %d", buf->type);
@@ -897,14 +973,15 @@
static std::string get_current_slot() {
std::string current_slot;
- if (!fb_getvar("current-slot", ¤t_slot)) return "";
+ if (fb->GetVar("current-slot", ¤t_slot) != fastboot::SUCCESS) return "";
return current_slot;
}
static int get_slot_count() {
std::string var;
int count = 0;
- if (!fb_getvar("slot-count", &var) || !android::base::ParseInt(var, &count)) {
+ if (fb->GetVar("slot-count", &var) != fastboot::SUCCESS ||
+ !android::base::ParseInt(var, &count)) {
return 0;
}
return count;
@@ -979,7 +1056,7 @@
std::string has_slot;
std::string current_slot;
- if (!fb_getvar("has-slot:" + part, &has_slot)) {
+ if (fb->GetVar("has-slot:" + part, &has_slot) != fastboot::SUCCESS) {
/* If has-slot is not supported, the answer is no. */
has_slot = "no";
}
@@ -1012,7 +1089,7 @@
std::string has_slot;
if (slot == "all") {
- if (!fb_getvar("has-slot:" + part, &has_slot)) {
+ if (fb->GetVar("has-slot:" + part, &has_slot) != fastboot::SUCCESS) {
die("Could not check if partition %s has slot %s", part.c_str(), slot.c_str());
}
if (has_slot == "yes") {
@@ -1027,12 +1104,28 @@
}
}
+static bool is_logical(const std::string& partition) {
+ std::string value;
+ return fb->GetVar("is-logical:" + partition, &value) == fastboot::SUCCESS && value == "yes";
+}
+
+static bool is_retrofit_device() {
+ std::string value;
+ if (fb->GetVar("super-partition-name", &value) != fastboot::SUCCESS) {
+ return false;
+ }
+ return android::base::StartsWith(value, "system_");
+}
+
static void do_flash(const char* pname, const char* fname) {
struct fastboot_buffer buf;
if (!load_buf(fname, &buf)) {
die("cannot load '%s': %s", fname, strerror(errno));
}
+ if (is_logical(pname)) {
+ fb->ResizePartition(pname, std::to_string(buf.image_size));
+ }
flash_buf(pname, &buf);
}
@@ -1042,58 +1135,39 @@
if (!supports_AB()) return;
if (slot_override != "") {
- fb_set_active(slot_override);
+ fb->SetActive(slot_override);
} else {
std::string current_slot = get_current_slot();
if (current_slot != "") {
- fb_set_active(current_slot);
+ fb->SetActive(current_slot);
}
}
}
static bool is_userspace_fastboot() {
std::string value;
- return fb_getvar("is-userspace", &value) && value == "yes";
-}
-
-static bool if_partition_exists(const std::string& partition, const std::string& slot) {
- std::string has_slot;
- std::string partition_name = partition;
-
- if (fb_getvar("has-slot:" + partition, &has_slot) && has_slot == "yes") {
- if (slot == "") {
- std::string current_slot = get_current_slot();
- if (current_slot == "") {
- die("Failed to identify current slot");
- }
- partition_name += "_" + current_slot;
- } else {
- partition_name += "_" + slot;
- }
- }
- std::string partition_size;
- return fb_getvar("partition-size:" + partition_name, &partition_size);
-}
-
-static bool is_logical(const std::string& partition) {
- std::string value;
- return fb_getvar("is-logical:" + partition, &value) && value == "yes";
+ return fb->GetVar("is-userspace", &value) == fastboot::SUCCESS && value == "yes";
}
static void reboot_to_userspace_fastboot() {
- if (!fb_reboot_to_userspace()) {
- die("Must reboot to userspace fastboot to flash logical partitions");
- }
+ fb->RebootTo("fastboot");
+
+ auto* old_transport = fb->set_transport(nullptr);
+ delete old_transport;
// Give the current connection time to close.
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
- fb_reinit(open_device());
+ fb->set_transport(open_device());
+
+ if (!is_userspace_fastboot()) {
+ die("Failed to boot into userspace fastboot; one or more components might be unbootable.");
+ }
}
class ImageSource {
public:
- virtual void* ReadFile(const std::string& name, int64_t* size) const = 0;
+ virtual bool ReadFile(const std::string& name, std::vector<char>* out) const = 0;
virtual int OpenFile(const std::string& name) const = 0;
};
@@ -1129,7 +1203,17 @@
}
void FlashAllTool::Flash() {
+ DumpInfo();
CheckRequirements();
+
+ // Change the slot first, so we boot into the correct recovery image when
+ // using fastbootd.
+ if (slot_override_ == "all") {
+ set_active("a");
+ } else {
+ set_active(slot_override_);
+ }
+
DetermineSecondarySlot();
CollectImages();
@@ -1145,7 +1229,7 @@
for (const auto& [image, slot] : os_images_) {
auto resize_partition = [](const std::string& partition) -> void {
if (is_logical(partition)) {
- fb_queue_resize_partition(partition, "0");
+ fb->ResizePartition(partition, "0");
}
};
do_for_partitions(image->part_name, slot, resize_partition, false);
@@ -1153,28 +1237,21 @@
// Flash OS images, resizing logical partitions as needed.
FlashImages(os_images_);
-
- if (slot_override_ == "all") {
- set_active("a");
- } else {
- set_active(slot_override_);
- }
}
void FlashAllTool::CheckRequirements() {
- int64_t sz;
- void* data = source_.ReadFile("android-info.txt", &sz);
- if (data == nullptr) {
+ std::vector<char> contents;
+ if (!source_.ReadFile("android-info.txt", &contents)) {
die("could not read android-info.txt");
}
- check_requirements(reinterpret_cast<char*>(data), sz);
+ ::CheckRequirements({contents.data(), contents.size()});
}
void FlashAllTool::DetermineSecondarySlot() {
if (skip_secondary_) {
return;
}
- if (slot_override_ != "") {
+ if (slot_override_ != "" && slot_override_ != "all") {
secondary_slot_ = get_other_slot(slot_override_);
} else {
secondary_slot_ = get_other_slot();
@@ -1220,15 +1297,14 @@
void FlashAllTool::FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf) {
auto flash = [&, this](const std::string& partition_name) {
- int64_t sz;
- void* data = source_.ReadFile(image.sig_name, &sz);
- if (data) {
- fb_queue_download("signature", data, sz);
- fb_queue_command("signature", "installing signature");
+ std::vector<char> signature_data;
+ if (source_.ReadFile(image.sig_name, &signature_data)) {
+ fb->Download("signature", signature_data);
+ fb->RawCommand("signature", "installing signature");
}
if (is_logical(partition_name)) {
- fb_queue_resize_partition(partition_name, std::to_string(buf->image_size));
+ fb->ResizePartition(partition_name, std::to_string(buf->image_size));
}
flash_buf(partition_name.c_str(), buf);
};
@@ -1236,10 +1312,6 @@
}
void FlashAllTool::UpdateSuperPartition() {
- if (!if_partition_exists("super", "")) {
- return;
- }
-
int fd = source_.OpenFile("super_empty.img");
if (fd < 0) {
return;
@@ -1247,31 +1319,45 @@
if (!is_userspace_fastboot()) {
reboot_to_userspace_fastboot();
}
- fb_queue_download_fd("super", fd, get_file_size(fd));
- std::string command = "update-super:super";
+ std::string super_name;
+ if (fb->GetVar("super-partition-name", &super_name) != fastboot::RetCode::SUCCESS) {
+ super_name = "super";
+ }
+ fb->Download(super_name, fd, get_file_size(fd));
+
+ std::string command = "update-super:" + super_name;
if (wipe_) {
command += ":wipe";
}
- fb_queue_command(command, "Updating super partition");
+ fb->RawCommand(command, "Updating super partition");
- // We need these commands to have finished before proceeding, since
- // otherwise "getvar is-logical" may not return a correct answer below.
- fb_execute_queue();
+ // Retrofit devices have two super partitions, named super_a and super_b.
+ // On these devices, secondary slots must be flashed as physical
+ // partitions (otherwise they would not mount on first boot). To enforce
+ // this, we delete any logical partitions for the "other" slot.
+ if (is_retrofit_device()) {
+ for (const auto& [image, slot] : os_images_) {
+ std::string partition_name = image->part_name + "_"s + slot;
+ if (image->IsSecondary() && is_logical(partition_name)) {
+ fb->DeletePartition(partition_name);
+ }
+ }
+ }
}
class ZipImageSource final : public ImageSource {
public:
explicit ZipImageSource(ZipArchiveHandle zip) : zip_(zip) {}
- void* ReadFile(const std::string& name, int64_t* size) const override;
+ bool ReadFile(const std::string& name, std::vector<char>* out) const override;
int OpenFile(const std::string& name) const override;
private:
ZipArchiveHandle zip_;
};
-void* ZipImageSource::ReadFile(const std::string& name, int64_t* size) const {
- return unzip_to_memory(zip_, name.c_str(), size);
+bool ZipImageSource::ReadFile(const std::string& name, std::vector<char>* out) const {
+ return UnzipToMemory(zip_, name, out);
}
int ZipImageSource::OpenFile(const std::string& name) const {
@@ -1279,10 +1365,6 @@
}
static void do_update(const char* filename, const std::string& slot_override, bool skip_secondary) {
- queue_info_dump();
-
- fb_queue_query_save("product", cur_product, sizeof(cur_product));
-
ZipArchiveHandle zip;
int error = OpenArchive(filename, &zip);
if (error != 0) {
@@ -1297,16 +1379,16 @@
class LocalImageSource final : public ImageSource {
public:
- void* ReadFile(const std::string& name, int64_t* size) const override;
+ bool ReadFile(const std::string& name, std::vector<char>* out) const override;
int OpenFile(const std::string& name) const override;
};
-void* LocalImageSource::ReadFile(const std::string& name, int64_t* size) const {
+bool LocalImageSource::ReadFile(const std::string& name, std::vector<char>* out) const {
auto path = find_item_given_name(name);
if (path.empty()) {
- return nullptr;
+ return false;
}
- return load_file(path.c_str(), size);
+ return ReadFileToVector(path, out);
}
int LocalImageSource::OpenFile(const std::string& name) const {
@@ -1315,11 +1397,6 @@
}
static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe) {
- std::string fname;
- queue_info_dump();
-
- fb_queue_query_save("product", cur_product, sizeof(cur_product));
-
FlashAllTool tool(LocalImageSource(), slot_override, skip_secondary, wipe);
tool.Flash();
}
@@ -1338,7 +1415,7 @@
while (!args->empty()) {
command += " " + next_arg(args);
}
- fb_queue_command(command, "");
+ fb->RawCommand(command, "");
}
static std::string fb_fix_numeric_var(std::string var) {
@@ -1352,7 +1429,7 @@
static unsigned fb_get_flash_block_size(std::string name) {
std::string sizeString;
- if (!fb_getvar(name, &sizeString) || sizeString.empty()) {
+ if (fb->GetVar(name, &sizeString) != fastboot::SUCCESS || sizeString.empty()) {
// This device does not report flash block sizes, so return 0.
return 0;
}
@@ -1390,7 +1467,7 @@
limit = sparse_limit;
}
- if (!fb_getvar("partition-type:" + partition, &partition_type)) {
+ if (fb->GetVar("partition-type:" + partition, &partition_type) != fastboot::SUCCESS) {
errMsg = "Can't determine partition type.\n";
goto failed;
}
@@ -1402,7 +1479,7 @@
partition_type = type_override;
}
- if (!fb_getvar("partition-size:" + partition, &partition_size)) {
+ if (fb->GetVar("partition-size:" + partition, &partition_size) != fastboot::SUCCESS) {
errMsg = "Unable to get partition size\n";
goto failed;
}
@@ -1422,15 +1499,13 @@
fprintf(stderr, "File system type %s not supported.\n", partition_type.c_str());
return;
}
- fprintf(stderr, "Formatting is not supported for file system with type '%s'.\n",
- partition_type.c_str());
- return;
+ die("Formatting is not supported for file system with type '%s'.",
+ partition_type.c_str());
}
int64_t size;
if (!android::base::ParseInt(partition_size, &size)) {
- fprintf(stderr, "Couldn't parse partition size '%s'.\n", partition_size.c_str());
- return;
+ die("Couldn't parse partition size '%s'.", partition_size.c_str());
}
unsigned eraseBlkSize, logicalBlkSize;
@@ -1440,17 +1515,14 @@
if (fs_generator_generate(gen, output.path, size, initial_dir,
eraseBlkSize, logicalBlkSize)) {
die("Cannot generate image for %s", partition.c_str());
- return;
}
fd.reset(open(output.path, O_RDONLY));
if (fd == -1) {
- fprintf(stderr, "Cannot open generated image: %s\n", strerror(errno));
- return;
+ die("Cannot open generated image: %s", strerror(errno));
}
if (!load_buf_fd(fd.release(), &buf)) {
- fprintf(stderr, "Cannot read image: %s\n", strerror(errno));
- return;
+ die("Cannot read image: %s", strerror(errno));
}
flash_buf(partition, &buf);
return;
@@ -1460,7 +1532,38 @@
fprintf(stderr, "Erase successful, but not automatically formatting.\n");
if (errMsg) fprintf(stderr, "%s", errMsg);
}
- fprintf(stderr, "FAILED (%s)\n", fb_get_error().c_str());
+ fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
+ if (!skip_if_not_supported) {
+ die("Command failed");
+ }
+}
+
+static bool should_flash_in_userspace(const std::string& partition_name) {
+ if (!get_android_product_out()) {
+ return false;
+ }
+ auto path = find_item_given_name("super_empty.img");
+ if (path.empty() || access(path.c_str(), R_OK)) {
+ return false;
+ }
+ auto metadata = android::fs_mgr::ReadFromImageFile(path);
+ if (!metadata) {
+ return false;
+ }
+ for (const auto& partition : metadata->partitions) {
+ auto candidate = android::fs_mgr::GetPartitionName(partition);
+ if (partition.attributes & LP_PARTITION_ATTR_SLOT_SUFFIXED) {
+ // On retrofit devices, we don't know if, or whether, the A or B
+ // slot has been flashed for dynamic partitions. Instead we add
+ // both names to the list as a conservative guess.
+ if (candidate + "_a" == partition_name || candidate + "_b" == partition_name) {
+ return true;
+ }
+ } else if (candidate == partition_name) {
+ return true;
+ }
+ }
+ return false;
}
int FastBootTool::Main(int argc, char* argv[]) {
@@ -1473,8 +1576,7 @@
bool wants_set_active = false;
bool skip_secondary = false;
bool set_fbe_marker = false;
- void *data;
- int64_t sz;
+ bool force_flash = false;
int longindex;
std::string slot_override;
std::string next_active;
@@ -1490,6 +1592,7 @@
{"cmdline", required_argument, 0, 0},
{"disable-verification", no_argument, 0, 0},
{"disable-verity", no_argument, 0, 0},
+ {"force", no_argument, 0, 0},
{"header-version", required_argument, 0, 0},
{"help", no_argument, 0, 'h'},
{"kernel-offset", required_argument, 0, 0},
@@ -1525,6 +1628,8 @@
g_disable_verification = true;
} else if (name == "disable-verity") {
g_disable_verity = true;
+ } else if (name == "force") {
+ force_flash = true;
} else if (name == "header-version") {
g_boot_img_hdr.header_version = strtoul(optarg, nullptr, 0);
} else if (name == "kernel-offset") {
@@ -1612,8 +1717,13 @@
if (transport == nullptr) {
return 1;
}
- fastboot::FastBootDriver fb(transport);
- fb_init(fb);
+ fastboot::DriverCallbacks driver_callbacks = {
+ .prolog = Status,
+ .epilog = Epilog,
+ .info = InfoMessage,
+ };
+ fastboot::FastBootDriver fastboot_driver(transport, driver_callbacks, false);
+ fb = &fastboot_driver;
const double start = now();
@@ -1624,7 +1734,7 @@
if (next_active == "") {
if (slot_override == "") {
std::string current_slot;
- if (fb_getvar("current-slot", ¤t_slot)) {
+ if (fb->GetVar("current-slot", ¤t_slot) == fastboot::SUCCESS) {
next_active = verify_slot(current_slot, false);
} else {
wants_set_active = false;
@@ -1639,21 +1749,20 @@
while (!args.empty()) {
std::string command = next_arg(&args);
- if (command == "getvar") {
+ if (command == FB_CMD_GETVAR) {
std::string variable = next_arg(&args);
- fb_queue_display(variable, variable);
- } else if (command == "erase") {
+ DisplayVarOrError(variable, variable);
+ } else if (command == FB_CMD_ERASE) {
std::string partition = next_arg(&args);
auto erase = [&](const std::string& partition) {
std::string partition_type;
- if (fb_getvar(std::string("partition-type:") + partition,
- &partition_type) &&
+ if (fb->GetVar("partition-type:" + partition, &partition_type) == fastboot::SUCCESS &&
fs_get_generator(partition_type) != nullptr) {
fprintf(stderr, "******** Did you mean to fastboot format this %s partition?\n",
partition_type.c_str());
}
- fb_queue_erase(partition);
+ fb->Erase(partition);
};
do_for_partitions(partition, slot_override, erase, true);
} else if (android::base::StartsWith(command, "format")) {
@@ -1678,12 +1787,14 @@
do_for_partitions(partition.c_str(), slot_override, format, true);
} else if (command == "signature") {
std::string filename = next_arg(&args);
- data = load_file(filename.c_str(), &sz);
- if (data == nullptr) die("could not load '%s': %s", filename.c_str(), strerror(errno));
- if (sz != 256) die("signature must be 256 bytes (got %" PRId64 ")", sz);
- fb_queue_download("signature", data, sz);
- fb_queue_command("signature", "installing signature");
- } else if (command == "reboot") {
+ std::vector<char> data;
+ if (!ReadFileToVector(filename, &data)) {
+ die("could not load '%s': %s", filename.c_str(), strerror(errno));
+ }
+ if (data.size() != 256) die("signature must be 256 bytes (got %zu)", data.size());
+ fb->Download("signature", data);
+ fb->RawCommand("signature", "installing signature");
+ } else if (command == FB_CMD_REBOOT) {
wants_reboot = true;
if (args.size() == 1) {
@@ -1703,25 +1814,25 @@
}
if (!args.empty()) syntax_error("junk after reboot command");
- } else if (command == "reboot-bootloader") {
+ } else if (command == FB_CMD_REBOOT_BOOTLOADER) {
wants_reboot_bootloader = true;
- } else if (command == "reboot-recovery") {
+ } else if (command == FB_CMD_REBOOT_RECOVERY) {
wants_reboot_recovery = true;
- } else if (command == "reboot-fastboot") {
+ } else if (command == FB_CMD_REBOOT_FASTBOOT) {
wants_reboot_fastboot = true;
- } else if (command == "continue") {
- fb_queue_command("continue", "resuming boot");
- } else if (command == "boot") {
+ } else if (command == FB_CMD_CONTINUE) {
+ fb->Continue();
+ } else if (command == FB_CMD_BOOT) {
std::string kernel = next_arg(&args);
std::string ramdisk;
if (!args.empty()) ramdisk = next_arg(&args);
std::string second_stage;
if (!args.empty()) second_stage = next_arg(&args);
- data = load_bootable_image(kernel, ramdisk, second_stage, &sz);
- fb_queue_download("boot.img", data, sz);
- fb_queue_command("boot", "booting");
- } else if (command == "flash") {
+ auto data = LoadBootableImage(kernel, ramdisk, second_stage);
+ fb->Download("boot.img", data);
+ fb->Boot();
+ } else if (command == FB_CMD_FLASH) {
std::string pname = next_arg(&args);
std::string fname;
@@ -1733,6 +1844,16 @@
if (fname.empty()) die("cannot determine image filename for '%s'", pname.c_str());
auto flash = [&](const std::string &partition) {
+ if (should_flash_in_userspace(partition) && !is_userspace_fastboot() &&
+ !force_flash) {
+ die("The partition you are trying to flash is dynamic, and "
+ "should be flashed via fastbootd. Please run:\n"
+ "\n"
+ " fastboot reboot fastboot\n"
+ "\n"
+ "And try again. If you are intentionally trying to "
+ "overwrite a fixed partition, use --force.");
+ }
do_flash(partition.c_str(), fname.c_str());
};
do_for_partitions(pname.c_str(), slot_override, flash, true);
@@ -1744,9 +1865,9 @@
std::string second_stage;
if (!args.empty()) second_stage = next_arg(&args);
- data = load_bootable_image(kernel, ramdisk, second_stage, &sz);
- auto flashraw = [&](const std::string& partition) {
- fb_queue_flash(partition, data, sz);
+ auto data = LoadBootableImage(kernel, ramdisk, second_stage);
+ auto flashraw = [&data](const std::string& partition) {
+ fb->FlashPartition(partition, data);
};
do_for_partitions(partition, slot_override, flashraw, true);
} else if (command == "flashall") {
@@ -1768,9 +1889,9 @@
}
do_update(filename.c_str(), slot_override, skip_secondary || slot_all);
wants_reboot = true;
- } else if (command == "set_active") {
+ } else if (command == FB_CMD_SET_ACTIVE) {
std::string slot = verify_slot(next_arg(&args), false);
- fb_set_active(slot);
+ fb->SetActive(slot);
} else if (command == "stage") {
std::string filename = next_arg(&args);
@@ -1778,12 +1899,12 @@
if (!load_buf(filename.c_str(), &buf) || buf.type != FB_BUFFER_FD) {
die("cannot load '%s'", filename.c_str());
}
- fb_queue_download_fd(filename, buf.fd, buf.sz);
+ fb->Download(filename, buf.fd, buf.sz);
} else if (command == "get_staged") {
std::string filename = next_arg(&args);
- fb_queue_upload(filename);
- } else if (command == "oem") {
- do_oem_command("oem", &args);
+ fb->Upload(filename);
+ } else if (command == FB_CMD_OEM) {
+ do_oem_command(FB_CMD_OEM, &args);
} else if (command == "flashing") {
if (args.empty()) {
syntax_error("missing 'flashing' command");
@@ -1795,17 +1916,27 @@
} else {
syntax_error("unknown 'flashing' command %s", args[0].c_str());
}
- } else if (command == "create-logical-partition") {
+ } else if (command == FB_CMD_CREATE_PARTITION) {
std::string partition = next_arg(&args);
std::string size = next_arg(&args);
- fb_queue_create_partition(partition, size);
- } else if (command == "delete-logical-partition") {
+ fb->CreatePartition(partition, size);
+ } else if (command == FB_CMD_DELETE_PARTITION) {
std::string partition = next_arg(&args);
- fb_queue_delete_partition(partition);
- } else if (command == "resize-logical-partition") {
+ fb->DeletePartition(partition);
+ } else if (command == FB_CMD_RESIZE_PARTITION) {
std::string partition = next_arg(&args);
std::string size = next_arg(&args);
- fb_queue_resize_partition(partition, size);
+ fb->ResizePartition(partition, size);
+ } else if (command == "gsi") {
+ if (args.empty()) {
+ syntax_error("missing 'wipe' or 'disable' argument");
+ } else if (args.size() == 1 && args[0] == "wipe") {
+ fb->RawCommand("gsi:wipe", "wiping GSI");
+ } else if (args.size() == 1 && args[0] == "disable") {
+ fb->RawCommand("gsi:disable", "disabling GSI");
+ } else {
+ syntax_error("expected 'wipe' or 'disable'");
+ }
} else {
syntax_error("unknown command %s", command.c_str());
}
@@ -1815,9 +1946,11 @@
std::vector<std::string> partitions = { "userdata", "cache", "metadata" };
for (const auto& partition : partitions) {
std::string partition_type;
- if (!fb_getvar(std::string{"partition-type:"} + partition, &partition_type)) continue;
+ if (fb->GetVar("partition-type:" + partition, &partition_type) != fastboot::SUCCESS) {
+ continue;
+ }
if (partition_type.empty()) continue;
- fb_queue_erase(partition);
+ fb->Erase(partition);
if (partition == "userdata" && set_fbe_marker) {
fprintf(stderr, "setting FBE marker on initial userdata...\n");
std::string initial_userdata_dir = create_fbemarker_tmpdir();
@@ -1829,25 +1962,27 @@
}
}
if (wants_set_active) {
- fb_set_active(next_active);
+ fb->SetActive(next_active);
}
if (wants_reboot && !skip_reboot) {
- fb_queue_reboot();
- fb_queue_wait_for_disconnect();
+ fb->Reboot();
+ fb->WaitForDisconnect();
} else if (wants_reboot_bootloader) {
- fb_queue_command("reboot-bootloader", "rebooting into bootloader");
- fb_queue_wait_for_disconnect();
+ fb->RebootTo("bootloader");
+ fb->WaitForDisconnect();
} else if (wants_reboot_recovery) {
- fb_queue_command("reboot-recovery", "rebooting into recovery");
- fb_queue_wait_for_disconnect();
+ fb->RebootTo("recovery");
+ fb->WaitForDisconnect();
} else if (wants_reboot_fastboot) {
- fb_queue_command("reboot-fastboot", "rebooting into fastboot");
- fb_queue_wait_for_disconnect();
+ reboot_to_userspace_fastboot();
}
- int status = fb_execute_queue() ? EXIT_FAILURE : EXIT_SUCCESS;
fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start));
- return status;
+
+ auto* old_transport = fb->set_transport(nullptr);
+ delete old_transport;
+
+ return 0;
}
void FastBootTool::ParseOsPatchLevel(boot_img_hdr_v1* hdr, const char* arg) {
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
new file mode 100644
index 0000000..9f18253
--- /dev/null
+++ b/fastboot/fastboot.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ */
+
+#include <bootimg.h>
+
+class FastBootTool {
+ public:
+ int Main(int argc, char* argv[]);
+
+ void ParseOsPatchLevel(boot_img_hdr_v1*, const char*);
+ void ParseOsVersion(boot_img_hdr_v1*, const char*);
+};
diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp
index ceee066..65a5247 100644
--- a/fastboot/fastboot_driver.cpp
+++ b/fastboot/fastboot_driver.cpp
@@ -25,6 +25,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
#include "fastboot_driver.h"
#include <errno.h>
@@ -40,48 +41,60 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/mapped_file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
-#include <utils/FileMap.h>
-#include "fastboot_driver.h"
+
+#include "constants.h"
#include "transport.h"
+using android::base::StringPrintf;
+
namespace fastboot {
/*************************** PUBLIC *******************************/
-FastBootDriver::FastBootDriver(Transport* transport, std::function<void(std::string&)> info,
+FastBootDriver::FastBootDriver(Transport* transport, DriverCallbacks driver_callbacks,
bool no_checks)
- : transport_(transport) {
- info_cb_ = info;
- disable_checks_ = no_checks;
-}
+ : transport_(transport),
+ prolog_(std::move(driver_callbacks.prolog)),
+ epilog_(std::move(driver_callbacks.epilog)),
+ info_(std::move(driver_callbacks.info)),
+ disable_checks_(no_checks) {}
FastBootDriver::~FastBootDriver() {
- set_transport(nullptr);
}
RetCode FastBootDriver::Boot(std::string* response, std::vector<std::string>* info) {
- return RawCommand(Commands::BOOT, response, info);
+ return RawCommand(FB_CMD_BOOT, "Booting", response, info);
}
RetCode FastBootDriver::Continue(std::string* response, std::vector<std::string>* info) {
- return RawCommand(Commands::CONTINUE, response, info);
+ return RawCommand(FB_CMD_CONTINUE, "Resuming boot", response, info);
}
-RetCode FastBootDriver::Erase(const std::string& part, std::string* response,
- std::vector<std::string>* info) {
- return RawCommand(Commands::ERASE + part, response, info);
+RetCode FastBootDriver::CreatePartition(const std::string& partition, const std::string& size) {
+ return RawCommand(FB_CMD_CREATE_PARTITION ":" + partition + ":" + size,
+ "Creating '" + partition + "'");
}
-RetCode FastBootDriver::Flash(const std::string& part, std::string* response,
+RetCode FastBootDriver::DeletePartition(const std::string& partition) {
+ return RawCommand(FB_CMD_DELETE_PARTITION ":" + partition, "Deleting '" + partition + "'");
+}
+
+RetCode FastBootDriver::Erase(const std::string& partition, std::string* response,
std::vector<std::string>* info) {
- return RawCommand(Commands::FLASH + part, response, info);
+ return RawCommand(FB_CMD_ERASE ":" + partition, "Erasing '" + partition + "'", response, info);
+}
+
+RetCode FastBootDriver::Flash(const std::string& partition, std::string* response,
+ std::vector<std::string>* info) {
+ return RawCommand(FB_CMD_FLASH ":" + partition, "Writing '" + partition + "'", response, info);
}
RetCode FastBootDriver::GetVar(const std::string& key, std::string* val,
std::vector<std::string>* info) {
- return RawCommand(Commands::GET_VAR + key, val, info);
+ return RawCommand(FB_CMD_GETVAR ":" + key, val, info);
}
RetCode FastBootDriver::GetVarAll(std::vector<std::string>* response) {
@@ -90,44 +103,52 @@
}
RetCode FastBootDriver::Reboot(std::string* response, std::vector<std::string>* info) {
- return RawCommand(Commands::REBOOT, response, info);
+ return RawCommand(FB_CMD_REBOOT, "Rebooting", response, info);
}
RetCode FastBootDriver::RebootTo(std::string target, std::string* response,
std::vector<std::string>* info) {
- return RawCommand("reboot-" + target, response, info);
+ return RawCommand("reboot-" + target, "Rebooting into " + target, response, info);
}
-RetCode FastBootDriver::SetActive(const std::string& part, std::string* response,
+RetCode FastBootDriver::ResizePartition(const std::string& partition, const std::string& size) {
+ return RawCommand(FB_CMD_RESIZE_PARTITION ":" + partition + ":" + size,
+ "Resizing '" + partition + "'");
+}
+
+RetCode FastBootDriver::SetActive(const std::string& slot, std::string* response,
std::vector<std::string>* info) {
- return RawCommand(Commands::SET_ACTIVE + part, response, info);
+ return RawCommand(FB_CMD_SET_ACTIVE ":" + slot, "Setting current slot to '" + slot + "'",
+ response, info);
}
-RetCode FastBootDriver::FlashPartition(const std::string& part, const std::vector<char>& data) {
+RetCode FastBootDriver::FlashPartition(const std::string& partition,
+ const std::vector<char>& data) {
RetCode ret;
- if ((ret = Download(data))) {
+ if ((ret = Download(partition, data))) {
return ret;
}
- return RawCommand(Commands::FLASH + part);
+ return Flash(partition);
}
-RetCode FastBootDriver::FlashPartition(const std::string& part, int fd, uint32_t sz) {
+RetCode FastBootDriver::FlashPartition(const std::string& partition, int fd, uint32_t size) {
RetCode ret;
- if ((ret = Download(fd, sz))) {
+ if ((ret = Download(partition, fd, size))) {
return ret;
}
- return RawCommand(Commands::FLASH + part);
+ return Flash(partition);
}
-RetCode FastBootDriver::FlashPartition(const std::string& part, sparse_file* s) {
+RetCode FastBootDriver::FlashPartition(const std::string& partition, sparse_file* s, uint32_t size,
+ size_t current, size_t total) {
RetCode ret;
- if ((ret = Download(s))) {
+ if ((ret = Download(partition, s, size, current, total, false))) {
return ret;
}
- return RawCommand(Commands::FLASH + part);
+ return Flash(partition);
}
-RetCode FastBootDriver::Partitions(std::vector<std::tuple<std::string, uint32_t>>* parts) {
+RetCode FastBootDriver::Partitions(std::vector<std::tuple<std::string, uint64_t>>* partitions) {
std::vector<std::string> all;
RetCode ret;
if ((ret = GetVarAll(&all))) {
@@ -141,33 +162,19 @@
if (std::regex_match(s, sm, reg)) {
std::string m1(sm[1]);
std::string m2(sm[2]);
- uint32_t tmp = strtol(m2.c_str(), 0, 16);
- parts->push_back(std::make_tuple(m1, tmp));
+ uint64_t tmp = strtoll(m2.c_str(), 0, 16);
+ partitions->push_back(std::make_tuple(m1, tmp));
}
}
return SUCCESS;
}
-RetCode FastBootDriver::Require(const std::string& var, const std::vector<std::string>& allowed,
- bool* reqmet, bool invert) {
- *reqmet = invert;
- RetCode ret;
- std::string response;
- if ((ret = GetVar(var, &response))) {
- return ret;
- }
-
- // Now check if we have a match
- for (const auto s : allowed) {
- // If it ends in *, and starting substring match
- if (response == s || (s.length() && s.back() == '*' &&
- !response.compare(0, s.length() - 1, s, 0, s.length() - 1))) {
- *reqmet = !invert;
- break;
- }
- }
-
- return SUCCESS;
+RetCode FastBootDriver::Download(const std::string& name, int fd, size_t size,
+ std::string* response, std::vector<std::string>* info) {
+ prolog_(StringPrintf("Sending '%s' (%zu KB)", name.c_str(), size / 1024));
+ auto result = Download(fd, size, response, info);
+ epilog_(result);
+ return result;
}
RetCode FastBootDriver::Download(int fd, size_t size, std::string* response,
@@ -193,26 +200,29 @@
return HandleResponse(response, info);
}
-RetCode FastBootDriver::Download(const std::vector<char>& buf, std::string* response,
- std::vector<std::string>* info) {
- return Download(buf.data(), buf.size(), response, info);
+RetCode FastBootDriver::Download(const std::string& name, const std::vector<char>& buf,
+ std::string* response, std::vector<std::string>* info) {
+ prolog_(StringPrintf("Sending '%s' (%zu KB)", name.c_str(), buf.size() / 1024));
+ auto result = Download(buf, response, info);
+ epilog_(result);
+ return result;
}
-RetCode FastBootDriver::Download(const char* buf, uint32_t size, std::string* response,
+RetCode FastBootDriver::Download(const std::vector<char>& buf, std::string* response,
std::vector<std::string>* info) {
RetCode ret;
error_ = "";
- if ((size == 0 || size > MAX_DOWNLOAD_SIZE) && !disable_checks_) {
+ if ((buf.size() == 0 || buf.size() > MAX_DOWNLOAD_SIZE) && !disable_checks_) {
error_ = "Buffer is too large or 0 bytes";
return BAD_ARG;
}
- if ((ret = DownloadCommand(size, response, info))) {
+ if ((ret = DownloadCommand(buf.size(), response, info))) {
return ret;
}
// Write the buffer
- if ((ret = SendBuffer(buf, size))) {
+ if ((ret = SendBuffer(buf))) {
return ret;
}
@@ -220,6 +230,16 @@
return HandleResponse(response, info);
}
+RetCode FastBootDriver::Download(const std::string& partition, struct sparse_file* s, uint32_t size,
+ size_t current, size_t total, bool use_crc, std::string* response,
+ std::vector<std::string>* info) {
+ prolog_(StringPrintf("Sending sparse '%s' %zu/%zu (%u KB)", partition.c_str(), current, total,
+ size / 1024));
+ auto result = Download(s, use_crc, response, info);
+ epilog_(result);
+ return result;
+}
+
RetCode FastBootDriver::Download(sparse_file* s, bool use_crc, std::string* response,
std::vector<std::string>* info) {
error_ = "";
@@ -262,9 +282,17 @@
RetCode FastBootDriver::Upload(const std::string& outfile, std::string* response,
std::vector<std::string>* info) {
+ prolog_("Uploading '" + outfile + "'");
+ auto result = UploadInner(outfile, response, info);
+ epilog_(result);
+ return result;
+}
+
+RetCode FastBootDriver::UploadInner(const std::string& outfile, std::string* response,
+ std::vector<std::string>* info) {
RetCode ret;
int dsize;
- if ((ret = RawCommand(Commands::UPLOAD, response, info, &dsize))) {
+ if ((ret = RawCommand(FB_CMD_UPLOAD, response, info, &dsize))) {
error_ = "Upload request failed: " + error_;
return ret;
}
@@ -298,8 +326,8 @@
}
// Helpers
-void FastBootDriver::SetInfoCallback(std::function<void(std::string&)> info) {
- info_cb_ = info;
+void FastBootDriver::SetInfoCallback(std::function<void(const std::string&)> info) {
+ info_ = info;
}
const std::string FastBootDriver::RCString(RetCode rc) {
@@ -336,6 +364,15 @@
}
/****************************** PROTECTED *************************************/
+RetCode FastBootDriver::RawCommand(const std::string& cmd, const std::string& message,
+ std::string* response, std::vector<std::string>* info,
+ int* dsize) {
+ prolog_(message);
+ auto result = RawCommand(cmd, response, info, dsize);
+ epilog_(result);
+ return result;
+}
+
RetCode FastBootDriver::RawCommand(const std::string& cmd, std::string* response,
std::vector<std::string>* info, int* dsize) {
error_ = ""; // Clear any pending error
@@ -355,7 +392,7 @@
RetCode FastBootDriver::DownloadCommand(uint32_t size, std::string* response,
std::vector<std::string>* info) {
- std::string cmd(android::base::StringPrintf("%s%08" PRIx32, Commands::DOWNLOAD.c_str(), size));
+ std::string cmd(android::base::StringPrintf("%s:%08" PRIx32, FB_CMD_DOWNLOAD, size));
RetCode ret;
if ((ret = RawCommand(cmd, response, info))) {
return ret;
@@ -388,7 +425,7 @@
std::string input(status);
if (android::base::StartsWith(input, "INFO")) {
std::string tmp = input.substr(strlen("INFO"));
- info_cb_(tmp);
+ info_(tmp);
add_info(std::move(tmp));
} else if (android::base::StartsWith(input, "OKAY")) {
set_response(input.substr(strlen("OKAY")));
@@ -421,16 +458,6 @@
return android::base::StringPrintf("%s (%s)", msg.c_str(), strerror(errno));
}
-const std::string FastBootDriver::Commands::BOOT = "boot";
-const std::string FastBootDriver::Commands::CONTINUE = "continue";
-const std::string FastBootDriver::Commands::DOWNLOAD = "download:";
-const std::string FastBootDriver::Commands::ERASE = "erase:";
-const std::string FastBootDriver::Commands::FLASH = "flash:";
-const std::string FastBootDriver::Commands::GET_VAR = "getvar:";
-const std::string FastBootDriver::Commands::REBOOT = "reboot";
-const std::string FastBootDriver::Commands::SET_ACTIVE = "set_active:";
-const std::string FastBootDriver::Commands::UPLOAD = "upload";
-
/******************************* PRIVATE **************************************/
RetCode FastBootDriver::SendBuffer(int fd, size_t size) {
static constexpr uint32_t MAX_MAP_SIZE = 512 * 1024 * 1024;
@@ -440,15 +467,14 @@
while (remaining) {
// Memory map the file
- android::FileMap filemap;
size_t len = std::min(remaining, MAX_MAP_SIZE);
-
- if (!filemap.create(NULL, fd, offset, len, true)) {
+ auto mapping{android::base::MappedFile::FromFd(fd, offset, len, PROT_READ)};
+ if (!mapping) {
error_ = "Creating filemap failed";
return IO_ERROR;
}
- if ((ret = SendBuffer(filemap.getDataPtr(), len))) {
+ if ((ret = SendBuffer(mapping->data(), mapping->size()))) {
return ret;
}
@@ -537,12 +563,9 @@
return 0;
}
-void FastBootDriver::set_transport(Transport* transport) {
- if (transport_) {
- transport_->Close();
- delete transport_;
- }
- transport_ = transport;
+Transport* FastBootDriver::set_transport(Transport* transport) {
+ std::swap(transport_, transport);
+ return transport;
}
} // End namespace fastboot
diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h
index 4647945..af02637 100644
--- a/fastboot/fastboot_driver.h
+++ b/fastboot/fastboot_driver.h
@@ -37,15 +37,14 @@
#include <bootimg.h>
#include <inttypes.h>
#include <sparse/sparse.h>
+
+#include "constants.h"
#include "transport.h"
class Transport;
namespace fastboot {
-static constexpr int FB_COMMAND_SZ = 64;
-static constexpr int FB_RESPONSE_SZ = 64;
-
enum RetCode : int {
SUCCESS = 0,
BAD_ARG,
@@ -55,6 +54,12 @@
TIMEOUT,
};
+struct DriverCallbacks {
+ std::function<void(const std::string&)> prolog = [](const std::string&) {};
+ std::function<void(int)> epilog = [](int) {};
+ std::function<void(const std::string&)> info = [](const std::string&) {};
+};
+
class FastBootDriver {
friend class FastBootTest;
@@ -63,25 +68,30 @@
static constexpr uint32_t MAX_DOWNLOAD_SIZE = std::numeric_limits<uint32_t>::max();
static constexpr size_t TRANSPORT_CHUNK_SIZE = 1024;
- FastBootDriver(Transport* transport,
- std::function<void(std::string&)> info = [](std::string&) {},
+ FastBootDriver(Transport* transport, DriverCallbacks driver_callbacks = {},
bool no_checks = false);
~FastBootDriver();
RetCode Boot(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
RetCode Continue(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
+ RetCode CreatePartition(const std::string& partition, const std::string& size);
+ RetCode DeletePartition(const std::string& partition);
+ RetCode Download(const std::string& name, int fd, size_t size, std::string* response = nullptr,
+ std::vector<std::string>* info = nullptr);
RetCode Download(int fd, size_t size, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
+ RetCode Download(const std::string& name, const std::vector<char>& buf,
+ std::string* response = nullptr, std::vector<std::string>* info = nullptr);
RetCode Download(const std::vector<char>& buf, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
- // This will be removed after fastboot is modified to use a vector
- RetCode Download(const char* buf, uint32_t size, std::string* response = nullptr,
+ RetCode Download(const std::string& partition, struct sparse_file* s, uint32_t sz,
+ size_t current, size_t total, bool use_crc, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
RetCode Download(sparse_file* s, bool use_crc = false, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
- RetCode Erase(const std::string& part, std::string* response = nullptr,
+ RetCode Erase(const std::string& partition, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
- RetCode Flash(const std::string& part, std::string* response = nullptr,
+ RetCode Flash(const std::string& partition, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
RetCode GetVar(const std::string& key, std::string* val,
std::vector<std::string>* info = nullptr);
@@ -89,31 +99,36 @@
RetCode Reboot(std::string* response = nullptr, std::vector<std::string>* info = nullptr);
RetCode RebootTo(std::string target, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
- RetCode SetActive(const std::string& part, std::string* response = nullptr,
+ RetCode ResizePartition(const std::string& partition, const std::string& size);
+ RetCode SetActive(const std::string& slot, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
RetCode Upload(const std::string& outfile, std::string* response = nullptr,
std::vector<std::string>* info = nullptr);
/* HIGHER LEVEL COMMANDS -- Composed of the commands above */
- RetCode FlashPartition(const std::string& part, const std::vector<char>& data);
- RetCode FlashPartition(const std::string& part, int fd, uint32_t sz);
- RetCode FlashPartition(const std::string& part, sparse_file* s);
+ RetCode FlashPartition(const std::string& partition, const std::vector<char>& data);
+ RetCode FlashPartition(const std::string& partition, int fd, uint32_t sz);
+ RetCode FlashPartition(const std::string& partition, sparse_file* s, uint32_t sz,
+ size_t current, size_t total);
- RetCode Partitions(std::vector<std::tuple<std::string, uint32_t>>* parts);
+ RetCode Partitions(std::vector<std::tuple<std::string, uint64_t>>* partitions);
RetCode Require(const std::string& var, const std::vector<std::string>& allowed, bool* reqmet,
bool invert = false);
/* HELPERS */
- void SetInfoCallback(std::function<void(std::string&)> info);
+ void SetInfoCallback(std::function<void(const std::string&)> info);
static const std::string RCString(RetCode rc);
std::string Error();
RetCode WaitForDisconnect();
- // Note: changing the transport will close and delete the existing one.
- void set_transport(Transport* transport);
+ // Note: set_transport will return the previous transport.
+ Transport* set_transport(Transport* transport);
Transport* transport() const { return transport_; }
- // This is temporarily public for engine.cpp
+ RetCode RawCommand(const std::string& cmd, const std::string& message,
+ std::string* response = nullptr, std::vector<std::string>* info = nullptr,
+ int* dsize = nullptr);
+
RetCode RawCommand(const std::string& cmd, std::string* response = nullptr,
std::vector<std::string>* info = nullptr, int* dsize = nullptr);
@@ -125,19 +140,6 @@
std::string ErrnoStr(const std::string& msg);
- // More like a namespace...
- struct Commands {
- static const std::string BOOT;
- static const std::string CONTINUE;
- static const std::string DOWNLOAD;
- static const std::string ERASE;
- static const std::string FLASH;
- static const std::string GET_VAR;
- static const std::string REBOOT;
- static const std::string SET_ACTIVE;
- static const std::string UPLOAD;
- };
-
Transport* transport_;
private:
@@ -148,10 +150,15 @@
RetCode ReadBuffer(std::vector<char>& buf);
RetCode ReadBuffer(void* buf, size_t size);
+ RetCode UploadInner(const std::string& outfile, std::string* response = nullptr,
+ std::vector<std::string>* info = nullptr);
+
int SparseWriteCallback(std::vector<char>& tpbuf, const char* data, size_t len);
std::string error_;
- std::function<void(std::string&)> info_cb_;
+ std::function<void(const std::string&)> prolog_;
+ std::function<void(int)> epilog_;
+ std::function<void(const std::string&)> info_;
bool disable_checks_;
};
diff --git a/fastboot/fastboot_test.cpp b/fastboot/fastboot_test.cpp
index 43201fa..9c3ab6e 100644
--- a/fastboot/fastboot_test.cpp
+++ b/fastboot/fastboot_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "engine.h"
+#include "fastboot.h"
#include <gtest/gtest.h>
@@ -59,3 +59,145 @@
EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.128.3"), "bad OS version");
EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.2.128"), "bad OS version");
}
+
+extern bool ParseRequirementLine(const std::string& line, std::string* name, std::string* product,
+ bool* invert, std::vector<std::string>* options);
+
+static void ParseRequirementLineTest(const std::string& line, const std::string& expected_name,
+ const std::string& expected_product, bool expected_invert,
+ const std::vector<std::string>& expected_options) {
+ std::string name;
+ std::string product;
+ bool invert;
+ std::vector<std::string> options;
+
+ EXPECT_TRUE(ParseRequirementLine(line, &name, &product, &invert, &options)) << line;
+
+ EXPECT_EQ(expected_name, name) << line;
+ EXPECT_EQ(expected_product, product) << line;
+ EXPECT_EQ(expected_invert, invert) << line;
+ EXPECT_EQ(expected_options, options) << line;
+}
+
+TEST(FastBoot, ParseRequirementLineSuccesses) {
+ // Examples provided in the code + slight variations.
+ ParseRequirementLineTest("require product=alpha", "product", "", false, {"alpha"});
+ ParseRequirementLineTest("require product=alpha|beta|gamma", "product", "", false,
+ {"alpha", "beta", "gamma"});
+ ParseRequirementLineTest("require version-bootloader=1234", "version-bootloader", "", false,
+ {"1234"});
+ ParseRequirementLineTest("require-for-product:gamma version-bootloader=istanbul",
+ "version-bootloader", "gamma", false, {"istanbul"});
+ ParseRequirementLineTest("require-for-product:gamma version-bootloader=istanbul|constantinople",
+ "version-bootloader", "gamma", false, {"istanbul", "constantinople"});
+ ParseRequirementLineTest("require partition-exists=vendor", "partition-exists", "", false,
+ {"vendor"});
+ ParseRequirementLineTest("reject product=alpha", "product", "", true, {"alpha"});
+ ParseRequirementLineTest("reject product=alpha|beta|gamma", "product", "", true,
+ {"alpha", "beta", "gamma"});
+
+ // Without any prefix, assume 'require'
+ ParseRequirementLineTest("product=alpha|beta|gamma", "product", "", false,
+ {"alpha", "beta", "gamma"});
+ // Including if the variable name is otherwise a prefix keyword
+ ParseRequirementLineTest("require = alpha", "require", "", false, {"alpha"});
+ ParseRequirementLineTest("reject = alpha", "reject", "", false, {"alpha"});
+ ParseRequirementLineTest("require-for-product:gamma = alpha", "require-for-product:gamma", "",
+ false, {"alpha"});
+
+ // Extra spaces are allowed.
+ ParseRequirementLineTest("require product=alpha|beta|gamma", "product", "", false,
+ {"alpha", "beta", "gamma"});
+ ParseRequirementLineTest("require product =alpha|beta|gamma", "product", "", false,
+ {"alpha", "beta", "gamma"});
+ ParseRequirementLineTest("require product= alpha|beta|gamma", "product", "", false,
+ {"alpha", "beta", "gamma"});
+ ParseRequirementLineTest("require product = alpha|beta|gamma", "product", "", false,
+ {"alpha", "beta", "gamma"});
+ ParseRequirementLineTest("require product=alpha |beta|gamma", "product", "", false,
+ {"alpha", "beta", "gamma"});
+ ParseRequirementLineTest("require product=alpha| beta|gamma", "product", "", false,
+ {"alpha", "beta", "gamma"});
+ ParseRequirementLineTest("require product=alpha | beta|gamma", "product", "", false,
+ {"alpha", "beta", "gamma"});
+ ParseRequirementLineTest("require product=alpha|beta|gamma ", "product", "", false,
+ {"alpha", "beta", "gamma"});
+ ParseRequirementLineTest("product = alpha | beta | gamma ", "product", "", false,
+ {"alpha", "beta", "gamma"});
+ ParseRequirementLineTest("require-for-product: gamma version-bootloader=istanbul",
+ "version-bootloader", "gamma", false, {"istanbul"});
+
+ // Extraneous ending | is okay, implies accepting an empty string.
+ ParseRequirementLineTest("require product=alpha|", "product", "", false, {"alpha", ""});
+ ParseRequirementLineTest("require product=alpha|beta|gamma|", "product", "", false,
+ {"alpha", "beta", "gamma", ""});
+
+ // Accept empty options, double ||, etc, implies accepting an empty string.
+ ParseRequirementLineTest("require product=alpha||beta| |gamma", "product", "", false,
+ {"alpha", "", "beta", "", "gamma"});
+ ParseRequirementLineTest("require product=alpha||beta|gamma", "product", "", false,
+ {"alpha", "", "beta", "gamma"});
+ ParseRequirementLineTest("require product=alpha|beta| |gamma", "product", "", false,
+ {"alpha", "beta", "", "gamma"});
+ ParseRequirementLineTest("require product=alpha||", "product", "", false, {"alpha", "", ""});
+ ParseRequirementLineTest("require product=alpha|| ", "product", "", false, {"alpha", "", ""});
+ ParseRequirementLineTest("require product=alpha| ", "product", "", false, {"alpha", ""});
+ ParseRequirementLineTest("require product=alpha|beta| ", "product", "", false,
+ {"alpha", "beta", ""});
+
+ // No option string is also treating as accepting an empty string.
+ ParseRequirementLineTest("require =", "require", "", false, {""});
+ ParseRequirementLineTest("require = |", "require", "", false, {"", ""});
+ ParseRequirementLineTest("reject =", "reject", "", false, {""});
+ ParseRequirementLineTest("reject = |", "reject", "", false, {"", ""});
+ ParseRequirementLineTest("require-for-product: =", "require-for-product:", "", false, {""});
+ ParseRequirementLineTest("require-for-product: = | ", "require-for-product:", "", false,
+ {"", ""});
+ ParseRequirementLineTest("require product=", "product", "", false, {""});
+ ParseRequirementLineTest("require product = ", "product", "", false, {""});
+ ParseRequirementLineTest("require product = | ", "product", "", false, {"", ""});
+ ParseRequirementLineTest("reject product=", "product", "", true, {""});
+ ParseRequirementLineTest("reject product = ", "product", "", true, {""});
+ ParseRequirementLineTest("reject product = | ", "product", "", true, {"", ""});
+ ParseRequirementLineTest("require-for-product:gamma product=", "product", "gamma", false, {""});
+ ParseRequirementLineTest("require-for-product:gamma product = ", "product", "gamma", false,
+ {""});
+ ParseRequirementLineTest("require-for-product:gamma product = |", "product", "gamma", false,
+ {"", ""});
+
+ // Check for board -> product substitution.
+ ParseRequirementLineTest("require board=alpha", "product", "", false, {"alpha"});
+ ParseRequirementLineTest("board=alpha", "product", "", false, {"alpha"});
+}
+
+static void ParseRequirementLineTestMalformed(const std::string& line) {
+ std::string name;
+ std::string product;
+ bool invert;
+ std::vector<std::string> options;
+
+ EXPECT_FALSE(ParseRequirementLine(line, &name, &product, &invert, &options)) << line;
+}
+
+TEST(FastBoot, ParseRequirementLineMalformed) {
+ ParseRequirementLineTestMalformed("nothing");
+ ParseRequirementLineTestMalformed("");
+ ParseRequirementLineTestMalformed("=");
+ ParseRequirementLineTestMalformed("|");
+
+ ParseRequirementLineTestMalformed("require");
+ ParseRequirementLineTestMalformed("require ");
+ ParseRequirementLineTestMalformed("reject");
+ ParseRequirementLineTestMalformed("reject ");
+ ParseRequirementLineTestMalformed("require-for-product:");
+ ParseRequirementLineTestMalformed("require-for-product: ");
+
+ ParseRequirementLineTestMalformed("require product");
+ ParseRequirementLineTestMalformed("reject product");
+
+ ParseRequirementLineTestMalformed("require-for-product:gamma");
+ ParseRequirementLineTestMalformed("require-for-product:gamma product");
+
+ // No spaces allowed before between require-for-product and :.
+ ParseRequirementLineTestMalformed("require-for-product :");
+}
diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp
index fc6a16b..8c0aa6b 100644
--- a/fastboot/fs.cpp
+++ b/fastboot/fs.cpp
@@ -172,13 +172,8 @@
mkf2fs_args.push_back("-S");
std::string size_str = std::to_string(partSize);
mkf2fs_args.push_back(size_str.c_str());
- mkf2fs_args.push_back("-f");
- mkf2fs_args.push_back("-O");
- mkf2fs_args.push_back("encrypt");
- mkf2fs_args.push_back("-O");
- mkf2fs_args.push_back("quota");
- mkf2fs_args.push_back("-O");
- mkf2fs_args.push_back("verity");
+ mkf2fs_args.push_back("-g");
+ mkf2fs_args.push_back("android");
mkf2fs_args.push_back(fileName);
mkf2fs_args.push_back(nullptr);
diff --git a/fastboot/fuzzy_fastboot/Android.bp b/fastboot/fuzzy_fastboot/Android.bp
index 301534b..277cc3a 100644
--- a/fastboot/fuzzy_fastboot/Android.bp
+++ b/fastboot/fuzzy_fastboot/Android.bp
@@ -26,6 +26,9 @@
"libadb_host",
"libtinyxml2",
"libsparse",
+ "liblp",
+ "libcrypto",
+ "libext4_utils",
],
// Static libs (libfastboot2) shared library dependencies are not transitively included
diff --git a/fastboot/fuzzy_fastboot/fixtures.cpp b/fastboot/fuzzy_fastboot/fixtures.cpp
index 0a87598..280cfb6 100644
--- a/fastboot/fuzzy_fastboot/fixtures.cpp
+++ b/fastboot/fuzzy_fastboot/fixtures.cpp
@@ -86,6 +86,12 @@
return true;
}
+bool FastBootTest::UserSpaceFastboot() {
+ std::string value;
+ fb->GetVar("is-userspace", &value);
+ return value == "yes";
+}
+
RetCode FastBootTest::DownloadCommand(uint32_t size, std::string* response,
std::vector<std::string>* info) {
return fb->DownloadCommand(size, response, info);
@@ -121,8 +127,7 @@
} else {
ASSERT_EQ(device_path, cb_scratch); // The path can not change
}
- fb = std::unique_ptr<FastBootDriver>(
- new FastBootDriver(transport.get(), [](std::string&) {}, true));
+ fb = std::unique_ptr<FastBootDriver>(new FastBootDriver(transport.get(), {}, true));
}
void FastBootTest::TearDown() {
@@ -133,7 +138,6 @@
fb.reset();
if (transport) {
- transport->Close();
transport.reset();
}
@@ -160,6 +164,12 @@
return;
}
+ // User space fastboot implementations are not allowed to communicate to
+ // secure hardware and hence cannot lock/unlock the device.
+ if (UserSpaceFastboot()) {
+ return;
+ }
+
std::string resp;
std::vector<std::string> info;
// To avoid risk of bricking device, make sure unlock ability is set to 1
@@ -188,7 +198,6 @@
ASSERT_EQ(fb->RawCommand("flashing " + cmd, &resp), SUCCESS)
<< "Attempting to change locked state, but 'flashing" + cmd + "' command failed";
fb.reset();
- transport->Close();
transport.reset();
printf("PLEASE RESPOND TO PROMPT FOR '%sing' BOOTLOADER ON DEVICE\n", cmd.c_str());
while (UsbStillAvailible())
@@ -206,8 +215,7 @@
putchar('.');
}
device_path = cb_scratch;
- fb = std::unique_ptr<FastBootDriver>(
- new FastBootDriver(transport.get(), [](std::string&) {}, true));
+ fb = std::unique_ptr<FastBootDriver>(new FastBootDriver(transport.get(), {}, true));
if (assert_change) {
ASSERT_EQ(fb->GetVar("unlocked", &resp), SUCCESS) << "getvar:unlocked failed";
ASSERT_EQ(resp, unlock ? "yes" : "no")
@@ -249,7 +257,6 @@
}
if (transport) {
- transport->Close();
transport.reset();
}
diff --git a/fastboot/fuzzy_fastboot/fixtures.h b/fastboot/fuzzy_fastboot/fixtures.h
index e47d0fd..e0f829e 100644
--- a/fastboot/fuzzy_fastboot/fixtures.h
+++ b/fastboot/fuzzy_fastboot/fixtures.h
@@ -47,6 +47,7 @@
static int MatchFastboot(usb_ifc_info* info, const char* local_serial = nullptr);
bool UsbStillAvailible();
+ bool UserSpaceFastboot();
protected:
RetCode DownloadCommand(uint32_t size, std::string* response = nullptr,
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index 1d30f8b..ef34771 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -43,6 +43,7 @@
#include <thread>
#include <vector>
+#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <gtest/gtest.h>
#include <sparse/sparse.h>
@@ -280,7 +281,7 @@
std::vector<std::string> vars;
EXPECT_EQ(fb->GetVarAll(&vars), SUCCESS) << "getvar:all failed";
EXPECT_GT(vars.size(), 0) << "getvar:all did not respond with any INFO responses";
- for (const auto s : vars) {
+ for (const auto& s : vars) {
EXPECT_LE(s.size(), FB_RESPONSE_SZ - 4)
<< "getvar:all included an INFO response: 'INFO" + s << "' which is too long";
}
@@ -289,6 +290,12 @@
TEST_F(Conformance, UnlockAbility) {
std::string resp;
std::vector<std::string> info;
+ // Userspace fastboot implementations do not have a way to get this
+ // information.
+ if (UserSpaceFastboot()) {
+ GTEST_LOG_(INFO) << "This test is skipped for userspace fastboot.";
+ return;
+ }
EXPECT_EQ(fb->RawCommand("flashing get_unlock_ability", &resp, &info), SUCCESS)
<< "'flashing get_unlock_ability' failed";
// There are two ways this can be reported, through info or the actual response
@@ -304,13 +311,13 @@
}
TEST_F(Conformance, PartitionInfo) {
- std::vector<std::tuple<std::string, uint32_t>> parts;
+ std::vector<std::tuple<std::string, uint64_t>> parts;
EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed";
EXPECT_GT(parts.size(), 0)
<< "getvar:all did not report any partition-size: through INFO responses";
std::set<std::string> allowed{"ext4", "f2fs", "raw"};
- for (const auto p : parts) {
- EXPECT_GT(std::get<1>(p), 0);
+ for (const auto& p : parts) {
+ EXPECT_GE(std::get<1>(p), 0);
std::string part(std::get<0>(p));
std::set<std::string> allowed{"ext4", "f2fs", "raw"};
std::string resp;
@@ -325,8 +332,9 @@
<< cmd + " responded with a string with leading whitespace";
EXPECT_FALSE(resp.compare(0, 2, "0x"))
<< cmd + "responded with a string that does not start with 0x...";
- int64_t size = strtoll(resp.c_str(), nullptr, 16);
- EXPECT_GT(size, 0) << "'" + resp + "' is not a valid response from " + cmd;
+ uint64_t size;
+ ASSERT_TRUE(android::base::ParseUint(resp, &size))
+ << "'" + resp + "' is not a valid response from " + cmd;
}
}
@@ -340,14 +348,14 @@
// Can't run out of alphabet letters...
ASSERT_LE(num_slots, 26) << "What?! You can't have more than 26 slots";
- std::vector<std::tuple<std::string, uint32_t>> parts;
+ std::vector<std::tuple<std::string, uint64_t>> parts;
EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed";
std::map<std::string, std::set<char>> part_slots;
if (num_slots > 0) {
EXPECT_EQ(fb->GetVar("current-slot", &var), SUCCESS) << "getvar:current-slot failed";
- for (const auto p : parts) {
+ for (const auto& p : parts) {
std::string part(std::get<0>(p));
std::regex reg("([[:graph:]]*)_([[:lower:]])");
std::smatch sm;
@@ -370,7 +378,7 @@
}
}
// Ensure each partition has the correct slot suffix
- for (const auto iter : part_slots) {
+ for (const auto& iter : part_slots) {
const std::set<char>& char_set = iter.second;
std::string chars;
for (char c : char_set) {
@@ -412,6 +420,10 @@
ASSERT_TRUE(resp == "yes" || resp == "no")
<< "Device did not respond with 'yes' or 'no' for getvar:unlocked";
bool curr = resp == "yes";
+ if (UserSpaceFastboot()) {
+ GTEST_LOG_(INFO) << "This test is skipped for userspace fastboot.";
+ return;
+ }
for (int i = 0; i < 2; i++) {
std::string action = !curr ? "unlock" : "lock";
@@ -441,9 +453,6 @@
ASSERT_TRUE(*sparse) << "Sparse file creation failed on: " << bs;
EXPECT_EQ(fb->Download(*sparse), SUCCESS) << "Download sparse failed: " << sparse.Rep();
EXPECT_EQ(fb->Flash("userdata"), SUCCESS) << "Flashing sparse failed: " << sparse.Rep();
- EXPECT_EQ(fb->Download(*sparse, true), SUCCESS)
- << "Download sparse with crc failed: " << sparse.Rep();
- EXPECT_EQ(fb->Flash("userdata"), SUCCESS) << "Flashing sparse failed: " << sparse.Rep();
}
}
@@ -462,9 +471,6 @@
<< "Adding data failed to sparse file: " << sparse.Rep();
EXPECT_EQ(fb->Download(*sparse), SUCCESS) << "Download sparse failed: " << sparse.Rep();
EXPECT_EQ(fb->Flash("userdata"), SUCCESS) << "Flashing sparse failed: " << sparse.Rep();
- EXPECT_EQ(fb->Download(*sparse, true), SUCCESS)
- << "Download sparse with crc failed: " << sparse.Rep();
- EXPECT_EQ(fb->Flash("userdata"), SUCCESS) << "Flashing sparse failed: " << sparse.Rep();
}
}
@@ -474,9 +480,6 @@
ASSERT_TRUE(*sparse) << "Sparse image creation failed";
EXPECT_EQ(fb->Download(*sparse), SUCCESS) << "Download sparse failed: " << sparse.Rep();
EXPECT_EQ(fb->Flash("userdata"), SUCCESS) << "Flashing sparse failed: " << sparse.Rep();
- EXPECT_EQ(fb->Download(*sparse, true), SUCCESS)
- << "Download sparse with crc failed: " << sparse.Rep();
- EXPECT_EQ(fb->Flash("userdata"), SUCCESS) << "Flashing sparse failed: " << sparse.Rep();
}
TEST_F(Conformance, SparseDownload1) {
@@ -487,9 +490,6 @@
<< "Adding data failed to sparse file: " << sparse.Rep();
EXPECT_EQ(fb->Download(*sparse), SUCCESS) << "Download sparse failed: " << sparse.Rep();
EXPECT_EQ(fb->Flash("userdata"), SUCCESS) << "Flashing sparse failed: " << sparse.Rep();
- EXPECT_EQ(fb->Download(*sparse, true), SUCCESS)
- << "Download sparse with crc failed: " << sparse.Rep();
- EXPECT_EQ(fb->Flash("userdata"), SUCCESS) << "Flashing sparse failed: " << sparse.Rep();
}
TEST_F(Conformance, SparseDownload2) {
@@ -503,9 +503,6 @@
<< "Adding data failed to sparse file: " << sparse.Rep();
EXPECT_EQ(fb->Download(*sparse), SUCCESS) << "Download sparse failed: " << sparse.Rep();
EXPECT_EQ(fb->Flash("userdata"), SUCCESS) << "Flashing sparse failed: " << sparse.Rep();
- EXPECT_EQ(fb->Download(*sparse, true), SUCCESS)
- << "Download sparse with crc failed: " << sparse.Rep();
- EXPECT_EQ(fb->Flash("userdata"), SUCCESS) << "Flashing sparse failed: " << sparse.Rep();
}
TEST_F(Conformance, SparseDownload3) {
@@ -537,9 +534,6 @@
}
EXPECT_EQ(fb->Download(*sparse), SUCCESS) << "Download sparse failed: " << sparse.Rep();
EXPECT_EQ(fb->Flash("userdata"), SUCCESS) << "Flashing sparse failed: " << sparse.Rep();
- EXPECT_EQ(fb->Download(*sparse, true), SUCCESS)
- << "Download sparse with crc failed: " << sparse.Rep();
- EXPECT_EQ(fb->Flash("userdata"), SUCCESS) << "Flashing sparse failed: " << sparse.Rep();
}
TEST_F(Conformance, SparseVersionCheck) {
@@ -559,25 +553,6 @@
}
}
-TEST_F(Conformance, SparseCRCCheck) {
- SparseWrapper sparse(4096, 4096);
- ASSERT_TRUE(*sparse) << "Sparse image creation failed";
- std::vector<char> buf = RandomBuf(4096);
- ASSERT_EQ(sparse_file_add_data(*sparse, buf.data(), buf.size(), 0), 0)
- << "Adding data failed to sparse file: " << sparse.Rep();
- ASSERT_TRUE(SparseToBuf(*sparse, &buf, true)) << "Sparse buffer creation failed";
- // Flip a bit in the crc
- buf.back() = buf.back() ^ 0x01;
- ASSERT_EQ(DownloadCommand(buf.size()), SUCCESS) << "Device rejected download command";
- ASSERT_EQ(SendBuffer(buf), SUCCESS) << "Downloading payload failed";
- printf("%02x\n", (unsigned char)buf.back());
- // It can either reject this download or reject it during flash
- if (HandleResponse() != DEVICE_FAIL) {
- EXPECT_EQ(fb->Flash("userdata"), DEVICE_FAIL)
- << "Flashing an invalid sparse version should fail " << sparse.Rep();
- }
-}
-
TEST_F(UnlockPermissions, Download) {
std::vector<char> buf{'a', 'o', 's', 'p'};
EXPECT_EQ(fb->Download(buf), SUCCESS) << "Download 4-byte payload failed";
@@ -587,17 +562,17 @@
std::vector<char> buf{'a', 'o', 's', 'p'};
EXPECT_EQ(fb->Download(buf), SUCCESS) << "Download failed in unlocked mode";
;
- std::vector<std::tuple<std::string, uint32_t>> parts;
+ std::vector<std::tuple<std::string, uint64_t>> parts;
EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed in unlocked mode";
}
TEST_F(LockPermissions, DownloadFlash) {
std::vector<char> buf{'a', 'o', 's', 'p'};
EXPECT_EQ(fb->Download(buf), SUCCESS) << "Download failed in locked mode";
- std::vector<std::tuple<std::string, uint32_t>> parts;
+ std::vector<std::tuple<std::string, uint64_t>> parts;
EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed in locked mode";
std::string resp;
- for (const auto tup : parts) {
+ for (const auto& tup : parts) {
EXPECT_EQ(fb->Flash(std::get<0>(tup), &resp), DEVICE_FAIL)
<< "Device did not respond with FAIL when trying to flash '" << std::get<0>(tup)
<< "' in locked mode";
@@ -607,10 +582,10 @@
}
TEST_F(LockPermissions, Erase) {
- std::vector<std::tuple<std::string, uint32_t>> parts;
+ std::vector<std::tuple<std::string, uint64_t>> parts;
EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed";
std::string resp;
- for (const auto tup : parts) {
+ for (const auto& tup : parts) {
EXPECT_EQ(fb->Erase(std::get<0>(tup), &resp), DEVICE_FAIL)
<< "Device did not respond with FAIL when trying to erase '" << std::get<0>(tup)
<< "' in locked mode";
@@ -619,14 +594,14 @@
}
TEST_F(LockPermissions, SetActive) {
- std::vector<std::tuple<std::string, uint32_t>> parts;
+ std::vector<std::tuple<std::string, uint64_t>> parts;
EXPECT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed";
std::string resp;
EXPECT_EQ(fb->GetVar("slot-count", &resp), SUCCESS) << "getvar:slot-count failed";
int32_t num_slots = strtol(resp.c_str(), nullptr, 10);
- for (const auto tup : parts) {
+ for (const auto& tup : parts) {
std::string part(std::get<0>(tup));
std::regex reg("([[:graph:]]*)_([[:lower:]])");
std::smatch sm;
@@ -772,7 +747,7 @@
}
TEST_F(Fuzz, BadCommandTooLarge) {
- std::string s = RandomString(fastboot::FB_COMMAND_SZ + 1, rand_legal);
+ std::string s = RandomString(FB_COMMAND_SZ + 1, rand_legal);
EXPECT_EQ(fb->RawCommand(s), DEVICE_FAIL)
<< "Device did not respond with failure after sending length " << s.size()
<< " string of random ASCII chars";
@@ -916,7 +891,7 @@
TEST_P(AnyPartition, ReportedGetVarAll) {
// As long as the partition is reported in INFO, it would be tested by generic Conformance
- std::vector<std::tuple<std::string, uint32_t>> parts;
+ std::vector<std::tuple<std::string, uint64_t>> parts;
ASSERT_EQ(fb->Partitions(&parts), SUCCESS) << "getvar:all failed";
const std::string name = GetParam().first;
if (GetParam().second.slots) {
@@ -1579,12 +1554,12 @@
void GenerateXmlTests(const extension::Configuration& config) {
// Build the getvar tests
- for (const auto it : config.getvars) {
+ for (const auto& it : config.getvars) {
GETVAR_XML_TESTS.push_back(std::make_pair(it.first, it.second));
}
// Build the partition tests, to interface with gtest we need to do it this way
- for (const auto it : config.partitions) {
+ for (const auto& it : config.partitions) {
const auto tup = std::make_tuple(it.first, it.second);
PARTITION_XML_TESTS.push_back(tup); // All partitions
@@ -1606,7 +1581,7 @@
// Build the packed tests, only useful if we have a hash
if (!config.checksum.empty()) {
- for (const auto it : config.packed) {
+ for (const auto& it : config.packed) {
for (const auto& test : it.second.tests) {
const auto tup = std::make_tuple(it.first, test);
if (test.expect == extension::OKAY) { // only testing the success case
@@ -1633,7 +1608,7 @@
}
// Build oem tests
- for (const auto it : config.oem) {
+ for (const auto& it : config.oem) {
auto oem_cmd = it.second;
for (const auto& t : oem_cmd.tests) {
OEM_XML_TESTS.push_back(std::make_tuple(it.first, oem_cmd.restricted, t));
diff --git a/fastboot/fuzzy_fastboot/usb_transport_sniffer.cpp b/fastboot/fuzzy_fastboot/usb_transport_sniffer.cpp
index ee510e9..7c595f4 100644
--- a/fastboot/fuzzy_fastboot/usb_transport_sniffer.cpp
+++ b/fastboot/fuzzy_fastboot/usb_transport_sniffer.cpp
@@ -12,6 +12,10 @@
const int serial_fd)
: transport_(std::move(transport)), serial_fd_(serial_fd) {}
+UsbTransportSniffer::~UsbTransportSniffer() {
+ Close();
+}
+
ssize_t UsbTransportSniffer::Read(void* data, size_t len) {
ProcessSerial();
diff --git a/fastboot/fuzzy_fastboot/usb_transport_sniffer.h b/fastboot/fuzzy_fastboot/usb_transport_sniffer.h
index 693f042..8119aea 100644
--- a/fastboot/fuzzy_fastboot/usb_transport_sniffer.h
+++ b/fastboot/fuzzy_fastboot/usb_transport_sniffer.h
@@ -68,10 +68,11 @@
};
UsbTransportSniffer(std::unique_ptr<UsbTransport> transport, const int serial_fd = 0);
+ ~UsbTransportSniffer() override;
virtual ssize_t Read(void* data, size_t len) override;
virtual ssize_t Write(const void* data, size_t len) override;
- virtual int Close() override;
+ virtual int Close() override final; // note usage in destructor
virtual int Reset() override;
const std::vector<Event> Transfers();
diff --git a/fastboot/main.cpp b/fastboot/main.cpp
index c3683f7..35f4218 100644
--- a/fastboot/main.cpp
+++ b/fastboot/main.cpp
@@ -26,7 +26,7 @@
* SUCH DAMAGE.
*/
-#include "engine.h"
+#include "fastboot.h"
int main(int argc, char* argv[]) {
FastBootTool fb;
diff --git a/fastboot/usb_linux.cpp b/fastboot/usb_linux.cpp
index 9b779dd..6363aa5 100644
--- a/fastboot/usb_linux.cpp
+++ b/fastboot/usb_linux.cpp
@@ -95,7 +95,7 @@
public:
explicit LinuxUsbTransport(std::unique_ptr<usb_handle> handle, uint32_t ms_timeout = 0)
: handle_(std::move(handle)), ms_timeout_(ms_timeout) {}
- ~LinuxUsbTransport() override = default;
+ ~LinuxUsbTransport() override;
ssize_t Read(void* data, size_t len) override;
ssize_t Write(const void* data, size_t len) override;
@@ -387,6 +387,10 @@
return usb;
}
+LinuxUsbTransport::~LinuxUsbTransport() {
+ Close();
+}
+
ssize_t LinuxUsbTransport::Write(const void* _data, size_t len)
{
unsigned char *data = (unsigned char*) _data;
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index 4d48f6e..f597f50 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -61,7 +61,7 @@
UInt8 bulkIn;
UInt8 bulkOut;
- IOUSBInterfaceInterface190 **interface;
+ IOUSBInterfaceInterface500** interface;
unsigned int zero_mask;
};
@@ -70,7 +70,7 @@
// A timeout of 0 is blocking
OsxUsbTransport(std::unique_ptr<usb_handle> handle, uint32_t ms_timeout = 0)
: handle_(std::move(handle)), ms_timeout_(ms_timeout) {}
- ~OsxUsbTransport() override = default;
+ ~OsxUsbTransport() override;
ssize_t Read(void* data, size_t len) override;
ssize_t Write(const void* data, size_t len) override;
@@ -86,13 +86,13 @@
/** Try out all the interfaces and see if there's a match. Returns 0 on
* success, -1 on failure. */
-static int try_interfaces(IOUSBDeviceInterface182 **dev, usb_handle *handle) {
+static int try_interfaces(IOUSBDeviceInterface500** dev, usb_handle* handle) {
IOReturn kr;
IOUSBFindInterfaceRequest request;
io_iterator_t iterator;
io_service_t usbInterface;
IOCFPlugInInterface **plugInInterface;
- IOUSBInterfaceInterface190 **interface = NULL;
+ IOUSBInterfaceInterface500** interface = NULL;
HRESULT result;
SInt32 score;
UInt8 interfaceNumEndpoints;
@@ -128,10 +128,10 @@
}
// Now create the interface interface for the interface
- result = (*plugInInterface)->QueryInterface(
- plugInInterface,
- CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
- (LPVOID*) &interface);
+ result = (*plugInInterface)
+ ->QueryInterface(plugInInterface,
+ CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID500),
+ (LPVOID*)&interface);
// No longer need the intermediate plugin
(*plugInInterface)->Release(plugInInterface);
@@ -270,7 +270,7 @@
static int try_device(io_service_t device, usb_handle *handle) {
kern_return_t kr;
IOCFPlugInInterface **plugin = NULL;
- IOUSBDeviceInterface182 **dev = NULL;
+ IOUSBDeviceInterface500** dev = NULL;
SInt32 score;
HRESULT result;
UInt8 serialIndex;
@@ -287,8 +287,8 @@
}
// Now create the device interface.
- result = (*plugin)->QueryInterface(plugin,
- CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &dev);
+ result = (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID500),
+ (LPVOID*)&dev);
if ((result != 0) || (dev == NULL)) {
ERR("Couldn't create a device interface (%08x)\n", (int) result);
goto error;
@@ -471,6 +471,10 @@
return new OsxUsbTransport(std::move(handle), timeout_ms);
}
+OsxUsbTransport::~OsxUsbTransport() {
+ Close();
+}
+
int OsxUsbTransport::Close() {
/* TODO: Something better here? */
return 0;
diff --git a/fastboot/usb_windows.cpp b/fastboot/usb_windows.cpp
index 8c60a71..b00edb3 100644
--- a/fastboot/usb_windows.cpp
+++ b/fastboot/usb_windows.cpp
@@ -69,7 +69,7 @@
class WindowsUsbTransport : public UsbTransport {
public:
WindowsUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
- ~WindowsUsbTransport() override = default;
+ ~WindowsUsbTransport() override;
ssize_t Read(void* data, size_t len) override;
ssize_t Write(const void* data, size_t len) override;
@@ -250,6 +250,10 @@
}
}
+WindowsUsbTransport::~WindowsUsbTransport() {
+ Close();
+}
+
int WindowsUsbTransport::Close() {
DBG("usb_close\n");
diff --git a/fastboot/util.cpp b/fastboot/util.cpp
index 8f6e52a..d02b37f 100644
--- a/fastboot/util.cpp
+++ b/fastboot/util.cpp
@@ -69,9 +69,3 @@
}
fprintf(stderr, "\n");
}
-
-char* xstrdup(const char* s) {
- char* result = strdup(s);
- if (!result) die("out of memory");
- return result;
-}
diff --git a/fastboot/util.h b/fastboot/util.h
index 9033f93..2535414 100644
--- a/fastboot/util.h
+++ b/fastboot/util.h
@@ -9,7 +9,6 @@
/* util stuff */
double now();
-char* xstrdup(const char*);
void set_verbose();
// These printf-like functions are implemented in terms of vsnprintf, so they
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index 3cce0e8..974e13e 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -23,10 +23,6 @@
cflags: [
"-Wall",
"-Werror",
- "-Wno-unused-variable",
- ],
- cppflags: [
- "-std=gnu++1z",
],
}
@@ -42,10 +38,10 @@
"fs_mgr.cpp",
"fs_mgr_format.cpp",
"fs_mgr_verity.cpp",
- "fs_mgr_avb.cpp",
- "fs_mgr_avb_ops.cpp",
"fs_mgr_dm_linear.cpp",
"fs_mgr_overlayfs.cpp",
+ "fs_mgr_roots.cpp",
+ "fs_mgr_vendor_overlay.cpp",
],
shared_libs: [
"libbase",
@@ -60,10 +56,13 @@
],
static_libs: [
"libavb",
+ "libfs_avb",
"libfstab",
"libdm",
+ "libgsi",
],
export_static_lib_headers: [
+ "libfs_avb",
"libfstab",
"libdm",
],
@@ -94,12 +93,21 @@
name: "libfstab",
vendor_available: true,
recovery_available: true,
+ host_supported: true,
defaults: ["fs_mgr_defaults"],
srcs: [
"fs_mgr_fstab.cpp",
"fs_mgr_boot_config.cpp",
"fs_mgr_slotselect.cpp",
],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
export_include_dirs: ["include_fstab"],
- header_libs: ["libbase_headers"],
+ header_libs: [
+ "libbase_headers",
+ "libgsi_headers",
+ ],
}
diff --git a/fs_mgr/OWNERS b/fs_mgr/OWNERS
index 817a0b8..cbbd3bc 100644
--- a/fs_mgr/OWNERS
+++ b/fs_mgr/OWNERS
@@ -1,2 +1,3 @@
bowgotsai@google.com
+dvander@google.com
tomcherry@google.com
diff --git a/fs_mgr/README.overlayfs.md b/fs_mgr/README.overlayfs.md
new file mode 100644
index 0000000..8784c94
--- /dev/null
+++ b/fs_mgr/README.overlayfs.md
@@ -0,0 +1,114 @@
+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.
+
+*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.
+
+Operations
+----------
+
+### Cookbook
+
+The typical action to utilize the remount facility is:
+
+ $ adb root
+ $ adb disable-verity
+ $ adb reboot
+ $ adb wait-for-device
+ $ adb root
+ $ adb remount
+
+Followed by one of the following:
+
+ $ adb stop
+ $ adb sync
+ $ adb start
+ $ adb reboot
+
+*or*
+
+ $ adb push <source> <destination>
+ $ adb reboot
+
+Note that the sequence above:
+
+ $ adb disable-verity
+ $ adb reboot
+
+*or*
+
+ $ adb remount
+
+can be replaced in both places with:
+
+ $ adb remount -R
+
+which will not reboot if everything is already prepared and ready
+to go.
+
+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.
+
+### Backing Storage
+
+When *overlayfs* logic is feasible, it will use 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 Resizeable Android Partitions*.
+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.
+
+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.
+
+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 higher than 4.6.
+- *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 incompatable with an OTA resources.
+- 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.
+- File bugs or submit fixes for review.
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index e3c2c2b..ded3678 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -20,6 +20,7 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
@@ -34,9 +35,11 @@
#include <unistd.h>
#include <functional>
+#include <map>
#include <memory>
#include <string>
#include <thread>
+#include <utility>
#include <vector>
#include <android-base/file.h>
@@ -49,19 +52,19 @@
#include <cutils/partition_utils.h>
#include <cutils/properties.h>
#include <ext4_utils/ext4.h>
-#include <ext4_utils/ext4_crypt_init_extensions.h>
#include <ext4_utils/ext4_sb.h>
#include <ext4_utils/ext4_utils.h>
#include <ext4_utils/wipe.h>
+#include <fs_avb/fs_avb.h>
#include <fs_mgr_overlayfs.h>
#include <libdm/dm.h>
+#include <liblp/metadata_format.h>
#include <linux/fs.h>
#include <linux/loop.h>
#include <linux/magic.h>
#include <log/log_properties.h>
#include <logwrap/logwrap.h>
-#include "fs_mgr_avb.h"
#include "fs_mgr_priv.h"
#define KEY_LOC_PROP "ro.crypto.keyfile.userdata"
@@ -76,11 +79,22 @@
#define ZRAM_CONF_DEV "/sys/block/zram0/disksize"
#define ZRAM_CONF_MCS "/sys/block/zram0/max_comp_streams"
+#define ZRAM_BACK_DEV "/sys/block/zram0/backing_dev"
+
+#define SYSFS_EXT4_VERITY "/sys/fs/ext4/features/verity"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+using android::base::Realpath;
+using android::base::StartsWith;
+using android::base::unique_fd;
using android::dm::DeviceMapper;
using android::dm::DmDeviceState;
+using android::fs_mgr::AvbHandle;
+using android::fs_mgr::AvbHashtreeResult;
+using android::fs_mgr::AvbUniquePtr;
+
+using namespace std::literals;
// record fs stat
enum FsStatFlags {
@@ -94,20 +108,25 @@
FS_STAT_FULL_MOUNT_FAILED = 0x0100,
FS_STAT_E2FSCK_FAILED = 0x0200,
FS_STAT_E2FSCK_FS_FIXED = 0x0400,
- FS_STAT_EXT4_INVALID_MAGIC = 0x0800,
+ FS_STAT_INVALID_MAGIC = 0x0800,
FS_STAT_TOGGLE_QUOTAS_FAILED = 0x10000,
FS_STAT_SET_RESERVED_BLOCKS_FAILED = 0x20000,
FS_STAT_ENABLE_ENCRYPTION_FAILED = 0x40000,
+ 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) {
+ const std::chrono::milliseconds relative_timeout,
+ FileWaitMode file_wait_mode) {
auto start_time = std::chrono::steady_clock::now();
while (true) {
- if (!access(filename.c_str(), F_OK) || errno != ENOENT) {
- return 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);
@@ -118,10 +137,10 @@
}
}
-static void log_fs_stat(const char* blk_device, int fs_stat)
-{
+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 = android::base::StringPrintf("\nfs_stat,%s,0x%x\n", blk_device, fs_stat);
+ std::string msg =
+ android::base::StringPrintf("\nfs_stat,%s,0x%x\n", blk_device.c_str(), fs_stat);
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(FSCK_LOG_FILE, O_WRONLY | O_CLOEXEC |
O_APPEND | O_CREAT, 0664)));
if (fd == -1 || !android::base::WriteStringToFd(msg, fd)) {
@@ -133,6 +152,18 @@
return fs_type == "ext4" || fs_type == "ext3" || fs_type == "ext2";
}
+static bool is_f2fs(const std::string& fs_type) {
+ return fs_type == "f2fs";
+}
+
+static std::string realpath(const std::string& blk_device) {
+ std::string real_path;
+ if (!Realpath(blk_device, &real_path)) {
+ real_path = blk_device;
+ }
+ return real_path;
+}
+
static bool should_force_check(int fs_stat) {
return fs_stat &
(FS_STAT_E2FSCK_F_ALWAYS | FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED |
@@ -141,20 +172,21 @@
FS_STAT_SET_RESERVED_BLOCKS_FAILED | FS_STAT_ENABLE_ENCRYPTION_FAILED);
}
-static void check_fs(const char *blk_device, char *fs_type, char *target, int *fs_stat)
-{
+static void check_fs(const std::string& blk_device, const std::string& fs_type,
+ const std::string& target, int* fs_stat) {
int status;
int ret;
long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
- char tmpmnt_opts[64] = "errors=remount-ro";
- const char* e2fsck_argv[] = {E2FSCK_BIN, "-y", blk_device};
- const char* e2fsck_forced_argv[] = {E2FSCK_BIN, "-f", "-y", blk_device};
+ auto tmpmnt_opts = "errors=remount-ro"s;
+ const char* e2fsck_argv[] = {E2FSCK_BIN, "-y", blk_device.c_str()};
+ const char* e2fsck_forced_argv[] = {E2FSCK_BIN, "-f", "-y", blk_device.c_str()};
+
+ if (*fs_stat & FS_STAT_INVALID_MAGIC) { // will fail, so do not try
+ return;
+ }
/* Check for the types of filesystems we know how to check */
if (is_extfs(fs_type)) {
- if (*fs_stat & FS_STAT_EXT4_INVALID_MAGIC) { // will fail, so do not try
- return;
- }
/*
* First try to mount and unmount the filesystem. We do this because
* the kernel is more efficient than e2fsck in running the journal and
@@ -170,18 +202,19 @@
*/
if (!(*fs_stat & FS_STAT_FULL_MOUNT_FAILED)) { // already tried if full mount failed
errno = 0;
- if (!strcmp(fs_type, "ext4")) {
+ if (fs_type == "ext4") {
// This option is only valid with ext4
- strlcat(tmpmnt_opts, ",nomblk_io_submit", sizeof(tmpmnt_opts));
+ tmpmnt_opts += ",nomblk_io_submit";
}
- ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);
+ ret = mount(blk_device.c_str(), target.c_str(), fs_type.c_str(), tmpmnt_flags,
+ tmpmnt_opts.c_str());
PINFO << __FUNCTION__ << "(): mount(" << blk_device << "," << target << "," << fs_type
<< ")=" << ret;
if (!ret) {
bool umounted = false;
int retry_count = 5;
while (retry_count-- > 0) {
- umounted = umount(target) == 0;
+ umounted = umount(target.c_str()) == 0;
if (umounted) {
LINFO << __FUNCTION__ << "(): unmount(" << target << ") succeeded";
break;
@@ -204,10 +237,10 @@
* (e.g. recent SDK system images). Detect these and skip the check.
*/
if (access(E2FSCK_BIN, X_OK)) {
- LINFO << "Not running " << E2FSCK_BIN << " on " << blk_device
+ LINFO << "Not running " << E2FSCK_BIN << " on " << realpath(blk_device)
<< " (executable not in system image)";
} else {
- LINFO << "Running " << E2FSCK_BIN << " on " << blk_device;
+ 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,
@@ -227,13 +260,9 @@
*fs_stat |= FS_STAT_E2FSCK_FS_FIXED;
}
}
- } else if (!strcmp(fs_type, "f2fs")) {
- const char *f2fs_fsck_argv[] = {
- F2FS_FSCK_BIN,
- "-a",
- blk_device
- };
- LINFO << "Running " << F2FS_FSCK_BIN << " -a " << blk_device;
+ } else if (is_f2fs(fs_type)) {
+ const char* f2fs_fsck_argv[] = {F2FS_FSCK_BIN, "-a", blk_device.c_str()};
+ 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),
@@ -267,9 +296,10 @@
}
// Read the primary superblock from an ext4 filesystem. On failure return
-// false. If it's not an ext4 filesystem, also set FS_STAT_EXT4_INVALID_MAGIC.
-static bool read_ext4_superblock(const char* blk_device, struct ext4_super_block* sb, int* fs_stat) {
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC)));
+// false. If it's not an ext4 filesystem, also set FS_STAT_INVALID_MAGIC.
+static bool read_ext4_superblock(const std::string& blk_device, struct ext4_super_block* sb,
+ int* fs_stat) {
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
if (fd < 0) {
PERROR << "Failed to open '" << blk_device << "'";
@@ -284,7 +314,7 @@
if (!is_ext4_superblock_valid(sb)) {
LINFO << "Invalid ext4 superblock on '" << blk_device << "'";
// not a valid fs, tune2fs, fsck, and mount will all fail.
- *fs_stat |= FS_STAT_EXT4_INVALID_MAGIC;
+ *fs_stat |= FS_STAT_INVALID_MAGIC;
return false;
}
*fs_stat |= FS_STAT_IS_EXT4;
@@ -310,10 +340,10 @@
}
// Enable/disable quota support on the filesystem if needed.
-static void tune_quota(const char* blk_device, const struct fstab_rec* rec,
+static void tune_quota(const std::string& blk_device, const FstabEntry& entry,
const struct ext4_super_block* sb, int* fs_stat) {
bool has_quota = (sb->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_QUOTA)) != 0;
- bool want_quota = fs_mgr_is_quota(rec) != 0;
+ bool want_quota = entry.fs_mgr_flags.quota;
if (has_quota == want_quota) {
return;
@@ -325,7 +355,7 @@
return;
}
- const char* argv[] = {TUNE2FS_BIN, nullptr, nullptr, blk_device};
+ const char* argv[] = {TUNE2FS_BIN, nullptr, nullptr, blk_device.c_str()};
if (want_quota) {
LINFO << "Enabling quotas on " << blk_device;
@@ -346,16 +376,16 @@
}
// Set the number of reserved filesystem blocks if needed.
-static void tune_reserved_size(const char* blk_device, const struct fstab_rec* rec,
+static void tune_reserved_size(const std::string& blk_device, const FstabEntry& entry,
const struct ext4_super_block* sb, int* fs_stat) {
- if (!(rec->fs_mgr_flags & MF_RESERVEDSIZE)) {
+ if (!entry.fs_mgr_flags.reserved_size) {
return;
}
// The size to reserve is given in the fstab, but we won't reserve more
// than 2% of the filesystem.
const uint64_t max_reserved_blocks = ext4_blocks_count(sb) * 0.02;
- uint64_t reserved_blocks = rec->reserved_size / EXT4_BLOCK_SIZE(sb);
+ uint64_t reserved_blocks = entry.reserved_size / EXT4_BLOCK_SIZE(sb);
if (reserved_blocks > max_reserved_blocks) {
LWARNING << "Reserved blocks " << reserved_blocks << " is too large; "
@@ -378,7 +408,8 @@
auto reserved_blocks_str = std::to_string(reserved_blocks);
auto reserved_gid_str = std::to_string(AID_RESERVED_DISK);
const char* argv[] = {
- TUNE2FS_BIN, "-r", reserved_blocks_str.c_str(), "-g", reserved_gid_str.c_str(), blk_device};
+ TUNE2FS_BIN, "-r", reserved_blocks_str.c_str(), "-g", reserved_gid_str.c_str(),
+ blk_device.c_str()};
if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
LERROR << "Failed to run " TUNE2FS_BIN " to set the number of reserved blocks on "
<< blk_device;
@@ -387,10 +418,10 @@
}
// Enable file-based encryption if needed.
-static void tune_encrypt(const char* blk_device, const struct fstab_rec* rec,
+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 = fs_mgr_is_file_encrypted(rec) != 0;
+ bool want_encrypt = entry.fs_mgr_flags.file_encryption;
if (has_encrypt || !want_encrypt) {
return;
@@ -402,7 +433,7 @@
return;
}
- const char* argv[] = {TUNE2FS_BIN, "-Oencrypt", blk_device};
+ const char* argv[] = {TUNE2FS_BIN, "-Oencrypt", blk_device.c_str()};
LINFO << "Enabling ext4 encryption on " << blk_device;
if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
@@ -412,6 +443,73 @@
}
}
+// Enable fs-verity if needed.
+static void tune_verity(const std::string& blk_device, const FstabEntry& entry,
+ const struct ext4_super_block* sb, int* fs_stat) {
+ bool has_verity = (sb->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_VERITY)) != 0;
+ bool want_verity = entry.fs_mgr_flags.fs_verity;
+
+ if (has_verity || !want_verity) {
+ return;
+ }
+
+ std::string verity_support;
+ if (!android::base::ReadFileToString(SYSFS_EXT4_VERITY, &verity_support)) {
+ LERROR << "Failed to open " << SYSFS_EXT4_VERITY;
+ return;
+ }
+
+ if (!(android::base::Trim(verity_support) == "supported")) {
+ LERROR << "Current ext4 verity not supported by kernel";
+ return;
+ }
+
+ if (!tune2fs_available()) {
+ LERROR << "Unable to enable ext4 verity on " << blk_device
+ << " because " TUNE2FS_BIN " is missing";
+ return;
+ }
+
+ LINFO << "Enabling ext4 verity on " << blk_device;
+
+ const char* argv[] = {TUNE2FS_BIN, "-O", "verity", blk_device.c_str()};
+ if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
+ LERROR << "Failed to run " TUNE2FS_BIN " to enable "
+ << "ext4 verity on " << blk_device;
+ *fs_stat |= FS_STAT_ENABLE_VERITY_FAILED;
+ }
+}
+
+// Read the primary superblock from an f2fs filesystem. On failure return
+// false. If it's not an f2fs filesystem, also set FS_STAT_INVALID_MAGIC.
+#define F2FS_BLKSIZE 4096
+#define F2FS_SUPER_OFFSET 1024
+static bool read_f2fs_superblock(const std::string& blk_device, int* fs_stat) {
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
+ __le32 sb1, sb2;
+
+ if (fd < 0) {
+ PERROR << "Failed to open '" << blk_device << "'";
+ return false;
+ }
+
+ if (pread(fd, &sb1, sizeof(sb1), F2FS_SUPER_OFFSET) != sizeof(sb1)) {
+ PERROR << "Can't read '" << blk_device << "' superblock1";
+ return false;
+ }
+ if (pread(fd, &sb2, sizeof(sb2), F2FS_BLKSIZE + F2FS_SUPER_OFFSET) != sizeof(sb2)) {
+ PERROR << "Can't read '" << blk_device << "' superblock2";
+ return false;
+ }
+
+ if (sb1 != cpu_to_le32(F2FS_SUPER_MAGIC) && sb2 != cpu_to_le32(F2FS_SUPER_MAGIC)) {
+ LINFO << "Invalid f2fs superblock on '" << blk_device << "'";
+ *fs_stat |= FS_STAT_INVALID_MAGIC;
+ return false;
+ }
+ return true;
+}
+
//
// Prepare the filesystem on the given block device to be mounted.
//
@@ -421,10 +519,10 @@
// If needed, we'll also enable (or disable) filesystem features as specified by
// the fstab record.
//
-static int prepare_fs_for_mount(const char* blk_device, const struct fstab_rec* rec) {
+static int prepare_fs_for_mount(const std::string& blk_device, const FstabEntry& entry) {
int fs_stat = 0;
- if (is_extfs(rec->fs_type)) {
+ if (is_extfs(entry.fs_type)) {
struct ext4_super_block sb;
if (read_ext4_superblock(blk_device, &sb, &fs_stat)) {
@@ -437,60 +535,45 @@
}
// Note: quotas should be enabled before running fsck.
- tune_quota(blk_device, rec, &sb, &fs_stat);
+ tune_quota(blk_device, entry, &sb, &fs_stat);
} else {
return fs_stat;
}
+ } else if (is_f2fs(entry.fs_type)) {
+ if (!read_f2fs_superblock(blk_device, &fs_stat)) {
+ return fs_stat;
+ }
}
- if ((rec->fs_mgr_flags & MF_CHECK) ||
+ if (entry.fs_mgr_flags.check ||
(fs_stat & (FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED))) {
- check_fs(blk_device, rec->fs_type, rec->mount_point, &fs_stat);
+ check_fs(blk_device, entry.fs_type, entry.mount_point, &fs_stat);
}
- if (is_extfs(rec->fs_type) && (rec->fs_mgr_flags & (MF_RESERVEDSIZE | MF_FILEENCRYPTION))) {
+ if (is_extfs(entry.fs_type) &&
+ (entry.fs_mgr_flags.reserved_size || entry.fs_mgr_flags.file_encryption ||
+ entry.fs_mgr_flags.fs_verity)) {
struct ext4_super_block sb;
if (read_ext4_superblock(blk_device, &sb, &fs_stat)) {
- tune_reserved_size(blk_device, rec, &sb, &fs_stat);
- tune_encrypt(blk_device, rec, &sb, &fs_stat);
+ tune_reserved_size(blk_device, entry, &sb, &fs_stat);
+ tune_encrypt(blk_device, entry, &sb, &fs_stat);
+ tune_verity(blk_device, entry, &sb, &fs_stat);
}
}
return fs_stat;
}
-static void remove_trailing_slashes(char *n)
-{
- int len;
-
- len = strlen(n) - 1;
- while ((*(n + len) == '/') && len) {
- *(n + len) = '\0';
- len--;
- }
-}
-
-/*
- * Mark the given block device as read-only, using the BLKROSET ioctl.
- * Return 0 on success, and -1 on error.
- */
-int fs_mgr_set_blk_ro(const char *blockdev)
-{
- int fd;
- int rc = -1;
- int ON = 1;
-
- fd = TEMP_FAILURE_RETRY(open(blockdev, O_RDONLY | O_CLOEXEC));
+// Mark the given block device as read-only, using the BLKROSET ioctl.
+bool fs_mgr_set_blk_ro(const std::string& blockdev, bool readonly) {
+ unique_fd fd(TEMP_FAILURE_RETRY(open(blockdev.c_str(), O_RDONLY | O_CLOEXEC)));
if (fd < 0) {
- // should never happen
- return rc;
+ return false;
}
- rc = ioctl(fd, BLKROSET, &ON);
- close(fd);
-
- return rc;
+ int ON = readonly;
+ return ioctl(fd, BLKROSET, &ON) == 0;
}
// Orange state means the device is unlocked, see the following link for details.
@@ -503,30 +586,42 @@
return false;
}
-/*
- * __mount(): wrapper around the mount() system call which also
- * sets the underlying block device to read-only if the mount is read-only.
- * See "man 2 mount" for return values.
- */
-static int __mount(const char *source, const char *target, const struct fstab_rec *rec)
-{
- unsigned long mountflags = rec->flags;
- int ret;
- int save_errno;
-
- /* We need this because sometimes we have legacy symlinks
- * that are lingering around and need cleaning up.
- */
+// __mount(): wrapper around the mount() system call which also
+// sets the underlying block device to read-only if the mount is read-only.
+// See "man 2 mount" for return values.
+static int __mount(const std::string& source, const std::string& target, const FstabEntry& entry) {
+ // We need this because sometimes we have legacy symlinks that are
+ // lingering around and need cleaning up.
struct stat info;
- if (!lstat(target, &info))
- if ((info.st_mode & S_IFMT) == S_IFLNK)
- unlink(target);
- mkdir(target, 0755);
+ if (lstat(target.c_str(), &info) == 0 && (info.st_mode & S_IFMT) == S_IFLNK) {
+ unlink(target.c_str());
+ }
+ mkdir(target.c_str(), 0755);
errno = 0;
- ret = mount(source, target, rec->fs_type, mountflags, rec->fs_options);
- save_errno = errno;
- PINFO << __FUNCTION__ << "(source=" << source << ",target=" << target
- << ",type=" << rec->fs_type << ")=" << ret;
+ unsigned long mountflags = entry.flags;
+ int ret = 0;
+ int save_errno = 0;
+ do {
+ if (save_errno == EAGAIN) {
+ PINFO << "Retrying mount (source=" << source << ",target=" << target
+ << ",type=" << entry.fs_type << ")=" << ret << "(" << save_errno << ")";
+ }
+ ret = mount(source.c_str(), target.c_str(), entry.fs_type.c_str(), mountflags,
+ entry.fs_options.c_str());
+ save_errno = errno;
+ } while (ret && save_errno == EAGAIN);
+ const char* target_missing = "";
+ const char* source_missing = "";
+ if (save_errno == ENOENT) {
+ if (access(target.c_str(), F_OK)) {
+ target_missing = "(missing)";
+ } else if (access(source.c_str(), F_OK)) {
+ source_missing = "(missing)";
+ }
+ errno = save_errno;
+ }
+ PINFO << __FUNCTION__ << "(source=" << source << source_missing << ",target=" << target
+ << target_missing << ",type=" << entry.fs_type << ")=" << ret;
if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
fs_mgr_set_blk_ro(source);
}
@@ -534,250 +629,208 @@
return ret;
}
-static int fs_match(const char *in1, const char *in2)
-{
- char *n1;
- char *n2;
- int ret;
-
- n1 = strdup(in1);
- n2 = strdup(in2);
-
- remove_trailing_slashes(n1);
- remove_trailing_slashes(n2);
-
- ret = !strcmp(n1, n2);
-
- free(n1);
- free(n2);
-
- return ret;
-}
-
-/*
- * Tries to mount any of the consecutive fstab entries that match
- * the mountpoint of the one given by fstab->recs[start_idx].
- *
- * end_idx: On return, will be the last rec that was looked at.
- * attempted_idx: On return, will indicate which fstab rec
- * succeeded. In case of failure, it will be the start_idx.
- * Returns
- * -1 on failure with errno set to match the 1st mount failure.
- * 0 on success.
- */
-static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_idx, int *attempted_idx)
-{
- int i;
- int mount_errno = 0;
- int mounted = 0;
-
- if (!end_idx || !attempted_idx || start_idx >= fstab->num_entries) {
- errno = EINVAL;
- if (end_idx) *end_idx = start_idx;
- if (attempted_idx) *attempted_idx = start_idx;
- return -1;
+static bool fs_match(const std::string& in1, const std::string& in2) {
+ if (in1.empty() || in2.empty()) {
+ return false;
}
- /* Hunt down an fstab entry for the same mount point that might succeed */
+ auto in1_end = in1.size() - 1;
+ while (in1_end > 0 && in1[in1_end] == '/') {
+ in1_end--;
+ }
+
+ auto in2_end = in2.size() - 1;
+ while (in2_end > 0 && in2[in2_end] == '/') {
+ in2_end--;
+ }
+
+ if (in1_end != in2_end) {
+ return false;
+ }
+
+ for (size_t i = 0; i <= in1_end; ++i) {
+ if (in1[i] != in2[i]) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Tries to mount any of the consecutive fstab entries that match
+// the mountpoint of the one given by fstab[start_idx].
+//
+// end_idx: On return, will be the last entry that was looked at.
+// attempted_idx: On return, will indicate which fstab entry
+// succeeded. In case of failure, it will be the start_idx.
+// Sets errno to match the 1st mount failure on failure.
+static bool mount_with_alternatives(const Fstab& fstab, int start_idx, int* end_idx,
+ int* attempted_idx) {
+ unsigned long i;
+ int mount_errno = 0;
+ bool mounted = false;
+
+ // Hunt down an fstab entry for the same mount point that might succeed.
for (i = start_idx;
- /* We required that fstab entries for the same mountpoint be consecutive */
- i < fstab->num_entries && !strcmp(fstab->recs[start_idx].mount_point, fstab->recs[i].mount_point);
- i++) {
- /*
- * Don't try to mount/encrypt the same mount point again.
- * Deal with alternate entries for the same point which are required to be all following
- * each other.
- */
- if (mounted) {
- LERROR << __FUNCTION__ << "(): skipping fstab dup mountpoint="
- << fstab->recs[i].mount_point << " rec[" << i
- << "].fs_type=" << fstab->recs[i].fs_type
- << " already mounted as "
- << fstab->recs[*attempted_idx].fs_type;
- continue;
- }
+ // We required that fstab entries for the same mountpoint be consecutive.
+ i < fstab.size() && fstab[start_idx].mount_point == fstab[i].mount_point; i++) {
+ // Don't try to mount/encrypt the same mount point again.
+ // Deal with alternate entries for the same point which are required to be all following
+ // each other.
+ if (mounted) {
+ LERROR << __FUNCTION__ << "(): skipping fstab dup mountpoint=" << fstab[i].mount_point
+ << " rec[" << i << "].fs_type=" << fstab[i].fs_type << " already mounted as "
+ << fstab[*attempted_idx].fs_type;
+ continue;
+ }
- int fs_stat = prepare_fs_for_mount(fstab->recs[i].blk_device, &fstab->recs[i]);
- if (fs_stat & FS_STAT_EXT4_INVALID_MAGIC) {
- LERROR << __FUNCTION__ << "(): skipping mount, invalid ext4, mountpoint="
- << fstab->recs[i].mount_point << " rec[" << i
- << "].fs_type=" << fstab->recs[i].fs_type;
- mount_errno = EINVAL; // continue bootup for FDE
- continue;
- }
+ int fs_stat = prepare_fs_for_mount(fstab[i].blk_device, fstab[i]);
+ if (fs_stat & FS_STAT_INVALID_MAGIC) {
+ LERROR << __FUNCTION__
+ << "(): skipping mount due to invalid magic, mountpoint=" << fstab[i].mount_point
+ << " blk_dev=" << realpath(fstab[i].blk_device) << " rec[" << i
+ << "].fs_type=" << fstab[i].fs_type;
+ mount_errno = EINVAL; // continue bootup for FDE
+ continue;
+ }
- int retry_count = 2;
- while (retry_count-- > 0) {
- if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point,
- &fstab->recs[i])) {
- *attempted_idx = i;
- mounted = 1;
- if (i != start_idx) {
- LERROR << __FUNCTION__ << "(): Mounted " << fstab->recs[i].blk_device
- << " on " << fstab->recs[i].mount_point
- << " with fs_type=" << fstab->recs[i].fs_type << " instead of "
- << fstab->recs[start_idx].fs_type;
- }
- fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
- mount_errno = 0;
- break;
- } else {
- if (retry_count <= 0) break; // run check_fs only once
- fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
- /* back up the first errno for crypto decisions */
- if (mount_errno == 0) {
- mount_errno = errno;
- }
- // retry after fsck
- check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
- fstab->recs[i].mount_point, &fs_stat);
+ int retry_count = 2;
+ while (retry_count-- > 0) {
+ if (!__mount(fstab[i].blk_device, fstab[i].mount_point, fstab[i])) {
+ *attempted_idx = i;
+ mounted = true;
+ if (i != start_idx) {
+ LERROR << __FUNCTION__ << "(): Mounted " << fstab[i].blk_device << " on "
+ << fstab[i].mount_point << " with fs_type=" << fstab[i].fs_type
+ << " instead of " << fstab[start_idx].fs_type;
}
+ fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
+ mount_errno = 0;
+ break;
+ } else {
+ if (retry_count <= 0) break; // run check_fs only once
+ fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
+ // back up the first errno for crypto decisions.
+ if (mount_errno == 0) {
+ mount_errno = errno;
+ }
+ // retry after fsck
+ check_fs(fstab[i].blk_device, fstab[i].fs_type, fstab[i].mount_point, &fs_stat);
}
- log_fs_stat(fstab->recs[i].blk_device, fs_stat);
+ }
+ log_fs_stat(fstab[i].blk_device, fs_stat);
}
/* Adjust i for the case where it was still withing the recs[] */
- if (i < fstab->num_entries) --i;
+ if (i < fstab.size()) --i;
*end_idx = i;
if (!mounted) {
*attempted_idx = start_idx;
errno = mount_errno;
- return -1;
+ return false;
}
- return 0;
+ return true;
}
-static int translate_ext_labels(struct fstab_rec *rec)
-{
- DIR *blockdir = NULL;
- struct dirent *ent;
- char *label;
- size_t label_len;
- int ret = -1;
-
- if (strncmp(rec->blk_device, "LABEL=", 6))
- return 0;
-
- label = rec->blk_device + 6;
- label_len = strlen(label);
-
- if (label_len > 16) {
- LERROR << "FS label is longer than allowed by filesystem";
- goto out;
+static bool TranslateExtLabels(FstabEntry* entry) {
+ if (!StartsWith(entry->blk_device, "LABEL=")) {
+ return true;
}
+ std::string label = entry->blk_device.substr(6);
+ if (label.size() > 16) {
+ LERROR << "FS label is longer than allowed by filesystem";
+ return false;
+ }
- blockdir = opendir("/dev/block");
+ auto blockdir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/dev/block"), closedir};
if (!blockdir) {
LERROR << "couldn't open /dev/block";
- goto out;
+ return false;
}
- while ((ent = readdir(blockdir))) {
- int fd;
- char super_buf[1024];
- struct ext4_super_block *sb;
-
+ struct dirent* ent;
+ while ((ent = readdir(blockdir.get()))) {
if (ent->d_type != DT_BLK)
continue;
- fd = openat(dirfd(blockdir), ent->d_name, O_RDONLY);
+ unique_fd fd(TEMP_FAILURE_RETRY(
+ openat(dirfd(blockdir.get()), ent->d_name, O_RDONLY | O_CLOEXEC)));
if (fd < 0) {
LERROR << "Cannot open block device /dev/block/" << ent->d_name;
- goto out;
+ return false;
}
+ ext4_super_block super_block;
if (TEMP_FAILURE_RETRY(lseek(fd, 1024, SEEK_SET)) < 0 ||
- TEMP_FAILURE_RETRY(read(fd, super_buf, 1024)) != 1024) {
- /* Probably a loopback device or something else without a readable
- * superblock.
- */
- close(fd);
+ TEMP_FAILURE_RETRY(read(fd, &super_block, sizeof(super_block))) !=
+ sizeof(super_block)) {
+ // Probably a loopback device or something else without a readable superblock.
continue;
}
- sb = (struct ext4_super_block *)super_buf;
- if (sb->s_magic != EXT4_SUPER_MAGIC) {
+ if (super_block.s_magic != EXT4_SUPER_MAGIC) {
LINFO << "/dev/block/" << ent->d_name << " not ext{234}";
continue;
}
- if (!strncmp(label, sb->s_volume_name, label_len)) {
- char *new_blk_device;
+ if (label == super_block.s_volume_name) {
+ std::string new_blk_device = "/dev/block/"s + ent->d_name;
- if (asprintf(&new_blk_device, "/dev/block/%s", ent->d_name) < 0) {
- LERROR << "Could not allocate block device string";
- goto out;
- }
+ LINFO << "resolved label " << entry->blk_device << " to " << new_blk_device;
- LINFO << "resolved label " << rec->blk_device << " to "
- << new_blk_device;
-
- free(rec->blk_device);
- rec->blk_device = new_blk_device;
- ret = 0;
- break;
+ entry->blk_device = new_blk_device;
+ return true;
}
}
-out:
- closedir(blockdir);
- return ret;
+ return false;
}
-static bool needs_block_encryption(const struct fstab_rec* rec)
-{
- if (android::base::GetBoolProperty("ro.vold.forceencryption", false) &&
- fs_mgr_is_encryptable(rec))
+static bool needs_block_encryption(const FstabEntry& entry) {
+ if (android::base::GetBoolProperty("ro.vold.forceencryption", false) && entry.is_encryptable())
return true;
- if (rec->fs_mgr_flags & MF_FORCECRYPT) return true;
- if (rec->fs_mgr_flags & MF_CRYPT) {
- /* Check for existence of convert_fde breadcrumb file */
- char convert_fde_name[PATH_MAX];
- snprintf(convert_fde_name, sizeof(convert_fde_name),
- "%s/misc/vold/convert_fde", rec->mount_point);
- if (access(convert_fde_name, F_OK) == 0) return true;
+ if (entry.fs_mgr_flags.force_crypt) return true;
+ if (entry.fs_mgr_flags.crypt) {
+ // Check for existence of convert_fde breadcrumb file.
+ auto convert_fde_name = entry.mount_point + "/misc/vold/convert_fde";
+ if (access(convert_fde_name.c_str(), F_OK) == 0) return true;
}
- if (rec->fs_mgr_flags & MF_FORCEFDEORFBE) {
- /* Check for absence of convert_fbe breadcrumb file */
- char convert_fbe_name[PATH_MAX];
- snprintf(convert_fbe_name, sizeof(convert_fbe_name),
- "%s/convert_fbe", rec->mount_point);
- if (access(convert_fbe_name, F_OK) != 0) return true;
+ if (entry.fs_mgr_flags.force_fde_or_fbe) {
+ // Check for absence of convert_fbe breadcrumb file.
+ auto convert_fbe_name = entry.mount_point + "/convert_fbe";
+ if (access(convert_fbe_name.c_str(), F_OK) != 0) return true;
}
return false;
}
-static bool should_use_metadata_encryption(const struct fstab_rec* rec) {
- if (!(rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE))) return false;
- if (!(rec->fs_mgr_flags & MF_KEYDIRECTORY)) return false;
- return true;
+static bool should_use_metadata_encryption(const FstabEntry& entry) {
+ return entry.fs_mgr_flags.key_directory &&
+ (entry.fs_mgr_flags.file_encryption || entry.fs_mgr_flags.force_fde_or_fbe);
}
// Check to see if a mountable volume has encryption requirements
-static int handle_encryptable(const struct fstab_rec* rec)
-{
- /* If this is block encryptable, need to trigger encryption */
- if (needs_block_encryption(rec)) {
- if (umount(rec->mount_point) == 0) {
+static int handle_encryptable(const FstabEntry& entry) {
+ // If this is block encryptable, need to trigger encryption.
+ if (needs_block_encryption(entry)) {
+ if (umount(entry.mount_point.c_str()) == 0) {
return FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION;
} else {
- PWARNING << "Could not umount " << rec->mount_point
- << " - allow continue unencrypted";
+ PWARNING << "Could not umount " << entry.mount_point << " - allow continue unencrypted";
return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
}
- } else if (should_use_metadata_encryption(rec)) {
- if (umount(rec->mount_point) == 0) {
+ } else if (should_use_metadata_encryption(entry)) {
+ if (umount(entry.mount_point.c_str()) == 0) {
return FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION;
} else {
- PERROR << "Could not umount " << rec->mount_point << " - fail since can't encrypt";
+ PERROR << "Could not umount " << entry.mount_point << " - fail since can't encrypt";
return FS_MGR_MNTALL_FAIL;
}
- } else if (rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE)) {
- LINFO << rec->mount_point << " is file encrypted";
+ } else if (entry.fs_mgr_flags.file_encryption || entry.fs_mgr_flags.force_fde_or_fbe) {
+ LINFO << entry.mount_point << " is file encrypted";
return FS_MGR_MNTALL_DEV_FILE_ENCRYPTED;
- } else if (fs_mgr_is_encryptable(rec)) {
+ } else if (entry.is_encryptable()) {
return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
} else {
return FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE;
@@ -801,106 +854,257 @@
return true;
}
-bool fs_mgr_update_logical_partition(struct fstab_rec* rec) {
+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);
+ if (err != 0) {
+ LOG(ERROR) << "vdc call failed with error code: " << err;
+ return false;
+ }
+ LOG(DEBUG) << "vdc finished successfully";
+ *ret = WEXITSTATUS(*ret);
+ return true;
+}
+
+bool fs_mgr_update_logical_partition(FstabEntry* entry) {
// Logical partitions are specified with a named partition rather than a
// block device, so if the block device is a path, then it has already
// been updated.
- if (rec->blk_device[0] == '/') {
+ if (entry->blk_device[0] == '/') {
return true;
}
DeviceMapper& dm = DeviceMapper::Instance();
std::string device_name;
- if (!dm.GetDmDevicePathByName(rec->blk_device, &device_name)) {
+ if (!dm.GetDmDevicePathByName(entry->blk_device, &device_name)) {
return false;
}
- free(rec->blk_device);
- rec->blk_device = strdup(device_name.c_str());
+
+ entry->blk_device = device_name;
return true;
}
-/* When multiple fstab records share the same mount_point, it will
- * try to mount each one in turn, and ignore any duplicates after a
- * first successful mount.
- * Returns -1 on error, and FS_MGR_MNTALL_* otherwise.
- */
-int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
-{
- int i = 0;
+bool fs_mgr_update_logical_partition(struct fstab_rec* rec) {
+ auto entry = FstabRecToFstabEntry(rec);
+
+ if (!fs_mgr_update_logical_partition(&entry)) {
+ return false;
+ }
+
+ free(rec->blk_device);
+ rec->blk_device = strdup(entry.blk_device.c_str());
+
+ return true;
+}
+
+class CheckpointManager {
+ public:
+ CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {}
+
+ bool Update(FstabEntry* entry) {
+ 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});
+ }
+
+ 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) {
+ return true;
+ }
+
+ if (!UpdateCheckpointPartition(entry)) {
+ LERROR << "Could not set up checkpoint partition, skipping!";
+ return false;
+ }
+
+ return true;
+ }
+
+ bool Revert(FstabEntry* entry) {
+ if (!entry->fs_mgr_flags.checkpoint_blk && !entry->fs_mgr_flags.checkpoint_fs) {
+ return true;
+ }
+
+ if (device_map_.find(entry->blk_device) == device_map_.end()) {
+ return true;
+ }
+
+ std::string bow_device = entry->blk_device;
+ entry->blk_device = device_map_[bow_device];
+ device_map_.erase(bow_device);
+
+ DeviceMapper& dm = DeviceMapper::Instance();
+ if (!dm.DeleteDevice("bow")) {
+ PERROR << "Failed to remove bow device";
+ }
+
+ return true;
+ }
+
+ private:
+ bool UpdateCheckpointPartition(FstabEntry* entry) {
+ if (entry->fs_mgr_flags.checkpoint_fs) {
+ if (is_f2fs(entry->fs_type)) {
+ entry->fs_options += ",checkpoint=disable";
+ } else {
+ LERROR << entry->fs_type << " does not implement checkpoints.";
+ }
+ } else if (entry->fs_mgr_flags.checkpoint_blk) {
+ unique_fd fd(TEMP_FAILURE_RETRY(open(entry->blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
+ if (fd < 0) {
+ PERROR << "Cannot open device " << entry->blk_device;
+ return false;
+ }
+
+ uint64_t size = get_block_device_size(fd) / 512;
+ if (!size) {
+ PERROR << "Cannot get device size";
+ return false;
+ }
+
+ android::dm::DmTable table;
+ if (!table.AddTarget(
+ std::make_unique<android::dm::DmTargetBow>(0, size, entry->blk_device))) {
+ LERROR << "Failed to add bow target";
+ return false;
+ }
+
+ DeviceMapper& dm = DeviceMapper::Instance();
+ if (!dm.CreateDevice("bow", table)) {
+ PERROR << "Failed to create bow device";
+ return false;
+ }
+
+ std::string name;
+ if (!dm.GetDmDevicePathByName("bow", &name)) {
+ PERROR << "Failed to get bow device name";
+ return false;
+ }
+
+ device_map_[name] = entry->blk_device;
+ entry->blk_device = name;
+ }
+ return true;
+ }
+
+ enum { UNKNOWN = -1, NO = 0, YES = 1 };
+ int needs_checkpoint_;
+ std::map<std::string, std::string> device_map_;
+};
+
+static bool IsMountPointMounted(const std::string& mount_point) {
+ // Check if this is already mounted.
+ Fstab fstab;
+ if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
+ return false;
+ }
+ auto it = std::find_if(fstab.begin(), fstab.end(),
+ [&](const auto& entry) { return entry.mount_point == mount_point; });
+ return it != fstab.end();
+}
+
+// When multiple fstab records share the same mount_point, it will try to mount each
+// one in turn, and ignore any duplicates after a first successful mount.
+// Returns -1 on error, and FS_MGR_MNTALL_* otherwise.
+int fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE;
int error_count = 0;
- int mret = -1;
- int mount_errno = 0;
- int attempted_idx = -1;
- FsManagerAvbUniquePtr avb_handle(nullptr);
+ CheckpointManager checkpoint_manager;
+ AvbUniquePtr avb_handle(nullptr);
- if (!fstab) {
+ if (fstab->empty()) {
return FS_MGR_MNTALL_FAIL;
}
- for (i = 0; i < fstab->num_entries; i++) {
- /* Don't mount entries that are managed by vold or not for the mount mode*/
- if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) ||
- ((mount_mode == MOUNT_MODE_LATE) && !fs_mgr_is_latemount(&fstab->recs[i])) ||
- ((mount_mode == MOUNT_MODE_EARLY) && fs_mgr_is_latemount(&fstab->recs[i]))) {
+ for (size_t i = 0; i < fstab->size(); i++) {
+ auto& current_entry = (*fstab)[i];
+
+ // If a filesystem should have been mounted in the first stage, we
+ // ignore it here. With one exception, if the filesystem is
+ // formattable, then it can only be formatted in the second stage,
+ // so we allow it to mount here.
+ if (current_entry.fs_mgr_flags.first_stage_mount &&
+ (!current_entry.fs_mgr_flags.formattable ||
+ IsMountPointMounted(current_entry.mount_point))) {
continue;
}
- /* Skip swap and raw partition entries such as boot, recovery, etc */
- if (!strcmp(fstab->recs[i].fs_type, "swap") ||
- !strcmp(fstab->recs[i].fs_type, "emmc") ||
- !strcmp(fstab->recs[i].fs_type, "mtd")) {
+ // Don't mount entries that are managed by vold or not for the mount mode.
+ if (current_entry.fs_mgr_flags.vold_managed || current_entry.fs_mgr_flags.recovery_only ||
+ ((mount_mode == MOUNT_MODE_LATE) && !current_entry.fs_mgr_flags.late_mount) ||
+ ((mount_mode == MOUNT_MODE_EARLY) && current_entry.fs_mgr_flags.late_mount)) {
continue;
}
- /* Skip mounting the root partition, as it will already have been mounted */
- if (!strcmp(fstab->recs[i].mount_point, "/") ||
- !strcmp(fstab->recs[i].mount_point, "/system")) {
- if ((fstab->recs[i].fs_mgr_flags & MS_RDONLY) != 0) {
- fs_mgr_set_blk_ro(fstab->recs[i].blk_device);
+ // Skip swap and raw partition entries such as boot, recovery, etc.
+ if (current_entry.fs_type == "swap" || current_entry.fs_type == "emmc" ||
+ current_entry.fs_type == "mtd") {
+ continue;
+ }
+
+ // Skip mounting the root partition, as it will already have been mounted.
+ if (current_entry.mount_point == "/" || current_entry.mount_point == "/system") {
+ if ((current_entry.flags & MS_RDONLY) != 0) {
+ fs_mgr_set_blk_ro(current_entry.blk_device);
}
continue;
}
- /* Translate LABEL= file system labels into block devices */
- if (is_extfs(fstab->recs[i].fs_type)) {
- int tret = translate_ext_labels(&fstab->recs[i]);
- if (tret < 0) {
+ // Translate LABEL= file system labels into block devices.
+ if (is_extfs(current_entry.fs_type)) {
+ if (!TranslateExtLabels(¤t_entry)) {
LERROR << "Could not translate label to block device";
continue;
}
}
- if ((fstab->recs[i].fs_mgr_flags & MF_LOGICAL)) {
- if (!fs_mgr_update_logical_partition(&fstab->recs[i])) {
+ if (current_entry.fs_mgr_flags.logical) {
+ if (!fs_mgr_update_logical_partition(¤t_entry)) {
LERROR << "Could not set up logical partition, skipping!";
continue;
}
}
- if (fstab->recs[i].fs_mgr_flags & MF_WAIT &&
- !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) {
- LERROR << "Skipping '" << fstab->recs[i].blk_device << "' during mount_all";
+ if (!checkpoint_manager.Update(¤t_entry)) {
continue;
}
- if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
+ if (current_entry.fs_mgr_flags.wait &&
+ !fs_mgr_wait_for_file(current_entry.blk_device, 20s)) {
+ LERROR << "Skipping '" << current_entry.blk_device << "' during mount_all";
+ continue;
+ }
+
+ if (current_entry.fs_mgr_flags.avb) {
if (!avb_handle) {
- avb_handle = FsManagerAvbHandle::Open(*fstab);
+ avb_handle = AvbHandle::Open();
if (!avb_handle) {
- LERROR << "Failed to open FsManagerAvbHandle";
+ LERROR << "Failed to open AvbHandle";
return FS_MGR_MNTALL_FAIL;
}
}
- if (avb_handle->SetUpAvbHashtree(&fstab->recs[i], true /* wait_for_verity_dev */) ==
- SetUpAvbHashtreeResult::kFail) {
- LERROR << "Failed to set up AVB on partition: "
- << fstab->recs[i].mount_point << ", skipping!";
- /* Skips mounting the device. */
+ if (avb_handle->SetUpAvbHashtree(¤t_entry, true /* wait_for_verity_dev */) ==
+ AvbHashtreeResult::kFail) {
+ LERROR << "Failed to set up AVB on partition: " << current_entry.mount_point
+ << ", skipping!";
+ // Skips mounting the device.
continue;
}
- } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY)) {
- int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
+ } else if ((current_entry.fs_mgr_flags.verify)) {
+ int rc = fs_mgr_setup_verity(¤t_entry, true);
if (__android_log_is_debuggable() &&
(rc == FS_MGR_SETUP_VERITY_DISABLED ||
rc == FS_MGR_SETUP_VERITY_SKIPPED)) {
@@ -913,17 +1117,19 @@
int last_idx_inspected;
int top_idx = i;
+ int attempted_idx = -1;
- mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx);
+ bool mret = mount_with_alternatives(*fstab, i, &last_idx_inspected, &attempted_idx);
+ auto& attempted_entry = (*fstab)[attempted_idx];
i = last_idx_inspected;
- mount_errno = errno;
+ int mount_errno = errno;
- /* Deal with encryptability. */
- if (!mret) {
- int status = handle_encryptable(&fstab->recs[attempted_idx]);
+ // Handle success and deal with encryptability.
+ if (mret) {
+ int status = handle_encryptable(attempted_entry);
if (status == FS_MGR_MNTALL_FAIL) {
- /* Fatal error - no point continuing */
+ // Fatal error - no point continuing.
return status;
}
@@ -934,48 +1140,45 @@
}
encryptable = status;
if (status == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
- if (!call_vdc(
- {"cryptfs", "encryptFstab", fstab->recs[attempted_idx].mount_point})) {
+ if (!call_vdc({"cryptfs", "encryptFstab", attempted_entry.mount_point})) {
LERROR << "Encryption failed";
return FS_MGR_MNTALL_FAIL;
}
}
}
- /* Success! Go get the next one */
+ // Success! Go get the next one.
continue;
}
- bool wiped = partition_wiped(fstab->recs[top_idx].blk_device);
+ // Mounting failed, understand why and retry.
+ bool wiped = partition_wiped(current_entry.blk_device.c_str());
bool crypt_footer = false;
- if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
- fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) {
- /* top_idx and attempted_idx point at the same partition, but sometimes
- * at two different lines in the fstab. Use the top one for formatting
- * as that is the preferred one.
- */
- LERROR << __FUNCTION__ << "(): " << fstab->recs[top_idx].blk_device
- << " is wiped and " << fstab->recs[top_idx].mount_point
- << " " << fstab->recs[top_idx].fs_type
+ if (mount_errno != EBUSY && mount_errno != EACCES &&
+ current_entry.fs_mgr_flags.formattable && wiped) {
+ // current_entry and attempted_entry point at the same partition, but sometimes
+ // at two different lines in the fstab. Use current_entry for formatting
+ // as that is the preferred one.
+ LERROR << __FUNCTION__ << "(): " << realpath(current_entry.blk_device)
+ << " is wiped and " << current_entry.mount_point << " " << current_entry.fs_type
<< " is formattable. Format it.";
- if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
- strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
- int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY);
+
+ checkpoint_manager.Revert(¤t_entry);
+
+ if (current_entry.is_encryptable() && current_entry.key_loc != KEY_IN_FOOTER) {
+ unique_fd fd(TEMP_FAILURE_RETRY(
+ open(current_entry.key_loc.c_str(), O_WRONLY | O_CLOEXEC)));
if (fd >= 0) {
- LINFO << __FUNCTION__ << "(): also wipe "
- << fstab->recs[top_idx].key_loc;
+ LINFO << __FUNCTION__ << "(): also wipe " << current_entry.key_loc;
wipe_block_device(fd, get_file_size(fd));
- close(fd);
} else {
- PERROR << __FUNCTION__ << "(): "
- << fstab->recs[top_idx].key_loc << " wouldn't open";
+ PERROR << __FUNCTION__ << "(): " << current_entry.key_loc << " wouldn't open";
}
- } else if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
- !strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
+ } else if (current_entry.is_encryptable() && current_entry.key_loc == KEY_IN_FOOTER) {
crypt_footer = true;
}
- if (fs_mgr_do_format(&fstab->recs[top_idx], crypt_footer) == 0) {
- /* Let's replay the mount actions. */
+ if (fs_mgr_do_format(current_entry, crypt_footer) == 0) {
+ // Let's replay the mount actions.
i = top_idx - 1;
continue;
} else {
@@ -986,35 +1189,29 @@
}
}
- /* mount(2) returned an error, handle the encryptable/formattable case */
- if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
- fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) {
+ // mount(2) returned an error, handle the encryptable/formattable case.
+ if (mount_errno != EBUSY && mount_errno != EACCES && attempted_entry.is_encryptable()) {
if (wiped) {
- LERROR << __FUNCTION__ << "(): "
- << fstab->recs[attempted_idx].blk_device
- << " is wiped and "
- << fstab->recs[attempted_idx].mount_point << " "
- << fstab->recs[attempted_idx].fs_type
+ LERROR << __FUNCTION__ << "(): " << attempted_entry.blk_device << " is wiped and "
+ << attempted_entry.mount_point << " " << attempted_entry.fs_type
<< " is encryptable. Suggest recovery...";
encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY;
continue;
} else {
- /* Need to mount a tmpfs at this mountpoint for now, and set
- * properties that vold will query later for decrypting
- */
+ // Need to mount a tmpfs at this mountpoint for now, and set
+ // properties that vold will query later for decrypting
LERROR << __FUNCTION__ << "(): possibly an encryptable blkdev "
- << fstab->recs[attempted_idx].blk_device
- << " for mount " << fstab->recs[attempted_idx].mount_point
- << " type " << fstab->recs[attempted_idx].fs_type;
- if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) {
+ << attempted_entry.blk_device << " for mount " << attempted_entry.mount_point
+ << " type " << attempted_entry.fs_type;
+ if (fs_mgr_do_tmpfs_mount(attempted_entry.mount_point.c_str()) < 0) {
++error_count;
continue;
}
}
encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
- } else if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
- should_use_metadata_encryption(&fstab->recs[attempted_idx])) {
- if (!call_vdc({"cryptfs", "mountFstab", fstab->recs[attempted_idx].mount_point})) {
+ } else if (mount_errno != EBUSY && mount_errno != EACCES &&
+ should_use_metadata_encryption(attempted_entry)) {
+ if (!call_vdc({"cryptfs", "mountFstab", attempted_entry.mount_point})) {
++error_count;
}
encryptable = FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED;
@@ -1022,18 +1219,18 @@
} else {
// fs_options might be null so we cannot use PERROR << directly.
// Use StringPrintf to output "(null)" instead.
- if (fs_mgr_is_nofail(&fstab->recs[attempted_idx])) {
+ if (attempted_entry.fs_mgr_flags.no_fail) {
PERROR << android::base::StringPrintf(
- "Ignoring failure to mount an un-encryptable or wiped "
- "partition on %s at %s options: %s",
- fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
- fstab->recs[attempted_idx].fs_options);
+ "Ignoring failure to mount an un-encryptable or wiped "
+ "partition on %s at %s options: %s",
+ attempted_entry.blk_device.c_str(), attempted_entry.mount_point.c_str(),
+ attempted_entry.fs_options.c_str());
} else {
PERROR << android::base::StringPrintf(
- "Failed to mount an un-encryptable or wiped partition "
- "on %s at %s options: %s",
- fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
- fstab->recs[attempted_idx].fs_options);
+ "Failed to mount an un-encryptable or wiped partition "
+ "on %s at %s options: %s",
+ attempted_entry.blk_device.c_str(), attempted_entry.mount_point.c_str(),
+ attempted_entry.fs_options.c_str());
++error_count;
}
continue;
@@ -1041,7 +1238,7 @@
}
#if ALLOW_ADBD_DISABLE_VERITY == 1 // "userdebug" build
- fs_mgr_overlayfs_mount_all();
+ fs_mgr_overlayfs_mount_all(fstab);
#endif
if (error_count) {
@@ -1051,20 +1248,14 @@
}
}
-/* 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(struct fstab_rec *rec)
-{
- if (!rec) {
- return FS_MGR_DOMNT_FAILED;
- }
-
+// 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) {
// Run fsck if needed
- prepare_fs_for_mount(rec->blk_device, rec);
+ prepare_fs_for_mount(entry.blk_device, entry);
- int ret = __mount(rec->blk_device, rec->mount_point, rec);
+ int ret =
+ __mount(entry.blk_device, mount_point.empty() ? entry.mount_point : mount_point, entry);
if (ret) {
ret = (errno == EBUSY) ? FS_MGR_DOMNT_BUSY : FS_MGR_DOMNT_FAILED;
}
@@ -1072,71 +1263,84 @@
return ret;
}
-/* If tmp_mount_point is non-null, mount the filesystem there. This is for the
- * tmp mount we do to check the user password
- * If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
- * in turn, and stop on 1st success, or no more match.
- */
-int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
- char *tmp_mount_point)
-{
- int i = 0;
+int fs_mgr_do_mount_one(struct fstab_rec* rec) {
+ if (!rec) {
+ return FS_MGR_DOMNT_FAILED;
+ }
+
+ auto entry = FstabRecToFstabEntry(rec);
+
+ return fs_mgr_do_mount_one(entry);
+}
+
+// If tmp_mount_point is non-null, mount the filesystem there. This is for the
+// tmp mount we do to check the user password
+// If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
+// in turn, and stop on 1st success, or no more match.
+static int fs_mgr_do_mount_helper(Fstab* fstab, const std::string& n_name,
+ const std::string& n_blk_device, const char* tmp_mount_point,
+ int needs_checkpoint) {
int mount_errors = 0;
int first_mount_errno = 0;
- char* mount_point;
- FsManagerAvbUniquePtr avb_handle(nullptr);
+ std::string mount_point;
+ CheckpointManager checkpoint_manager(needs_checkpoint);
+ AvbUniquePtr avb_handle(nullptr);
if (!fstab) {
return FS_MGR_DOMNT_FAILED;
}
- for (i = 0; i < fstab->num_entries; i++) {
- if (!fs_match(fstab->recs[i].mount_point, n_name)) {
+ for (auto& fstab_entry : *fstab) {
+ if (!fs_match(fstab_entry.mount_point, n_name)) {
continue;
}
- /* We found our match */
- /* If this swap or a raw partition, report an error */
- if (!strcmp(fstab->recs[i].fs_type, "swap") ||
- !strcmp(fstab->recs[i].fs_type, "emmc") ||
- !strcmp(fstab->recs[i].fs_type, "mtd")) {
- LERROR << "Cannot mount filesystem of type "
- << fstab->recs[i].fs_type << " on " << n_blk_device;
+ // We found our match.
+ // If this swap or a raw partition, report an error.
+ if (fstab_entry.fs_type == "swap" || fstab_entry.fs_type == "emmc" ||
+ fstab_entry.fs_type == "mtd") {
+ LERROR << "Cannot mount filesystem of type " << fstab_entry.fs_type << " on "
+ << n_blk_device;
return FS_MGR_DOMNT_FAILED;
}
- if ((fstab->recs[i].fs_mgr_flags & MF_LOGICAL)) {
- if (!fs_mgr_update_logical_partition(&fstab->recs[i])) {
+ if (fstab_entry.fs_mgr_flags.logical) {
+ if (!fs_mgr_update_logical_partition(&fstab_entry)) {
LERROR << "Could not set up logical partition, skipping!";
continue;
}
}
- /* First check the filesystem if requested */
- if (fstab->recs[i].fs_mgr_flags & MF_WAIT && !fs_mgr_wait_for_file(n_blk_device, 20s)) {
+ if (!checkpoint_manager.Update(&fstab_entry)) {
+ LERROR << "Could not set up checkpoint partition, skipping!";
+ continue;
+ }
+
+ // First check the filesystem if requested.
+ if (fstab_entry.fs_mgr_flags.wait && !fs_mgr_wait_for_file(n_blk_device, 20s)) {
LERROR << "Skipping mounting '" << n_blk_device << "'";
continue;
}
- int fs_stat = prepare_fs_for_mount(n_blk_device, &fstab->recs[i]);
+ int fs_stat = prepare_fs_for_mount(n_blk_device, fstab_entry);
- if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
+ if (fstab_entry.fs_mgr_flags.avb) {
if (!avb_handle) {
- avb_handle = FsManagerAvbHandle::Open(*fstab);
+ avb_handle = AvbHandle::Open();
if (!avb_handle) {
- LERROR << "Failed to open FsManagerAvbHandle";
+ LERROR << "Failed to open AvbHandle";
return FS_MGR_DOMNT_FAILED;
}
}
- if (avb_handle->SetUpAvbHashtree(&fstab->recs[i], true /* wait_for_verity_dev */) ==
- SetUpAvbHashtreeResult::kFail) {
- LERROR << "Failed to set up AVB on partition: "
- << fstab->recs[i].mount_point << ", skipping!";
- /* Skips mounting the device. */
+ if (avb_handle->SetUpAvbHashtree(&fstab_entry, true /* wait_for_verity_dev */) ==
+ AvbHashtreeResult::kFail) {
+ LERROR << "Failed to set up AVB on partition: " << fstab_entry.mount_point
+ << ", skipping!";
+ // Skips mounting the device.
continue;
}
- } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY)) {
- int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
+ } else if (fstab_entry.fs_mgr_flags.verify) {
+ int rc = fs_mgr_setup_verity(&fstab_entry, true);
if (__android_log_is_debuggable() &&
(rc == FS_MGR_SETUP_VERITY_DISABLED ||
rc == FS_MGR_SETUP_VERITY_SKIPPED)) {
@@ -1147,15 +1351,15 @@
}
}
- /* Now mount it where requested */
+ // Now mount it where requested */
if (tmp_mount_point) {
mount_point = tmp_mount_point;
} else {
- mount_point = fstab->recs[i].mount_point;
+ mount_point = fstab_entry.mount_point;
}
int retry_count = 2;
while (retry_count-- > 0) {
- if (!__mount(n_blk_device, mount_point, &fstab->recs[i])) {
+ if (!__mount(n_blk_device, mount_point, fstab_entry)) {
fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
return FS_MGR_DOMNT_SUCCESS;
} else {
@@ -1164,10 +1368,10 @@
mount_errors++;
fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
// try again after fsck
- check_fs(n_blk_device, fstab->recs[i].fs_type, fstab->recs[i].mount_point, &fs_stat);
+ check_fs(n_blk_device, fstab_entry.fs_type, fstab_entry.mount_point, &fs_stat);
}
}
- log_fs_stat(fstab->recs[i].blk_device, fs_stat);
+ log_fs_stat(fstab_entry.blk_device, fs_stat);
}
// Reach here means the mount attempt fails.
@@ -1175,12 +1379,24 @@
PERROR << "Cannot mount filesystem on " << n_blk_device << " at " << mount_point;
if (first_mount_errno == EBUSY) return FS_MGR_DOMNT_BUSY;
} else {
- /* We didn't find a match, say so and return an error */
+ // We didn't find a match, say so and return an error.
LERROR << "Cannot find mount point " << n_name << " in fstab";
}
return FS_MGR_DOMNT_FAILED;
}
+int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point) {
+ auto new_fstab = LegacyFstabToFstab(fstab);
+ return fs_mgr_do_mount_helper(&new_fstab, n_name, n_blk_device, tmp_mount_point, -1);
+}
+
+int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
+ bool needs_checkpoint) {
+ auto new_fstab = LegacyFstabToFstab(fstab);
+ return fs_mgr_do_mount_helper(&new_fstab, n_name, n_blk_device, tmp_mount_point,
+ needs_checkpoint);
+}
+
/*
* mount a tmpfs filesystem at the given point.
* return 0 on success, non-zero on failure.
@@ -1200,101 +1416,149 @@
return 0;
}
-/* This must be called after mount_all, because the mkswap command needs to be
- * available.
- */
-int fs_mgr_swapon_all(struct fstab *fstab)
-{
- int i = 0;
- int flags = 0;
- int err = 0;
- int ret = 0;
- int status;
- const char *mkswap_argv[2] = {
- MKSWAP_BIN,
- nullptr
- };
+static bool InstallZramDevice(const std::string& device) {
+ if (!android::base::WriteStringToFile(device, ZRAM_BACK_DEV)) {
+ PERROR << "Cannot write " << device << " in: " << ZRAM_BACK_DEV;
+ return false;
+ }
+ LINFO << "Success to set " << device << " to " << ZRAM_BACK_DEV;
+ return true;
+}
- if (!fstab) {
- return -1;
+static bool PrepareZramDevice(const std::string& loop, off64_t size, const std::string& bdev) {
+ if (loop.empty() && bdev.empty()) return true;
+
+ if (bdev.length()) {
+ return InstallZramDevice(bdev);
}
- for (i = 0; i < fstab->num_entries; i++) {
- /* Skip non-swap entries */
- if (strcmp(fstab->recs[i].fs_type, "swap")) {
+ // Get free loopback
+ unique_fd loop_fd(TEMP_FAILURE_RETRY(open("/dev/loop-control", O_RDWR | O_CLOEXEC)));
+ if (loop_fd.get() == -1) {
+ PERROR << "Cannot open loop-control";
+ return false;
+ }
+
+ int num = ioctl(loop_fd.get(), LOOP_CTL_GET_FREE);
+ if (num == -1) {
+ PERROR << "Cannot get free loop slot";
+ return false;
+ }
+
+ // Prepare target path
+ unique_fd target_fd(TEMP_FAILURE_RETRY(open(loop.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0664)));
+ if (target_fd.get() == -1) {
+ PERROR << "Cannot open target path: " << loop;
+ return false;
+ }
+ if (fallocate(target_fd.get(), 0, 0, size) < 0) {
+ PERROR << "Cannot truncate target path: " << loop;
+ return false;
+ }
+
+ // Connect loopback (device_fd) to target path (target_fd)
+ std::string device = android::base::StringPrintf("/dev/block/loop%d", num);
+ unique_fd device_fd(TEMP_FAILURE_RETRY(open(device.c_str(), O_RDWR | O_CLOEXEC)));
+ if (device_fd.get() == -1) {
+ PERROR << "Cannot open /dev/block/loop" << num;
+ return false;
+ }
+
+ if (ioctl(device_fd.get(), LOOP_SET_FD, target_fd.get())) {
+ PERROR << "Cannot set loopback to target path";
+ return false;
+ }
+
+ // set block size & direct IO
+ if (ioctl(device_fd.get(), LOOP_SET_BLOCK_SIZE, 4096)) {
+ PWARNING << "Cannot set 4KB blocksize to /dev/block/loop" << num;
+ }
+ if (ioctl(device_fd.get(), LOOP_SET_DIRECT_IO, 1)) {
+ PWARNING << "Cannot set direct_io to /dev/block/loop" << num;
+ }
+
+ return InstallZramDevice(device);
+}
+
+bool fs_mgr_swapon_all(const Fstab& fstab) {
+ bool ret = true;
+ for (const auto& entry : fstab) {
+ // Skip non-swap entries.
+ if (entry.fs_type != "swap") {
continue;
}
- if (fstab->recs[i].zram_size > 0) {
- /* A zram_size was specified, so we need to configure the
- * device. There is no point in having multiple zram devices
- * on a system (all the memory comes from the same pool) so
- * we can assume the device number is 0.
- */
- FILE *zram_fp;
- FILE *zram_mcs_fp;
+ if (!PrepareZramDevice(entry.zram_loopback_path, entry.zram_loopback_size, entry.zram_backing_dev_path)) {
+ LERROR << "Skipping losetup for '" << entry.blk_device << "'";
+ }
- if (fstab->recs[i].max_comp_streams >= 0) {
- zram_mcs_fp = fopen(ZRAM_CONF_MCS, "r+");
- if (zram_mcs_fp == NULL) {
- LERROR << "Unable to open zram conf comp device "
- << ZRAM_CONF_MCS;
- ret = -1;
- continue;
- }
- fprintf(zram_mcs_fp, "%d\n", fstab->recs[i].max_comp_streams);
- fclose(zram_mcs_fp);
+ if (entry.zram_size > 0) {
+ // A zram_size was specified, so we need to configure the
+ // device. There is no point in having multiple zram devices
+ // on a system (all the memory comes from the same pool) so
+ // we can assume the device number is 0.
+ if (entry.max_comp_streams >= 0) {
+ auto zram_mcs_fp = std::unique_ptr<FILE, decltype(&fclose)>{
+ fopen(ZRAM_CONF_MCS, "re"), fclose};
+ if (zram_mcs_fp == nullptr) {
+ LERROR << "Unable to open zram conf comp device " << ZRAM_CONF_MCS;
+ ret = false;
+ continue;
+ }
+ fprintf(zram_mcs_fp.get(), "%d\n", entry.max_comp_streams);
}
- zram_fp = fopen(ZRAM_CONF_DEV, "r+");
- if (zram_fp == NULL) {
+ auto zram_fp =
+ std::unique_ptr<FILE, decltype(&fclose)>{fopen(ZRAM_CONF_DEV, "re+"), fclose};
+ if (zram_fp == nullptr) {
LERROR << "Unable to open zram conf device " << ZRAM_CONF_DEV;
- ret = -1;
+ ret = false;
continue;
}
- fprintf(zram_fp, "%u\n", fstab->recs[i].zram_size);
- fclose(zram_fp);
+ fprintf(zram_fp.get(), "%" PRId64 "\n", entry.zram_size);
}
- if (fstab->recs[i].fs_mgr_flags & MF_WAIT &&
- !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) {
- LERROR << "Skipping mkswap for '" << fstab->recs[i].blk_device << "'";
- ret = -1;
+ if (entry.fs_mgr_flags.wait && !fs_mgr_wait_for_file(entry.blk_device, 20s)) {
+ LERROR << "Skipping mkswap for '" << entry.blk_device << "'";
+ ret = false;
continue;
}
- /* Initialize the swap area */
- mkswap_argv[1] = fstab->recs[i].blk_device;
- err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv),
- const_cast<char **>(mkswap_argv),
- &status, true, LOG_KLOG, false, NULL,
- NULL, 0);
+ // Initialize the swap area.
+ const char* mkswap_argv[2] = {
+ 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);
if (err) {
- LERROR << "mkswap failed for " << fstab->recs[i].blk_device;
- ret = -1;
+ LERROR << "mkswap failed for " << entry.blk_device;
+ ret = false;
continue;
}
/* If -1, then no priority was specified in fstab, so don't set
* SWAP_FLAG_PREFER or encode the priority */
- if (fstab->recs[i].swap_prio >= 0) {
- flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) &
- SWAP_FLAG_PRIO_MASK;
+ int flags = 0;
+ if (entry.swap_prio >= 0) {
+ flags = (entry.swap_prio << SWAP_FLAG_PRIO_SHIFT) & SWAP_FLAG_PRIO_MASK;
flags |= SWAP_FLAG_PREFER;
} else {
flags = 0;
}
- err = swapon(fstab->recs[i].blk_device, flags);
+ err = swapon(entry.blk_device.c_str(), flags);
if (err) {
- LERROR << "swapon failed for " << fstab->recs[i].blk_device;
- ret = -1;
+ LERROR << "swapon failed for " << entry.blk_device;
+ ret = false;
}
}
return ret;
}
-struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab) {
+struct fstab_rec const* fs_mgr_get_crypt_entry(fstab const* fstab) {
int i;
if (!fstab) {
@@ -1318,7 +1582,7 @@
*
* real_blk_device must be at least PROPERTY_VALUE_MAX bytes long
*/
-void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size) {
+void fs_mgr_get_crypt_info(fstab* fstab, char* key_loc, char* real_blk_device, size_t size) {
struct fstab_rec const* rec = fs_mgr_get_crypt_entry(fstab);
if (key_loc) {
if (rec) {
@@ -1341,23 +1605,22 @@
* logging mode, in which case return that */
*mode = VERITY_MODE_DEFAULT;
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- if (!fstab) {
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
LERROR << "Failed to read default fstab";
return false;
}
- for (int i = 0; i < fstab->num_entries; i++) {
- if (fs_mgr_is_avb(&fstab->recs[i])) {
+ for (const auto& entry : fstab) {
+ if (entry.fs_mgr_flags.avb) {
*mode = VERITY_MODE_RESTART; // avb only supports restart mode.
break;
- } else if (!fs_mgr_is_verified(&fstab->recs[i])) {
+ } else if (!entry.fs_mgr_flags.verify) {
continue;
}
int current;
- if (load_verity_state(&fstab->recs[i], ¤t) < 0) {
+ if (load_verity_state(entry, ¤t) < 0) {
continue;
}
if (current != VERITY_MODE_DEFAULT) {
@@ -1369,7 +1632,8 @@
return true;
}
-bool fs_mgr_update_verity_state(std::function<fs_mgr_verity_state_callback> callback) {
+bool fs_mgr_update_verity_state(
+ std::function<void(const std::string& mount_point, int mode)> callback) {
if (!callback) {
return false;
}
@@ -1379,28 +1643,25 @@
return false;
}
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- if (!fstab) {
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
LERROR << "Failed to read default fstab";
return false;
}
DeviceMapper& dm = DeviceMapper::Instance();
- bool system_root = android::base::GetProperty("ro.build.system_root_image", "") == "true";
-
- for (int i = 0; i < fstab->num_entries; i++) {
- if (!fs_mgr_is_verified(&fstab->recs[i]) && !fs_mgr_is_avb(&fstab->recs[i])) {
+ for (const auto& entry : fstab) {
+ if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
continue;
}
std::string mount_point;
- if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) {
+ if (entry.mount_point == "/") {
// In AVB, the dm device name is vroot instead of system.
- mount_point = fs_mgr_is_avb(&fstab->recs[i]) ? "vroot" : "system";
+ mount_point = entry.fs_mgr_flags.avb ? "vroot" : "system";
} else {
- mount_point = basename(fstab->recs[i].mount_point);
+ mount_point = basename(entry.mount_point.c_str());
}
if (dm.GetState(mount_point) == DmDeviceState::INVALID) {
@@ -1408,15 +1669,14 @@
continue;
}
- const char* status = nullptr;
+ const char* status;
std::vector<DeviceMapper::TargetInfo> table;
if (!dm.GetTableStatus(mount_point, &table) || table.empty() || table[0].data.empty()) {
- if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
- status = "V";
- } else {
- PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point.c_str();
+ if (!entry.fs_mgr_flags.verify_at_boot) {
+ PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point;
continue;
}
+ status = "V";
} else {
status = table[0].data.c_str();
}
@@ -1426,9 +1686,29 @@
// instead of [partition.vroot.verified].
if (mount_point == "vroot") mount_point = "system";
if (*status == 'C' || *status == 'V') {
- callback(&fstab->recs[i], mount_point.c_str(), mode, *status);
+ callback(mount_point, mode);
}
}
return true;
}
+
+std::string fs_mgr_get_super_partition_name(int slot) {
+ // Devices upgrading to dynamic partitions are allowed to specify a super
+ // partition name, assumed to be A/B (non-A/B retrofit is not supported).
+ // For devices launching with dynamic partition support, the partition
+ // name must be "super".
+ std::string super_partition;
+ if (fs_mgr_get_boot_config_from_kernel_cmdline("super_partition", &super_partition)) {
+ std::string suffix;
+ if (slot == 0) {
+ suffix = "_a";
+ } else if (slot == 1) {
+ suffix = "_b";
+ } else if (slot == -1) {
+ suffix = fs_mgr_get_slot_suffix();
+ }
+ return super_partition + suffix;
+ }
+ return LP_METADATA_DEFAULT_PARTITION_NAME;
+}
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
deleted file mode 100644
index 7c6093e..0000000
--- a/fs_mgr/fs_mgr_avb.cpp
+++ /dev/null
@@ -1,515 +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 "fs_mgr_avb.h"
-
-#include <fcntl.h>
-#include <libgen.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <android-base/file.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 <libavb/libavb.h>
-#include <libdm/dm.h>
-
-#include "fs_mgr.h"
-#include "fs_mgr_priv.h"
-#include "fs_mgr_priv_avb_ops.h"
-#include "fs_mgr_priv_sha.h"
-
-static inline bool nibble_value(const char& c, uint8_t* value) {
- FS_MGR_CHECK(value != nullptr);
-
- switch (c) {
- case '0' ... '9':
- *value = c - '0';
- break;
- case 'a' ... 'f':
- *value = c - 'a' + 10;
- break;
- case 'A' ... 'F':
- *value = c - 'A' + 10;
- break;
- default:
- return false;
- }
-
- return true;
-}
-
-static bool hex_to_bytes(uint8_t* bytes, size_t bytes_len, const std::string& hex) {
- FS_MGR_CHECK(bytes != nullptr);
-
- if (hex.size() % 2 != 0) {
- return false;
- }
- if (hex.size() / 2 > bytes_len) {
- return false;
- }
- for (size_t i = 0, j = 0, n = hex.size(); i < n; i += 2, ++j) {
- uint8_t high;
- if (!nibble_value(hex[i], &high)) {
- return false;
- }
- uint8_t low;
- if (!nibble_value(hex[i + 1], &low)) {
- return false;
- }
- bytes[j] = (high << 4) | low;
- }
- return true;
-}
-
-static std::string bytes_to_hex(const uint8_t* bytes, size_t bytes_len) {
- FS_MGR_CHECK(bytes != nullptr);
-
- static const char* hex_digits = "0123456789abcdef";
- std::string hex;
-
- for (size_t i = 0; i < bytes_len; i++) {
- hex.push_back(hex_digits[(bytes[i] & 0xF0) >> 4]);
- hex.push_back(hex_digits[bytes[i] & 0x0F]);
- }
- return hex;
-}
-
-template <typename Hasher>
-static std::pair<size_t, bool> verify_vbmeta_digest(const AvbSlotVerifyData& verify_data,
- const uint8_t* expected_digest) {
- size_t total_size = 0;
- Hasher hasher;
- for (size_t n = 0; n < verify_data.num_vbmeta_images; n++) {
- hasher.update(verify_data.vbmeta_images[n].vbmeta_data,
- verify_data.vbmeta_images[n].vbmeta_size);
- total_size += verify_data.vbmeta_images[n].vbmeta_size;
- }
-
- bool matched = (memcmp(hasher.finalize(), expected_digest, Hasher::DIGEST_SIZE) == 0);
-
- return std::make_pair(total_size, matched);
-}
-
-// Reads the following values from kernel cmdline and provides the
-// VerifyVbmetaImages() to verify AvbSlotVerifyData.
-// - androidboot.vbmeta.hash_alg
-// - androidboot.vbmeta.size
-// - androidboot.vbmeta.digest
-class FsManagerAvbVerifier {
- public:
- // The factory method to return a unique_ptr<FsManagerAvbVerifier>
- static std::unique_ptr<FsManagerAvbVerifier> Create();
- bool VerifyVbmetaImages(const AvbSlotVerifyData& verify_data);
-
- protected:
- FsManagerAvbVerifier() = default;
-
- private:
- enum HashAlgorithm {
- kInvalid = 0,
- kSHA256 = 1,
- kSHA512 = 2,
- };
-
- HashAlgorithm hash_alg_;
- uint8_t digest_[SHA512_DIGEST_LENGTH];
- size_t vbmeta_size_;
-};
-
-std::unique_ptr<FsManagerAvbVerifier> FsManagerAvbVerifier::Create() {
- std::unique_ptr<FsManagerAvbVerifier> avb_verifier(new FsManagerAvbVerifier());
- if (!avb_verifier) {
- LERROR << "Failed to create unique_ptr<FsManagerAvbVerifier>";
- return nullptr;
- }
-
- std::string value;
- if (!fs_mgr_get_boot_config("vbmeta.size", &value) ||
- !android::base::ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) {
- LERROR << "Invalid hash size: " << value.c_str();
- return nullptr;
- }
-
- // Reads hash algorithm.
- size_t expected_digest_size = 0;
- std::string hash_alg;
- fs_mgr_get_boot_config("vbmeta.hash_alg", &hash_alg);
- if (hash_alg == "sha256") {
- expected_digest_size = SHA256_DIGEST_LENGTH * 2;
- avb_verifier->hash_alg_ = kSHA256;
- } else if (hash_alg == "sha512") {
- expected_digest_size = SHA512_DIGEST_LENGTH * 2;
- avb_verifier->hash_alg_ = kSHA512;
- } else {
- LERROR << "Unknown hash algorithm: " << hash_alg.c_str();
- return nullptr;
- }
-
- // Reads digest.
- std::string digest;
- fs_mgr_get_boot_config("vbmeta.digest", &digest);
- if (digest.size() != expected_digest_size) {
- LERROR << "Unexpected digest size: " << digest.size()
- << " (expected: " << expected_digest_size << ")";
- return nullptr;
- }
-
- if (!hex_to_bytes(avb_verifier->digest_, sizeof(avb_verifier->digest_), digest)) {
- LERROR << "Hash digest contains non-hexidecimal character: " << digest.c_str();
- return nullptr;
- }
-
- return avb_verifier;
-}
-
-bool FsManagerAvbVerifier::VerifyVbmetaImages(const AvbSlotVerifyData& verify_data) {
- if (verify_data.num_vbmeta_images == 0) {
- LERROR << "No vbmeta images";
- return false;
- }
-
- size_t total_size = 0;
- bool digest_matched = false;
-
- if (hash_alg_ == kSHA256) {
- std::tie(total_size, digest_matched) =
- verify_vbmeta_digest<SHA256Hasher>(verify_data, digest_);
- } else if (hash_alg_ == kSHA512) {
- std::tie(total_size, digest_matched) =
- verify_vbmeta_digest<SHA512Hasher>(verify_data, digest_);
- }
-
- if (total_size != vbmeta_size_) {
- LERROR << "total vbmeta size mismatch: " << total_size << " (expected: " << vbmeta_size_
- << ")";
- return false;
- }
-
- if (!digest_matched) {
- LERROR << "vbmeta digest mismatch";
- return false;
- }
-
- return true;
-}
-
-// Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel.
-// See the following link for more details:
-// https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
-static bool construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc,
- const std::string& salt, const std::string& root_digest,
- const std::string& blk_device, android::dm::DmTable* table) {
- // Loads androidboot.veritymode from kernel cmdline.
- std::string verity_mode;
- if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) {
- verity_mode = "enforcing"; // Defaults to enforcing when it's absent.
- }
-
- // Converts veritymode to the format used in kernel.
- std::string dm_verity_mode;
- if (verity_mode == "enforcing") {
- dm_verity_mode = "restart_on_corruption";
- } else if (verity_mode == "logging") {
- dm_verity_mode = "ignore_corruption";
- } else if (verity_mode != "eio") { // Default dm_verity_mode is eio.
- LERROR << "Unknown androidboot.veritymode: " << verity_mode;
- return false;
- }
-
- std::ostringstream hash_algorithm;
- hash_algorithm << hashtree_desc.hash_algorithm;
-
- android::dm::DmTargetVerity target(0, hashtree_desc.image_size / 512,
- hashtree_desc.dm_verity_version, blk_device, blk_device,
- hashtree_desc.data_block_size, hashtree_desc.hash_block_size,
- hashtree_desc.image_size / hashtree_desc.data_block_size,
- hashtree_desc.tree_offset / hashtree_desc.hash_block_size,
- hash_algorithm.str(), root_digest, salt);
- if (hashtree_desc.fec_size > 0) {
- target.UseFec(blk_device, hashtree_desc.fec_num_roots,
- hashtree_desc.fec_offset / hashtree_desc.data_block_size,
- hashtree_desc.fec_offset / hashtree_desc.data_block_size);
- }
- if (!dm_verity_mode.empty()) {
- target.SetVerityMode(dm_verity_mode);
- }
- // Always use ignore_zero_blocks.
- target.IgnoreZeroBlocks();
-
- LINFO << "Built verity table: '" << target.GetParameterString() << "'";
-
- return table->AddTarget(std::make_unique<android::dm::DmTargetVerity>(target));
-}
-
-static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry,
- const AvbHashtreeDescriptor& hashtree_desc,
- const std::string& salt, const std::string& root_digest,
- bool wait_for_verity_dev) {
- android::dm::DmTable table;
- if (!construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device, &table) ||
- !table.valid()) {
- LERROR << "Failed to construct verity table.";
- return false;
- }
- table.set_readonly(true);
-
- const std::string mount_point(basename(fstab_entry->mount_point));
- android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
- if (!dm.CreateDevice(mount_point, table)) {
- LERROR << "Couldn't create verity device!";
- return false;
- }
-
- std::string dev_path;
- if (!dm.GetDmDevicePathByName(mount_point, &dev_path)) {
- LERROR << "Couldn't get verity device path!";
- return false;
- }
-
- // Marks the underlying block device as read-only.
- fs_mgr_set_blk_ro(fstab_entry->blk_device);
-
- // Updates fstab_rec->blk_device to verity device name.
- free(fstab_entry->blk_device);
- fstab_entry->blk_device = strdup(dev_path.c_str());
-
- // Makes sure we've set everything up properly.
- if (wait_for_verity_dev && !fs_mgr_wait_for_file(dev_path, 1s)) {
- return false;
- }
-
- return true;
-}
-
-static bool get_hashtree_descriptor(const std::string& partition_name,
- const AvbSlotVerifyData& verify_data,
- AvbHashtreeDescriptor* out_hashtree_desc, std::string* out_salt,
- std::string* out_digest) {
- bool found = false;
- const uint8_t* desc_partition_name;
-
- for (size_t i = 0; i < verify_data.num_vbmeta_images && !found; i++) {
- // Get descriptors from vbmeta_images[i].
- size_t num_descriptors;
- std::unique_ptr<const AvbDescriptor* [], decltype(&avb_free)> descriptors(
- avb_descriptor_get_all(verify_data.vbmeta_images[i].vbmeta_data,
- verify_data.vbmeta_images[i].vbmeta_size, &num_descriptors),
- avb_free);
-
- if (!descriptors || num_descriptors < 1) {
- continue;
- }
-
- // Ensures that hashtree descriptor is in /vbmeta or /boot or in
- // the same partition for verity setup.
- std::string vbmeta_partition_name(verify_data.vbmeta_images[i].partition_name);
- if (vbmeta_partition_name != "vbmeta" &&
- vbmeta_partition_name != "boot" && // for legacy device to append top-level vbmeta
- vbmeta_partition_name != partition_name) {
- LWARNING << "Skip vbmeta image at " << verify_data.vbmeta_images[i].partition_name
- << " for partition: " << partition_name.c_str();
- continue;
- }
-
- for (size_t j = 0; j < num_descriptors && !found; j++) {
- AvbDescriptor desc;
- if (!avb_descriptor_validate_and_byteswap(descriptors[j], &desc)) {
- LWARNING << "Descriptor[" << j << "] is invalid";
- continue;
- }
- if (desc.tag == AVB_DESCRIPTOR_TAG_HASHTREE) {
- desc_partition_name = (const uint8_t*)descriptors[j] + sizeof(AvbHashtreeDescriptor);
- if (!avb_hashtree_descriptor_validate_and_byteswap(
- (AvbHashtreeDescriptor*)descriptors[j], out_hashtree_desc)) {
- continue;
- }
- if (out_hashtree_desc->partition_name_len != partition_name.length()) {
- continue;
- }
- // Notes that desc_partition_name is not NUL-terminated.
- std::string hashtree_partition_name((const char*)desc_partition_name,
- out_hashtree_desc->partition_name_len);
- if (hashtree_partition_name == partition_name) {
- found = true;
- }
- }
- }
- }
-
- if (!found) {
- LERROR << "Partition descriptor not found: " << partition_name.c_str();
- return false;
- }
-
- const uint8_t* desc_salt = desc_partition_name + out_hashtree_desc->partition_name_len;
- *out_salt = bytes_to_hex(desc_salt, out_hashtree_desc->salt_len);
-
- const uint8_t* desc_digest = desc_salt + out_hashtree_desc->salt_len;
- *out_digest = bytes_to_hex(desc_digest, out_hashtree_desc->root_digest_len);
-
- return true;
-}
-
-FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const fstab& fstab) {
- FsManagerAvbOps avb_ops(fstab);
- return DoOpen(&avb_ops);
-}
-
-FsManagerAvbUniquePtr FsManagerAvbHandle::Open(ByNameSymlinkMap&& by_name_symlink_map) {
- if (by_name_symlink_map.empty()) {
- LERROR << "Empty by_name_symlink_map when opening FsManagerAvbHandle";
- return nullptr;
- }
- FsManagerAvbOps avb_ops(std::move(by_name_symlink_map));
- return DoOpen(&avb_ops);
-}
-
-FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) {
- bool is_device_unlocked = fs_mgr_is_device_unlocked();
-
- FsManagerAvbUniquePtr avb_handle(new FsManagerAvbHandle());
- if (!avb_handle) {
- LERROR << "Failed to allocate FsManagerAvbHandle";
- return nullptr;
- }
-
- AvbSlotVerifyFlags flags = is_device_unlocked ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
- : AVB_SLOT_VERIFY_FLAGS_NONE;
- AvbSlotVerifyResult verify_result =
- avb_ops->AvbSlotVerify(fs_mgr_get_slot_suffix(), flags, &avb_handle->avb_slot_data_);
-
- // Only allow two verify results:
- // - AVB_SLOT_VERIFY_RESULT_OK.
- // - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (for UNLOCKED state).
- // If the device is UNLOCKED, i.e., |allow_verification_error| is true for
- // AvbSlotVerify(), then the following return values are all non-fatal:
- // * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
- // * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED
- // * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX
- // The latter two results were checked by bootloader prior to start fs_mgr so
- // we just need to handle the first result here. See *dummy* operations in
- // FsManagerAvbOps and the comments in external/avb/libavb/avb_slot_verify.h
- // for more details.
- switch (verify_result) {
- case AVB_SLOT_VERIFY_RESULT_OK:
- avb_handle->status_ = kAvbHandleSuccess;
- break;
- case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
- if (!is_device_unlocked) {
- LERROR << "ERROR_VERIFICATION isn't allowed when the device is LOCKED";
- return nullptr;
- }
- avb_handle->status_ = kAvbHandleVerificationError;
- break;
- default:
- LERROR << "avb_slot_verify failed, result: " << verify_result;
- return nullptr;
- }
-
- // Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version".
- avb_handle->avb_version_ =
- android::base::StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);
-
- // Checks whether FLAGS_VERIFICATION_DISABLED is set:
- // - Only the top-level vbmeta struct is read.
- // - vbmeta struct in other partitions are NOT processed, including AVB HASH descriptor(s)
- // and AVB HASHTREE descriptor(s).
- AvbVBMetaImageHeader vbmeta_header;
- avb_vbmeta_image_header_to_host_byte_order(
- (AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data,
- &vbmeta_header);
- bool verification_disabled =
- ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
-
- if (verification_disabled) {
- avb_handle->status_ = kAvbHandleVerificationDisabled;
- } else {
- // Verifies vbmeta structs against the digest passed from bootloader in kernel cmdline.
- std::unique_ptr<FsManagerAvbVerifier> avb_verifier = FsManagerAvbVerifier::Create();
- if (!avb_verifier) {
- LERROR << "Failed to create FsManagerAvbVerifier";
- return nullptr;
- }
- if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) {
- LERROR << "VerifyVbmetaImages failed";
- return nullptr;
- }
-
- // Checks whether FLAGS_HASHTREE_DISABLED is set.
- bool hashtree_disabled =
- ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
- if (hashtree_disabled) {
- avb_handle->status_ = kAvbHandleHashtreeDisabled;
- }
- }
-
- LINFO << "Returning avb_handle with status: " << avb_handle->status_;
- return avb_handle;
-}
-
-SetUpAvbHashtreeResult FsManagerAvbHandle::SetUpAvbHashtree(struct fstab_rec* fstab_entry,
- bool wait_for_verity_dev) {
- if (!fstab_entry || status_ == kAvbHandleUninitialized || !avb_slot_data_ ||
- avb_slot_data_->num_vbmeta_images < 1) {
- return SetUpAvbHashtreeResult::kFail;
- }
-
- if (status_ == kAvbHandleHashtreeDisabled || status_ == kAvbHandleVerificationDisabled) {
- LINFO << "AVB HASHTREE disabled on: " << fstab_entry->mount_point;
- return SetUpAvbHashtreeResult::kDisabled;
- }
-
- // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor
- // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix.
- std::string partition_name;
- if (fstab_entry->fs_mgr_flags & MF_LOGICAL) {
- partition_name = fstab_entry->logical_partition_name;
- } else {
- partition_name = basename(fstab_entry->blk_device);
- }
-
- if (fstab_entry->fs_mgr_flags & MF_SLOTSELECT) {
- auto ab_suffix = partition_name.rfind(fs_mgr_get_slot_suffix());
- if (ab_suffix != std::string::npos) {
- partition_name.erase(ab_suffix);
- }
- }
-
- AvbHashtreeDescriptor hashtree_descriptor;
- std::string salt;
- std::string root_digest;
- if (!get_hashtree_descriptor(partition_name, *avb_slot_data_, &hashtree_descriptor, &salt,
- &root_digest)) {
- return SetUpAvbHashtreeResult::kFail;
- }
-
- // Converts HASHTREE descriptor to verity_table_params.
- if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest,
- wait_for_verity_dev)) {
- return SetUpAvbHashtreeResult::kFail;
- }
-
- return SetUpAvbHashtreeResult::kSuccess;
-}
diff --git a/fs_mgr/fs_mgr_boot_config.cpp b/fs_mgr/fs_mgr_boot_config.cpp
index 733ad55..abece4d 100644
--- a/fs_mgr/fs_mgr_boot_config.cpp
+++ b/fs_mgr/fs_mgr_boot_config.cpp
@@ -81,6 +81,9 @@
bool fs_mgr_get_boot_config_from_kernel_cmdline(const std::string& key, std::string* out_val) {
std::string cmdline;
if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) return false;
+ if (!cmdline.empty() && cmdline.back() == '\n') {
+ cmdline.pop_back();
+ }
return fs_mgr_get_boot_config_from_kernel(cmdline, key, out_val);
}
diff --git a/fs_mgr/fs_mgr_dm_linear.cpp b/fs_mgr/fs_mgr_dm_linear.cpp
index a91e92e..45cbff3 100644
--- a/fs_mgr/fs_mgr_dm_linear.cpp
+++ b/fs_mgr/fs_mgr_dm_linear.cpp
@@ -33,6 +33,7 @@
#include <sstream>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -50,8 +51,29 @@
using DmTargetZero = android::dm::DmTargetZero;
using DmTargetLinear = android::dm::DmTargetLinear;
-static bool CreateDmTable(const std::string& block_device, const LpMetadata& metadata,
- const LpMetadataPartition& partition, DmTable* table) {
+static bool GetPhysicalPartitionDevicePath(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;
+ // 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.)
+ if (GetMetadataSuperBlockDevice(metadata) == &block_device) {
+ path = super_device;
+ }
+ if (!android::base::Realpath(path, result)) {
+ PERROR << "realpath: " << path;
+ return false;
+ }
+ return true;
+}
+
+static bool CreateDmTable(const LpMetadata& metadata, const LpMetadataPartition& partition,
+ const std::string& super_device, DmTable* table) {
uint64_t sector = 0;
for (size_t i = 0; i < partition.num_extents; i++) {
const auto& extent = metadata.extents[partition.first_extent_index + i];
@@ -60,10 +82,17 @@
case LP_TARGET_TYPE_ZERO:
target = std::make_unique<DmTargetZero>(sector, extent.num_sectors);
break;
- case LP_TARGET_TYPE_LINEAR:
- target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, block_device,
+ 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)) {
+ LOG(ERROR) << "Unable to complete device-mapper table, unknown block device";
+ return false;
+ }
+ target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, path,
extent.target_data);
break;
+ }
default:
LOG(ERROR) << "Unknown target type in metadata: " << extent.target_type;
return false;
@@ -79,13 +108,13 @@
return true;
}
-static bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata,
- const LpMetadataPartition& partition, bool force_writable,
- std::string* path) {
+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(block_device, metadata, partition, &table)) {
+ if (!CreateDmTable(metadata, partition, super_device, &table)) {
return false;
}
if (force_writable) {
@@ -98,6 +127,13 @@
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;
}
@@ -109,13 +145,22 @@
LOG(ERROR) << "Could not read partition table.";
return true;
}
- for (const auto& partition : metadata->partitions) {
+ return CreateLogicalPartitions(*metadata.get(), block_device);
+}
+
+std::unique_ptr<LpMetadata> ReadCurrentMetadata(const std::string& block_device) {
+ uint32_t slot = SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix());
+ return ReadMetadata(block_device.c_str(), slot);
+}
+
+bool CreateLogicalPartitions(const LpMetadata& metadata, const std::string& super_device) {
+ for (const auto& partition : metadata.partitions) {
if (!partition.num_extents) {
LINFO << "Skipping zero-length logical partition: " << GetPartitionName(partition);
continue;
}
std::string path;
- if (!CreateLogicalPartition(block_device, *metadata.get(), partition, false, &path)) {
+ if (!CreateLogicalPartition(metadata, partition, false, {}, super_device, &path)) {
LERROR << "Could not create logical partition: " << GetPartitionName(partition);
return false;
}
@@ -123,29 +168,44 @@
return true;
}
-bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_slot,
+bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata,
const std::string& partition_name, bool force_writable,
- std::string* path) {
- auto metadata = ReadMetadata(block_device.c_str(), metadata_slot);
- if (!metadata) {
- LOG(ERROR) << "Could not read partition table.";
- return true;
- }
- for (const auto& partition : metadata->partitions) {
+ const std::chrono::milliseconds& timeout_ms, std::string* path) {
+ for (const auto& partition : metadata.partitions) {
if (GetPartitionName(partition) == partition_name) {
- return CreateLogicalPartition(block_device, *metadata.get(), partition, force_writable,
- path);
+ return CreateLogicalPartition(metadata, partition, force_writable, timeout_ms,
+ block_device, path);
}
}
LERROR << "Could not find any partition with name: " << partition_name;
return false;
}
-bool DestroyLogicalPartition(const std::string& name) {
+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 DestroyLogicalPartition(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)) {
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;
+ return false;
+ }
LINFO << "Unmapped logical partition " << name;
return true;
}
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index 845cca9..1a0e7ab 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -24,6 +24,7 @@
#include <cutils/partition_utils.h>
#include <sys/mount.h>
+#include <android-base/unique_fd.h>
#include <ext4_utils/ext4.h>
#include <ext4_utils/ext4_utils.h>
#include <logwrap/logwrap.h>
@@ -34,30 +35,28 @@
#include "fs_mgr_priv.h"
#include "cryptfs.h"
-static int get_dev_sz(char *fs_blkdev, uint64_t *dev_sz)
-{
- int fd;
+using android::base::unique_fd;
- if ((fd = open(fs_blkdev, O_RDONLY)) < 0) {
+static int get_dev_sz(const std::string& fs_blkdev, uint64_t* dev_sz) {
+ unique_fd fd(TEMP_FAILURE_RETRY(open(fs_blkdev.c_str(), O_RDONLY | O_CLOEXEC)));
+
+ if (fd < 0) {
PERROR << "Cannot open block device";
return -1;
}
if ((ioctl(fd, BLKGETSIZE64, dev_sz)) == -1) {
PERROR << "Cannot get block device size";
- close(fd);
return -1;
}
- close(fd);
return 0;
}
-static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer)
-{
+static int format_ext4(const std::string& fs_blkdev, const std::string& fs_mnt_point,
+ bool crypt_footer) {
uint64_t dev_sz;
int rc = 0;
- int status;
rc = get_dev_sz(fs_blkdev, &dev_sz);
if (rc) {
@@ -71,7 +70,8 @@
std::string size_str = std::to_string(dev_sz / 4096);
const char* const mke2fs_args[] = {
- "/system/bin/mke2fs", "-t", "ext4", "-b", "4096", fs_blkdev, size_str.c_str(), nullptr};
+ "/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);
@@ -81,12 +81,7 @@
}
const char* const e2fsdroid_args[] = {
- "/system/bin/e2fsdroid",
- "-e",
- "-a",
- fs_mnt_point,
- fs_blkdev,
- nullptr};
+ "/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);
@@ -97,10 +92,7 @@
return rc;
}
-static int format_f2fs(char *fs_blkdev, uint64_t dev_sz, bool crypt_footer)
-{
- int status;
-
+static int format_f2fs(const std::string& fs_blkdev, uint64_t dev_sz, bool crypt_footer) {
if (!dev_sz) {
int rc = get_dev_sz(fs_blkdev, &dev_sz);
if (rc) {
@@ -117,13 +109,8 @@
// clang-format off
const char* const args[] = {
"/system/bin/make_f2fs",
- "-d1",
- "-f",
- "-O", "encrypt",
- "-O", "quota",
- "-O", "verity",
- "-w", "4096",
- fs_blkdev,
+ "-g", "android",
+ fs_blkdev.c_str(),
size_str.c_str(),
nullptr
};
@@ -133,20 +120,21 @@
LOG_KLOG, true, nullptr, nullptr, 0);
}
-int fs_mgr_do_format(struct fstab_rec *fstab, bool crypt_footer)
-{
- int rc = -EINVAL;
+int fs_mgr_do_format(const FstabEntry& entry, bool crypt_footer) {
+ LERROR << __FUNCTION__ << ": Format " << entry.blk_device << " as '" << entry.fs_type << "'";
- LERROR << __FUNCTION__ << ": Format " << fstab->blk_device
- << " as '" << fstab->fs_type << "'";
-
- if (!strncmp(fstab->fs_type, "f2fs", 4)) {
- rc = format_f2fs(fstab->blk_device, fstab->length, crypt_footer);
- } else if (!strncmp(fstab->fs_type, "ext4", 4)) {
- rc = format_ext4(fstab->blk_device, fstab->mount_point, crypt_footer);
+ if (entry.fs_type == "f2fs") {
+ return format_f2fs(entry.blk_device, entry.length, crypt_footer);
+ } else if (entry.fs_type == "ext4") {
+ return format_ext4(entry.blk_device, entry.mount_point, crypt_footer);
} else {
- LERROR << "File system type '" << fstab->fs_type << "' is not supported";
+ LERROR << "File system type '" << entry.fs_type << "' is not supported";
+ return -EINVAL;
}
+}
- return rc;
+int fs_mgr_do_format(struct fstab_rec* rec, bool crypt_footer) {
+ auto entry = FstabRecToFstabEntry(rec);
+
+ return fs_mgr_do_format(entry, crypt_footer);
}
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index f87a3b1..9d4f280 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -28,36 +28,43 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <libgsi/libgsi.h>
#include "fs_mgr_priv.h"
+using android::base::Split;
using android::base::StartsWith;
const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android");
struct fs_mgr_flag_values {
- char *key_loc;
- char* key_dir;
- char *verity_loc;
- char *sysfs_path;
- long long part_length;
- char *label;
- int partnum;
- int swap_prio;
- int max_comp_streams;
- unsigned int zram_size;
- uint64_t reserved_size;
- unsigned int file_contents_mode;
- unsigned int file_names_mode;
- unsigned int erase_blk_size;
- unsigned int logical_blk_size;
+ std::string key_loc;
+ std::string key_dir;
+ std::string verity_loc;
+ std::string sysfs_path;
+ std::string zram_loopback_path;
+ uint64_t zram_loopback_size = 512 * 1024 * 1024; // 512MB by default
+ std::string zram_backing_dev_path;
+ off64_t part_length = 0;
+ std::string label;
+ int partnum = -1;
+ int swap_prio = -1;
+ int max_comp_streams = 0;
+ off64_t zram_size = 0;
+ off64_t reserved_size = 0;
+ int file_contents_mode = 0;
+ int file_names_mode = 0;
+ off64_t erase_blk_size = 0;
+ off64_t logical_blk_size = 0;
+ std::string vbmeta_partition;
};
struct flag_list {
const char *name;
- unsigned int flag;
+ uint64_t flag;
};
static struct flag_list mount_flags[] = {
@@ -80,46 +87,57 @@
};
static struct flag_list fs_mgr_flags[] = {
- {"wait", MF_WAIT},
- {"check", MF_CHECK},
- {"encryptable=", MF_CRYPT},
- {"forceencrypt=", MF_FORCECRYPT},
- {"fileencryption=", MF_FILEENCRYPTION},
- {"forcefdeorfbe=", MF_FORCEFDEORFBE},
- {"keydirectory=", MF_KEYDIRECTORY},
- {"nonremovable", MF_NONREMOVABLE},
- {"voldmanaged=", MF_VOLDMANAGED},
- {"length=", MF_LENGTH},
- {"recoveryonly", MF_RECOVERYONLY},
- {"swapprio=", MF_SWAPPRIO},
- {"zramsize=", MF_ZRAMSIZE},
- {"max_comp_streams=", MF_MAX_COMP_STREAMS},
- {"verifyatboot", MF_VERIFYATBOOT},
- {"verify", MF_VERIFY},
- {"avb", MF_AVB},
- {"noemulatedsd", MF_NOEMULATEDSD},
- {"notrim", MF_NOTRIM},
- {"formattable", MF_FORMATTABLE},
- {"slotselect", MF_SLOTSELECT},
- {"nofail", MF_NOFAIL},
- {"latemount", MF_LATEMOUNT},
- {"reservedsize=", MF_RESERVEDSIZE},
- {"quota", MF_QUOTA},
- {"eraseblk=", MF_ERASEBLKSIZE},
- {"logicalblk=", MF_LOGICALBLKSIZE},
- {"sysfs_path=", MF_SYSFS},
- {"defaults", 0},
- {"logical", MF_LOGICAL},
- {0, 0},
+ {"wait", MF_WAIT},
+ {"check", MF_CHECK},
+ {"encryptable=", MF_CRYPT},
+ {"forceencrypt=", MF_FORCECRYPT},
+ {"fileencryption=", MF_FILEENCRYPTION},
+ {"forcefdeorfbe=", MF_FORCEFDEORFBE},
+ {"keydirectory=", MF_KEYDIRECTORY},
+ {"nonremovable", MF_NONREMOVABLE},
+ {"voldmanaged=", MF_VOLDMANAGED},
+ {"length=", MF_LENGTH},
+ {"recoveryonly", MF_RECOVERYONLY},
+ {"swapprio=", MF_SWAPPRIO},
+ {"zramsize=", MF_ZRAMSIZE},
+ {"max_comp_streams=", MF_MAX_COMP_STREAMS},
+ {"verifyatboot", MF_VERIFYATBOOT},
+ {"verify", MF_VERIFY},
+ {"avb", MF_AVB},
+ {"avb=", MF_AVB},
+ {"noemulatedsd", MF_NOEMULATEDSD},
+ {"notrim", MF_NOTRIM},
+ {"formattable", MF_FORMATTABLE},
+ {"slotselect", MF_SLOTSELECT},
+ {"nofail", MF_NOFAIL},
+ {"first_stage_mount", MF_FIRST_STAGE_MOUNT},
+ {"latemount", MF_LATEMOUNT},
+ {"reservedsize=", MF_RESERVEDSIZE},
+ {"quota", MF_QUOTA},
+ {"eraseblk=", MF_ERASEBLKSIZE},
+ {"logicalblk=", MF_LOGICALBLKSIZE},
+ {"sysfs_path=", MF_SYSFS},
+ {"defaults", 0},
+ {"logical", MF_LOGICAL},
+ {"checkpoint=block", MF_CHECKPOINT_BLK},
+ {"checkpoint=fs", MF_CHECKPOINT_FS},
+ {"slotselect_other", MF_SLOTSELECT_OTHER},
+ {"zram_loopback_path=", MF_ZRAM_LOOPBACK_PATH},
+ {"zram_loopback_size=", MF_ZRAM_LOOPBACK_SIZE},
+ {"zram_backing_dev_path=", MF_ZRAM_BACKING_DEV_PATH},
+ {"fsverity", MF_FS_VERITY},
+ {0, 0},
};
#define EM_AES_256_XTS 1
#define EM_ICE 2
#define EM_AES_256_CTS 3
#define EM_AES_256_HEH 4
+#define EM_ADIANTUM 5
static const struct flag_list file_contents_encryption_modes[] = {
{"aes-256-xts", EM_AES_256_XTS},
+ {"adiantum", EM_ADIANTUM},
{"software", EM_AES_256_XTS}, /* alias for backwards compatibility */
{"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */
{0, 0},
@@ -128,12 +146,12 @@
static const struct flag_list file_names_encryption_modes[] = {
{"aes-256-cts", EM_AES_256_CTS},
{"aes-256-heh", EM_AES_256_HEH},
+ {"adiantum", EM_ADIANTUM},
{0, 0},
};
-static unsigned int encryption_mode_to_flag(const struct flag_list *list,
- const char *mode, const char *type)
-{
+static int encryption_mode_to_flag(const struct flag_list* list, const char* mode,
+ const char* type) {
const struct flag_list *j;
for (j = list; j->name; ++j) {
@@ -145,9 +163,7 @@
return 0;
}
-static const char *flag_to_encryption_mode(const struct flag_list *list,
- unsigned int flag)
-{
+static const char* flag_to_encryption_mode(const struct flag_list* list, uint64_t flag) {
const struct flag_list *j;
for (j = list; j->name; ++j) {
@@ -158,9 +174,8 @@
return nullptr;
}
-static uint64_t calculate_zram_size(unsigned int percentage)
-{
- uint64_t total;
+static off64_t calculate_zram_size(unsigned int percentage) {
+ off64_t total;
total = sysconf(_SC_PHYS_PAGES);
total *= percentage;
@@ -171,10 +186,9 @@
return total;
}
-static uint64_t parse_size(const char *arg)
-{
+static off64_t parse_size(const char* arg) {
char *endptr;
- uint64_t size = strtoull(arg, &endptr, 10);
+ off64_t size = strtoll(arg, &endptr, 10);
if (*endptr == 'k' || *endptr == 'K')
size *= 1024LL;
else if (*endptr == 'm' || *endptr == 'M')
@@ -203,28 +217,13 @@
return false;
}
-static int parse_flags(char *flags, struct flag_list *fl,
- struct fs_mgr_flag_values *flag_vals,
- char *fs_options, int fs_options_len)
-{
- int f = 0;
+static uint64_t parse_flags(char* flags, struct flag_list* fl, struct fs_mgr_flag_values* flag_vals,
+ std::string* fs_options) {
+ uint64_t f = 0;
int i;
char *p;
char *savep;
- /* initialize flag values. If we find a relevant flag, we'll
- * update the value */
- if (flag_vals) {
- memset(flag_vals, 0, sizeof(*flag_vals));
- flag_vals->partnum = -1;
- flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
- }
-
- /* initialize fs_options to the null string */
- if (fs_options && (fs_options_len > 0)) {
- fs_options[0] = '\0';
- }
-
p = strtok_r(flags, ",", &savep);
while (p) {
/* Look for the flag "p" in the flag list "fl"
@@ -245,22 +244,22 @@
/* The encryptable flag is followed by an = and the
* location of the keys. Get it and return it.
*/
- flag_vals->key_loc = strdup(arg);
+ flag_vals->key_loc = arg;
} else if (flag == MF_VERIFY) {
/* If the verify flag is followed by an = and the
* location for the verity state, get it and return it.
*/
- flag_vals->verity_loc = strdup(arg);
+ flag_vals->verity_loc = arg;
} else if (flag == MF_FORCECRYPT) {
/* The forceencrypt flag is followed by an = and the
* location of the keys. Get it and return it.
*/
- flag_vals->key_loc = strdup(arg);
+ flag_vals->key_loc = arg;
} else if (flag == MF_FORCEFDEORFBE) {
/* The forcefdeorfbe flag is followed by an = and the
* location of the keys. Get it and return it.
*/
- flag_vals->key_loc = strdup(arg);
+ flag_vals->key_loc = arg;
flag_vals->file_contents_mode = EM_AES_256_XTS;
flag_vals->file_names_mode = EM_AES_256_CTS;
} else if (flag == MF_FILEENCRYPTION) {
@@ -281,6 +280,8 @@
flag_vals->file_names_mode =
encryption_mode_to_flag(file_names_encryption_modes,
colon + 1, "file names");
+ } else if (flag_vals->file_contents_mode == EM_ADIANTUM) {
+ flag_vals->file_names_mode = EM_ADIANTUM;
} else {
flag_vals->file_names_mode = EM_AES_256_CTS;
}
@@ -288,7 +289,7 @@
/* The metadata flag is followed by an = and the
* directory for the keys. Get it and return it.
*/
- flag_vals->key_dir = strdup(arg);
+ flag_vals->key_dir = arg;
} else if (flag == MF_LENGTH) {
/* The length flag is followed by an = and the
* size of the partition. Get it and return it.
@@ -305,8 +306,7 @@
auto label_end = strchr(label_start, ':');
if (label_end) {
- flag_vals->label = strndup(label_start,
- (int) (label_end - label_start));
+ flag_vals->label = std::string(label_start, (int)(label_end - label_start));
auto part_start = label_end + 1;
if (!strcmp(part_start, "auto")) {
flag_vals->partnum = -1;
@@ -320,6 +320,8 @@
flag_vals->swap_prio = strtoll(arg, NULL, 0);
} else if (flag == MF_MAX_COMP_STREAMS) {
flag_vals->max_comp_streams = strtoll(arg, NULL, 0);
+ } else if (flag == MF_AVB) {
+ flag_vals->vbmeta_partition = arg;
} else if (flag == MF_ZRAMSIZE) {
auto is_percent = !!strrchr(arg, '%');
auto val = strtoll(arg, NULL, 0);
@@ -337,7 +339,7 @@
* erase block size. Get it, check that it is a power of 2 and
* at least 4096, and return it.
*/
- auto val = strtoul(arg, NULL, 0);
+ auto val = strtoll(arg, nullptr, 0);
if (val >= 4096 && (val & (val - 1)) == 0)
flag_vals->erase_blk_size = val;
} else if (flag == MF_LOGICALBLKSIZE) {
@@ -345,12 +347,22 @@
* logical block size. Get it, check that it is a power of 2 and
* at least 4096, and return it.
*/
- auto val = strtoul(arg, NULL, 0);
+ auto val = strtoll(arg, nullptr, 0);
if (val >= 4096 && (val & (val - 1)) == 0)
flag_vals->logical_blk_size = val;
} else if (flag == MF_SYSFS) {
/* The path to trigger device gc by idle-maint of vold. */
- flag_vals->sysfs_path = strdup(arg);
+ flag_vals->sysfs_path = arg;
+ } else if (flag == MF_ZRAM_LOOPBACK_PATH) {
+ /* The path to use loopback for zram. */
+ flag_vals->zram_loopback_path = arg;
+ } else if (flag == MF_ZRAM_LOOPBACK_SIZE) {
+ if (!android::base::ParseByteCount(arg, &flag_vals->zram_loopback_size)) {
+ LERROR << "Warning: zram_loopback_size = flag malformed";
+ }
+ } else if (flag == MF_ZRAM_BACKING_DEV_PATH) {
+ /* The path to use loopback for zram. */
+ flag_vals->zram_backing_dev_path = arg;
}
break;
}
@@ -358,26 +370,20 @@
if (!fl[i].name) {
if (fs_options) {
- /* It's not a known flag, so it must be a filesystem specific
- * option. Add it to fs_options if it was passed in.
- */
- strlcat(fs_options, p, fs_options_len);
- strlcat(fs_options, ",", fs_options_len);
+ // It's not a known flag, so it must be a filesystem specific
+ // option. Add it to fs_options if it was passed in.
+ if (!fs_options->empty()) {
+ fs_options->append(","); // appends a comma if not the first
+ }
+ fs_options->append(p);
} else {
- /* fs_options was not passed in, so if the flag is unknown
- * it's an error.
- */
+ // fs_options was not passed in, so if the flag is unknown it's an error.
LERROR << "Warning: unknown flag " << p;
}
}
p = strtok_r(NULL, ",", &savep);
}
- if (fs_options && fs_options[0]) {
- /* remove the last trailing comma from the list of options */
- fs_options[strlen(fs_options) - 1] = '\0';
- }
-
return f;
}
@@ -401,10 +407,13 @@
static bool is_dt_fstab_compatible() {
std::string dt_value;
std::string file_name = get_android_dt_dir() + "/fstab/compatible";
- if (read_dt_file(file_name, &dt_value)) {
- if (dt_value == "android,fstab") {
- return true;
- }
+
+ if (read_dt_file(file_name, &dt_value) && dt_value == "android,fstab") {
+ // If there's no status property or its set to "ok" or "okay", then we use the DT fstab.
+ std::string status_value;
+ std::string status_file_name = get_android_dt_dir() + "/fstab/status";
+ return !read_dt_file(status_file_name, &status_value) || status_value == "ok" ||
+ status_value == "okay";
}
return false;
@@ -504,49 +513,15 @@
return false;
}
-static struct fstab* fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts) {
- int cnt, entries;
+static bool fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts, Fstab* fstab_out) {
ssize_t len;
size_t alloc_len = 0;
char *line = NULL;
const char *delim = " \t";
char *save_ptr, *p;
- struct fstab *fstab = NULL;
+ Fstab fstab;
struct fs_mgr_flag_values flag_vals;
-#define FS_OPTIONS_LEN 1024
- char tmp_fs_options[FS_OPTIONS_LEN];
- entries = 0;
- while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
- /* if the last character is a newline, shorten the string by 1 byte */
- if (line[len - 1] == '\n') {
- line[len - 1] = '\0';
- }
- /* Skip any leading whitespace */
- p = line;
- while (isspace(*p)) {
- p++;
- }
- /* ignore comments or empty lines */
- if (*p == '#' || *p == '\0')
- continue;
- entries++;
- }
-
- if (!entries) {
- LERROR << "No entries found in fstab";
- goto err;
- }
-
- /* Allocate and init the fstab structure */
- fstab = static_cast<struct fstab *>(calloc(1, sizeof(struct fstab)));
- fstab->num_entries = entries;
- fstab->recs = static_cast<struct fstab_rec *>(
- calloc(fstab->num_entries, sizeof(struct fstab_rec)));
-
- fseek(fstab_file, 0, SEEK_SET);
-
- cnt = 0;
while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
/* if the last character is a newline, shorten the string by 1 byte */
if (line[len - 1] == '\n') {
@@ -562,47 +537,31 @@
if (*p == '#' || *p == '\0')
continue;
- /* If a non-comment entry is greater than the size we allocated, give an
- * error and quit. This can happen in the unlikely case the file changes
- * between the two reads.
- */
- if (cnt >= entries) {
- LERROR << "Tried to process more entries than counted";
- break;
- }
+ FstabEntry entry;
if (!(p = strtok_r(line, delim, &save_ptr))) {
LERROR << "Error parsing mount source";
goto err;
}
- fstab->recs[cnt].blk_device = strdup(p);
+ entry.blk_device = p;
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
LERROR << "Error parsing mount_point";
goto err;
}
- fstab->recs[cnt].mount_point = strdup(p);
+ entry.mount_point = p;
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
LERROR << "Error parsing fs_type";
goto err;
}
- fstab->recs[cnt].fs_type = strdup(p);
+ entry.fs_type = p;
if (!(p = strtok_r(NULL, delim, &save_ptr))) {
LERROR << "Error parsing mount_flags";
goto err;
}
- tmp_fs_options[0] = '\0';
- fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
- tmp_fs_options, FS_OPTIONS_LEN);
-
- /* fs_options are optional */
- if (tmp_fs_options[0]) {
- fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
- } else {
- fstab->recs[cnt].fs_options = NULL;
- }
+ entry.flags = parse_flags(p, mount_flags, nullptr, &entry.fs_options);
// For /proc/mounts, ignore everything after mnt_freq and mnt_passno
if (proc_mounts) {
@@ -611,78 +570,51 @@
LERROR << "Error parsing fs_mgr_options";
goto err;
}
- fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
- &flag_vals, NULL, 0);
- fstab->recs[cnt].key_loc = flag_vals.key_loc;
- fstab->recs[cnt].key_dir = flag_vals.key_dir;
- fstab->recs[cnt].verity_loc = flag_vals.verity_loc;
- fstab->recs[cnt].length = flag_vals.part_length;
- fstab->recs[cnt].label = flag_vals.label;
- fstab->recs[cnt].partnum = flag_vals.partnum;
- fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
- fstab->recs[cnt].max_comp_streams = flag_vals.max_comp_streams;
- fstab->recs[cnt].zram_size = flag_vals.zram_size;
- fstab->recs[cnt].reserved_size = flag_vals.reserved_size;
- fstab->recs[cnt].file_contents_mode = flag_vals.file_contents_mode;
- fstab->recs[cnt].file_names_mode = flag_vals.file_names_mode;
- fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size;
- fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size;
- fstab->recs[cnt].sysfs_path = flag_vals.sysfs_path;
- if (fstab->recs[cnt].fs_mgr_flags & MF_LOGICAL) {
- fstab->recs[cnt].logical_partition_name = strdup(fstab->recs[cnt].blk_device);
+ entry.fs_mgr_flags.val = parse_flags(p, fs_mgr_flags, &flag_vals, nullptr);
+
+ entry.key_loc = std::move(flag_vals.key_loc);
+ entry.key_dir = std::move(flag_vals.key_dir);
+ entry.verity_loc = std::move(flag_vals.verity_loc);
+ entry.length = flag_vals.part_length;
+ entry.label = std::move(flag_vals.label);
+ entry.partnum = flag_vals.partnum;
+ entry.swap_prio = flag_vals.swap_prio;
+ entry.max_comp_streams = flag_vals.max_comp_streams;
+ entry.zram_size = flag_vals.zram_size;
+ entry.reserved_size = flag_vals.reserved_size;
+ entry.file_contents_mode = flag_vals.file_contents_mode;
+ entry.file_names_mode = flag_vals.file_names_mode;
+ entry.erase_blk_size = flag_vals.erase_blk_size;
+ entry.logical_blk_size = flag_vals.logical_blk_size;
+ entry.sysfs_path = std::move(flag_vals.sysfs_path);
+ entry.vbmeta_partition = std::move(flag_vals.vbmeta_partition);
+ entry.zram_loopback_path = std::move(flag_vals.zram_loopback_path);
+ entry.zram_loopback_size = std::move(flag_vals.zram_loopback_size);
+ entry.zram_backing_dev_path = std::move(flag_vals.zram_backing_dev_path);
+ if (entry.fs_mgr_flags.logical) {
+ entry.logical_partition_name = entry.blk_device;
}
- cnt++;
+ fstab.emplace_back(std::move(entry));
}
+
+ if (fstab.empty()) {
+ LERROR << "No entries found in fstab";
+ goto err;
+ }
+
/* If an A/B partition, modify block device to be the real block device */
- if (!fs_mgr_update_for_slotselect(fstab)) {
+ if (!fs_mgr_update_for_slotselect(&fstab)) {
LERROR << "Error updating for slotselect";
goto err;
}
free(line);
- return fstab;
+ *fstab_out = std::move(fstab);
+ return true;
err:
free(line);
- if (fstab)
- fs_mgr_free_fstab(fstab);
- return NULL;
-}
-
-/* merges fstab entries from both a and b, then returns the merged result.
- * note that the caller should only manage the return pointer without
- * doing further memory management for the two inputs, i.e. only need to
- * frees up memory of the return value without touching a and b. */
-static struct fstab *in_place_merge(struct fstab *a, struct fstab *b)
-{
- if (!a && !b) return nullptr;
- if (!a) return b;
- if (!b) return a;
-
- int total_entries = a->num_entries + b->num_entries;
- a->recs = static_cast<struct fstab_rec *>(realloc(
- a->recs, total_entries * (sizeof(struct fstab_rec))));
- if (!a->recs) {
- LERROR << __FUNCTION__ << "(): failed to allocate fstab recs";
- // If realloc() fails the original block is left untouched;
- // it is not freed or moved. So we have to free both a and b here.
- fs_mgr_free_fstab(a);
- fs_mgr_free_fstab(b);
- return nullptr;
- }
-
- for (int i = a->num_entries, j = 0; i < total_entries; i++, j++) {
- // Copy the structs by assignment.
- a->recs[i] = b->recs[j];
- }
-
- // We can't call fs_mgr_free_fstab because a->recs still references the
- // memory allocated by strdup.
- free(b->recs);
- free(b);
-
- a->num_entries = total_entries;
- return a;
+ return false;
}
/* Extracts <device>s from the by-name symlinks specified in a fstab:
@@ -695,11 +627,11 @@
* /dev/block/pci/soc.0/f9824900.sdhci/by-name/vendor
* it returns a set { "soc/1da4000.ufshc", "soc.0/f9824900.sdhci" }.
*/
-static std::set<std::string> extract_boot_devices(const fstab& fstab) {
+static std::set<std::string> extract_boot_devices(const Fstab& fstab) {
std::set<std::string> boot_devices;
- for (int i = 0; i < fstab.num_entries; i++) {
- std::string blk_device(fstab.recs[i].blk_device);
+ for (const auto& entry : fstab) {
+ std::string blk_device = entry.blk_device;
// Skips blk_device that doesn't conform to the format.
if (!android::base::StartsWith(blk_device, "/dev/block") ||
android::base::StartsWith(blk_device, "/dev/block/by-name") ||
@@ -728,35 +660,70 @@
return boot_devices;
}
-struct fstab *fs_mgr_read_fstab(const char *fstab_path)
-{
- FILE *fstab_file;
- struct fstab *fstab;
+static void EraseFstabEntry(Fstab* fstab, const std::string& mount_point) {
+ auto iter = std::remove_if(fstab->begin(), fstab->end(),
+ [&](const auto& entry) { return entry.mount_point == mount_point; });
+ fstab->erase(iter, fstab->end());
+}
- fstab_file = fopen(fstab_path, "r");
+static void TransformFstabForGsi(Fstab* fstab) {
+ EraseFstabEntry(fstab, "/system");
+ EraseFstabEntry(fstab, "/data");
+
+ fstab->emplace_back(BuildGsiSystemFstabEntry());
+
+ constexpr uint32_t kFlags = MS_NOATIME | MS_NOSUID | MS_NODEV;
+
+ FstabEntry userdata = {
+ .blk_device = "userdata_gsi",
+ .mount_point = "/data",
+ .fs_type = "ext4",
+ .flags = kFlags,
+ .reserved_size = 128 * 1024 * 1024,
+ };
+ userdata.fs_mgr_flags.wait = true;
+ userdata.fs_mgr_flags.check = true;
+ userdata.fs_mgr_flags.logical = true;
+ userdata.fs_mgr_flags.quota = true;
+ userdata.fs_mgr_flags.late_mount = true;
+ fstab->emplace_back(userdata);
+}
+
+bool ReadFstabFromFile(const std::string& path, Fstab* fstab) {
+ auto fstab_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
if (!fstab_file) {
- PERROR << __FUNCTION__<< "(): cannot open file: '" << fstab_path << "'";
+ PERROR << __FUNCTION__ << "(): cannot open file: '" << path << "'";
+ return false;
+ }
+
+ bool is_proc_mounts = path == "/proc/mounts";
+
+ if (!fs_mgr_read_fstab_file(fstab_file.get(), is_proc_mounts, fstab)) {
+ LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << path << "'";
+ return false;
+ }
+ if (!is_proc_mounts && !access(android::gsi::kGsiBootedIndicatorFile, F_OK)) {
+ TransformFstabForGsi(fstab);
+ }
+
+ return true;
+}
+
+struct fstab* fs_mgr_read_fstab(const char* fstab_path) {
+ Fstab fstab;
+ if (!ReadFstabFromFile(fstab_path, &fstab)) {
return nullptr;
}
- fstab = fs_mgr_read_fstab_file(fstab_file, !strcmp("/proc/mounts", fstab_path));
- if (!fstab) {
- LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << fstab_path << "'";
- }
-
- fclose(fstab_file);
- return fstab;
+ return FstabToLegacyFstab(fstab);
}
-/* Returns fstab entries parsed from the device tree if they
- * exist
- */
-struct fstab *fs_mgr_read_fstab_dt()
-{
+// Returns fstab entries parsed from the device tree if they exist
+bool ReadFstabFromDt(Fstab* fstab) {
std::string fstab_buf = read_fstab_from_dt();
if (fstab_buf.empty()) {
LINFO << __FUNCTION__ << "(): failed to read fstab from dt";
- return nullptr;
+ return false;
}
std::unique_ptr<FILE, decltype(&fclose)> fstab_file(
@@ -764,16 +731,25 @@
fstab_buf.length(), "r"), fclose);
if (!fstab_file) {
PERROR << __FUNCTION__ << "(): failed to create a file stream for fstab dt";
+ return false;
+ }
+
+ if (!fs_mgr_read_fstab_file(fstab_file.get(), false, fstab)) {
+ LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:"
+ << std::endl << fstab_buf;
+ return false;
+ }
+
+ return true;
+}
+
+struct fstab* fs_mgr_read_fstab_dt() {
+ Fstab fstab;
+ if (!ReadFstabFromDt(&fstab)) {
return nullptr;
}
- struct fstab* fstab = fs_mgr_read_fstab_file(fstab_file.get(), false);
- if (!fstab) {
- LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:"
- << std::endl << fstab_buf;
- }
-
- return fstab;
+ return FstabToLegacyFstab(fstab);
}
/*
@@ -799,32 +775,42 @@
return std::string();
}
-/*
- * loads the fstab file and combines with fstab entries passed in from device tree.
- */
-struct fstab *fs_mgr_read_fstab_default()
-{
- std::string default_fstab;
+// Loads the fstab file and combines with fstab entries passed in from device tree.
+bool ReadDefaultFstab(Fstab* fstab) {
+ Fstab dt_fstab;
+ ReadFstabFromDt(&dt_fstab);
+ *fstab = std::move(dt_fstab);
+
+ std::string default_fstab_path;
// Use different fstab paths for normal boot and recovery boot, respectively
if (access("/system/bin/recovery", F_OK) == 0) {
- default_fstab = "/etc/recovery.fstab";
+ default_fstab_path = "/etc/recovery.fstab";
} else { // normal boot
- default_fstab = get_fstab_path();
+ default_fstab_path = get_fstab_path();
}
- struct fstab* fstab = nullptr;
- if (!default_fstab.empty()) {
- fstab = fs_mgr_read_fstab(default_fstab.c_str());
+ Fstab default_fstab;
+ if (!default_fstab_path.empty()) {
+ ReadFstabFromFile(default_fstab_path, &default_fstab);
} else {
LINFO << __FUNCTION__ << "(): failed to find device default fstab";
}
- struct fstab* fstab_dt = fs_mgr_read_fstab_dt();
+ for (auto&& entry : default_fstab) {
+ fstab->emplace_back(std::move(entry));
+ }
- // combines fstab entries passed in from device tree with
- // the ones found from default_fstab file
- return in_place_merge(fstab_dt, fstab);
+ return !fstab->empty();
+}
+
+struct fstab* fs_mgr_read_fstab_default() {
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
+ return nullptr;
+ }
+
+ return FstabToLegacyFstab(fstab);
}
void fs_mgr_free_fstab(struct fstab *fstab)
@@ -846,6 +832,8 @@
free(fstab->recs[i].key_dir);
free(fstab->recs[i].label);
free(fstab->recs[i].sysfs_path);
+ free(fstab->recs[i].zram_loopback_path);
+ free(fstab->recs[i].zram_backing_dev_path);
}
/* Free the fstab_recs array created by calloc(3) */
@@ -901,20 +889,99 @@
}
std::set<std::string> fs_mgr_get_boot_devices() {
- // boot_devices can be specified in device tree.
- std::string dt_value;
- std::string file_name = get_android_dt_dir() + "/boot_devices";
- if (read_dt_file(file_name, &dt_value)) {
- auto boot_devices = android::base::Split(dt_value, ",");
+ // First check the kernel commandline, then try the device tree otherwise
+ std::string dt_file_name = get_android_dt_dir() + "/boot_devices";
+ std::string value;
+ if (fs_mgr_get_boot_config_from_kernel_cmdline("boot_devices", &value) ||
+ read_dt_file(dt_file_name, &value)) {
+ auto boot_devices = Split(value, ",");
return std::set<std::string>(boot_devices.begin(), boot_devices.end());
}
// Fallback to extract boot devices from fstab.
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- if (fstab) return extract_boot_devices(*fstab);
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
+ return {};
+ }
- return {};
+ return extract_boot_devices(fstab);
+}
+
+FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec) {
+ FstabEntry entry;
+ entry.blk_device = fstab_rec->blk_device;
+ entry.logical_partition_name = fstab_rec->logical_partition_name;
+ entry.mount_point = fstab_rec->mount_point;
+ entry.fs_type = fstab_rec->fs_type;
+ entry.flags = fstab_rec->flags;
+ entry.fs_options = fstab_rec->fs_options;
+ entry.fs_mgr_flags.val = fstab_rec->fs_mgr_flags;
+ entry.key_loc = fstab_rec->key_loc;
+ entry.key_dir = fstab_rec->key_dir;
+ entry.verity_loc = fstab_rec->verity_loc;
+ entry.length = fstab_rec->length;
+ entry.label = fstab_rec->label;
+ entry.partnum = fstab_rec->partnum;
+ entry.swap_prio = fstab_rec->swap_prio;
+ entry.max_comp_streams = fstab_rec->max_comp_streams;
+ entry.zram_size = fstab_rec->zram_size;
+ entry.reserved_size = fstab_rec->reserved_size;
+ entry.file_contents_mode = fstab_rec->file_contents_mode;
+ entry.file_names_mode = fstab_rec->file_names_mode;
+ entry.erase_blk_size = fstab_rec->erase_blk_size;
+ entry.logical_blk_size = fstab_rec->logical_blk_size;
+ entry.sysfs_path = fstab_rec->sysfs_path;
+ entry.zram_loopback_path = fstab_rec->zram_loopback_path;
+ entry.zram_loopback_size = fstab_rec->zram_loopback_size;
+ entry.zram_backing_dev_path = fstab_rec->zram_backing_dev_path;
+
+ return entry;
+}
+
+Fstab LegacyFstabToFstab(const struct fstab* legacy_fstab) {
+ Fstab fstab;
+ for (int i = 0; i < legacy_fstab->num_entries; i++) {
+ fstab.emplace_back(FstabRecToFstabEntry(&legacy_fstab->recs[i]));
+ }
+
+ return fstab;
+}
+
+fstab* FstabToLegacyFstab(const Fstab& fstab) {
+ struct fstab* legacy_fstab = static_cast<struct fstab*>(calloc(1, sizeof(struct fstab)));
+ legacy_fstab->num_entries = fstab.size();
+ legacy_fstab->recs =
+ static_cast<fstab_rec*>(calloc(legacy_fstab->num_entries, sizeof(fstab_rec)));
+
+ for (int i = 0; i < legacy_fstab->num_entries; i++) {
+ legacy_fstab->recs[i].blk_device = strdup(fstab[i].blk_device.c_str());
+ legacy_fstab->recs[i].logical_partition_name =
+ strdup(fstab[i].logical_partition_name.c_str());
+ legacy_fstab->recs[i].mount_point = strdup(fstab[i].mount_point.c_str());
+ legacy_fstab->recs[i].fs_type = strdup(fstab[i].fs_type.c_str());
+ legacy_fstab->recs[i].flags = fstab[i].flags;
+ legacy_fstab->recs[i].fs_options = strdup(fstab[i].fs_options.c_str());
+ legacy_fstab->recs[i].fs_mgr_flags = fstab[i].fs_mgr_flags.val;
+ legacy_fstab->recs[i].key_loc = strdup(fstab[i].key_loc.c_str());
+ legacy_fstab->recs[i].key_dir = strdup(fstab[i].key_dir.c_str());
+ legacy_fstab->recs[i].verity_loc = strdup(fstab[i].verity_loc.c_str());
+ legacy_fstab->recs[i].length = fstab[i].length;
+ legacy_fstab->recs[i].label = strdup(fstab[i].label.c_str());
+ legacy_fstab->recs[i].partnum = fstab[i].partnum;
+ legacy_fstab->recs[i].swap_prio = fstab[i].swap_prio;
+ legacy_fstab->recs[i].max_comp_streams = fstab[i].max_comp_streams;
+ legacy_fstab->recs[i].zram_size = fstab[i].zram_size;
+ legacy_fstab->recs[i].reserved_size = fstab[i].reserved_size;
+ legacy_fstab->recs[i].file_contents_mode = fstab[i].file_contents_mode;
+ legacy_fstab->recs[i].file_names_mode = fstab[i].file_names_mode;
+ legacy_fstab->recs[i].erase_blk_size = fstab[i].erase_blk_size;
+ legacy_fstab->recs[i].logical_blk_size = fstab[i].logical_blk_size;
+ legacy_fstab->recs[i].sysfs_path = strdup(fstab[i].sysfs_path.c_str());
+ legacy_fstab->recs[i].zram_loopback_path = strdup(fstab[i].zram_loopback_path.c_str());
+ legacy_fstab->recs[i].zram_loopback_size = fstab[i].zram_loopback_size;
+ legacy_fstab->recs[i].zram_backing_dev_path = strdup(fstab[i].zram_backing_dev_path.c_str());
+ }
+ return legacy_fstab;
}
int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
@@ -988,6 +1055,10 @@
return fstab->fs_mgr_flags & MF_NOFAIL;
}
+int fs_mgr_is_first_stage_mount(const struct fstab_rec* fstab) {
+ return fstab->fs_mgr_flags & MF_FIRST_STAGE_MOUNT;
+}
+
int fs_mgr_is_latemount(const struct fstab_rec* fstab) {
return fstab->fs_mgr_flags & MF_LATEMOUNT;
}
@@ -1004,3 +1075,33 @@
int fs_mgr_is_logical(const struct fstab_rec* fstab) {
return fstab->fs_mgr_flags & MF_LOGICAL;
}
+
+int fs_mgr_is_checkpoint(const struct fstab_rec* fstab) {
+ return fstab->fs_mgr_flags & (MF_CHECKPOINT_FS | MF_CHECKPOINT_BLK);
+}
+
+int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab) {
+ return fstab->fs_mgr_flags & MF_CHECKPOINT_FS;
+}
+
+int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab) {
+ return fstab->fs_mgr_flags & MF_CHECKPOINT_BLK;
+}
+
+int fs_mgr_is_fs_verity(const struct fstab_rec* fstab) {
+ return fstab->fs_mgr_flags & MF_FS_VERITY;
+}
+
+FstabEntry BuildGsiSystemFstabEntry() {
+ FstabEntry system = {
+ .blk_device = "system_gsi",
+ .mount_point = "/system",
+ .fs_type = "ext4",
+ .flags = MS_RDONLY,
+ .fs_options = "barrier=1",
+ };
+ system.fs_mgr_flags.wait = true;
+ system.fs_mgr_flags.logical = true;
+ system.fs_mgr_flags.first_stage_mount = true;
+ return system;
+}
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 720dcfd..3908683 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -20,15 +20,18 @@
#include <linux/fs.h>
#include <selinux/selinux.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/types.h>
+#include <sys/utsname.h>
#include <sys/vfs.h>
#include <unistd.h>
+#include <algorithm>
#include <map>
#include <memory>
#include <string>
@@ -40,19 +43,42 @@
#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 <fs_mgr_overlayfs.h>
#include <fstab/fstab.h>
+#include <libdm/dm.h>
+#include <libgsi/libgsi.h>
+#include <liblp/builder.h>
+#include <liblp/liblp.h>
#include "fs_mgr_priv.h"
using namespace std::literals;
+using namespace android::dm;
+using namespace android::fs_mgr;
+
+namespace {
+
+bool fs_mgr_access(const std::string& path) {
+ auto save_errno = errno;
+ auto ret = access(path.c_str(), F_OK) == 0;
+ errno = save_errno;
+ return ret;
+}
+
+} // namespace
#if ALLOW_ADBD_DISABLE_VERITY == 0 // If we are a user build, provide stubs
-bool fs_mgr_overlayfs_mount_all() {
+bool fs_mgr_overlayfs_mount_all(Fstab*) {
return false;
}
+std::vector<std::string> fs_mgr_overlayfs_required_devices(Fstab*) {
+ return {};
+}
+
bool fs_mgr_overlayfs_setup(const char*, const char*, bool* change) {
if (change) *change = false;
return false;
@@ -63,12 +89,18 @@
return false;
}
+bool fs_mgr_overlayfs_is_setup() {
+ return false;
+}
+
#else // ALLOW_ADBD_DISABLE_VERITY == 0
namespace {
-// acceptable overlayfs backing storage
-const auto kOverlayMountPoint = "/cache"s;
+// list of acceptable overlayfs backing storage
+const auto kScratchMountPoint = "/mnt/scratch"s;
+const auto kCacheMountPoint = "/cache"s;
+const std::vector<const std::string> kOverlayMountPoints = {kScratchMountPoint, kCacheMountPoint};
// Return true if everything is mounted, but before adb is started. Right
// after 'trigger load_persist_props_action' is done.
@@ -90,142 +122,36 @@
return ret | !rmdir(test_directory.c_str());
}
-std::string fs_mgr_get_context(const std::string& mount_point) {
- char* ctx = nullptr;
- auto len = getfilecon(mount_point.c_str(), &ctx);
- if ((len > 0) && ctx) {
- std::string context(ctx, len);
- free(ctx);
- return context;
- }
- return "";
-}
-
// At less than 1% free space return value of false,
// means we will try to wrap with overlayfs.
-bool fs_mgr_filesystem_has_space(const char* mount_point) {
+bool fs_mgr_filesystem_has_space(const std::string& mount_point) {
// If we have access issues to find out space remaining, return true
// to prevent us trying to override with overlayfs.
struct statvfs vst;
- if (statvfs(mount_point, &vst)) return true;
+ if (statvfs(mount_point.c_str(), &vst)) return true;
- static constexpr int percent = 1; // 1%
+ static constexpr int kPercentThreshold = 1; // 1%
- return (vst.f_bfree >= (vst.f_blocks * percent / 100));
+ return (vst.f_bfree >= (vst.f_blocks * kPercentThreshold / 100));
}
-bool fs_mgr_overlayfs_enabled(const struct fstab_rec* fsrec) {
+bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
// readonly filesystem, can not be mount -o remount,rw
- // if squashfs or if free space is (near) zero making such a remount
+ // for squashfs, erofs or if free space is (near) zero making such a remount
// virtually useless, or if there are shared blocks that prevent remount,rw
- return ("squashfs"s == fsrec->fs_type) ||
- fs_mgr_has_shared_blocks(fsrec->mount_point, fsrec->blk_device) ||
- !fs_mgr_filesystem_has_space(fsrec->mount_point);
-}
-
-constexpr char upper_name[] = "upper";
-constexpr char work_name[] = "work";
-
-std::string fs_mgr_get_overlayfs_candidate(const std::string& mount_point) {
- if (!fs_mgr_is_dir(mount_point)) return "";
- auto dir = kOverlayMountPoint + "/overlay/" + android::base::Basename(mount_point) + "/";
- auto upper = dir + upper_name;
- if (!fs_mgr_is_dir(upper)) return "";
- auto work = dir + work_name;
- if (!fs_mgr_is_dir(work)) return "";
- if (!fs_mgr_dir_is_writable(work)) return "";
- return dir;
-}
-
-constexpr char lowerdir_option[] = "lowerdir=";
-constexpr char upperdir_option[] = "upperdir=";
-
-// default options for mount_point, returns empty string for none available.
-std::string fs_mgr_get_overlayfs_options(const std::string& mount_point) {
- auto candidate = fs_mgr_get_overlayfs_candidate(mount_point);
- if (candidate.empty()) return "";
-
- auto context = fs_mgr_get_context(mount_point);
- if (!context.empty()) context = ",rootcontext="s + context;
- return "override_creds=off,"s + lowerdir_option + mount_point + "," + upperdir_option +
- candidate + upper_name + ",workdir=" + candidate + work_name + context;
-}
-
-bool fs_mgr_system_root_image(const fstab* fstab) {
- if (!fstab) { // can not happen?
- // This will return empty on init first_stage_mount,
- // hence why we prefer checking the fstab instead.
- return android::base::GetBoolProperty("ro.build.system_root_image", false);
+ if (!fs_mgr_filesystem_has_space(entry->mount_point)) {
+ return true;
}
- for (auto i = 0; i < fstab->num_entries; i++) {
- const auto fsrec = &fstab->recs[i];
- auto fsrec_mount_point = fsrec->mount_point;
- if (!fsrec_mount_point) continue;
- if ("/system"s == fsrec_mount_point) return false;
+ if (entry->fs_mgr_flags.logical) {
+ fs_mgr_update_logical_partition(entry);
}
- return true;
+ auto save_errno = errno;
+ auto has_shared_blocks = fs_mgr_has_shared_blocks(entry->mount_point, entry->blk_device);
+ errno = save_errno;
+ return has_shared_blocks;
}
-const char* fs_mgr_mount_point(const fstab* fstab, const char* mount_point) {
- if (!mount_point) return mount_point;
- if ("/"s != mount_point) return mount_point;
- if (!fs_mgr_system_root_image(fstab)) return mount_point;
- return "/system";
-}
-
-// return true if system supports overlayfs
-bool fs_mgr_wants_overlayfs() {
- // This will return empty on init first_stage_mount, so speculative
- // determination, empty (unset) _or_ "1" is true which differs from the
- // official ro.debuggable policy. ALLOW_ADBD_DISABLE_VERITY == 0 should
- // protect us from false in any case, so this is insurance.
- auto debuggable = android::base::GetProperty("ro.debuggable", "1");
- if (debuggable != "1") return false;
-
- // Overlayfs available in the kernel, and patched for override_creds?
- static signed char overlayfs_in_kernel = -1; // cache for constant condition
- if (overlayfs_in_kernel == -1) {
- auto save_errno = errno;
- overlayfs_in_kernel = !access("/sys/module/overlay/parameters/override_creds", F_OK);
- errno = save_errno;
- }
- return overlayfs_in_kernel;
-}
-
-bool fs_mgr_wants_overlayfs(const fstab_rec* fsrec) {
- if (!fsrec) return false;
-
- auto fsrec_mount_point = fsrec->mount_point;
- if (!fsrec_mount_point || !fsrec_mount_point[0]) return false;
- if (!fsrec->blk_device) return false;
-
- if (!fsrec->fs_type) return false;
-
- // Don't check entries that are managed by vold.
- if (fsrec->fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) return false;
-
- // Only concerned with readonly partitions.
- if (!(fsrec->flags & MS_RDONLY)) return false;
-
- // If unbindable, do not allow overlayfs as this could expose us to
- // security issues. On Android, this could also be used to turn off
- // the ability to overlay an otherwise acceptable filesystem since
- // /system and /vendor are never bound(sic) to.
- if (fsrec->flags & MS_UNBINDABLE) return false;
-
- if (!fs_mgr_overlayfs_enabled(fsrec)) return false;
-
- // Verity enabled?
- const auto basename_mount_point(android::base::Basename(fsrec_mount_point));
- auto found = false;
- fs_mgr_update_verity_state(
- [&basename_mount_point, &found](fstab_rec*, const char* mount_point, int, int) {
- if (mount_point && (basename_mount_point == mount_point)) found = true;
- });
- return !found;
-}
-
-bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr) {
+bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr, int level = 0) {
auto save_errno = errno;
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
if (!dir) {
@@ -233,7 +159,11 @@
errno = save_errno;
return true;
}
- PERROR << "overlayfs open " << path;
+ PERROR << "opendir " << path << " depth=" << level;
+ if ((errno == EPERM) && (level != 0)) {
+ errno = save_errno;
+ return true;
+ }
return false;
}
dirent* entry;
@@ -243,55 +173,176 @@
auto file = path + "/" + entry->d_name;
if (entry->d_type == DT_UNKNOWN) {
struct stat st;
+ save_errno = errno;
if (!lstat(file.c_str(), &st) && (st.st_mode & S_IFDIR)) entry->d_type = DT_DIR;
+ errno = save_errno;
}
if (entry->d_type == DT_DIR) {
- ret &= fs_mgr_rm_all(file, change);
+ ret &= fs_mgr_rm_all(file, change, level + 1);
if (!rmdir(file.c_str())) {
if (change) *change = true;
} else {
- ret = false;
- PERROR << "overlayfs rmdir " << file;
+ if (errno != ENOENT) ret = false;
+ PERROR << "rmdir " << file << " depth=" << level;
}
continue;
}
if (!unlink(file.c_str())) {
if (change) *change = true;
} else {
- ret = false;
- PERROR << "overlayfs rm " << file;
+ if (errno != ENOENT) ret = false;
+ PERROR << "rm " << file << " depth=" << level;
}
}
return ret;
}
-constexpr char overlayfs_file_context[] = "u:object_r:overlayfs_file:s0";
+const auto kUpperName = "upper"s;
+const auto kWorkName = "work"s;
+const auto kOverlayTopDir = "/overlay"s;
+
+std::string fs_mgr_get_overlayfs_candidate(const std::string& mount_point) {
+ if (!fs_mgr_is_dir(mount_point)) return "";
+ const auto base = android::base::Basename(mount_point) + "/";
+ for (const auto& overlay_mount_point : kOverlayMountPoints) {
+ auto dir = overlay_mount_point + kOverlayTopDir + "/" + base;
+ auto upper = dir + kUpperName;
+ if (!fs_mgr_is_dir(upper)) continue;
+ auto work = dir + kWorkName;
+ if (!fs_mgr_is_dir(work)) continue;
+ if (!fs_mgr_dir_is_writable(work)) continue;
+ return dir;
+ }
+ return "";
+}
+
+const auto kLowerdirOption = "lowerdir="s;
+const auto kUpperdirOption = "upperdir="s;
+
+// default options for mount_point, returns empty string for none available.
+std::string fs_mgr_get_overlayfs_options(const std::string& mount_point) {
+ auto candidate = fs_mgr_get_overlayfs_candidate(mount_point);
+ if (candidate.empty()) return "";
+ auto ret = kLowerdirOption + mount_point + "," + kUpperdirOption + candidate + kUpperName +
+ ",workdir=" + candidate + kWorkName;
+ if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kOverrideCredsRequired) {
+ ret += ",override_creds=off";
+ }
+ return ret;
+}
+
+const char* fs_mgr_mount_point(const char* mount_point) {
+ if (!mount_point) return mount_point;
+ if ("/"s != mount_point) return mount_point;
+ return "/system";
+}
+
+bool fs_mgr_rw_access(const std::string& path) {
+ if (path.empty()) return false;
+ auto save_errno = errno;
+ auto ret = access(path.c_str(), R_OK | W_OK) == 0;
+ errno = save_errno;
+ return ret;
+}
+
+bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true) {
+ Fstab fstab;
+ if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
+ return false;
+ }
+ const auto lowerdir = kLowerdirOption + mount_point;
+ for (const auto& entry : fstab) {
+ if (overlay_only && "overlay" != entry.fs_type && "overlayfs" != entry.fs_type) continue;
+ if (mount_point != entry.mount_point) continue;
+ if (!overlay_only) return true;
+ const auto options = android::base::Split(entry.fs_options, ",");
+ for (const auto& opt : options) {
+ if (opt == lowerdir) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+std::vector<std::string> fs_mgr_overlayfs_verity_enabled_list() {
+ std::vector<std::string> ret;
+ auto save_errno = errno;
+ fs_mgr_update_verity_state(
+ [&ret](const std::string& mount_point, int) { ret.emplace_back(mount_point); });
+ if ((errno == ENOENT) || (errno == ENXIO)) errno = save_errno;
+ return ret;
+}
+
+bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
+ // Don't check entries that are managed by vold.
+ if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;
+
+ // *_other doesn't want overlayfs.
+ if (entry->fs_mgr_flags.slot_select_other) return false;
+
+ // Only concerned with readonly partitions.
+ if (!(entry->flags & MS_RDONLY)) return false;
+
+ // If unbindable, do not allow overlayfs as this could expose us to
+ // security issues. On Android, this could also be used to turn off
+ // the ability to overlay an otherwise acceptable filesystem since
+ // /system and /vendor are never bound(sic) to.
+ if (entry->flags & MS_UNBINDABLE) return false;
+
+ if (!fs_mgr_overlayfs_enabled(entry)) return false;
+
+ return true;
+}
+constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
+
+bool fs_mgr_overlayfs_setup_dir(const std::string& dir, std::string* overlay, bool* change) {
+ auto ret = true;
+ auto top = dir + kOverlayTopDir;
+ if (setfscreatecon(kOverlayfsFileContext)) {
+ ret = false;
+ PERROR << "setfscreatecon " << kOverlayfsFileContext;
+ }
+ auto save_errno = errno;
+ if (!mkdir(top.c_str(), 0755)) {
+ if (change) *change = true;
+ } else if (errno != EEXIST) {
+ ret = false;
+ PERROR << "mkdir " << top;
+ } else {
+ errno = save_errno;
+ }
+ setfscreatecon(nullptr);
+
+ if (overlay) *overlay = std::move(top);
+ return ret;
+}
bool fs_mgr_overlayfs_setup_one(const std::string& overlay, const std::string& mount_point,
bool* change) {
auto ret = true;
- auto fsrec_mount_point = overlay + android::base::Basename(mount_point) + "/";
+ auto fsrec_mount_point = overlay + "/" + android::base::Basename(mount_point) + "/";
- if (setfscreatecon(overlayfs_file_context)) {
+ if (setfscreatecon(kOverlayfsFileContext)) {
ret = false;
- PERROR << "overlayfs setfscreatecon " << overlayfs_file_context;
+ PERROR << "setfscreatecon " << kOverlayfsFileContext;
}
auto save_errno = errno;
if (!mkdir(fsrec_mount_point.c_str(), 0755)) {
if (change) *change = true;
} else if (errno != EEXIST) {
ret = false;
- PERROR << "overlayfs mkdir " << fsrec_mount_point;
+ PERROR << "mkdir " << fsrec_mount_point;
} else {
errno = save_errno;
}
save_errno = errno;
- if (!mkdir((fsrec_mount_point + work_name).c_str(), 0755)) {
+ if (!mkdir((fsrec_mount_point + kWorkName).c_str(), 0755)) {
if (change) *change = true;
} else if (errno != EEXIST) {
ret = false;
- PERROR << "overlayfs mkdir " << fsrec_mount_point << work_name;
+ PERROR << "mkdir " << fsrec_mount_point << kWorkName;
} else {
errno = save_errno;
}
@@ -300,15 +351,15 @@
auto new_context = fs_mgr_get_context(mount_point);
if (!new_context.empty() && setfscreatecon(new_context.c_str())) {
ret = false;
- PERROR << "overlayfs setfscreatecon " << new_context;
+ PERROR << "setfscreatecon " << new_context;
}
- auto upper = fsrec_mount_point + upper_name;
+ auto upper = fsrec_mount_point + kUpperName;
save_errno = errno;
if (!mkdir(upper.c_str(), 0755)) {
if (change) *change = true;
} else if (errno != EEXIST) {
ret = false;
- PERROR << "overlayfs mkdir " << upper;
+ PERROR << "mkdir " << upper;
} else {
errno = save_errno;
}
@@ -317,6 +368,139 @@
return ret;
}
+uint32_t fs_mgr_overlayfs_slot_number() {
+ 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);
+}
+
+bool fs_mgr_overlayfs_has_logical(const Fstab& fstab) {
+ for (const auto& entry : fstab) {
+ if (entry.fs_mgr_flags.logical) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void fs_mgr_overlayfs_umount_scratch() {
+ // Lazy umount will allow us to move on and possibly later
+ // establish a new fresh mount without requiring a reboot should
+ // the developer wish to restart. Old references should melt
+ // away or have no data. Main goal is to shut the door on the
+ // current overrides with an expectation of a subsequent reboot,
+ // thus any errors here are ignored.
+ umount2(kScratchMountPoint.c_str(), MNT_DETACH);
+ LINFO << "umount(" << kScratchMountPoint << ")";
+ 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;
+
+ auto save_errno = errno;
+ if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
+ fs_mgr_overlayfs_umount_scratch();
+ }
+ auto builder = MetadataBuilder::New(super_device, slot_number);
+ if (!builder) {
+ errno = save_errno;
+ return true;
+ }
+ const auto partition_name = android::base::Basename(kScratchMountPoint);
+ if (builder->FindPartition(partition_name) == nullptr) {
+ errno = save_errno;
+ return true;
+ }
+ builder->RemovePartition(partition_name);
+ auto metadata = builder->Export();
+ if (metadata && UpdatePartitionTable(super_device, *metadata.get(), slot_number)) {
+ if (change) *change = true;
+ if (!DestroyLogicalPartition(partition_name, 0s)) return false;
+ } else {
+ LERROR << "delete partition " << overlay;
+ return false;
+ }
+ errno = save_errno;
+ return true;
+}
+
+bool fs_mgr_overlayfs_teardown_one(const std::string& overlay, const std::string& mount_point,
+ bool* change) {
+ const auto top = overlay + kOverlayTopDir;
+
+ if (!fs_mgr_access(top)) return fs_mgr_overlayfs_teardown_scratch(overlay, change);
+
+ auto cleanup_all = mount_point.empty();
+ const auto partition_name = android::base::Basename(mount_point);
+ const auto oldpath = top + (cleanup_all ? "" : ("/" + partition_name));
+ const auto newpath = cleanup_all ? overlay + "/." + kOverlayTopDir.substr(1) + ".teardown"
+ : top + "/." + partition_name + ".teardown";
+ auto ret = fs_mgr_rm_all(newpath);
+ auto save_errno = errno;
+ if (!rename(oldpath.c_str(), newpath.c_str())) {
+ if (change) *change = true;
+ } else if (errno != ENOENT) {
+ ret = false;
+ PERROR << "mv " << oldpath << " " << newpath;
+ } else {
+ errno = save_errno;
+ }
+ ret &= fs_mgr_rm_all(newpath, change);
+ save_errno = errno;
+ if (!rmdir(newpath.c_str())) {
+ if (change) *change = true;
+ } else if (errno != ENOENT) {
+ ret = false;
+ PERROR << "rmdir " << newpath;
+ } else {
+ errno = save_errno;
+ }
+ if (!cleanup_all) {
+ save_errno = errno;
+ if (!rmdir(top.c_str())) {
+ if (change) *change = true;
+ cleanup_all = true;
+ } else if (errno == ENOTEMPTY) {
+ cleanup_all = true;
+ // cleanup all if the content is all hidden (leading .)
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(top.c_str()), closedir);
+ if (!dir) {
+ PERROR << "opendir " << top;
+ } else {
+ dirent* entry;
+ while ((entry = readdir(dir.get()))) {
+ if (entry->d_name[0] != '.') {
+ cleanup_all = false;
+ break;
+ }
+ }
+ }
+ errno = save_errno;
+ } else if (errno == ENOENT) {
+ cleanup_all = true;
+ errno = save_errno;
+ } else {
+ ret = false;
+ PERROR << "rmdir " << top;
+ }
+ }
+ if (cleanup_all) ret &= fs_mgr_overlayfs_teardown_scratch(overlay, change);
+ return ret;
+}
+
bool fs_mgr_overlayfs_mount(const std::string& mount_point) {
auto options = fs_mgr_get_overlayfs_options(mount_point);
if (options.empty()) return false;
@@ -324,8 +508,8 @@
// hijack __mount() report format to help triage
auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay";
const auto opt_list = android::base::Split(options, ",");
- for (const auto opt : opt_list) {
- if (android::base::StartsWith(opt, upperdir_option)) {
+ for (const auto& opt : opt_list) {
+ if (android::base::StartsWith(opt, kUpperdirOption)) {
report = report + "," + opt;
break;
}
@@ -343,41 +527,17 @@
}
}
-bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point) {
- std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(
- fs_mgr_read_fstab("/proc/mounts"), fs_mgr_free_fstab);
- if (!fstab) return false;
- const auto lowerdir = std::string(lowerdir_option) + mount_point;
- for (auto i = 0; i < fstab->num_entries; ++i) {
- const auto fsrec = &fstab->recs[i];
- const auto fs_type = fsrec->fs_type;
- if (!fs_type) continue;
- if (("overlay"s != fs_type) && ("overlayfs"s != fs_type)) continue;
- auto fsrec_mount_point = fsrec->mount_point;
- if (!fsrec_mount_point) continue;
- if (mount_point != fsrec_mount_point) continue;
- const auto fs_options = fsrec->fs_options;
- if (!fs_options) continue;
- const auto options = android::base::Split(fs_options, ",");
- for (const auto opt : options) {
- if (opt == lowerdir) {
- return true;
- }
- }
- }
- return false;
-}
-
-std::vector<std::string> fs_mgr_candidate_list(const fstab* fstab,
- const char* mount_point = nullptr) {
+std::vector<std::string> fs_mgr_candidate_list(Fstab* fstab, const char* mount_point = nullptr) {
std::vector<std::string> mounts;
- if (!fstab) return mounts;
-
- for (auto i = 0; i < fstab->num_entries; i++) {
- const auto fsrec = &fstab->recs[i];
- if (!fs_mgr_wants_overlayfs(fsrec)) continue;
- std::string new_mount_point(fs_mgr_mount_point(fstab, fsrec->mount_point));
+ auto verity = fs_mgr_overlayfs_verity_enabled_list();
+ for (auto& entry : *fstab) {
+ if (!fs_mgr_wants_overlayfs(&entry)) continue;
+ std::string new_mount_point(fs_mgr_mount_point(entry.mount_point.c_str()));
if (mount_point && (new_mount_point != mount_point)) continue;
+ if (std::find(verity.begin(), verity.end(), android::base::Basename(new_mount_point)) !=
+ verity.end()) {
+ continue;
+ }
auto duplicate_or_more_specific = false;
for (auto it = mounts.begin(); it != mounts.end();) {
if ((*it == new_mount_point) ||
@@ -393,65 +553,358 @@
}
if (!duplicate_or_more_specific) mounts.emplace_back(new_mount_point);
}
+
+ // if not itemized /system or /, system as root, fake one up?
+
+ // do we want or need to?
+ if (mount_point && ("/system"s != mount_point)) return mounts;
+ if (std::find(mounts.begin(), mounts.end(), "/system") != mounts.end()) return mounts;
+
+ // fs_mgr_overlayfs_verity_enabled_list says not to?
+ if (std::find(verity.begin(), verity.end(), "system") != verity.end()) return mounts;
+
+ // confirm that fstab is missing system
+ if (std::find_if(fstab->begin(), fstab->end(), [](const auto& entry) {
+ return entry.mount_point == "/" || entry.mount_point == "/system ";
+ }) != fstab->end()) {
+ return mounts;
+ }
+
+ // We have a stunted fstab (w/o system or / ) passed in by the caller,
+ // verity claims are assumed accurate because they are collected internally
+ // from fs_mgr_fstab_default() from within fs_mgr_update_verity_state(),
+ // Can (re)evaluate /system with impunity since we know it is ever-present.
+ mounts.emplace_back("/system");
return mounts;
}
+// Mount kScratchMountPoint
+bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type,
+ bool readonly = false) {
+ if (readonly) {
+ if (!fs_mgr_access(device_path)) return false;
+ } else {
+ if (!fs_mgr_rw_access(device_path)) return false;
+ }
+
+ if (setfscreatecon(kOverlayfsFileContext)) {
+ PERROR << "setfscreatecon " << kOverlayfsFileContext;
+ }
+ if (mkdir(kScratchMountPoint.c_str(), 0755) && (errno != EEXIST)) {
+ PERROR << "create " << kScratchMountPoint;
+ }
+
+ FstabEntry entry;
+ entry.blk_device = device_path;
+ entry.mount_point = kScratchMountPoint;
+ entry.fs_type = mnt_type;
+ entry.flags = MS_RELATIME;
+ if (readonly) {
+ entry.flags |= MS_RDONLY;
+ } else {
+ fs_mgr_set_blk_ro(device_path, false);
+ }
+ auto save_errno = errno;
+ auto mounted = fs_mgr_do_mount_one(entry) == 0;
+ if (!mounted) {
+ if (mnt_type == "f2fs") {
+ entry.fs_type = "ext4";
+ } else {
+ entry.fs_type = "f2fs";
+ }
+ mounted = fs_mgr_do_mount_one(entry) == 0;
+ if (!mounted) save_errno = errno;
+ }
+ setfscreatecon(nullptr);
+ if (!mounted) rmdir(kScratchMountPoint.c_str());
+ errno = save_errno;
+ return mounted;
+}
+
+const std::string kMkF2fs("/system/bin/make_f2fs");
+const std::string kMkExt4("/system/bin/mke2fs");
+
+// Only a suggestion for _first_ try during mounting
+std::string fs_mgr_overlayfs_scratch_mount_type() {
+ if (!access(kMkF2fs.c_str(), X_OK)) return "f2fs";
+ if (!access(kMkExt4.c_str(), X_OK)) return "ext4";
+ 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)?
+ 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)) return "";
+ }
+ return scratch_device_cache = path;
+}
+
+bool fs_mgr_overlayfs_make_scratch(const std::string& scratch_device, const std::string& mnt_type) {
+ // Force mkfs by design for overlay support of adb remount, simplify and
+ // thus do not rely on fsck to correct problems that could creep in.
+ auto command = ""s;
+ if (mnt_type == "f2fs") {
+ command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint);
+ } else if (mnt_type == "ext4") {
+ command = kMkExt4 + " -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint;
+ } else {
+ errno = ESRCH;
+ LERROR << mnt_type << " has no mkfs cookbook";
+ return false;
+ }
+ command += " " + scratch_device;
+ fs_mgr_set_blk_ro(scratch_device, false);
+ auto ret = system(command.c_str());
+ if (ret) {
+ LERROR << "make " << mnt_type << " filesystem on " << scratch_device << " return=" << ret;
+ return false;
+ }
+ 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;
+ }
+ 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;
+ if (!*partition_exists) {
+ partition = builder->AddPartition(partition_name, LP_PARTITION_ATTR_NONE);
+ if (!partition) {
+ LERROR << "create " << partition_name;
+ return false;
+ }
+ changed = true;
+ }
+ // Take half of free space, minimum 512MB or maximum free - margin.
+ static constexpr auto kMinimumSize = uint64_t(512 * 1024 * 1024);
+ if (partition->size() < kMinimumSize) {
+ auto partition_size =
+ builder->AllocatableSpace() - builder->UsedSpace() + partition->size();
+ if ((partition_size > kMinimumSize) || !partition->size()) {
+ // Leave some space for free space jitter of a few erase
+ // blocks, in case they are needed for any individual updates
+ // to any other partition that needs to be flashed while
+ // overlayfs is in force. Of course if margin_size is not
+ // enough could normally get a flash failure, so
+ // ResizePartition() will delete the scratch partition in
+ // order to fulfill. Deleting scratch will destroy all of
+ // the adb remount overrides :-( .
+ auto margin_size = uint64_t(3 * 256 * 1024);
+ BlockDeviceInfo info;
+ if (builder->GetBlockDeviceInfo(partition_name, &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;
+ }
+ if (!partition_create) DestroyLogicalPartition(partition_name, 10s);
+ changed = true;
+ *partition_exists = false;
+ }
+ }
+ }
+ // land the update back on to the partition
+ if (changed) {
+ auto metadata = builder->Export();
+ if (!metadata || !UpdatePartitionTable(super_device, *metadata.get(), slot_number)) {
+ LERROR << "add partition " << partition_name;
+ return false;
+ }
+
+ if (change) *change = true;
+ }
+
+ if (changed || partition_create) {
+ if (!CreateLogicalPartition(super_device, slot_number, partition_name, true, 0s,
+ scratch_device))
+ return false;
+
+ if (change) *change = true;
+ }
+ return true;
+}
+
+// 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;
+
+ std::string scratch_device;
+ bool partition_exists;
+ if (!fs_mgr_overlayfs_create_scratch(fstab, &scratch_device, &partition_exists, change)) {
+ return false;
+ }
+
+ // If the partition exists, assume first that it can be mounted.
+ auto mnt_type = fs_mgr_overlayfs_scratch_mount_type();
+ if (partition_exists) {
+ if (fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type)) {
+ if (!fs_mgr_access(kScratchMountPoint + kOverlayTopDir) &&
+ !fs_mgr_filesystem_has_space(kScratchMountPoint)) {
+ // declare it useless, no overrides and no free space
+ fs_mgr_overlayfs_umount_scratch();
+ } else {
+ if (change) *change = true;
+ return true;
+ }
+ }
+ // partition existed, but was not initialized; fall through to make it.
+ errno = 0;
+ }
+
+ if (!fs_mgr_overlayfs_make_scratch(scratch_device, mnt_type)) return false;
+
+ if (change) *change = true;
+
+ return fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type);
+}
+
+bool fs_mgr_overlayfs_scratch_can_be_mounted(const std::string& scratch_device) {
+ if (scratch_device.empty()) return false;
+ if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return false;
+ if (android::base::StartsWith(scratch_device, kPhysicalDevice)) return true;
+ if (fs_mgr_rw_access(scratch_device)) return true;
+ 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;
+ auto builder = MetadataBuilder::New(super_device, slot_number);
+ if (!builder) return false;
+ return builder->FindPartition(android::base::Basename(kScratchMountPoint)) != nullptr;
+}
+
+bool fs_mgr_overlayfs_invalid() {
+ if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return true;
+
+ // in recovery, fastbootd, or gsi mode, not allowed!
+ if (fs_mgr_access("/system/bin/recovery")) return true;
+ if (android::gsi::IsGsiRunning()) return true;
+
+ return false;
+}
+
} // namespace
-bool fs_mgr_overlayfs_mount_all() {
+bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
auto ret = false;
+ if (fs_mgr_overlayfs_invalid()) return ret;
- if (!fs_mgr_wants_overlayfs()) return ret;
-
- std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- if (!fstab) return ret;
-
- for (const auto& mount_point : fs_mgr_candidate_list(fstab.get())) {
+ auto scratch_can_be_mounted = true;
+ for (const auto& mount_point : fs_mgr_candidate_list(fstab)) {
if (fs_mgr_overlayfs_already_mounted(mount_point)) continue;
+ 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);
+ }
+ }
+ }
if (fs_mgr_overlayfs_mount(mount_point)) ret = true;
}
return ret;
}
+std::vector<std::string> fs_mgr_overlayfs_required_devices(Fstab* fstab) {
+ if (fs_mgr_overlayfs_invalid()) return {};
+
+ if (std::find_if(fstab->begin(), fstab->end(), [](const auto& entry) {
+ return entry.mount_point == kScratchMountPoint;
+ }) != fstab->end()) {
+ return {};
+ }
+
+ for (const auto& mount_point : fs_mgr_candidate_list(fstab)) {
+ if (fs_mgr_overlayfs_already_mounted(mount_point)) continue;
+ auto device = fs_mgr_overlayfs_scratch_device();
+ if (!fs_mgr_overlayfs_scratch_can_be_mounted(device)) break;
+ return {device};
+ }
+ return {};
+}
+
// Returns false if setup not permitted, errno set to last error.
// If something is altered, set *change.
bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* change) {
if (change) *change = false;
auto ret = false;
- if (backing && (kOverlayMountPoint != backing)) {
- errno = EINVAL;
- return ret;
- }
- if (!fs_mgr_wants_overlayfs()) return ret;
+ if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return ret;
if (!fs_mgr_boot_completed()) {
errno = EBUSY;
- PERROR << "overlayfs setup";
+ PERROR << "setup";
return ret;
}
- std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
- fs_mgr_free_fstab);
- if (fstab && !fs_mgr_get_entry_for_mount_point(fstab.get(), kOverlayMountPoint)) return ret;
- auto mounts = fs_mgr_candidate_list(fstab.get(), fs_mgr_mount_point(fstab.get(), mount_point));
- if (fstab && mounts.empty()) return ret;
-
- if (setfscreatecon(overlayfs_file_context)) {
- PERROR << "overlayfs setfscreatecon " << overlayfs_file_context;
- }
- auto overlay = kOverlayMountPoint + "/overlay/";
auto save_errno = errno;
- if (!mkdir(overlay.c_str(), 0755)) {
- if (change) *change = true;
- } else if (errno != EEXIST) {
- PERROR << "overlayfs mkdir " << overlay;
- } else {
- errno = save_errno;
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
+ return false;
}
- setfscreatecon(nullptr);
- if (!fstab && mount_point && fs_mgr_overlayfs_setup_one(overlay, mount_point, change)) {
- ret = true;
+ errno = save_errno;
+ auto mounts = fs_mgr_candidate_list(&fstab, fs_mgr_mount_point(mount_point));
+ if (mounts.empty()) return ret;
+
+ std::string dir;
+ for (const auto& overlay_mount_point : kOverlayMountPoints) {
+ if (backing && backing[0] && (overlay_mount_point != backing)) continue;
+ if (overlay_mount_point == kScratchMountPoint) {
+ if (!fs_mgr_rw_access(fs_mgr_overlayfs_super_device(fs_mgr_overlayfs_slot_number())) ||
+ !fs_mgr_overlayfs_has_logical(fstab)) {
+ continue;
+ }
+ if (!fs_mgr_overlayfs_setup_scratch(fstab, change)) continue;
+ } else {
+ if (std::find_if(fstab.begin(), fstab.end(), [&overlay_mount_point](const auto& entry) {
+ return entry.mount_point == overlay_mount_point;
+ }) == fstab.end()) {
+ continue;
+ }
+ }
+ dir = overlay_mount_point;
+ break;
}
+ if (dir.empty()) {
+ if (change && *change) errno = ESRCH;
+ if (errno == EPERM) errno = save_errno;
+ return ret;
+ }
+
+ std::string overlay;
+ ret |= fs_mgr_overlayfs_setup_dir(dir, &overlay, change);
for (const auto& fsrec_mount_point : mounts) {
ret |= fs_mgr_overlayfs_setup_one(overlay, fsrec_mount_point, change);
}
@@ -462,46 +915,27 @@
// If something is altered, set *change.
bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
if (change) *change = false;
- mount_point = fs_mgr_mount_point(std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)>(
- fs_mgr_read_fstab_default(), fs_mgr_free_fstab)
- .get(),
- mount_point);
+ mount_point = fs_mgr_mount_point(mount_point);
auto ret = true;
- const auto overlay = kOverlayMountPoint + "/overlay";
- const auto oldpath = overlay + (mount_point ?: "");
- const auto newpath = oldpath + ".teardown";
- ret &= fs_mgr_rm_all(newpath);
- auto save_errno = errno;
- if (!rename(oldpath.c_str(), newpath.c_str())) {
- if (change) *change = true;
- } else if (errno != ENOENT) {
- ret = false;
- PERROR << "overlayfs mv " << oldpath << " " << newpath;
- } else {
- errno = save_errno;
- }
- ret &= fs_mgr_rm_all(newpath, change);
- save_errno = errno;
- if (!rmdir(newpath.c_str())) {
- if (change) *change = true;
- } else if (errno != ENOENT) {
- ret = false;
- PERROR << "overlayfs rmdir " << newpath;
- } else {
- errno = save_errno;
- }
- if (mount_point) {
- save_errno = errno;
- if (!rmdir(overlay.c_str())) {
- if (change) *change = true;
- } else if ((errno != ENOENT) && (errno != ENOTEMPTY)) {
- ret = false;
- PERROR << "overlayfs rmdir " << overlay;
- } else {
- errno = save_errno;
+ // If scratch exists, but is not mounted, lets gain access to clean
+ // specific override entries.
+ auto mount_scratch = 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, 0s,
+ &scratch_device);
}
+ mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device,
+ fs_mgr_overlayfs_scratch_mount_type());
}
- if (!fs_mgr_wants_overlayfs()) {
+ for (const auto& overlay_mount_point : kOverlayMountPoints) {
+ ret &= fs_mgr_overlayfs_teardown_one(overlay_mount_point, mount_point ?: "", change);
+ }
+ if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
// After obligatory teardown to make sure everything is clean, but if
// we didn't want overlayfs in the the first place, we do not want to
// waste time on a reboot (or reboot request message).
@@ -511,12 +945,27 @@
// caller that there may still be more to do.
if (!fs_mgr_boot_completed()) {
errno = EBUSY;
- PERROR << "overlayfs teardown";
+ PERROR << "teardown";
ret = false;
}
+ if (mount_scratch) fs_mgr_overlayfs_umount_scratch();
+
return ret;
}
+bool fs_mgr_overlayfs_is_setup() {
+ if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
+ return false;
+ }
+ if (fs_mgr_overlayfs_invalid()) return false;
+ for (const auto& mount_point : fs_mgr_candidate_list(&fstab)) {
+ if (fs_mgr_overlayfs_already_mounted(mount_point)) return true;
+ }
+ return false;
+}
+
#endif // ALLOW_ADBD_DISABLE_VERITY != 0
bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) {
@@ -540,3 +989,42 @@
return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
}
+
+std::string fs_mgr_get_context(const std::string& mount_point) {
+ char* ctx = nullptr;
+ if (getfilecon(mount_point.c_str(), &ctx) == -1) {
+ return "";
+ }
+
+ std::string context(ctx);
+ free(ctx);
+ return context;
+}
+
+OverlayfsValidResult fs_mgr_overlayfs_valid() {
+ // Overlayfs available in the kernel, and patched for override_creds?
+ if (fs_mgr_access("/sys/module/overlay/parameters/override_creds")) {
+ return OverlayfsValidResult::kOverrideCredsRequired;
+ }
+ if (!fs_mgr_access("/sys/module/overlay")) {
+ return OverlayfsValidResult::kNotSupported;
+ }
+ struct utsname uts;
+ if (uname(&uts) == -1) {
+ return OverlayfsValidResult::kNotSupported;
+ }
+ int major, minor;
+ if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
+ return OverlayfsValidResult::kNotSupported;
+ }
+ if (major < 4) {
+ return OverlayfsValidResult::kOk;
+ }
+ if (major > 4) {
+ return OverlayfsValidResult::kNotSupported;
+ }
+ if (minor > 6) {
+ return OverlayfsValidResult::kNotSupported;
+ }
+ return OverlayfsValidResult::kOk;
+}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index a347faf..3b9ddee 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -21,8 +21,9 @@
#include <string>
#include <android-base/logging.h>
+#include <fs_mgr.h>
+#include <fstab/fstab.h>
-#include "fs_mgr.h"
#include "fs_mgr_priv_boot_config.h"
/* The CHECK() in logging.h will use program invocation name as the tag.
@@ -39,11 +40,13 @@
#define LINFO LOG(INFO) << FS_MGR_TAG
#define LWARNING LOG(WARNING) << FS_MGR_TAG
#define LERROR LOG(ERROR) << FS_MGR_TAG
+#define LFATAL LOG(FATAL) << FS_MGR_TAG
// Logs a message with strerror(errno) at the end
#define PINFO PLOG(INFO) << FS_MGR_TAG
#define PWARNING PLOG(WARNING) << FS_MGR_TAG
#define PERROR PLOG(ERROR) << FS_MGR_TAG
+#define PFATAL PLOG(FATAL) << FS_MGR_TAG
#define CRYPTO_TMPFS_OPTIONS "size=512m,mode=0771,uid=1000,gid=1000"
@@ -113,19 +116,37 @@
#define MF_KEYDIRECTORY 0X4000000
#define MF_SYSFS 0X8000000
#define MF_LOGICAL 0x10000000
+#define MF_CHECKPOINT_BLK 0x20000000
+#define MF_CHECKPOINT_FS 0x40000000
+#define MF_FIRST_STAGE_MOUNT \
+ 0x80000000
+#define MF_SLOTSELECT_OTHER \
+ 0x100000000
+#define MF_ZRAM_LOOPBACK_PATH \
+ 0x200000000
+#define MF_ZRAM_LOOPBACK_SIZE \
+ 0x400000000
+#define MF_ZRAM_BACKING_DEV_PATH \
+ 0x800000000
+#define MF_FS_VERITY \
+ 0x1000000000
// clang-format on
#define DM_BUF_SIZE 4096
using namespace std::chrono_literals;
-int fs_mgr_set_blk_ro(const char *blockdev);
+enum class FileWaitMode { Exists, DoesNotExist };
+
bool fs_mgr_wait_for_file(const std::string& filename,
- const std::chrono::milliseconds relative_timeout);
-bool fs_mgr_update_for_slotselect(struct fstab *fstab);
+ 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(Fstab* fstab);
bool fs_mgr_is_device_unlocked();
const std::string& get_android_dt_dir();
bool is_dt_compatible();
-int load_verity_state(struct fstab_rec* fstab, int* mode);
+int load_verity_state(const FstabEntry& entry, int* mode);
#endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/fs_mgr_roots.cpp b/fs_mgr/fs_mgr_roots.cpp
new file mode 100644
index 0000000..32a5d21
--- /dev/null
+++ b/fs_mgr/fs_mgr_roots.cpp
@@ -0,0 +1,195 @@
+/*
+ * 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 "fs_mgr/roots.h"
+
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <string>
+
+#include "fs_mgr.h"
+#include "fs_mgr_dm_linear.h"
+#include "fs_mgr_priv.h"
+
+namespace android {
+namespace fs_mgr {
+
+static constexpr const char* kSystemRoot = "/system";
+
+static bool gDidMapLogicalPartitions = false;
+
+FstabEntry* GetEntryForPath(Fstab* fstab, const std::string& path) {
+ if (path.empty()) return nullptr;
+ std::string str(path);
+ while (true) {
+ auto it = std::find_if(fstab->begin(), fstab->end(),
+ [&str](const auto& entry) { return entry.mount_point == str; });
+ if (it != fstab->end()) return &*it;
+ if (str == "/") break;
+ auto slash = str.find_last_of('/');
+ if (slash == std::string::npos) break;
+ if (slash == 0) {
+ str = "/";
+ } else {
+ str = str.substr(0, slash);
+ }
+ }
+ return nullptr;
+}
+
+enum class MountState {
+ ERROR = -1,
+ NOT_MOUNTED = 0,
+ MOUNTED = 1,
+};
+
+static MountState GetMountState(const std::string& mount_point) {
+ Fstab mounted_fstab;
+ if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
+ LERROR << "Failed to scan mounted volumes";
+ return MountState::ERROR;
+ }
+
+ auto mv = std::find_if(
+ mounted_fstab.begin(), mounted_fstab.end(),
+ [&mount_point](const auto& entry) { return entry.mount_point == mount_point; });
+ if (mv != mounted_fstab.end()) {
+ return MountState::MOUNTED;
+ }
+ return MountState::NOT_MOUNTED;
+}
+
+bool EnsurePathMounted(Fstab* fstab, const std::string& path, const std::string& mount_pt) {
+ auto rec = GetEntryForPath(fstab, path);
+ if (rec == nullptr) {
+ LERROR << "unknown volume for path [" << path << "]";
+ return false;
+ }
+ if (rec->fs_type == "ramdisk") {
+ // The ramdisk is always mounted.
+ return true;
+ }
+
+ // If we can't acquire the block device for a logical partition, it likely
+ // was never created. In that case we try to create it.
+ if (rec->fs_mgr_flags.logical && !fs_mgr_update_logical_partition(rec)) {
+ if (gDidMapLogicalPartitions) {
+ LERROR << "Failed to find block device for partition";
+ return false;
+ }
+ std::string super_name = fs_mgr_get_super_partition_name();
+ if (!android::fs_mgr::CreateLogicalPartitions("/dev/block/by-name/" + super_name)) {
+ LERROR << "Failed to create logical partitions";
+ return false;
+ }
+ gDidMapLogicalPartitions = true;
+ if (!fs_mgr_update_logical_partition(rec)) {
+ LERROR << "Failed to find block device for partition";
+ return false;
+ }
+ }
+
+ auto mounted = GetMountState(rec->mount_point);
+ if (mounted == MountState::ERROR) {
+ return false;
+ }
+ if (mounted == MountState::MOUNTED) {
+ 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;
+ return false;
+ }
+
+ int result = fs_mgr_do_mount_one(*rec, mount_point);
+ if (result == -1 && rec->fs_mgr_flags.formattable) {
+ PERROR << "Failed to mount " << mount_point << "; formatting";
+ bool crypt_footer = rec->is_encryptable() && rec->key_loc == "footer";
+ if (fs_mgr_do_format(*rec, crypt_footer) != 0) {
+ PERROR << "Failed to format " << mount_point;
+ return false;
+ }
+ result = fs_mgr_do_mount_one(*rec, mount_point);
+ }
+
+ if (result == -1) {
+ PERROR << "Failed to mount " << mount_point;
+ return false;
+ }
+ return true;
+}
+
+bool EnsurePathUnmounted(Fstab* fstab, const std::string& path) {
+ auto rec = GetEntryForPath(fstab, path);
+ if (rec == nullptr) {
+ LERROR << "unknown volume for path [" << path << "]";
+ return false;
+ }
+ if (rec->fs_type == "ramdisk") {
+ // The ramdisk is always mounted; you can't unmount it.
+ return false;
+ }
+
+ Fstab mounted_fstab;
+ if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
+ LERROR << "Failed to scan mounted volumes";
+ return false;
+ }
+
+ auto mounted = GetMountState(rec->mount_point);
+ if (mounted == MountState::ERROR) {
+ return false;
+ }
+ if (mounted == MountState::NOT_MOUNTED) {
+ return true;
+ }
+
+ int result = umount(rec->mount_point.c_str());
+ if (result == -1) {
+ PWARNING << "Failed to umount " << rec->mount_point;
+ return false;
+ }
+ return true;
+}
+
+std::string GetSystemRoot() {
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
+ LERROR << "Failed to read default fstab";
+ return "";
+ }
+
+ auto it = std::find_if(fstab.begin(), fstab.end(),
+ [](const auto& entry) { return entry.mount_point == kSystemRoot; });
+ if (it == fstab.end()) {
+ return "/";
+ }
+
+ return kSystemRoot;
+}
+
+bool LogicalPartitionsMapped() {
+ return gDidMapLogicalPartitions;
+}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/fs_mgr_slotselect.cpp b/fs_mgr/fs_mgr_slotselect.cpp
index 3b01d0e..3cb718c 100644
--- a/fs_mgr/fs_mgr_slotselect.cpp
+++ b/fs_mgr/fs_mgr_slotselect.cpp
@@ -21,6 +21,19 @@
#include "fs_mgr.h"
#include "fs_mgr_priv.h"
+// https://source.android.com/devices/tech/ota/ab/ab_implement#partitions
+// All partitions that are A/B-ed should be named as follows (slots are always
+// named a, b, etc.): boot_a, boot_b, system_a, system_b, vendor_a, vendor_b.
+static std::string other_suffix(const std::string& slot_suffix) {
+ if (slot_suffix == "_a") {
+ return "_b";
+ }
+ if (slot_suffix == "_b") {
+ return "_a";
+ }
+ return "";
+}
+
// Returns "_a" or "_b" based on androidboot.slot_suffix in kernel cmdline, or an empty string
// if that parameter does not exist.
std::string fs_mgr_get_slot_suffix() {
@@ -31,36 +44,24 @@
}
// Updates |fstab| for slot_suffix. Returns true on success, false on error.
-bool fs_mgr_update_for_slotselect(struct fstab *fstab) {
- int n;
+bool fs_mgr_update_for_slotselect(Fstab* fstab) {
std::string ab_suffix;
- for (n = 0; n < fstab->num_entries; n++) {
- fstab_rec& record = fstab->recs[n];
- if (record.fs_mgr_flags & MF_SLOTSELECT) {
- if (ab_suffix.empty()) {
- ab_suffix = fs_mgr_get_slot_suffix();
- // Return false if failed to get ab_suffix when MF_SLOTSELECT is specified.
- if (ab_suffix.empty()) return false;
- }
-
- char* new_blk_device;
- if (asprintf(&new_blk_device, "%s%s", record.blk_device, ab_suffix.c_str()) <= 0) {
- return false;
- }
- free(record.blk_device);
- record.blk_device = new_blk_device;
-
- char* new_partition_name;
- if (record.logical_partition_name) {
- if (asprintf(&new_partition_name, "%s%s", record.logical_partition_name,
- ab_suffix.c_str()) <= 0) {
- return false;
- }
- free(record.logical_partition_name);
- record.logical_partition_name = new_partition_name;
- }
+ for (auto& entry : *fstab) {
+ if (!entry.fs_mgr_flags.slot_select && !entry.fs_mgr_flags.slot_select_other) {
+ continue;
}
+
+ if (ab_suffix.empty()) {
+ ab_suffix = fs_mgr_get_slot_suffix();
+ // Return false if failed to get ab_suffix when MF_SLOTSELECT is specified.
+ if (ab_suffix.empty()) return false;
+ }
+
+ const auto& update_suffix =
+ entry.fs_mgr_flags.slot_select ? ab_suffix : other_suffix(ab_suffix);
+ entry.blk_device = entry.blk_device + update_suffix;
+ entry.logical_partition_name = entry.logical_partition_name + update_suffix;
}
return true;
}
diff --git a/fs_mgr/fs_mgr_vendor_overlay.cpp b/fs_mgr/fs_mgr_vendor_overlay.cpp
new file mode 100644
index 0000000..830f0dd
--- /dev/null
+++ b/fs_mgr/fs_mgr_vendor_overlay.cpp
@@ -0,0 +1,137 @@
+/*
+ * 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 <selinux/selinux.h>
+#include <sys/mount.h>
+#include <unistd.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <fs_mgr_overlayfs.h>
+#include <fs_mgr_vendor_overlay.h>
+#include <fstab/fstab.h>
+
+#include "fs_mgr_priv.h"
+
+using namespace std::literals;
+
+namespace {
+
+// The order of the list means the priority to show the files in the directory.
+// The last one has the highest priority.
+const std::vector<const std::string> kVendorOverlaySourceDirs = {
+ "/system/vendor_overlay/",
+ "/product/vendor_overlay/",
+};
+const auto kVndkVersionPropertyName = "ro.vndk.version"s;
+const auto kVendorTopDir = "/vendor/"s;
+const auto kLowerdirOption = "lowerdir="s;
+
+std::vector<std::pair<std::string, std::string>> fs_mgr_get_vendor_overlay_dirs(
+ const std::string& vndk_version) {
+ std::vector<std::pair<std::string, std::string>> vendor_overlay_dirs;
+ for (const auto& vendor_overlay_source : kVendorOverlaySourceDirs) {
+ const auto overlay_top = vendor_overlay_source + vndk_version;
+ std::unique_ptr<DIR, decltype(&closedir)> vendor_overlay_top(opendir(overlay_top.c_str()),
+ closedir);
+ if (!vendor_overlay_top) continue;
+
+ // Vendor overlay root for current vendor version found!
+ LINFO << "vendor overlay root: " << overlay_top;
+
+ struct dirent* dp;
+ while ((dp = readdir(vendor_overlay_top.get())) != nullptr) {
+ if (dp->d_type != DT_DIR || dp->d_name[0] == '.') {
+ continue;
+ }
+ vendor_overlay_dirs.emplace_back(overlay_top, dp->d_name);
+ }
+ }
+ return vendor_overlay_dirs;
+}
+
+bool fs_mgr_vendor_overlay_mount(const std::pair<std::string, std::string>& mount_point) {
+ const auto [overlay_top, mount_dir] = mount_point;
+ const auto vendor_mount_point = kVendorTopDir + mount_dir;
+ LINFO << "vendor overlay mount on " << vendor_mount_point;
+
+ const auto target_context = fs_mgr_get_context(vendor_mount_point);
+ if (target_context.empty()) {
+ PERROR << " failed: cannot find the target vendor mount point";
+ return false;
+ }
+ const auto source_directory = overlay_top + "/" + mount_dir;
+ const auto source_context = fs_mgr_get_context(source_directory);
+ if (target_context != source_context) {
+ LERROR << " failed: source and target contexts do not match (source:" << source_context
+ << ", target:" << target_context << ")";
+ return false;
+ }
+
+ auto options = kLowerdirOption + source_directory + ":" + vendor_mount_point;
+ if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kOverrideCredsRequired) {
+ options += ",override_creds=off";
+ }
+ auto report = "__mount(source=overlay,target="s + vendor_mount_point + ",type=overlay," +
+ options + ")=";
+ auto ret = mount("overlay", vendor_mount_point.c_str(), "overlay", MS_RDONLY | MS_RELATIME,
+ options.c_str());
+ if (ret) {
+ PERROR << report << ret;
+ return false;
+ } else {
+ LINFO << report << ret;
+ return true;
+ }
+}
+
+} // namespace
+
+// Since the vendor overlay requires to know the version of the vendor partition,
+// it is not possible to mount vendor overlay at the first stage that cannot
+// initialize properties.
+// To read the properties, vendor overlay must be mounted at the second stage, right
+// after "property_load_boot_defaults()" is called.
+bool fs_mgr_vendor_overlay_mount_all() {
+ // To read the property, it must be called at the second init stage after the default
+ // properties are loaded.
+ static const auto vndk_version = android::base::GetProperty(kVndkVersionPropertyName, "");
+ if (vndk_version.empty()) {
+ LINFO << "vendor overlay: vndk version not defined";
+ return false;
+ }
+
+ const auto vendor_overlay_dirs = fs_mgr_get_vendor_overlay_dirs(vndk_version);
+ if (vendor_overlay_dirs.empty()) return true;
+ if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
+ LINFO << "vendor overlay: kernel does not support overlayfs";
+ return false;
+ }
+
+ // Mount each directory in /(system|product)/vendor_overlay/<ver> on /vendor
+ auto ret = true;
+ for (const auto& vendor_overlay_dir : vendor_overlay_dirs) {
+ if (!fs_mgr_vendor_overlay_mount(vendor_overlay_dir)) {
+ ret = false;
+ }
+ }
+ return ret;
+}
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 5fb4ebb..9adf8cc 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -89,24 +89,21 @@
{
uint8_t key_data[ANDROID_PUBKEY_ENCODED_SIZE];
- FILE* f = fopen(path, "r");
+ auto f = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path, "re"), fclose};
if (!f) {
LERROR << "Can't open " << path;
- return NULL;
+ return nullptr;
}
- if (!fread(key_data, sizeof(key_data), 1, f)) {
+ if (!fread(key_data, sizeof(key_data), 1, f.get())) {
LERROR << "Could not read key!";
- fclose(f);
- return NULL;
+ return nullptr;
}
- fclose(f);
-
- RSA* key = NULL;
+ RSA* key = nullptr;
if (!android_pubkey_decode(key_data, sizeof(key_data), &key)) {
LERROR << "Could not parse key!";
- return NULL;
+ return nullptr;
}
return key;
@@ -368,7 +365,6 @@
static int metadata_find(const char *fname, const char *stag,
unsigned int slength, off64_t *offset)
{
- FILE *fp = NULL;
char tag[METADATA_TAG_MAX_LENGTH + 1];
int rc = -1;
int n;
@@ -380,75 +376,64 @@
return -1;
}
- fp = fopen(fname, "r+");
+ auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(fname, "re+"), fclose};
if (!fp) {
PERROR << "Failed to open " << fname;
- goto out;
+ return -1;
}
/* check magic */
- if (fseek(fp, start, SEEK_SET) < 0 ||
- fread(&magic, sizeof(magic), 1, fp) != 1) {
+ if (fseek(fp.get(), start, SEEK_SET) < 0 || fread(&magic, sizeof(magic), 1, fp.get()) != 1) {
PERROR << "Failed to read magic from " << fname;
- goto out;
+ return -1;
}
if (magic != METADATA_MAGIC) {
magic = METADATA_MAGIC;
- if (fseek(fp, start, SEEK_SET) < 0 ||
- fwrite(&magic, sizeof(magic), 1, fp) != 1) {
+ if (fseek(fp.get(), start, SEEK_SET) < 0 ||
+ fwrite(&magic, sizeof(magic), 1, fp.get()) != 1) {
PERROR << "Failed to write magic to " << fname;
- goto out;
+ return -1;
}
- rc = metadata_add(fp, start + sizeof(magic), stag, slength, offset);
+ rc = metadata_add(fp.get(), start + sizeof(magic), stag, slength, offset);
if (rc < 0) {
PERROR << "Failed to add metadata to " << fname;
}
- goto out;
+ return rc;
}
start += sizeof(magic);
while (1) {
- n = fscanf(fp, "%" STRINGIFY(METADATA_TAG_MAX_LENGTH) "s %u\n",
- tag, &length);
+ 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);
+ start = ftell(fp.get());
if (!strcmp(tag, stag) && length == slength) {
*offset = start;
- rc = 0;
- goto out;
+ return 0;
}
start += length;
- if (fseek(fp, length, SEEK_CUR) < 0) {
+ if (fseek(fp.get(), length, SEEK_CUR) < 0) {
PERROR << "Failed to seek " << fname;
- goto out;
+ return -1;
}
} else {
- rc = metadata_add(fp, start, stag, slength, offset);
+ rc = metadata_add(fp.get(), start, stag, slength, offset);
if (rc < 0) {
PERROR << "Failed to write metadata to " << fname;
}
- goto out;
+ return rc;
}
- }
-
-out:
- if (fp) {
- fflush(fp);
- fclose(fp);
}
-
- return rc;
}
static int write_verity_state(const char *fname, off64_t offset, int32_t mode)
@@ -551,8 +536,7 @@
return 0;
}
-static int compare_last_signature(struct fstab_rec *fstab, int *match)
-{
+static int compare_last_signature(const FstabEntry& entry, int* match) {
char tag[METADATA_TAG_MAX_LENGTH + 1];
int fd = -1;
int rc = -1;
@@ -564,42 +548,40 @@
*match = 1;
- if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
- FEC_DEFAULT_ROOTS) == -1) {
- PERROR << "Failed to open '" << fstab->blk_device << "'";
+ 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 '" << fstab->blk_device << "'";
+ 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(fstab->mount_point)) >= (int)sizeof(tag)) {
- LERROR << "Metadata tag name too long for " << fstab->mount_point;
+ 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(fstab->verity_loc, tag, SHA256_DIGEST_LENGTH,
- &offset) < 0) {
+ if (metadata_find(entry.verity_loc.c_str(), tag, SHA256_DIGEST_LENGTH, &offset) < 0) {
goto out;
}
- fd = TEMP_FAILURE_RETRY(open(fstab->verity_loc, O_RDWR | O_SYNC | O_CLOEXEC));
+ fd = TEMP_FAILURE_RETRY(open(entry.verity_loc.c_str(), O_RDWR | O_SYNC | O_CLOEXEC));
if (fd == -1) {
- PERROR << "Failed to open " << fstab->verity_loc;
+ 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 "
- << fstab->verity_loc << " offset " << offset;
+ 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;
}
@@ -609,8 +591,8 @@
/* update current signature hash */
if (TEMP_FAILURE_RETRY(pwrite64(fd, curr, sizeof(curr),
offset)) != sizeof(curr)) {
- PERROR << "Failed to write " << sizeof(curr) << " bytes to "
- << fstab->verity_loc << " offset " << offset;
+ PERROR << "Failed to write " << sizeof(curr) << " bytes to " << entry.verity_loc
+ << " offset " << offset;
goto out;
}
}
@@ -622,28 +604,23 @@
return rc;
}
-static int get_verity_state_offset(struct fstab_rec *fstab, off64_t *offset)
-{
+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(fstab->mount_point)) >= (int)sizeof(tag)) {
- LERROR << "Metadata tag name too long for " << fstab->mount_point;
+ 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(fstab->verity_loc, tag, sizeof(struct verity_state),
- offset);
+ return metadata_find(entry.verity_loc.c_str(), tag, sizeof(struct verity_state), offset);
}
-int load_verity_state(struct fstab_rec* fstab, int* mode) {
- int match = 0;
- off64_t offset = 0;
-
- /* unless otherwise specified, use EIO mode */
+int load_verity_state(const FstabEntry& entry, int* mode) {
+ // unless otherwise specified, use EIO mode.
*mode = VERITY_MODE_EIO;
- /* use the kernel parameter if set */
+ // use the kernel parameter if set.
std::string veritymode;
if (fs_mgr_get_boot_config("veritymode", &veritymode)) {
if (veritymode == "enforcing") {
@@ -652,7 +629,8 @@
return 0;
}
- if (get_verity_state_offset(fstab, &offset) < 0) {
+ off64_t offset = 0;
+ if (get_verity_state_offset(entry, &offset) < 0) {
/* fall back to stateless behavior */
return 0;
}
@@ -660,16 +638,17 @@
if (was_verity_restart()) {
/* device was restarted after dm-verity detected a corrupted
* block, so use EIO mode */
- return write_verity_state(fstab->verity_loc, offset, *mode);
+ return write_verity_state(entry.verity_loc.c_str(), offset, *mode);
}
- if (!compare_last_signature(fstab, &match) && !match) {
+ int match = 0;
+ if (!compare_last_signature(entry, &match) && !match) {
/* partition has been reflashed, reset dm-verity state */
*mode = VERITY_MODE_DEFAULT;
- return write_verity_state(fstab->verity_loc, offset, *mode);
+ return write_verity_state(entry.verity_loc.c_str(), offset, *mode);
}
- return read_verity_state(fstab->verity_loc, offset, mode);
+ return read_verity_state(entry.verity_loc.c_str(), offset, mode);
}
// Update the verity table using the actual block device path.
@@ -731,8 +710,7 @@
// prepares the verity enabled (MF_VERIFY / MF_VERIFYATBOOT) fstab record for
// mount. The 'wait_for_verity_dev' parameter makes this function wait for the
// verity device to get created before return
-int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev)
-{
+int fs_mgr_setup_verity(FstabEntry* entry, bool wait_for_verity_dev) {
int retval = FS_MGR_SETUP_VERITY_FAIL;
int fd = -1;
std::string verity_blk_name;
@@ -740,20 +718,20 @@
struct fec_verity_metadata verity;
struct verity_table_params params = { .table = NULL };
- const std::string mount_point(basename(fstab->mount_point));
+ const std::string mount_point(basename(entry->mount_point.c_str()));
bool verified_at_boot = false;
android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
- if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
- FEC_DEFAULT_ROOTS) < 0) {
- PERROR << "Failed to open '" << fstab->blk_device << "'";
+ if (fec_open(&f, entry->blk_device.c_str(), O_RDONLY, FEC_VERITY_DISABLE, FEC_DEFAULT_ROOTS) <
+ 0) {
+ PERROR << "Failed to open '" << entry->blk_device << "'";
return retval;
}
// read verity metadata
if (fec_verity_get_metadata(f, &verity) < 0) {
- PERROR << "Failed to get verity metadata '" << fstab->blk_device << "'";
+ PERROR << "Failed to get verity metadata '" << entry->blk_device << "'";
// Allow verity disabled when the device is unlocked without metadata
if (fs_mgr_is_device_unlocked()) {
retval = FS_MGR_SETUP_VERITY_SKIPPED;
@@ -775,9 +753,9 @@
params.ecc.valid = false;
}
- params.ecc_dev = fstab->blk_device;
+ params.ecc_dev = entry->blk_device.c_str();
- if (load_verity_state(fstab, ¶ms.mode) < 0) {
+ if (load_verity_state(*entry, ¶ms.mode) < 0) {
/* 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
@@ -818,8 +796,8 @@
<< " (mode " << params.mode << ")";
// Update the verity params using the actual block device path
- update_verity_table_blk_device(fstab->blk_device, ¶ms.table,
- fstab->fs_mgr_flags & MF_SLOTSELECT);
+ update_verity_table_blk_device(entry->blk_device, ¶ms.table,
+ entry->fs_mgr_flags.slot_select);
// load the verity mapping table
if (load_verity_table(dm, mount_point, verity.data_size, ¶ms, format_verity_table) == 0) {
@@ -863,31 +841,29 @@
}
// mark the underlying block device as read-only
- fs_mgr_set_blk_ro(fstab->blk_device);
+ fs_mgr_set_blk_ro(entry->blk_device);
// Verify the entire partition in one go
// If there is an error, allow it to mount as a normal verity partition.
- if (fstab->fs_mgr_flags & MF_VERIFYATBOOT) {
- LINFO << "Verifying partition " << fstab->blk_device << " at boot";
+ if (entry->fs_mgr_flags.verify_at_boot) {
+ LINFO << "Verifying partition " << entry->blk_device << " at boot";
int err = read_partition(verity_blk_name.c_str(), verity.data_size);
if (!err) {
- LINFO << "Verified verity partition "
- << fstab->blk_device << " at boot";
+ LINFO << "Verified verity partition " << entry->blk_device << " at boot";
verified_at_boot = true;
}
}
// assign the new verity block device as the block device
if (!verified_at_boot) {
- free(fstab->blk_device);
- fstab->blk_device = strdup(verity_blk_name.c_str());
+ entry->blk_device = verity_blk_name;
} else if (!dm.DeleteDevice(mount_point)) {
LERROR << "Failed to remove verity device " << mount_point.c_str();
goto out;
}
// make sure we've set everything up properly
- if (wait_for_verity_dev && !fs_mgr_wait_for_file(fstab->blk_device, 1s)) {
+ if (wait_for_verity_dev && !fs_mgr_wait_for_file(entry->blk_device, 1s)) {
goto out;
}
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 1049fb6..e87332f 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -23,6 +23,7 @@
#include <linux/dm-ioctl.h>
#include <functional>
+#include <string>
#include <fstab/fstab.h>
@@ -49,10 +50,6 @@
MOUNT_MODE_LATE = 2
};
-// Callback function for verity status
-typedef void fs_mgr_verity_state_callback(struct fstab_rec* fstab, const char* mount_point,
- int mode, int status);
-
#define FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED 7
#define FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION 6
#define FS_MGR_MNTALL_DEV_FILE_ENCRYPTED 5
@@ -62,29 +59,40 @@
#define FS_MGR_MNTALL_DEV_NOT_ENCRYPTED 1
#define FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE 0
#define FS_MGR_MNTALL_FAIL (-1)
-int fs_mgr_mount_all(struct fstab *fstab, int mount_mode);
+// fs_mgr_mount_all() updates fstab entries that reference device-mapper.
+int fs_mgr_mount_all(Fstab* fstab, int mount_mode);
#define FS_MGR_DOMNT_FAILED (-1)
#define FS_MGR_DOMNT_BUSY (-2)
#define FS_MGR_DOMNT_SUCCESS 0
-int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
- char *tmp_mount_point);
-int fs_mgr_do_mount_one(struct fstab_rec *rec);
+int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point);
+int fs_mgr_do_mount(fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
+ bool need_cp);
+int fs_mgr_do_mount_one(const FstabEntry& entry, const std::string& mount_point = "");
+int fs_mgr_do_mount_one(fstab_rec* rec);
int fs_mgr_do_tmpfs_mount(const char *n_name);
-struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab);
-void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size);
+fstab_rec const* fs_mgr_get_crypt_entry(fstab const* fstab);
+void fs_mgr_get_crypt_info(fstab* fstab, char* key_loc, char* real_blk_device, size_t size);
bool fs_mgr_load_verity_state(int* mode);
-bool fs_mgr_update_verity_state(std::function<fs_mgr_verity_state_callback> callback);
-int fs_mgr_swapon_all(struct fstab *fstab);
+bool fs_mgr_update_verity_state(
+ std::function<void(const std::string& mount_point, int mode)> callback);
+bool fs_mgr_swapon_all(const Fstab& fstab);
+bool fs_mgr_update_logical_partition(FstabEntry* entry);
bool fs_mgr_update_logical_partition(struct fstab_rec* rec);
-int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer);
+int fs_mgr_do_format(const FstabEntry& entry, bool reserve_footer);
+int fs_mgr_do_format(fstab_rec* rec, bool reserve_footer);
#define FS_MGR_SETUP_VERITY_SKIPPED (-3)
#define FS_MGR_SETUP_VERITY_DISABLED (-2)
#define FS_MGR_SETUP_VERITY_FAIL (-1)
#define FS_MGR_SETUP_VERITY_SUCCESS 0
-int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev);
+int fs_mgr_setup_verity(FstabEntry* fstab, bool wait_for_verity_dev);
+
+// Return the name of the super partition if it exists. If a slot number is
+// specified, the super partition for the corresponding metadata slot will be
+// returned. Otherwise, it will use the current slot.
+std::string fs_mgr_get_super_partition_name(int slot = -1);
#endif /* __CORE_FS_MGR_H */
diff --git a/fs_mgr/include/fs_mgr/roots.h b/fs_mgr/include/fs_mgr/roots.h
new file mode 100644
index 0000000..65c59cf
--- /dev/null
+++ b/fs_mgr/include/fs_mgr/roots.h
@@ -0,0 +1,52 @@
+/*
+ * 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>
+
+#include <fs_mgr.h>
+
+namespace android {
+namespace fs_mgr {
+
+// Finds the volume specified by the given path. fs_mgr_get_entry_for_mount_point() does exact match
+// only, so it attempts the prefixes recursively (e.g. "/cache/recovery/last_log",
+// "/cache/recovery", "/cache", "/" for a given path of "/cache/recovery/last_log") and returns the
+// first match or nullptr.
+FstabEntry* GetEntryForPath(Fstab* fstab, const std::string& path);
+
+// Make sure that the volume 'path' is on is mounted.
+// * If 'mount_point' is nullptr, use mount point in fstab. Caller can call
+// fs_mgr_ensure_path_unmounted() with the same 'path' argument to unmount.
+// * If 'mount_point' is not nullptr, the mount point is overridden. Caller can
+// call umount(mount_point) to unmount.
+// Returns true on success (volume is mounted).
+bool EnsurePathMounted(Fstab* fstab, const std::string& path, const std::string& mount_point = "");
+
+// Make sure that the volume 'path' is on is unmounted. Returns true on
+// success (volume is unmounted).
+bool EnsurePathUnmounted(Fstab* fstab, const std::string& path);
+
+// Return "/system" if it is in default fstab, otherwise "/".
+std::string GetSystemRoot();
+
+// Return true iff logical partitions are mapped when partitions are mounted via ensure_path_mounted
+// functions.
+bool LogicalPartitionsMapped();
+
+} // 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 f15c450..f33fc02 100644
--- a/fs_mgr/include/fs_mgr_dm_linear.h
+++ b/fs_mgr/include/fs_mgr_dm_linear.h
@@ -27,28 +27,48 @@
#include <stdint.h>
+#include <chrono>
#include <memory>
#include <string>
#include <vector>
#include <libdm/dm.h>
-#include <liblp/metadata_format.h>
+#include <liblp/liblp.h>
namespace android {
namespace fs_mgr {
+// Read metadata from the current slot.
+std::unique_ptr<LpMetadata> ReadCurrentMetadata(const std::string& block_device);
+
+// Create block devices for all logical partitions in the given metadata. The
+// metadata must have been read from the current slot.
+bool CreateLogicalPartitions(const LpMetadata& metadata, const std::string& block_device);
+
+// Create block devices for all logical partitions. This is a convenience
+// 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,
- std::string* path);
+ const std::chrono::milliseconds& timeout_ms, std::string* path);
-// Destroy the block device for a logical partition, by name.
-bool DestroyLogicalPartition(const std::string& name);
+// 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);
+
+// 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);
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h
index ceb45de..4bf2238 100644
--- a/fs_mgr/include/fs_mgr_overlayfs.h
+++ b/fs_mgr/include/fs_mgr_overlayfs.h
@@ -19,9 +19,20 @@
#include <fstab/fstab.h>
#include <string>
+#include <vector>
-bool fs_mgr_overlayfs_mount_all();
+bool fs_mgr_overlayfs_mount_all(Fstab* fstab);
+std::vector<std::string> fs_mgr_overlayfs_required_devices(Fstab* fstab);
bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,
bool* change = nullptr);
bool fs_mgr_overlayfs_teardown(const char* mount_point = nullptr, bool* change = nullptr);
+bool fs_mgr_overlayfs_is_setup();
bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev);
+std::string fs_mgr_get_context(const std::string& mount_point);
+
+enum class OverlayfsValidResult {
+ kNotSupported = 0,
+ kOk,
+ kOverrideCredsRequired,
+};
+OverlayfsValidResult fs_mgr_overlayfs_valid();
diff --git a/libbacktrace/GetPss.h b/fs_mgr/include/fs_mgr_vendor_overlay.h
similarity index 75%
copy from libbacktrace/GetPss.h
copy to fs_mgr/include/fs_mgr_vendor_overlay.h
index 787c33d..9771a0c 100644
--- a/libbacktrace/GetPss.h
+++ b/fs_mgr/include/fs_mgr_vendor_overlay.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-#ifndef _LIBBACKTRACE_GET_PSS_H
-#define _LIBBACKTRACE_GET_PSS_H
+#pragma once
-size_t GetPssBytes();
+#include <fstab/fstab.h>
-#endif // _LIBBACKTRACE_GET_PSS_H
+bool fs_mgr_vendor_overlay_mount_all();
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index b1ee328..4a05949 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -14,16 +14,17 @@
* limitations under the License.
*/
-#ifndef __CORE_FS_TAB_H
-#define __CORE_FS_TAB_H
+#pragma once
#include <linux/dm-ioctl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
+#include <sys/types.h>
#include <set>
#include <string>
+#include <vector>
/*
* The entries must be kept in the same order as they were seen in the fstab.
@@ -42,22 +43,25 @@
char* fs_type;
unsigned long flags;
char* fs_options;
- int fs_mgr_flags;
+ uint64_t fs_mgr_flags;
char* key_loc;
char* key_dir;
char* verity_loc;
- long long length;
+ off64_t length;
char* label;
int partnum;
int swap_prio;
int max_comp_streams;
- unsigned int zram_size;
- uint64_t reserved_size;
- unsigned int file_contents_mode;
- unsigned int file_names_mode;
- unsigned int erase_blk_size;
- unsigned int logical_blk_size;
+ off64_t zram_size;
+ off64_t reserved_size;
+ int file_contents_mode;
+ int file_names_mode;
+ off64_t erase_blk_size;
+ off64_t logical_blk_size;
char* sysfs_path;
+ char* zram_loopback_path;
+ uint64_t zram_loopback_size;
+ char* zram_backing_dev_path;
};
struct fstab* fs_mgr_read_fstab_default();
@@ -83,12 +87,117 @@
int fs_mgr_is_formattable(const struct fstab_rec* fstab);
int fs_mgr_is_slotselect(const struct fstab_rec* fstab);
int fs_mgr_is_nofail(const struct fstab_rec* fstab);
+int fs_mgr_is_first_stage_mount(const struct fstab_rec* fstab);
int fs_mgr_is_latemount(const struct fstab_rec* fstab);
int fs_mgr_is_quota(const struct fstab_rec* fstab);
int fs_mgr_is_logical(const struct fstab_rec* fstab);
+int fs_mgr_is_checkpoint(const struct fstab_rec* fstab);
+int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab);
+int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab);
int fs_mgr_has_sysfs_path(const struct fstab_rec* fstab);
+int fs_mgr_is_fs_verity(const struct fstab_rec* fstab);
std::string fs_mgr_get_slot_suffix();
std::set<std::string> fs_mgr_get_boot_devices();
-#endif /* __CORE_FS_TAB_H */
+struct FstabEntry {
+ std::string blk_device;
+ std::string logical_partition_name;
+ std::string mount_point;
+ std::string fs_type;
+ unsigned long flags = 0;
+ 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;
+ int swap_prio = -1;
+ int max_comp_streams = 0;
+ off64_t zram_size = 0;
+ off64_t reserved_size = 0;
+ int file_contents_mode = 0;
+ int file_names_mode = 0;
+ off64_t erase_blk_size = 0;
+ off64_t logical_blk_size = 0;
+ std::string sysfs_path;
+ std::string vbmeta_partition;
+ std::string zram_loopback_path;
+ uint64_t zram_loopback_size;
+ std::string zram_backing_dev_path;
+
+ // TODO: Remove this union once fstab_rec is deprecated. It only serves as a
+ // convenient way to convert between fstab_rec::fs_mgr_flags and these bools.
+ union {
+ uint64_t val;
+ struct {
+ // bit 0
+ bool wait : 1;
+ bool check : 1;
+ bool crypt : 1;
+ bool nonremovable : 1;
+ bool vold_managed : 1;
+ bool length : 1;
+ bool recovery_only : 1;
+ bool swap_prio : 1;
+
+ // bit 8
+ bool zram_size : 1;
+ bool verify : 1;
+ bool force_crypt : 1;
+ bool no_emulated_sd : 1; // No emulated sdcard daemon; sd card is the only external
+ // storage.
+ bool no_trim : 1;
+ bool file_encryption : 1;
+ bool formattable : 1;
+ bool slot_select : 1;
+
+ // bit 16
+ bool force_fde_or_fbe : 1;
+ bool late_mount : 1;
+ bool no_fail : 1;
+ bool verify_at_boot : 1;
+ bool max_comp_streams : 1;
+ bool reserved_size : 1;
+ bool quota : 1;
+ bool erase_blk_size : 1;
+
+ // bit 24
+ bool logical_blk_size : 1;
+ bool avb : 1;
+ bool key_directory : 1;
+ bool sysfs : 1;
+ bool logical : 1;
+ bool checkpoint_blk : 1;
+ bool checkpoint_fs : 1;
+ bool first_stage_mount : 1;
+
+ // bit 32
+ bool slot_select_other : 1;
+ bool zram_loopback_path : 1;
+ bool zram_loopback_size : 1;
+ bool zram_backing_dev_path : 1;
+ bool fs_verity : 1;
+ };
+ } fs_mgr_flags;
+
+ bool is_encryptable() const {
+ return fs_mgr_flags.crypt || fs_mgr_flags.force_crypt || fs_mgr_flags.force_fde_or_fbe;
+ }
+};
+
+// An Fstab is a collection of FstabEntry structs.
+using Fstab = std::vector<FstabEntry>;
+
+bool ReadFstabFromFile(const std::string& path, Fstab* fstab);
+bool ReadFstabFromDt(Fstab* fstab);
+bool ReadDefaultFstab(Fstab* fstab);
+
+// Temporary conversion functions.
+FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec);
+Fstab LegacyFstabToFstab(const struct fstab* legacy_fstab);
+fstab* FstabToLegacyFstab(const Fstab& fstab);
+
+// Helper method to build a GSI fstab entry for mounting /system.
+FstabEntry BuildGsiSystemFstabEntry();
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index 22af123..c8c2d83 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -18,12 +18,9 @@
name: "libdm",
defaults: ["fs_mgr_defaults"],
recovery_available: true,
+ host_supported: true,
export_include_dirs: ["include"],
- cflags: [
- // TODO(b/110035986): Allows us to create a skeleton of required classes
- "-Wno-unused-private-field",
- ],
srcs: [
"dm_table.cpp",
@@ -36,6 +33,11 @@
"libbase_headers",
"liblog_headers",
],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
}
cc_test {
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index 2b526f6..c6a9e0b 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -203,7 +203,8 @@
}
next += vers->next;
data_size -= vers->next;
- vers = reinterpret_cast<struct dm_target_versions*>(static_cast<char*>(buffer.get()) + next);
+ vers = reinterpret_cast<struct dm_target_versions*>(static_cast<char*>(buffer.get()) +
+ next);
}
return true;
@@ -278,7 +279,7 @@
struct dm_ioctl io;
InitIo(&io, name);
if (ioctl(fd_, DM_DEV_STATUS, &io) < 0) {
- PLOG(ERROR) << "DM_DEV_STATUS failed for " << name;
+ PLOG(WARNING) << "DM_DEV_STATUS failed for " << name;
return false;
}
@@ -288,12 +289,23 @@
}
bool DeviceMapper::GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) {
+ return GetTable(name, 0, table);
+}
+
+bool DeviceMapper::GetTableInfo(const std::string& name, std::vector<TargetInfo>* table) {
+ return GetTable(name, DM_STATUS_TABLE_FLAG, table);
+}
+
+// private methods of DeviceMapper
+bool DeviceMapper::GetTable(const std::string& name, uint32_t flags,
+ std::vector<TargetInfo>* table) {
char buffer[4096];
struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer);
InitIo(io, name);
io->data_size = sizeof(buffer);
io->data_start = sizeof(*io);
+ io->flags = flags;
if (ioctl(fd_, DM_TABLE_STATUS, io) < 0) {
PLOG(ERROR) << "DM_TABLE_STATUS failed for " << name;
return false;
@@ -327,7 +339,6 @@
return true;
}
-// private methods of DeviceMapper
void DeviceMapper::InitIo(struct dm_ioctl* io, const std::string& name) const {
CHECK(io != nullptr) << "nullptr passed to dm_ioctl initialization";
memset(io, 0, sizeof(*io));
@@ -338,7 +349,7 @@
io->data_size = sizeof(*io);
io->data_start = 0;
if (!name.empty()) {
- strlcpy(io->name, name.c_str(), sizeof(io->name));
+ snprintf(io->name, sizeof(io->name), "%s", name.c_str());
}
}
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 7c18267..cb33eea 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -42,7 +42,7 @@
struct dm_target_spec* spec = reinterpret_cast<struct dm_target_spec*>(&data[0]);
spec->sector_start = start();
spec->length = size();
- strlcpy(spec->target_type, name().c_str(), sizeof(spec->target_type));
+ snprintf(spec->target_type, sizeof(spec->target_type), "%s", name().c_str());
spec->next = (uint32_t)data.size();
return data;
}
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index cc61917..70823c6 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -59,7 +59,8 @@
: dm_(DeviceMapper::Instance()), name_(name), valid_(false) {
valid_ = dm_.CreateDevice(name, table);
}
- TempDevice(TempDevice&& other) : dm_(other.dm_), name_(other.name_), valid_(other.valid_) {
+ TempDevice(TempDevice&& other) noexcept
+ : dm_(other.dm_), name_(other.name_), valid_(other.valid_) {
other.valid_ = false;
}
~TempDevice() {
@@ -103,7 +104,7 @@
TempDevice(const TempDevice&) = delete;
TempDevice& operator=(const TempDevice&) = delete;
- TempDevice& operator=(TempDevice&& other) {
+ TempDevice& operator=(TempDevice&& other) noexcept {
name_ = other.name_;
valid_ = other.valid_;
other.valid_ = false;
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 91f8bb4..28e6e01 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -128,6 +128,10 @@
};
bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table);
+ // Identical to GetTableStatus, except also retrives the active table for the device
+ // mapper device from the kernel.
+ bool GetTableInfo(const std::string& name, std::vector<TargetInfo>* table);
+
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
@@ -140,6 +144,8 @@
// limit we are imposing here of 256.
static constexpr uint32_t kMaxPossibleDmDevices = 256;
+ 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();
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index aab89e5..175b0f0 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -156,6 +156,20 @@
std::string target_string_;
};
+// dm-bow is the backup on write target that can provide checkpoint capability
+// for file systems that do not support checkpoints natively
+class DmTargetBow final : public DmTarget {
+ public:
+ DmTargetBow(uint64_t start, uint64_t length, const std::string& target_string)
+ : DmTarget(start, length), target_string_(target_string) {}
+
+ std::string name() const override { return "bow"; }
+ std::string GetParameterString() const override { return target_string_; }
+
+ private:
+ std::string target_string_;
+};
+
} // namespace dm
} // namespace android
diff --git a/fs_mgr/libfiemap_writer/.clang-format b/fs_mgr/libfiemap_writer/.clang-format
new file mode 120000
index 0000000..8b770a1
--- /dev/null
+++ b/fs_mgr/libfiemap_writer/.clang-format
@@ -0,0 +1 @@
+../../.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
new file mode 100644
index 0000000..33c3cad
--- /dev/null
+++ b/fs_mgr/libfiemap_writer/Android.bp
@@ -0,0 +1,56 @@
+//
+// 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: [
+ // TODO(b/121211685): Allows us to create a skeleton of required classes
+ "-Wno-unused-private-field",
+ "-Wno-unused-parameter",
+ ],
+
+ srcs: [
+ "fiemap_writer.cpp",
+ ],
+
+ header_libs: [
+ "libbase_headers",
+ "liblog_headers",
+ ],
+}
+
+cc_test {
+ name: "fiemap_writer_test",
+ 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/fiemap_writer.cpp b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
new file mode 100644
index 0000000..164fc91
--- /dev/null
+++ b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
@@ -0,0 +1,645 @@
+/*
+ * 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 <libfiemap_writer/fiemap_writer.h>
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+
+#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>
+
+namespace android {
+namespace fiemap_writer {
+
+// 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;
+
+// TODO: Fallback to using fibmap if FIEMAP_EXTENT_MERGED is set.
+static constexpr const uint32_t kUnsupportedExtentFlags =
+ FIEMAP_EXTENT_UNKNOWN | FIEMAP_EXTENT_UNWRITTEN | FIEMAP_EXTENT_DELALLOC |
+ FIEMAP_EXTENT_NOT_ALIGNED | FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_DATA_TAIL |
+ FIEMAP_EXTENT_UNWRITTEN | FIEMAP_EXTENT_SHARED | FIEMAP_EXTENT_MERGED;
+
+static inline void cleanup(const std::string& file_path, bool created) {
+ if (created) {
+ unlink(file_path.c_str());
+ }
+}
+
+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;
+ 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;
+}
+
+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;
+ return true;
+ }
+
+ std::string dm_leaf_dir = ::android::base::StringPrintf("/sys/block/%s/slaves", bdev.c_str());
+ 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;
+ return false;
+ }
+
+ struct dirent* de;
+ uint32_t num_leaves = 0;
+ std::string bdev_next = "";
+ while ((de = readdir(d.get())) != nullptr) {
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
+ continue;
+ }
+
+ // We set the first name we find here
+ if (bdev_next.empty()) {
+ bdev_next = de->d_name;
+ }
+ num_leaves++;
+ }
+
+ // if we have more than one leaves, we return immediately. We can't continue to create the
+ // file since we don't know how to write it out using fiemap, so it will be readable via the
+ // underlying block devices later. The reader will also have to construct the same device mapper
+ // target in order read the file out.
+ if (num_leaves > 1) {
+ LOG(ERROR) << "Found " << num_leaves << " leaf block devices under device mapper device "
+ << bdev;
+ return false;
+ }
+
+ // recursively call with the block device we found in order to pop the device mapper stack.
+ return DeviceMapperStackPop(bdev_next, bdev_raw);
+}
+
+static bool FileToBlockDevicePath(const std::string& file_path, std::string* bdev_path) {
+ struct stat sb;
+ if (stat(file_path.c_str(), &sb)) {
+ PLOG(ERROR) << "Failed to get stat for: " << file_path;
+ return false;
+ }
+
+ std::string bdev;
+ if (!BlockDeviceToName(major(sb.st_dev), minor(sb.st_dev), &bdev)) {
+ LOG(ERROR) << "Failed to get block device name for " << major(sb.st_dev) << ":"
+ << minor(sb.st_dev);
+ return false;
+ }
+
+ std::string bdev_raw;
+ if (!DeviceMapperStackPop(bdev, &bdev_raw)) {
+ LOG(ERROR) << "Failed to get the bottom of the device mapper stack for device: " << bdev;
+ return false;
+ }
+
+ LOG(DEBUG) << "Popped device (" << bdev_raw << ") from device mapper stack starting with ("
+ << bdev << ")";
+
+ *bdev_path = ::android::base::StringPrintf("/dev/block/%s", bdev_raw.c_str());
+
+ // Make sure we are talking to a block device before calling it a success.
+ if (stat(bdev_path->c_str(), &sb)) {
+ PLOG(ERROR) << "Failed to get stat for block device: " << *bdev_path;
+ return false;
+ }
+
+ if ((sb.st_mode & S_IFMT) != S_IFBLK) {
+ PLOG(ERROR) << "File: " << *bdev_path << " is not a block device";
+ return false;
+ }
+
+ return true;
+}
+
+static bool GetBlockDeviceSize(int bdev_fd, const std::string& bdev_path, uint64_t* bdev_size) {
+ uint64_t size_in_bytes = 0;
+ if (ioctl(bdev_fd, BLKGETSIZE64, &size_in_bytes)) {
+ PLOG(ERROR) << "Failed to get total size for: " << bdev_path;
+ return false;
+ }
+
+ *bdev_size = size_in_bytes;
+
+ return true;
+}
+
+static uint64_t GetFileSize(const std::string& file_path) {
+ struct stat sb;
+ if (stat(file_path.c_str(), &sb)) {
+ PLOG(ERROR) << "Failed to get size for file: " << file_path;
+ return 0;
+ }
+
+ return sb.st_size;
+}
+
+static bool PerformFileChecks(const std::string& file_path, uint64_t file_size, 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;
+ return false;
+ }
+
+ if (file_size % sfs.f_bsize) {
+ LOG(ERROR) << "File size " << file_size << " is not aligned to optimal block size "
+ << sfs.f_bsize << " for file " << file_path;
+ return false;
+ }
+
+ // Check if the filesystem is of supported types.
+ // Only ext4 and f2fs are tested and supported.
+ if ((sfs.f_type != EXT4_SUPER_MAGIC) && (sfs.f_type != F2FS_SUPER_MAGIC)) {
+ LOG(ERROR) << "Unsupported file system type: 0x" << std::hex << sfs.f_type;
+ 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;
+}
+
+static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blocksz,
+ uint64_t file_size, 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.
+ 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;
+ }
+
+ // 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.
+ auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, blocksz), free);
+ if (buffer == nullptr) {
+ LOG(ERROR) << "failed to allocate memory for writing file";
+ return false;
+ }
+
+ off64_t offset = lseek64(file_fd, 0, SEEK_SET);
+ if (offset < 0) {
+ PLOG(ERROR) << "Failed to seek at the beginning of : " << file_path;
+ return false;
+ }
+
+ int permille = -1;
+ for (; offset < file_size; offset += blocksz) {
+ if (!::android::base::WriteFully(file_fd, buffer.get(), blocksz)) {
+ PLOG(ERROR) << "Failed to write" << blocksz << " bytes at offset" << offset
+ << " in file " << file_path;
+ return false;
+ }
+ // Don't invoke the callback every iteration - wait until a significant
+ // chunk (here, 1/1000th) of the data has been processed.
+ int new_permille = (static_cast<uint64_t>(offset) * 1000) / file_size;
+ if (new_permille != permille) {
+ if (on_progress && !on_progress(offset, file_size)) {
+ return false;
+ }
+ permille = new_permille;
+ }
+ }
+
+ if (lseek64(file_fd, 0, SEEK_SET) < 0) {
+ PLOG(ERROR) << "Failed to reset offset at the beginning of : " << file_path;
+ return false;
+ }
+
+ // flush all writes here ..
+ if (fsync(file_fd)) {
+ PLOG(ERROR) << "Failed to synchronize written file:" << file_path;
+ return false;
+ }
+
+ // Send one last progress notification.
+ if (on_progress && !on_progress(file_size, file_size)) {
+ return false;
+ }
+ return true;
+}
+
+static bool PinFile(int file_fd, const std::string& file_path, uint32_t fs_type) {
+ if (fs_type == EXT4_SUPER_MAGIC) {
+ // No pinning necessary for ext4. 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 == EXT4_SUPER_MAGIC) {
+ // No pinning necessary for ext4. 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_IOC_GET_PIN_FILE returns the number of blocks moved.
+ uint32_t moved_blocks_nr;
+ int 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;
+}
+
+static void LogExtent(uint32_t num, const struct fiemap_extent& ext) {
+ LOG(INFO) << "Extent #" << num;
+ LOG(INFO) << " fe_logical: " << ext.fe_logical;
+ LOG(INFO) << " fe_physical: " << ext.fe_physical;
+ LOG(INFO) << " fe_length: " << ext.fe_length;
+ LOG(INFO) << " fe_flags: 0x" << std::hex << ext.fe_flags;
+}
+
+static bool ReadFiemap(int file_fd, const std::string& file_path,
+ std::vector<struct fiemap_extent>* extents) {
+ uint64_t fiemap_size =
+ sizeof(struct fiemap_extent) + kMaxExtents * 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";
+ return false;
+ }
+
+ struct fiemap* fiemap = reinterpret_cast<struct fiemap*>(buffer.get());
+ fiemap->fm_start = 0;
+ 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;
+
+ 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";
+ 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;
+}
+
+FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_size, bool create,
+ std::function<bool(uint64_t, uint64_t)> progress) {
+ // if 'create' is false, open an existing file and do not truncate.
+ int open_flags = O_RDWR | O_CLOEXEC;
+ if (create) {
+ if (access(file_path.c_str(), F_OK) == 0) {
+ LOG(WARNING) << "File " << file_path << " already exists, truncating";
+ }
+ open_flags |= O_CREAT | O_TRUNC;
+ }
+ ::android::base::unique_fd file_fd(
+ TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags, S_IRUSR | S_IWUSR)));
+ if (file_fd < 0) {
+ PLOG(ERROR) << "Failed to create file at: " << file_path;
+ return nullptr;
+ }
+
+ std::string abs_path;
+ if (!::android::base::Realpath(file_path, &abs_path)) {
+ PLOG(ERROR) << "Invalid file path: " << file_path;
+ cleanup(file_path, create);
+ return nullptr;
+ }
+
+ std::string bdev_path;
+ if (!FileToBlockDevicePath(abs_path, &bdev_path)) {
+ LOG(ERROR) << "Failed to get block dev path for file: " << file_path;
+ cleanup(abs_path, create);
+ return nullptr;
+ }
+
+ ::android::base::unique_fd bdev_fd(
+ TEMP_FAILURE_RETRY(open(bdev_path.c_str(), O_RDWR | O_CLOEXEC)));
+ if (bdev_fd < 0) {
+ PLOG(ERROR) << "Failed to open block device: " << bdev_path;
+ cleanup(file_path, create);
+ return nullptr;
+ }
+
+ uint64_t bdevsz;
+ if (!GetBlockDeviceSize(bdev_fd, bdev_path, &bdevsz)) {
+ LOG(ERROR) << "Failed to get block device size for : " << bdev_path;
+ cleanup(file_path, create);
+ return nullptr;
+ }
+
+ if (!create) {
+ file_size = GetFileSize(abs_path);
+ if (file_size == 0) {
+ LOG(ERROR) << "Invalid file size of zero bytes for file: " << abs_path;
+ return nullptr;
+ }
+ }
+
+ uint64_t blocksz;
+ uint32_t fs_type;
+ if (!PerformFileChecks(abs_path, file_size, &blocksz, &fs_type)) {
+ LOG(ERROR) << "Failed to validate file or file system for file:" << abs_path;
+ cleanup(abs_path, create);
+ return nullptr;
+ }
+
+ if (create) {
+ if (!AllocateFile(file_fd, abs_path, blocksz, file_size, std::move(progress))) {
+ LOG(ERROR) << "Failed to allocate file: " << abs_path << " of size: " << file_size
+ << " bytes";
+ cleanup(abs_path, create);
+ return nullptr;
+ }
+ }
+
+ // f2fs may move the file blocks around.
+ if (!PinFile(file_fd, abs_path, fs_type)) {
+ cleanup(abs_path, create);
+ LOG(ERROR) << "Failed to pin the file in storage";
+ return nullptr;
+ }
+
+ // now allocate the FiemapWriter and start setting it up
+ FiemapUniquePtr fmap(new FiemapWriter());
+ if (!ReadFiemap(file_fd, abs_path, &fmap->extents_)) {
+ LOG(ERROR) << "Failed to read fiemap of file: " << abs_path;
+ cleanup(abs_path, create);
+ return nullptr;
+ }
+
+ fmap->file_path_ = abs_path;
+ fmap->bdev_path_ = bdev_path;
+ fmap->file_fd_ = std::move(file_fd);
+ fmap->bdev_fd_ = std::move(bdev_fd);
+ fmap->file_size_ = file_size;
+ fmap->bdev_size_ = bdevsz;
+ fmap->fs_type_ = fs_type;
+ fmap->block_size_ = blocksz;
+
+ LOG(INFO) << "Successfully created FiemapWriter for file " << abs_path << " on block device "
+ << bdev_path;
+ return fmap;
+}
+
+bool FiemapWriter::Flush() const {
+ if (fsync(bdev_fd_)) {
+ PLOG(ERROR) << "Failed to flush " << bdev_path_ << " with fsync";
+ return false;
+ }
+ return true;
+}
+
+// TODO: Test with fs block_size > bdev block_size
+bool FiemapWriter::Write(off64_t off, uint8_t* buffer, uint64_t size) {
+ if (!size || size > file_size_) {
+ LOG(ERROR) << "Failed write: size " << size << " is invalid for file's size " << file_size_;
+ return false;
+ }
+
+ if (off + size > file_size_) {
+ LOG(ERROR) << "Failed write: Invalid offset " << off << " or size " << size
+ << " for file size " << file_size_;
+ return false;
+ }
+
+ if ((off & (block_size_ - 1)) || (size & (block_size_ - 1))) {
+ LOG(ERROR) << "Failed write: Unaligned offset " << off << " or size " << size
+ << " for block size " << block_size_;
+ return false;
+ }
+
+ if (!IsFilePinned(file_fd_, file_path_, fs_type_)) {
+ LOG(ERROR) << "Failed write: file " << file_path_ << " is not pinned";
+ return false;
+ }
+
+ // find extents that must be written to and then write one at a time.
+ uint32_t num_extent = 1;
+ uint32_t buffer_offset = 0;
+ for (auto& extent : extents_) {
+ uint64_t e_start = extent.fe_logical;
+ uint64_t e_end = extent.fe_logical + extent.fe_length;
+ // Do we write in this extent ?
+ if (off >= e_start && off < e_end) {
+ uint64_t written = WriteExtent(extent, buffer + buffer_offset, off, size);
+ if (written == 0) {
+ return false;
+ }
+
+ buffer_offset += written;
+ off += written;
+ size -= written;
+
+ // Paranoid check to make sure we are done with this extent now
+ if (size && (off >= e_start && off < e_end)) {
+ LOG(ERROR) << "Failed to write extent fully";
+ LogExtent(num_extent, extent);
+ return false;
+ }
+
+ if (size == 0) {
+ // done
+ break;
+ }
+ }
+ num_extent++;
+ }
+
+ return true;
+}
+
+bool FiemapWriter::Read(off64_t off, uint8_t* buffer, uint64_t size) {
+ return false;
+}
+
+// private helpers
+
+// WriteExtent() Returns the total number of bytes written. It will always be multiple of
+// block_size_. 0 is returned in one of the two cases.
+// 1. Any write failed between logical_off & logical_off + length.
+// 2. The logical_offset + length doesn't overlap with the extent passed.
+// The function can either partially for fully write the extent depending on the
+// logical_off + length. It is expected that alignment checks for size and offset are
+// performed before calling into this function.
+uint64_t FiemapWriter::WriteExtent(const struct fiemap_extent& ext, uint8_t* buffer,
+ off64_t logical_off, uint64_t length) {
+ uint64_t e_start = ext.fe_logical;
+ uint64_t e_end = ext.fe_logical + ext.fe_length;
+ if (logical_off < e_start || logical_off >= e_end) {
+ LOG(ERROR) << "Failed write extent, invalid offset " << logical_off << " and size "
+ << length;
+ LogExtent(0, ext);
+ return 0;
+ }
+
+ off64_t bdev_offset = ext.fe_physical + (logical_off - e_start);
+ if (bdev_offset >= bdev_size_) {
+ LOG(ERROR) << "Failed write extent, invalid block # " << bdev_offset << " for block device "
+ << bdev_path_ << " of size " << bdev_size_ << " bytes";
+ return 0;
+ }
+ if (TEMP_FAILURE_RETRY(lseek64(bdev_fd_, bdev_offset, SEEK_SET)) == -1) {
+ PLOG(ERROR) << "Failed write extent, seek offset for " << bdev_path_ << " offset "
+ << bdev_offset;
+ return 0;
+ }
+
+ // Determine how much we want to write at once.
+ uint64_t logical_end = logical_off + length;
+ uint64_t write_size = (e_end <= logical_end) ? (e_end - logical_off) : length;
+ if (!android::base::WriteFully(bdev_fd_, buffer, write_size)) {
+ PLOG(ERROR) << "Failed write extent, write " << bdev_path_ << " at " << bdev_offset
+ << " size " << write_size;
+ return 0;
+ }
+
+ return write_size;
+}
+
+} // namespace fiemap_writer
+} // namespace android
diff --git a/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp b/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
new file mode 100644
index 0000000..5101537
--- /dev/null
+++ b/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
@@ -0,0 +1,389 @@
+/*
+ * 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 <fcntl.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.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 <gtest/gtest.h>
+#include <libdm/loop_control.h>
+
+#include <libfiemap_writer/fiemap_writer.h>
+
+using namespace std;
+using namespace android::fiemap_writer;
+using unique_fd = android::base::unique_fd;
+using LoopDevice = android::dm::LoopDevice;
+
+std::string testbdev = "";
+uint64_t testfile_size = 536870912; // default of 512MiB
+
+class FiemapWriterTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ const ::testing::TestInfo* tinfo = ::testing::UnitTest::GetInstance()->current_test_info();
+ std::string exec_dir = ::android::base::GetExecutableDirectory();
+ testfile = ::android::base::StringPrintf("%s/testdata/%s", exec_dir.c_str(), tinfo->name());
+ }
+
+ // name of the file we use for testing
+ std::string testfile;
+};
+
+TEST_F(FiemapWriterTest, CreateImpossiblyLargeFile) {
+ // Try creating a file of size ~100TB but aligned to
+ // 512 byte to make sure block alignment tests don't
+ // fail.
+ FiemapUniquePtr fptr = FiemapWriter::Open(testfile, 1099511627997184);
+ EXPECT_EQ(fptr, nullptr);
+ EXPECT_EQ(access(testfile.c_str(), F_OK), -1);
+ EXPECT_EQ(errno, ENOENT);
+}
+
+TEST_F(FiemapWriterTest, CreateUnalignedFile) {
+ // Try creating a file of size 4097 bytes which is guaranteed
+ // to be unaligned to all known block sizes. The creation must
+ // fail.
+ FiemapUniquePtr fptr = FiemapWriter::Open(testfile, 4097);
+ EXPECT_EQ(fptr, nullptr);
+ EXPECT_EQ(access(testfile.c_str(), F_OK), -1);
+ EXPECT_EQ(errno, ENOENT);
+}
+
+TEST_F(FiemapWriterTest, CheckFilePath) {
+ FiemapUniquePtr fptr = FiemapWriter::Open(testfile, 4096);
+ ASSERT_NE(fptr, nullptr);
+ EXPECT_EQ(fptr->size(), 4096);
+ EXPECT_EQ(fptr->file_path(), testfile);
+ EXPECT_EQ(access(testfile.c_str(), F_OK), 0);
+}
+
+TEST_F(FiemapWriterTest, CheckProgress) {
+ std::vector<uint64_t> expected{
+ 0,
+ 4096,
+ };
+ size_t invocations = 0;
+ auto callback = [&](uint64_t done, uint64_t total) -> bool {
+ EXPECT_LT(invocations, expected.size());
+ EXPECT_EQ(done, expected[invocations]);
+ EXPECT_EQ(total, 4096);
+ invocations++;
+ return true;
+ };
+
+ auto ptr = FiemapWriter::Open(testfile, 4096, true, std::move(callback));
+ EXPECT_NE(ptr, nullptr);
+ EXPECT_EQ(invocations, 2);
+}
+
+TEST_F(FiemapWriterTest, CheckBlockDevicePath) {
+ FiemapUniquePtr fptr = FiemapWriter::Open(testfile, 4096);
+ EXPECT_EQ(fptr->size(), 4096);
+ EXPECT_EQ(fptr->bdev_path(), testbdev);
+}
+
+TEST_F(FiemapWriterTest, CheckFileCreated) {
+ FiemapUniquePtr fptr = FiemapWriter::Open(testfile, 32768);
+ ASSERT_NE(fptr, nullptr);
+ unique_fd fd(open(testfile.c_str(), O_RDONLY));
+ EXPECT_GT(fd, -1);
+}
+
+TEST_F(FiemapWriterTest, CheckFileSizeActual) {
+ FiemapUniquePtr fptr = FiemapWriter::Open(testfile, testfile_size);
+ ASSERT_NE(fptr, nullptr);
+
+ struct stat sb;
+ ASSERT_EQ(stat(testfile.c_str(), &sb), 0);
+ EXPECT_EQ(sb.st_size, testfile_size);
+}
+
+TEST_F(FiemapWriterTest, CheckFileExtents) {
+ FiemapUniquePtr fptr = FiemapWriter::Open(testfile, testfile_size);
+ ASSERT_NE(fptr, nullptr);
+ EXPECT_GT(fptr->extents().size(), 0);
+}
+
+TEST_F(FiemapWriterTest, CheckWriteError) {
+ FiemapUniquePtr fptr = FiemapWriter::Open(testfile, testfile_size);
+ ASSERT_NE(fptr, nullptr);
+
+ // prepare buffer for writing the pattern - 0xa0
+ uint64_t blocksize = fptr->block_size();
+ auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, blocksize), free);
+ ASSERT_NE(buffer, nullptr);
+ memset(buffer.get(), 0xa0, blocksize);
+
+ uint8_t* p = static_cast<uint8_t*>(buffer.get());
+ for (off64_t off = 0; off < testfile_size; off += blocksize) {
+ ASSERT_TRUE(fptr->Write(off, p, blocksize));
+ }
+
+ EXPECT_TRUE(fptr->Flush());
+}
+
+class TestExistingFile : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ std::string exec_dir = ::android::base::GetExecutableDirectory();
+ std::string unaligned_file = exec_dir + "/testdata/unaligned_file";
+ std::string file_4k = exec_dir + "/testdata/file_4k";
+ std::string file_32k = exec_dir + "/testdata/file_32k";
+ fptr_unaligned = FiemapWriter::Open(unaligned_file, 4097, false);
+ fptr_4k = FiemapWriter::Open(file_4k, 4096, false);
+ fptr_32k = FiemapWriter::Open(file_32k, 32768, false);
+ }
+
+ FiemapUniquePtr fptr_unaligned;
+ FiemapUniquePtr fptr_4k;
+ FiemapUniquePtr fptr_32k;
+};
+
+TEST_F(TestExistingFile, ErrorChecks) {
+ EXPECT_EQ(fptr_unaligned, nullptr);
+ EXPECT_NE(fptr_4k, nullptr);
+ EXPECT_NE(fptr_32k, nullptr);
+
+ EXPECT_EQ(fptr_4k->size(), 4096);
+ EXPECT_EQ(fptr_32k->size(), 32768);
+ EXPECT_GT(fptr_4k->extents().size(), 0);
+ EXPECT_GT(fptr_32k->extents().size(), 0);
+}
+
+TEST_F(TestExistingFile, CheckWriteError) {
+ ASSERT_NE(fptr_4k, nullptr);
+ // prepare buffer for writing the pattern - 0xa0
+ uint64_t blocksize = fptr_4k->block_size();
+ auto buff_4k = std::unique_ptr<void, decltype(&free)>(calloc(1, blocksize), free);
+ ASSERT_NE(buff_4k, nullptr);
+ memset(buff_4k.get(), 0xa0, blocksize);
+
+ uint8_t* p = static_cast<uint8_t*>(buff_4k.get());
+ for (off64_t off = 0; off < 4096; off += blocksize) {
+ ASSERT_TRUE(fptr_4k->Write(off, p, blocksize));
+ }
+ EXPECT_TRUE(fptr_4k->Flush());
+
+ ASSERT_NE(fptr_32k, nullptr);
+ // prepare buffer for writing the pattern - 0xa0
+ blocksize = fptr_32k->block_size();
+ auto buff_32k = std::unique_ptr<void, decltype(&free)>(calloc(1, blocksize), free);
+ ASSERT_NE(buff_32k, nullptr);
+ memset(buff_32k.get(), 0xa0, blocksize);
+ p = static_cast<uint8_t*>(buff_32k.get());
+ for (off64_t off = 0; off < 4096; off += blocksize) {
+ ASSERT_TRUE(fptr_32k->Write(off, p, blocksize));
+ }
+ EXPECT_TRUE(fptr_32k->Flush());
+}
+
+class VerifyBlockWritesExt4 : public ::testing::Test {
+ // 2GB Filesystem and 4k block size by default
+ static constexpr uint64_t block_size = 4096;
+ static constexpr uint64_t fs_size = 2147483648;
+
+ protected:
+ void SetUp() override {
+ fs_path = std::string(getenv("TMPDIR")) + "/ext4_2G.img";
+ uint64_t count = fs_size / block_size;
+ std::string dd_cmd =
+ ::android::base::StringPrintf("/system/bin/dd if=/dev/zero of=%s bs=%" PRIu64
+ " count=%" PRIu64 " > /dev/null 2>&1",
+ fs_path.c_str(), block_size, count);
+ std::string mkfs_cmd =
+ ::android::base::StringPrintf("/system/bin/mkfs.ext4 -q %s", fs_path.c_str());
+ // create mount point
+ mntpoint = std::string(getenv("TMPDIR")) + "/fiemap_mnt";
+ ASSERT_EQ(mkdir(mntpoint.c_str(), S_IRWXU), 0);
+ // create file for the file system
+ 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);
+ ASSERT_TRUE(loop_dev.valid());
+ // create file system
+ ret = system(mkfs_cmd.c_str());
+ ASSERT_EQ(ret, 0);
+
+ // mount the file system
+ ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "ext4", 0, nullptr), 0);
+ }
+
+ void TearDown() override {
+ umount(mntpoint.c_str());
+ rmdir(mntpoint.c_str());
+ unlink(fs_path.c_str());
+ }
+
+ std::string mntpoint;
+ std::string fs_path;
+};
+
+TEST_F(VerifyBlockWritesExt4, CheckWrites) {
+ EXPECT_EQ(access(fs_path.c_str(), F_OK), 0);
+
+ std::string file_path = mntpoint + "/testfile";
+ uint64_t file_size = 100 * 1024 * 1024;
+ auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, getpagesize()), free);
+ ASSERT_NE(buffer, nullptr);
+ memset(buffer.get(), 0xa0, getpagesize());
+ {
+ // scoped fiemap writer
+ FiemapUniquePtr fptr = FiemapWriter::Open(file_path, file_size);
+ ASSERT_NE(fptr, nullptr);
+ uint8_t* p = static_cast<uint8_t*>(buffer.get());
+ for (off64_t off = 0; off < file_size / getpagesize(); off += getpagesize()) {
+ ASSERT_TRUE(fptr->Write(off, p, getpagesize()));
+ }
+ EXPECT_TRUE(fptr->Flush());
+ }
+ // unmount file system here to make sure we invalidated all page cache and
+ // remount the filesystem again for verification
+ ASSERT_EQ(umount(mntpoint.c_str()), 0);
+
+ LoopDevice loop_dev(fs_path);
+ ASSERT_TRUE(loop_dev.valid());
+ ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "ext4", 0, nullptr), 0)
+ << "failed to mount: " << loop_dev.device() << " on " << mntpoint << ": "
+ << strerror(errno);
+
+ ::android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY | O_SYNC));
+ ASSERT_NE(fd, -1);
+ auto filebuf = std::unique_ptr<void, decltype(&free)>(calloc(1, getpagesize()), free);
+ ASSERT_NE(filebuf, nullptr);
+ for (off64_t off = 0; off < file_size / getpagesize(); off += getpagesize()) {
+ memset(filebuf.get(), 0x00, getpagesize());
+ ASSERT_EQ(pread64(fd, filebuf.get(), getpagesize(), off), getpagesize());
+ ASSERT_EQ(memcmp(filebuf.get(), buffer.get(), getpagesize()), 0)
+ << "Invalid pattern at offset: " << off << " size " << getpagesize();
+ }
+}
+
+class VerifyBlockWritesF2fs : public ::testing::Test {
+ // 2GB Filesystem and 4k block size by default
+ static constexpr uint64_t block_size = 4096;
+ static constexpr uint64_t fs_size = 2147483648;
+
+ protected:
+ void SetUp() override {
+ fs_path = std::string(getenv("TMPDIR")) + "/f2fs_2G.img";
+ uint64_t count = fs_size / block_size;
+ std::string dd_cmd =
+ ::android::base::StringPrintf("/system/bin/dd if=/dev/zero of=%s bs=%" PRIu64
+ " count=%" PRIu64 " > /dev/null 2>&1",
+ fs_path.c_str(), block_size, count);
+ std::string mkfs_cmd =
+ ::android::base::StringPrintf("/system/bin/make_f2fs -q %s", fs_path.c_str());
+ // create mount point
+ mntpoint = std::string(getenv("TMPDIR")) + "/fiemap_mnt";
+ ASSERT_EQ(mkdir(mntpoint.c_str(), S_IRWXU), 0);
+ // create file for the file system
+ 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);
+ ASSERT_TRUE(loop_dev.valid());
+ // create file system
+ ret = system(mkfs_cmd.c_str());
+ ASSERT_EQ(ret, 0);
+
+ // mount the file system
+ ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "f2fs", 0, nullptr), 0);
+ }
+
+ void TearDown() override {
+ umount(mntpoint.c_str());
+ rmdir(mntpoint.c_str());
+ unlink(fs_path.c_str());
+ }
+
+ std::string mntpoint;
+ std::string fs_path;
+};
+
+TEST_F(VerifyBlockWritesF2fs, CheckWrites) {
+ EXPECT_EQ(access(fs_path.c_str(), F_OK), 0);
+
+ std::string file_path = mntpoint + "/testfile";
+ uint64_t file_size = 100 * 1024 * 1024;
+ auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, getpagesize()), free);
+ ASSERT_NE(buffer, nullptr);
+ memset(buffer.get(), 0xa0, getpagesize());
+ {
+ // scoped fiemap writer
+ FiemapUniquePtr fptr = FiemapWriter::Open(file_path, file_size);
+ ASSERT_NE(fptr, nullptr);
+ uint8_t* p = static_cast<uint8_t*>(buffer.get());
+ for (off64_t off = 0; off < file_size / getpagesize(); off += getpagesize()) {
+ ASSERT_TRUE(fptr->Write(off, p, getpagesize()));
+ }
+ EXPECT_TRUE(fptr->Flush());
+ }
+ // unmount file system here to make sure we invalidated all page cache and
+ // remount the filesystem again for verification
+ ASSERT_EQ(umount(mntpoint.c_str()), 0);
+
+ LoopDevice loop_dev(fs_path);
+ ASSERT_TRUE(loop_dev.valid());
+ ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "f2fs", 0, nullptr), 0)
+ << "failed to mount: " << loop_dev.device() << " on " << mntpoint << ": "
+ << strerror(errno);
+
+ ::android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY | O_SYNC));
+ ASSERT_NE(fd, -1);
+ auto filebuf = std::unique_ptr<void, decltype(&free)>(calloc(1, getpagesize()), free);
+ ASSERT_NE(filebuf, nullptr);
+ for (off64_t off = 0; off < file_size / getpagesize(); off += getpagesize()) {
+ memset(filebuf.get(), 0x00, getpagesize());
+ ASSERT_EQ(pread64(fd, filebuf.get(), getpagesize(), off), getpagesize());
+ ASSERT_EQ(memcmp(filebuf.get(), buffer.get(), getpagesize()), 0)
+ << "Invalid pattern at offset: " << off << " size " << getpagesize();
+ }
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ if (argc <= 1) {
+ cerr << "Filepath with its bdev path must be provided as follows:" << endl;
+ cerr << " $ fiemap_writer_test </dev/block/XXXX" << endl;
+ cerr << " where, /dev/block/XXX is the block device where the file resides" << endl;
+ exit(EXIT_FAILURE);
+ }
+ ::android::base::InitLogging(argv, ::android::base::StderrLogger);
+
+ testbdev = argv[1];
+ if (argc > 2) {
+ testfile_size = strtoull(argv[2], NULL, 0);
+ if (testfile_size == ULLONG_MAX) {
+ testfile_size = 512 * 1024 * 1024;
+ }
+ }
+
+ return RUN_ALL_TESTS();
+}
diff --git a/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h b/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
new file mode 100644
index 0000000..ab78f93
--- /dev/null
+++ b/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
@@ -0,0 +1,109 @@
+/*
+ * 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 <linux/fiemap.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <functional>
+#include <string>
+#include <vector>
+
+#include <android-base/unique_fd.h>
+
+namespace android {
+namespace fiemap_writer {
+
+class FiemapWriter;
+using FiemapUniquePtr = std::unique_ptr<FiemapWriter>;
+
+class FiemapWriter final {
+ public:
+ // Factory method for FiemapWriter.
+ // The method returns FiemapUniquePtr that contains all the data necessary to be able to write
+ // to the given file directly using raw block i/o. The optional progress callback will be
+ // invoked, if create is true, while the file is being initialized. It receives the bytes
+ // written and the number of total bytes. If the callback returns false, the operation will
+ // fail.
+ static FiemapUniquePtr Open(const std::string& file_path, uint64_t file_size,
+ bool create = true,
+ std::function<bool(uint64_t, uint64_t)> progress = {});
+
+ // Syncs block device writes.
+ bool Flush() const;
+
+ // Writes the file by using its FIEMAP and performing i/o on the raw block device.
+ // The return value is success / failure. This will happen in particular if the
+ // kernel write returns errors, extents are not writeable or more importantly, if the 'size' is
+ // not aligned to the block device's block size.
+ bool Write(off64_t off, uint8_t* buffer, uint64_t size);
+
+ // The counter part of Write(). It is an error for the offset to be unaligned with
+ // the block device's block size.
+ // In case of error, the contents of buffer MUST be discarded.
+ bool Read(off64_t off, uint8_t* buffer, uint64_t size);
+
+ ~FiemapWriter() = default;
+
+ const std::string& file_path() const { return file_path_; };
+ uint64_t size() const { return file_size_; };
+ const std::string& bdev_path() const { return bdev_path_; };
+ uint64_t block_size() const { return block_size_; };
+ const std::vector<struct fiemap_extent>& extents() { return extents_; };
+
+ // Non-copyable & Non-movable
+ FiemapWriter(const FiemapWriter&) = delete;
+ FiemapWriter& operator=(const FiemapWriter&) = delete;
+ FiemapWriter& operator=(FiemapWriter&&) = delete;
+ FiemapWriter(FiemapWriter&&) = delete;
+
+ private:
+ // Name of the file managed by this class.
+ std::string file_path_;
+ // Block device on which we have created the file.
+ std::string bdev_path_;
+
+ // File descriptors for the file and block device
+ ::android::base::unique_fd file_fd_;
+ ::android::base::unique_fd bdev_fd_;
+
+ // Size in bytes of the file this class is writing
+ uint64_t file_size_;
+
+ // total size in bytes of the block device
+ uint64_t bdev_size_;
+
+ // Filesystem type where the file is being created.
+ // See: <uapi/linux/magic.h> for filesystem magic numbers
+ uint32_t fs_type_;
+
+ // block size as reported by the kernel of the underlying block device;
+ uint64_t block_size_;
+
+ // This file's fiemap
+ std::vector<struct fiemap_extent> extents_;
+
+ FiemapWriter() = default;
+
+ uint64_t WriteExtent(const struct fiemap_extent& ext, uint8_t* buffer, off64_t logical_off,
+ uint64_t length);
+};
+
+} // namespace fiemap_writer
+} // namespace android
diff --git a/fs_mgr/libfiemap_writer/testdata/file_32k b/fs_mgr/libfiemap_writer/testdata/file_32k
new file mode 100644
index 0000000..12f3be4
--- /dev/null
+++ b/fs_mgr/libfiemap_writer/testdata/file_32k
Binary files differ
diff --git a/fs_mgr/libfiemap_writer/testdata/file_4k b/fs_mgr/libfiemap_writer/testdata/file_4k
new file mode 100644
index 0000000..08e7df1
--- /dev/null
+++ b/fs_mgr/libfiemap_writer/testdata/file_4k
Binary files differ
diff --git a/fs_mgr/libfiemap_writer/testdata/unaligned_file b/fs_mgr/libfiemap_writer/testdata/unaligned_file
new file mode 100644
index 0000000..c107c26
--- /dev/null
+++ b/fs_mgr/libfiemap_writer/testdata/unaligned_file
Binary files differ
diff --git a/fs_mgr/libfs_avb/Android.bp b/fs_mgr/libfs_avb/Android.bp
new file mode 100644
index 0000000..6f368e4
--- /dev/null
+++ b/fs_mgr/libfs_avb/Android.bp
@@ -0,0 +1,105 @@
+//
+// 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_library_static {
+ name: "libfs_avb",
+ defaults: ["fs_mgr_defaults"],
+ recovery_available: true,
+ host_supported: true,
+ export_include_dirs: ["include"],
+ srcs: [
+ "avb_ops.cpp",
+ "avb_util.cpp",
+ "fs_avb.cpp",
+ "util.cpp",
+ ],
+ static_libs: [
+ "libavb",
+ "libdm",
+ "libfstab",
+ ],
+ export_static_lib_headers: [
+ "libfstab",
+ ],
+ shared_libs: [
+ "libcrypto",
+ ],
+ header_libs: [
+ "libbase_headers",
+ ],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
+cc_defaults {
+ name: "libfs_avb_host_test_defaults",
+ required: [
+ "avbtool",
+ ],
+ data: [
+ "tests/data/*",
+ ],
+ static_libs: [
+ "libgtest_host",
+ ],
+ shared_libs: [
+ "libbase",
+ "libchrome",
+ ],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+ cflags: [
+ "-DHOST_TEST",
+ ],
+}
+
+cc_library_host_static {
+ name: "libfs_avb_test_util",
+ defaults: ["libfs_avb_host_test_defaults"],
+ srcs: [
+ "tests/fs_avb_test_util.cpp",
+ ],
+}
+
+cc_test_host {
+ name: "libfs_avb_test",
+ defaults: ["libfs_avb_host_test_defaults"],
+ static_libs: [
+ "libfs_avb_test_util",
+ ],
+ srcs: [
+ "tests/basic_test.cpp",
+ ],
+}
+
+cc_test_host {
+ name: "libfs_avb_internal_test",
+ defaults: ["libfs_avb_host_test_defaults"],
+ static_libs: [
+ "libfs_avb_test_util",
+ "libfstab",
+ ],
+ srcs: [
+ "util.cpp",
+ "tests/util_test.cpp",
+ ],
+}
diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/libfs_avb/avb_ops.cpp
similarity index 80%
rename from fs_mgr/fs_mgr_avb_ops.cpp
rename to fs_mgr/libfs_avb/avb_ops.cpp
index 43879fe..3efa794 100644
--- a/fs_mgr/fs_mgr_avb_ops.cpp
+++ b/fs_mgr/libfs_avb/avb_ops.cpp
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-#include "fs_mgr_priv_avb_ops.h"
+#include "avb_ops.h"
#include <errno.h>
#include <fcntl.h>
@@ -37,13 +37,17 @@
#include <libavb/libavb.h>
#include <utils/Compat.h>
-#include "fs_mgr.h"
-#include "fs_mgr_priv.h"
+#include "util.h"
+
+using namespace std::literals;
+
+namespace android {
+namespace fs_mgr {
static AvbIOResult read_from_partition(AvbOps* ops, const char* partition, int64_t offset,
size_t num_bytes, void* buffer, size_t* out_num_read) {
return FsManagerAvbOps::GetInstanceFromAvbOps(ops)->ReadFromPartition(
- partition, offset, num_bytes, buffer, out_num_read);
+ partition, offset, num_bytes, buffer, out_num_read);
}
static AvbIOResult dummy_read_rollback_index(AvbOps* ops ATTRIBUTE_UNUSED,
@@ -56,9 +60,10 @@
}
static AvbIOResult dummy_validate_vbmeta_public_key(
- AvbOps* ops ATTRIBUTE_UNUSED, const uint8_t* public_key_data ATTRIBUTE_UNUSED,
- size_t public_key_length ATTRIBUTE_UNUSED, const uint8_t* public_key_metadata ATTRIBUTE_UNUSED,
- size_t public_key_metadata_length ATTRIBUTE_UNUSED, bool* out_is_trusted) {
+ AvbOps* ops ATTRIBUTE_UNUSED, const uint8_t* public_key_data ATTRIBUTE_UNUSED,
+ size_t public_key_length ATTRIBUTE_UNUSED,
+ const uint8_t* public_key_metadata ATTRIBUTE_UNUSED,
+ size_t public_key_metadata_length ATTRIBUTE_UNUSED, bool* out_is_trusted) {
// vbmeta public key has been checked in bootloader phase.
// In user-space, returns true to pass the check.
//
@@ -98,7 +103,7 @@
return AVB_IO_RESULT_OK;
}
-void FsManagerAvbOps::InitializeAvbOps() {
+FsManagerAvbOps::FsManagerAvbOps() {
// We only need to provide the implementation of read_from_partition()
// operation since that's all what is being used by the avb_slot_verify().
// Other I/O operations are only required in bootloader but not in
@@ -116,34 +121,13 @@
avb_ops_.user_data = this;
}
-FsManagerAvbOps::FsManagerAvbOps(std::map<std::string, std::string>&& by_name_symlink_map)
- : by_name_symlink_map_(std::move(by_name_symlink_map)) {
- InitializeAvbOps();
-}
-
-FsManagerAvbOps::FsManagerAvbOps(const fstab& fstab) {
- // Constructs the by-name symlink map for each fstab record.
- // /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a =>
- // by_name_symlink_map_["system_a"] = "/dev/block/platform/soc.0/7824900.sdhci/by-name/system_a"
- for (int i = 0; i < fstab.num_entries; i++) {
- std::string partition_name = basename(fstab.recs[i].blk_device);
- by_name_symlink_map_[partition_name] = fstab.recs[i].blk_device;
- }
- InitializeAvbOps();
-}
-
AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset,
size_t num_bytes, void* buffer,
size_t* out_num_read) {
- const auto iter = by_name_symlink_map_.find(partition);
- if (iter == by_name_symlink_map_.end()) {
- LERROR << "by-name symlink not found for partition: '" << partition << "'";
- return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
- }
- std::string path = iter->second;
+ const std::string path = "/dev/block/by-name/"s + partition;
// Ensures the device path (a symlink created by init) is ready to access.
- if (!fs_mgr_wait_for_file(path, 1s)) {
+ if (!WaitForFile(path, 1s)) {
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
}
@@ -186,14 +170,34 @@
AvbSlotVerifyResult FsManagerAvbOps::AvbSlotVerify(const std::string& ab_suffix,
AvbSlotVerifyFlags flags,
- AvbSlotVerifyData** out_data) {
+ std::vector<VBMetaData>* out_vbmeta_images) {
// Invokes avb_slot_verify() to load and verify all vbmeta images.
// Sets requested_partitions to nullptr as it's to copy the contents
// of HASH partitions into handle>avb_slot_data_, which is not required as
// fs_mgr only deals with HASHTREE partitions.
const char* requested_partitions[] = {nullptr};
+
+ // Local resource to store vbmeta images from avb_slot_verify();
+ AvbSlotVerifyData* avb_slot_data;
+
// The |hashtree_error_mode| field doesn't matter as it only
// influences the generated kernel cmdline parameters.
- return avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix.c_str(), flags,
- AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, out_data);
+ auto verify_result =
+ avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix.c_str(), flags,
+ AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &avb_slot_data);
+
+ if (!avb_slot_data) return verify_result;
+ // Copies avb_slot_data->vbmeta_images[].
+ for (size_t i = 0; i < avb_slot_data->num_vbmeta_images; i++) {
+ out_vbmeta_images->emplace_back(VBMetaData(avb_slot_data->vbmeta_images[i].vbmeta_data,
+ avb_slot_data->vbmeta_images[i].vbmeta_size));
+ }
+
+ // Free the local resource.
+ avb_slot_verify_data_free(avb_slot_data);
+
+ return verify_result;
}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/fs_mgr_priv_avb_ops.h b/fs_mgr/libfs_avb/avb_ops.h
similarity index 82%
rename from fs_mgr/fs_mgr_priv_avb_ops.h
rename to fs_mgr/libfs_avb/avb_ops.h
index d1ef2e9..c0f12aa 100644
--- a/fs_mgr/fs_mgr_priv_avb_ops.h
+++ b/fs_mgr/libfs_avb/avb_ops.h
@@ -22,15 +22,16 @@
* SOFTWARE.
*/
-#ifndef __CORE_FS_MGR_PRIV_AVB_OPS_H
-#define __CORE_FS_MGR_PRIV_AVB_OPS_H
+#pragma once
-#include <map>
#include <string>
+#include <vector>
+#include <fs_avb/fs_avb.h>
#include <libavb/libavb.h>
-#include "fs_mgr.h"
+namespace android {
+namespace fs_mgr {
// This class provides C++ bindings to interact with libavb, a small
// self-contained piece of code that's intended to be used in bootloaders.
@@ -42,12 +43,11 @@
// read and verify the metadata and store it into the out_data parameter.
// The caller MUST check the integrity of metadata against the
// androidboot.vbmeta.{hash_alg, size, digest} values from /proc/cmdline.
-// e.g., see class FsManagerAvbVerifier for more details.
+// e.g., see class AvbVerifier for more details.
//
class FsManagerAvbOps {
public:
- FsManagerAvbOps(const fstab& fstab);
- FsManagerAvbOps(std::map<std::string, std::string>&& by_name_symlink_map);
+ FsManagerAvbOps();
static FsManagerAvbOps* GetInstanceFromAvbOps(AvbOps* ops) {
return reinterpret_cast<FsManagerAvbOps*>(ops->user_data);
@@ -57,12 +57,11 @@
void* buffer, size_t* out_num_read);
AvbSlotVerifyResult AvbSlotVerify(const std::string& ab_suffix, AvbSlotVerifyFlags flags,
- AvbSlotVerifyData** out_data);
+ std::vector<VBMetaData>* out_vbmeta_images);
private:
- void InitializeAvbOps();
-
AvbOps avb_ops_;
- std::map<std::string, std::string> by_name_symlink_map_;
};
-#endif /* __CORE_FS_MGR_PRIV_AVB_OPS_H */
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/libfs_avb/avb_util.cpp b/fs_mgr/libfs_avb/avb_util.cpp
new file mode 100644
index 0000000..0ceb6ee
--- /dev/null
+++ b/fs_mgr/libfs_avb/avb_util.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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 "avb_util.h"
+
+#include <array>
+#include <sstream>
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
+
+#include "util.h"
+
+using android::base::unique_fd;
+
+namespace android {
+namespace fs_mgr {
+
+// Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel.
+// See the following link for more details:
+// https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
+bool ConstructVerityTable(const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt,
+ const std::string& root_digest, const std::string& blk_device,
+ android::dm::DmTable* table) {
+ // Loads androidboot.veritymode from kernel cmdline.
+ std::string verity_mode;
+ if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) {
+ verity_mode = "enforcing"; // Defaults to enforcing when it's absent.
+ }
+
+ // Converts veritymode to the format used in kernel.
+ std::string dm_verity_mode;
+ if (verity_mode == "enforcing") {
+ dm_verity_mode = "restart_on_corruption";
+ } else if (verity_mode == "logging") {
+ dm_verity_mode = "ignore_corruption";
+ } else if (verity_mode != "eio") { // Default dm_verity_mode is eio.
+ LERROR << "Unknown androidboot.veritymode: " << verity_mode;
+ return false;
+ }
+
+ std::ostringstream hash_algorithm;
+ hash_algorithm << hashtree_desc.hash_algorithm;
+
+ android::dm::DmTargetVerity target(0, hashtree_desc.image_size / 512,
+ hashtree_desc.dm_verity_version, blk_device, blk_device,
+ hashtree_desc.data_block_size, hashtree_desc.hash_block_size,
+ hashtree_desc.image_size / hashtree_desc.data_block_size,
+ hashtree_desc.tree_offset / hashtree_desc.hash_block_size,
+ hash_algorithm.str(), root_digest, salt);
+ if (hashtree_desc.fec_size > 0) {
+ target.UseFec(blk_device, hashtree_desc.fec_num_roots,
+ hashtree_desc.fec_offset / hashtree_desc.data_block_size,
+ hashtree_desc.fec_offset / hashtree_desc.data_block_size);
+ }
+ if (!dm_verity_mode.empty()) {
+ target.SetVerityMode(dm_verity_mode);
+ }
+ // Always use ignore_zero_blocks.
+ target.IgnoreZeroBlocks();
+
+ LINFO << "Built verity table: '" << target.GetParameterString() << "'";
+
+ return table->AddTarget(std::make_unique<android::dm::DmTargetVerity>(target));
+}
+
+bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const AvbHashtreeDescriptor& hashtree_desc,
+ const std::string& salt, const std::string& root_digest,
+ bool wait_for_verity_dev) {
+ android::dm::DmTable table;
+ if (!ConstructVerityTable(hashtree_desc, salt, root_digest, fstab_entry->blk_device, &table) ||
+ !table.valid()) {
+ LERROR << "Failed to construct verity table.";
+ return false;
+ }
+ table.set_readonly(true);
+
+ const std::string mount_point(basename(fstab_entry->mount_point.c_str()));
+ android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
+ if (!dm.CreateDevice(mount_point, table)) {
+ LERROR << "Couldn't create verity device!";
+ return false;
+ }
+
+ std::string dev_path;
+ if (!dm.GetDmDevicePathByName(mount_point, &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;
+}
+
+bool GetHashtreeDescriptor(const std::string& partition_name,
+ const std::vector<VBMetaData>& vbmeta_images,
+ AvbHashtreeDescriptor* out_hashtree_desc, std::string* out_salt,
+ std::string* out_digest) {
+ bool found = false;
+ const uint8_t* desc_partition_name;
+
+ for (const auto& vbmeta : vbmeta_images) {
+ size_t num_descriptors;
+ std::unique_ptr<const AvbDescriptor* [], decltype(&avb_free)> descriptors(
+ avb_descriptor_get_all(vbmeta.data(), vbmeta.size(), &num_descriptors), avb_free);
+
+ if (!descriptors || num_descriptors < 1) {
+ continue;
+ }
+
+ for (size_t n = 0; n < num_descriptors && !found; n++) {
+ AvbDescriptor desc;
+ if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
+ LWARNING << "Descriptor[" << n << "] is invalid";
+ continue;
+ }
+ if (desc.tag == AVB_DESCRIPTOR_TAG_HASHTREE) {
+ desc_partition_name =
+ (const uint8_t*)descriptors[n] + sizeof(AvbHashtreeDescriptor);
+ if (!avb_hashtree_descriptor_validate_and_byteswap(
+ (AvbHashtreeDescriptor*)descriptors[n], out_hashtree_desc)) {
+ continue;
+ }
+ if (out_hashtree_desc->partition_name_len != partition_name.length()) {
+ continue;
+ }
+ // Notes that desc_partition_name is not NUL-terminated.
+ std::string hashtree_partition_name((const char*)desc_partition_name,
+ out_hashtree_desc->partition_name_len);
+ if (hashtree_partition_name == partition_name) {
+ found = true;
+ }
+ }
+ }
+
+ if (found) break;
+ }
+
+ if (!found) {
+ LERROR << "Partition descriptor not found: " << partition_name.c_str();
+ return false;
+ }
+
+ const uint8_t* desc_salt = desc_partition_name + out_hashtree_desc->partition_name_len;
+ *out_salt = BytesToHex(desc_salt, out_hashtree_desc->salt_len);
+
+ const uint8_t* desc_digest = desc_salt + out_hashtree_desc->salt_len;
+ *out_digest = BytesToHex(desc_digest, out_hashtree_desc->root_digest_len);
+
+ return true;
+}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/libfs_avb/avb_util.h b/fs_mgr/libfs_avb/avb_util.h
new file mode 100644
index 0000000..b81e931
--- /dev/null
+++ b/fs_mgr/libfs_avb/avb_util.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.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <libavb/libavb.h>
+#include <libdm/dm.h>
+
+#include "fs_avb/fs_avb.h"
+
+namespace android {
+namespace fs_mgr {
+
+// AvbHashtreeDescriptor to dm-verity table setup.
+bool GetHashtreeDescriptor(const std::string& partition_name,
+ const std::vector<VBMetaData>& vbmeta_images,
+ AvbHashtreeDescriptor* out_hashtree_desc, std::string* out_salt,
+ std::string* out_digest);
+
+bool ConstructVerityTable(const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt,
+ const std::string& root_digest, const std::string& blk_device,
+ android::dm::DmTable* table);
+
+bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const AvbHashtreeDescriptor& hashtree_desc,
+ const std::string& salt, const std::string& root_digest,
+ bool wait_for_verity_dev);
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/libfs_avb/fs_avb.cpp b/fs_mgr/libfs_avb/fs_avb.cpp
new file mode 100644
index 0000000..957aa87
--- /dev/null
+++ b/fs_mgr/libfs_avb/fs_avb.cpp
@@ -0,0 +1,292 @@
+/*
+ * 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 "fs_avb/fs_avb.h"
+
+#include <fcntl.h>
+#include <libgen.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
+#include <libavb/libavb.h>
+#include <libdm/dm.h>
+
+#include "avb_ops.h"
+#include "avb_util.h"
+#include "sha.h"
+#include "util.h"
+
+using android::base::Basename;
+using android::base::ParseUint;
+using android::base::StringPrintf;
+
+namespace android {
+namespace fs_mgr {
+
+template <typename Hasher>
+std::pair<size_t, bool> VerifyVbmetaDigest(const std::vector<VBMetaData>& vbmeta_images,
+ const uint8_t* expected_digest) {
+ size_t total_size = 0;
+ Hasher hasher;
+ for (const auto& vbmeta : vbmeta_images) {
+ hasher.update(vbmeta.data(), vbmeta.size());
+ total_size += vbmeta.size();
+ }
+
+ bool matched = (memcmp(hasher.finalize(), expected_digest, Hasher::DIGEST_SIZE) == 0);
+
+ return std::make_pair(total_size, matched);
+}
+
+// Reads the following values from kernel cmdline and provides the
+// VerifyVbmetaImages() to verify AvbSlotVerifyData.
+// - androidboot.vbmeta.hash_alg
+// - androidboot.vbmeta.size
+// - androidboot.vbmeta.digest
+class AvbVerifier {
+ public:
+ // The factory method to return a unique_ptr<AvbVerifier>
+ static std::unique_ptr<AvbVerifier> Create();
+ bool VerifyVbmetaImages(const std::vector<VBMetaData>& vbmeta_images);
+
+ protected:
+ AvbVerifier() = default;
+
+ private:
+ enum HashAlgorithm {
+ kInvalid = 0,
+ kSHA256 = 1,
+ kSHA512 = 2,
+ };
+
+ HashAlgorithm hash_alg_;
+ uint8_t digest_[SHA512_DIGEST_LENGTH];
+ size_t vbmeta_size_;
+};
+
+std::unique_ptr<AvbVerifier> AvbVerifier::Create() {
+ std::unique_ptr<AvbVerifier> avb_verifier(new AvbVerifier());
+ if (!avb_verifier) {
+ LERROR << "Failed to create unique_ptr<AvbVerifier>";
+ return nullptr;
+ }
+
+ std::string value;
+ if (!fs_mgr_get_boot_config("vbmeta.size", &value) ||
+ !ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) {
+ LERROR << "Invalid hash size: " << value.c_str();
+ return nullptr;
+ }
+
+ // Reads hash algorithm.
+ size_t expected_digest_size = 0;
+ std::string hash_alg;
+ fs_mgr_get_boot_config("vbmeta.hash_alg", &hash_alg);
+ if (hash_alg == "sha256") {
+ expected_digest_size = SHA256_DIGEST_LENGTH * 2;
+ avb_verifier->hash_alg_ = kSHA256;
+ } else if (hash_alg == "sha512") {
+ expected_digest_size = SHA512_DIGEST_LENGTH * 2;
+ avb_verifier->hash_alg_ = kSHA512;
+ } else {
+ LERROR << "Unknown hash algorithm: " << hash_alg.c_str();
+ return nullptr;
+ }
+
+ // Reads digest.
+ std::string digest;
+ fs_mgr_get_boot_config("vbmeta.digest", &digest);
+ if (digest.size() != expected_digest_size) {
+ LERROR << "Unexpected digest size: " << digest.size()
+ << " (expected: " << expected_digest_size << ")";
+ return nullptr;
+ }
+
+ if (!HexToBytes(avb_verifier->digest_, sizeof(avb_verifier->digest_), digest)) {
+ LERROR << "Hash digest contains non-hexidecimal character: " << digest.c_str();
+ return nullptr;
+ }
+
+ return avb_verifier;
+}
+
+bool AvbVerifier::VerifyVbmetaImages(const std::vector<VBMetaData>& vbmeta_images) {
+ if (vbmeta_images.empty()) {
+ LERROR << "No vbmeta images";
+ return false;
+ }
+
+ size_t total_size = 0;
+ bool digest_matched = false;
+
+ if (hash_alg_ == kSHA256) {
+ std::tie(total_size, digest_matched) =
+ VerifyVbmetaDigest<SHA256Hasher>(vbmeta_images, digest_);
+ } else if (hash_alg_ == kSHA512) {
+ std::tie(total_size, digest_matched) =
+ VerifyVbmetaDigest<SHA512Hasher>(vbmeta_images, digest_);
+ }
+
+ if (total_size != vbmeta_size_) {
+ LERROR << "total vbmeta size mismatch: " << total_size << " (expected: " << vbmeta_size_
+ << ")";
+ return false;
+ }
+
+ if (!digest_matched) {
+ LERROR << "vbmeta digest mismatch";
+ return false;
+ }
+
+ return true;
+}
+
+
+AvbUniquePtr AvbHandle::Open() {
+ bool is_device_unlocked = IsDeviceUnlocked();
+
+ AvbUniquePtr avb_handle(new AvbHandle());
+ if (!avb_handle) {
+ LERROR << "Failed to allocate AvbHandle";
+ return nullptr;
+ }
+
+ FsManagerAvbOps avb_ops;
+ AvbSlotVerifyFlags flags = is_device_unlocked ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
+ : AVB_SLOT_VERIFY_FLAGS_NONE;
+ AvbSlotVerifyResult verify_result =
+ avb_ops.AvbSlotVerify(fs_mgr_get_slot_suffix(), flags, &avb_handle->vbmeta_images_);
+
+ // Only allow two verify results:
+ // - AVB_SLOT_VERIFY_RESULT_OK.
+ // - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (for UNLOCKED state).
+ // If the device is UNLOCKED, i.e., |allow_verification_error| is true for
+ // AvbSlotVerify(), then the following return values are all non-fatal:
+ // * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
+ // * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED
+ // * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX
+ // The latter two results were checked by bootloader prior to start fs_mgr so
+ // we just need to handle the first result here. See *dummy* operations in
+ // FsManagerAvbOps and the comments in external/avb/libavb/avb_slot_verify.h
+ // for more details.
+ switch (verify_result) {
+ case AVB_SLOT_VERIFY_RESULT_OK:
+ avb_handle->status_ = kAvbHandleSuccess;
+ break;
+ case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
+ if (!is_device_unlocked) {
+ LERROR << "ERROR_VERIFICATION isn't allowed when the device is LOCKED";
+ return nullptr;
+ }
+ avb_handle->status_ = kAvbHandleVerificationError;
+ break;
+ default:
+ LERROR << "avb_slot_verify failed, result: " << verify_result;
+ return nullptr;
+ }
+
+ // Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version".
+ avb_handle->avb_version_ = StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);
+
+ // Checks whether FLAGS_VERIFICATION_DISABLED is set:
+ // - Only the top-level vbmeta struct is read.
+ // - vbmeta struct in other partitions are NOT processed, including AVB HASH descriptor(s)
+ // and AVB HASHTREE descriptor(s).
+ AvbVBMetaImageHeader vbmeta_header;
+ avb_vbmeta_image_header_to_host_byte_order(
+ (AvbVBMetaImageHeader*)avb_handle->vbmeta_images_[0].data(), &vbmeta_header);
+ bool verification_disabled = ((AvbVBMetaImageFlags)vbmeta_header.flags &
+ AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
+
+ if (verification_disabled) {
+ avb_handle->status_ = kAvbHandleVerificationDisabled;
+ } else {
+ // Verifies vbmeta structs against the digest passed from bootloader in kernel cmdline.
+ std::unique_ptr<AvbVerifier> avb_verifier = AvbVerifier::Create();
+ if (!avb_verifier) {
+ LERROR << "Failed to create AvbVerifier";
+ return nullptr;
+ }
+ if (!avb_verifier->VerifyVbmetaImages(avb_handle->vbmeta_images_)) {
+ LERROR << "VerifyVbmetaImages failed";
+ return nullptr;
+ }
+
+ // Checks whether FLAGS_HASHTREE_DISABLED is set.
+ bool hashtree_disabled = ((AvbVBMetaImageFlags)vbmeta_header.flags &
+ AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
+ if (hashtree_disabled) {
+ avb_handle->status_ = kAvbHandleHashtreeDisabled;
+ }
+ }
+
+ LINFO << "Returning avb_handle with status: " << avb_handle->status_;
+ return avb_handle;
+}
+
+AvbHashtreeResult AvbHandle::SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait_for_verity_dev) {
+ if (!fstab_entry || status_ == kAvbHandleUninitialized || vbmeta_images_.size() < 1) {
+ return AvbHashtreeResult::kFail;
+ }
+
+ if (status_ == kAvbHandleHashtreeDisabled || status_ == kAvbHandleVerificationDisabled) {
+ LINFO << "AVB HASHTREE disabled on: " << fstab_entry->mount_point;
+ return AvbHashtreeResult::kDisabled;
+ }
+
+ // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor
+ // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix.
+ std::string partition_name;
+ if (fstab_entry->fs_mgr_flags.logical) {
+ partition_name = fstab_entry->logical_partition_name;
+ } else {
+ partition_name = Basename(fstab_entry->blk_device);
+ }
+
+ if (fstab_entry->fs_mgr_flags.slot_select) {
+ auto ab_suffix = partition_name.rfind(fs_mgr_get_slot_suffix());
+ if (ab_suffix != std::string::npos) {
+ partition_name.erase(ab_suffix);
+ }
+ }
+
+ AvbHashtreeDescriptor hashtree_descriptor;
+ std::string salt;
+ std::string root_digest;
+ if (!GetHashtreeDescriptor(partition_name, vbmeta_images_, &hashtree_descriptor, &salt,
+ &root_digest)) {
+ return AvbHashtreeResult::kFail;
+ }
+
+ // Converts HASHTREE descriptor to verity_table_params.
+ if (!HashtreeDmVeritySetup(fstab_entry, hashtree_descriptor, salt, root_digest,
+ wait_for_verity_dev)) {
+ return AvbHashtreeResult::kFail;
+ }
+
+ return AvbHashtreeResult::kSuccess;
+}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/include/fs_mgr_avb.h b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
similarity index 62%
rename from fs_mgr/include/fs_mgr_avb.h
rename to fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
index 73a22c8..eca6984 100644
--- a/fs_mgr/include/fs_mgr_avb.h
+++ b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
@@ -14,51 +14,72 @@
* limitations under the License.
*/
-#ifndef __CORE_FS_MGR_AVB_H
-#define __CORE_FS_MGR_AVB_H
+#pragma once
-#include <map>
#include <memory>
#include <string>
+#include <vector>
+#include <fstab/fstab.h>
#include <libavb/libavb.h>
-#include "fs_mgr.h"
+namespace android {
+namespace fs_mgr {
-enum class SetUpAvbHashtreeResult {
+enum class AvbHashtreeResult {
kSuccess = 0,
kFail,
kDisabled,
};
+class VBMetaData {
+ public:
+ // Constructors
+ VBMetaData() : vbmeta_ptr_(nullptr), vbmeta_size_(0){};
+
+ VBMetaData(const uint8_t* data, size_t size)
+ : vbmeta_ptr_(new (std::nothrow) uint8_t[size]), vbmeta_size_(size) {
+ // The ownership of data is NOT transferred, i.e., the caller still
+ // needs to release the memory as we make a copy here.
+ memcpy(vbmeta_ptr_.get(), data, size * sizeof(uint8_t));
+ }
+
+ explicit VBMetaData(size_t size)
+ : vbmeta_ptr_(new (std::nothrow) uint8_t[size]), vbmeta_size_(size) {}
+
+ // Get methods for each data member.
+ const std::string& device_path() const { return device_path_; }
+ uint8_t* data() const { return vbmeta_ptr_.get(); }
+ const size_t& size() const { return vbmeta_size_; }
+
+ // Maximum size of a vbmeta data - 64 KiB.
+ static const size_t kMaxVBMetaSize = 64 * 1024;
+
+ private:
+ std::string device_path_;
+ std::unique_ptr<uint8_t[]> vbmeta_ptr_;
+ size_t vbmeta_size_;
+};
+
class FsManagerAvbOps;
-class FsManagerAvbHandle;
-using FsManagerAvbUniquePtr = std::unique_ptr<FsManagerAvbHandle>;
-
-using ByNameSymlinkMap = std::map<std::string, std::string>;
+class AvbHandle;
+using AvbUniquePtr = std::unique_ptr<AvbHandle>;
// Provides a factory method to return a unique_ptr pointing to itself and the
// SetUpAvbHashtree() function to extract dm-verity parameters from AVB HASHTREE
// descriptors to load verity table into kernel through ioctl.
-class FsManagerAvbHandle {
+class AvbHandle {
public:
- // The factory method to return a FsManagerAvbUniquePtr that holds
+ // The factory method to return a AvbUniquePtr that holds
// the verified AVB (external/avb) metadata of all verified partitions
- // in avb_slot_data_.vbmeta_images[].
+ // in vbmeta_images_.
//
// The metadata is checked against the following values from /proc/cmdline.
// - androidboot.vbmeta.{hash_alg, size, digest}.
//
// A typical usage will be:
- // - FsManagerAvbUniquePtr handle = FsManagerAvbHandle::Open();
- //
- // There are two overloaded Open() functions with a single parameter.
- // The argument can be a ByNameSymlinkMap describing the mapping from partition
- // name to by-name symlink, or a fstab file to which the ByNameSymlinkMap is
- // constructed from. e.g.,
- // - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a ->
- // - ByNameSymlinkMap["system_a"] = "/dev/block/platform/soc.0/7824900.sdhci/by-name/system_a"
+ // - AvbUniquePtr handle = AvbHandle::Open();
//
// Possible return values:
// - nullptr: any error when reading and verifying the metadata,
@@ -82,8 +103,7 @@
// - a valid unique_ptr with status kAvbHandleSuccess: the metadata
// is verified and can be trusted.
//
- static FsManagerAvbUniquePtr Open(const fstab& fstab);
- static FsManagerAvbUniquePtr Open(ByNameSymlinkMap&& by_name_symlink_map);
+ static AvbUniquePtr Open();
// Sets up dm-verity on the given fstab entry.
// The 'wait_for_verity_dev' parameter makes this function wait for the
@@ -95,21 +115,15 @@
// failed to get the HASHTREE descriptor, runtime error when set up
// device-mapper, etc.
// - kDisabled: hashtree is disabled.
- SetUpAvbHashtreeResult SetUpAvbHashtree(fstab_rec* fstab_entry, bool wait_for_verity_dev);
+ AvbHashtreeResult SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait_for_verity_dev);
const std::string& avb_version() const { return avb_version_; }
- FsManagerAvbHandle(const FsManagerAvbHandle&) = delete; // no copy
- FsManagerAvbHandle& operator=(const FsManagerAvbHandle&) = delete; // no assignment
+ AvbHandle(const AvbHandle&) = delete; // no copy
+ AvbHandle& operator=(const AvbHandle&) = delete; // no assignment
- FsManagerAvbHandle(FsManagerAvbHandle&&) noexcept = delete; // no move
- FsManagerAvbHandle& operator=(FsManagerAvbHandle&&) noexcept = delete; // no move assignment
-
- ~FsManagerAvbHandle() {
- if (avb_slot_data_) {
- avb_slot_verify_data_free(avb_slot_data_);
- }
- };
+ AvbHandle(AvbHandle&&) noexcept = delete; // no move
+ AvbHandle& operator=(AvbHandle&&) noexcept = delete; // no move assignment
private:
enum AvbHandleStatus {
@@ -120,12 +134,12 @@
kAvbHandleVerificationError,
};
- FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kAvbHandleUninitialized) {}
- static FsManagerAvbUniquePtr DoOpen(FsManagerAvbOps* avb_ops);
+ AvbHandle() : status_(kAvbHandleUninitialized) {}
- AvbSlotVerifyData* avb_slot_data_;
+ std::vector<VBMetaData> vbmeta_images_;
AvbHandleStatus status_;
std::string avb_version_;
};
-#endif /* __CORE_FS_MGR_AVB_H */
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/fs_mgr_priv_sha.h b/fs_mgr/libfs_avb/sha.h
similarity index 92%
rename from fs_mgr/fs_mgr_priv_sha.h
rename to fs_mgr/libfs_avb/sha.h
index 5b53eea..2d3ca6d 100644
--- a/fs_mgr/fs_mgr_priv_sha.h
+++ b/fs_mgr/libfs_avb/sha.h
@@ -14,11 +14,13 @@
* limitations under the License.
*/
-#ifndef __CORE_FS_MGR_PRIV_SHA_H
-#define __CORE_FS_MGR_PRIV_SHA_H
+#pragma once
#include <openssl/sha.h>
+namespace android {
+namespace fs_mgr {
+
class SHA256Hasher {
private:
SHA256_CTX sha256_ctx;
@@ -59,4 +61,5 @@
}
};
-#endif /* __CORE_FS_MGR_PRIV_SHA_H */
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/libfs_avb/tests/basic_test.cpp b/fs_mgr/libfs_avb/tests/basic_test.cpp
new file mode 100644
index 0000000..5a1cd0d
--- /dev/null
+++ b/fs_mgr/libfs_avb/tests/basic_test.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 "fs_avb_test_util.h"
+
+#include <stdlib.h>
+
+#include <android-base/file.h>
+#include <base/files/file_util.h>
+#include <base/strings/string_util.h>
+
+namespace fs_avb_host_test {
+
+TEST_F(BaseFsAvbTest, GenerateImage) {
+ const size_t image_size = 5 * 1024 * 1024;
+ base::FilePath boot_path = GenerateImage("boot.img", image_size);
+ EXPECT_NE(0U, boot_path.value().size());
+
+ // Checks file size is as expected.
+ int64_t file_size;
+ ASSERT_TRUE(base::GetFileSize(boot_path, &file_size));
+ EXPECT_EQ(file_size, image_size);
+
+ // Checks file content is as expected.
+ std::vector<uint8_t> expected_content;
+ expected_content.resize(image_size);
+ for (size_t n = 0; n < image_size; n++) {
+ expected_content[n] = uint8_t(n);
+ }
+ std::vector<uint8_t> actual_content;
+ actual_content.resize(image_size);
+ EXPECT_TRUE(
+ base::ReadFile(boot_path, reinterpret_cast<char*>(actual_content.data()), image_size));
+ EXPECT_EQ(expected_content, actual_content);
+}
+
+TEST_F(BaseFsAvbTest, GenerateVBMetaImage) {
+ GenerateVBMetaImage("vbmeta.img", "SHA256_RSA2048", 0, data_dir_.Append("testkey_rsa2048.pem"),
+ {}, /* include_descriptor_image_paths */
+ {}, /* chain_partitions */
+ "--internal_release_string \"unit test\"");
+ EXPECT_EQ("5eba9ad4e775645e7eac441a563c200681ae868158d06f6a6cd36d06c07bd781",
+ CalcVBMetaDigest("vbmeta.img", "sha256"));
+ EXPECT_EQ(
+ "Minimum libavb version: 1.0\n"
+ "Header Block: 256 bytes\n"
+ "Authentication Block: 320 bytes\n"
+ "Auxiliary Block: 576 bytes\n"
+ "Algorithm: SHA256_RSA2048\n"
+ "Rollback Index: 0\n"
+ "Flags: 0\n"
+ "Release String: 'unit test'\n"
+ "Descriptors:\n"
+ " (none)\n",
+ InfoImage("vbmeta.img"));
+}
+
+TEST_F(BaseFsAvbTest, AddHashFooter) {
+ // Generates a raw boot.img
+ const size_t image_size = 5 * 1024 * 1024;
+ const size_t partition_size = 10 * 1024 * 1024;
+ base::FilePath boot_path = GenerateImage("boot.img", image_size);
+ EXPECT_NE(0U, boot_path.value().size());
+ // Checks file size is as expected.
+ int64_t file_size;
+ ASSERT_TRUE(base::GetFileSize(boot_path, &file_size));
+ EXPECT_EQ(file_size, image_size);
+ // Appends AVB Hash Footer.
+ AddAvbFooter(boot_path, "hash", "boot", partition_size, "SHA256_RSA4096", 10,
+ data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+ // Extracts boot vbmeta from boot.img into boot-vbmeta.img.
+ ExtractVBMetaImage(boot_path, "boot-vbmeta.img");
+ EXPECT_EQ(
+ "Minimum libavb version: 1.0\n"
+ "Header Block: 256 bytes\n"
+ "Authentication Block: 576 bytes\n"
+ "Auxiliary Block: 1216 bytes\n"
+ "Algorithm: SHA256_RSA4096\n"
+ "Rollback Index: 10\n"
+ "Flags: 0\n"
+ "Release String: 'unit test'\n"
+ "Descriptors:\n"
+ " Hash descriptor:\n"
+ " Image Size: 5242880 bytes\n"
+ " Hash Algorithm: sha256\n"
+ " Partition Name: boot\n"
+ " Salt: d00df00d\n"
+ " Digest: "
+ "222dd01e98284a1fcd7781f85d1392e43a530511a64eff96db197db90ebc4df1\n"
+ " Flags: 0\n",
+ InfoImage("boot-vbmeta.img"));
+}
+
+TEST_F(BaseFsAvbTest, AddHashtreeFooter) {
+ // Generates a raw system.img
+ const size_t image_size = 50 * 1024 * 1024;
+ const size_t partition_size = 60 * 1024 * 1024;
+ base::FilePath system_path = GenerateImage("system.img", image_size);
+ EXPECT_NE(0U, system_path.value().size());
+ // Checks file size is as expected.
+ int64_t file_size;
+ ASSERT_TRUE(base::GetFileSize(system_path, &file_size));
+ EXPECT_EQ(file_size, image_size);
+ // Appends AVB Hashtree Footer.
+ AddAvbFooter(system_path, "hashtree", "system", partition_size, "SHA512_RSA8192", 20,
+ data_dir_.Append("testkey_rsa8192.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+ // Extracts system vbmeta from system.img into system-vbmeta.img.
+ ExtractVBMetaImage(system_path, "system-vbmeta.img");
+ EXPECT_EQ(
+ "Minimum libavb version: 1.0\n"
+ "Header Block: 256 bytes\n"
+ "Authentication Block: 1088 bytes\n"
+ "Auxiliary Block: 2304 bytes\n"
+ "Algorithm: SHA512_RSA8192\n"
+ "Rollback Index: 20\n"
+ "Flags: 0\n"
+ "Release String: 'unit test'\n"
+ "Descriptors:\n"
+ " Hashtree descriptor:\n"
+ " Version of dm-verity: 1\n"
+ " Image Size: 52428800 bytes\n"
+ " Tree Offset: 52428800\n"
+ " Tree Size: 413696 bytes\n"
+ " Data Block Size: 4096 bytes\n"
+ " Hash Block Size: 4096 bytes\n"
+ " FEC num roots: 2\n"
+ " FEC offset: 52842496\n"
+ " FEC size: 417792 bytes\n"
+ " Hash Algorithm: sha1\n"
+ " Partition Name: system\n"
+ " Salt: d00df00d\n"
+ " Root Digest: d20d40c02298e385ab6d398a61a3b91dc9947d99\n"
+ " Flags: 0\n",
+ InfoImage("system-vbmeta.img"));
+}
+
+TEST_F(BaseFsAvbTest, GenerateVBMetaImageWithDescriptors) {
+ // Generates a raw boot.img
+ const size_t boot_image_size = 5 * 1024 * 1024;
+ const size_t boot_partition_size = 10 * 1024 * 1024;
+ base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
+ // Adds AVB Hash Footer.
+ AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA4096", 10,
+ data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ // Generates a raw system.img, use a smaller size to speed-up unit test.
+ const size_t system_image_size = 10 * 1024 * 1024;
+ const size_t system_partition_size = 15 * 1024 * 1024;
+ base::FilePath system_path = GenerateImage("system.img", system_image_size);
+ // Adds AVB Hashtree Footer.
+ AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA8192", 20,
+ data_dir_.Append("testkey_rsa8192.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ // Makes a vbmeta.img including both 'boot' and 'system' descriptors.
+ GenerateVBMetaImage("vbmeta.img", "SHA256_RSA2048", 0, data_dir_.Append("testkey_rsa2048.pem"),
+ {boot_path, system_path}, /* include_descriptor_image_paths */
+ {}, /* chain_partitions */
+ "--internal_release_string \"unit test\"");
+ EXPECT_EQ("a069cbfc30c816cddf3b53f1ad53b7ca5d61a3d93845eb596bbb1b40caa1c62f",
+ CalcVBMetaDigest("vbmeta.img", "sha256"));
+ EXPECT_EQ(
+ "Minimum libavb version: 1.0\n"
+ "Header Block: 256 bytes\n"
+ "Authentication Block: 320 bytes\n"
+ "Auxiliary Block: 960 bytes\n"
+ "Algorithm: SHA256_RSA2048\n"
+ "Rollback Index: 0\n"
+ "Flags: 0\n"
+ "Release String: 'unit test'\n"
+ "Descriptors:\n"
+ " Hash descriptor:\n"
+ " Image Size: 5242880 bytes\n"
+ " Hash Algorithm: sha256\n"
+ " Partition Name: boot\n"
+ " Salt: d00df00d\n"
+ " Digest: "
+ "222dd01e98284a1fcd7781f85d1392e43a530511a64eff96db197db90ebc4df1\n"
+ " Flags: 0\n"
+ " Hashtree descriptor:\n"
+ " Version of dm-verity: 1\n"
+ " Image Size: 10485760 bytes\n"
+ " Tree Offset: 10485760\n"
+ " Tree Size: 86016 bytes\n"
+ " Data Block Size: 4096 bytes\n"
+ " Hash Block Size: 4096 bytes\n"
+ " FEC num roots: 2\n"
+ " FEC offset: 10571776\n"
+ " FEC size: 90112 bytes\n"
+ " Hash Algorithm: sha1\n"
+ " Partition Name: system\n"
+ " Salt: d00df00d\n"
+ " Root Digest: a3d5dd307341393d85de356c384ff543ec1ed81b\n"
+ " Flags: 0\n",
+ InfoImage("vbmeta.img"));
+}
+
+TEST_F(BaseFsAvbTest, GenerateVBMetaImageWithChainDescriptors) {
+ // Generates a raw boot.img
+ const size_t boot_image_size = 5 * 1024 * 1024;
+ const size_t boot_partition_size = 10 * 1024 * 1024;
+ base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
+ // Adds AVB Hash Footer.
+ AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
+ data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ // Generates a raw system.img, use a smaller size to speed-up unit test.
+ const size_t system_image_size = 10 * 1024 * 1024;
+ const size_t system_partition_size = 15 * 1024 * 1024;
+ base::FilePath system_path = GenerateImage("system.img", system_image_size);
+ // Adds AVB Hashtree Footer.
+ AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
+ data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ // Make a vbmeta image with chain partitions.
+ base::FilePath rsa2048_public_key =
+ ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
+ base::FilePath rsa4096_public_key =
+ ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
+ GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0, data_dir_.Append("testkey_rsa8192.pem"),
+ {}, /* include_descriptor_image_paths */
+ {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
+ {"system", 2, rsa4096_public_key}},
+ "--internal_release_string \"unit test\"");
+
+ // vbmeta digest calculation includes the chained vbmeta from boot.img and system.img.
+ EXPECT_EQ("abbe11b316901f3336e26630f64c4732dadbe14532186ac8640e4141a403721f",
+ CalcVBMetaDigest("vbmeta.img", "sha256"));
+ EXPECT_EQ(
+ "Minimum libavb version: 1.0\n"
+ "Header Block: 256 bytes\n"
+ "Authentication Block: 1088 bytes\n"
+ "Auxiliary Block: 3840 bytes\n"
+ "Algorithm: SHA256_RSA8192\n"
+ "Rollback Index: 0\n"
+ "Flags: 0\n"
+ "Release String: 'unit test'\n"
+ "Descriptors:\n"
+ " Chain Partition descriptor:\n"
+ " Partition Name: boot\n"
+ " Rollback Index Location: 1\n"
+ " Public key (sha1): cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
+ " Chain Partition descriptor:\n"
+ " Partition Name: system\n"
+ " Rollback Index Location: 2\n"
+ " Public key (sha1): 2597c218aae470a130f61162feaae70afd97f011\n",
+ InfoImage("vbmeta.img"));
+}
+
+} // namespace fs_avb_host_test
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/fs_mgr/libfs_avb/tests/data/testkey_rsa2048.pem b/fs_mgr/libfs_avb/tests/data/testkey_rsa2048.pem
new file mode 100644
index 0000000..867dcff
--- /dev/null
+++ b/fs_mgr/libfs_avb/tests/data/testkey_rsa2048.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAxlVR3TIkouAOvH79vaJTgFhpfvVKQIeVkFRZPVXK/zY0Gvrh
+4JAqGjJoW/PfrQv5sdD36qtHH3a+G5hLZ6Ni+t/mtfjucxZfuLGC3kmJ1T3XqEKZ
+gXXI2IR7vVSoImREvDQGEDyJwtHzLANlkbGg0cghVhWZSCAndO8BenalC2v94/rt
+DfkPekH6dgU3Sf40T0sBSeSY94mOzTaqOR2pfV1rWlLRdWmo33zeHBv52Rlbt0dM
+uXAureXWiHztkm5GCBC1dgM+CaxNtizNEgC91KcD0xuRCCM2WxH+r1lpszyIJDct
+YbrFmVEYl/kjQpafhy7Nsk1fqSTyRdriZSYmTQIDAQABAoIBAQC+kJgaCuX8wYAn
+SXWQ0fmdZlXnMNRpcF0a0pD0SAzGb1RdYBXMaXiqtyhiwc53PPxsCDdNecjayIMd
+jJVXPTwLhTruOgMS/bp3gcgWwV34UHV4LJXGOGAE+jbS0hbDBMiudOYmj6RmVshp
+z9G1zZCSQNMXHaWsEYkX59XpzzoB384nRul2QgEtwzUNR9XlpzgtJBLk3SACkvsN
+mQ/DW8IWHXLg8vLn1LzVJ2e3B16H4MoE2TCHxqfMgr03IDRRJogkenQuQsFhevYT
+o/mJyHSWavVgzMHG9I5m+eepF4Wyhj1Y4WyKAuMI+9dHAX/h7Lt8XFCQCh5DbkVG
+zGr34sWBAoGBAOs7n7YZqNaaguovfIdRRsxxZr1yJAyDsr6w3yGImDZYju4c4WY9
+5esO2kP3FA4p0c7FhQF5oOb1rBuHEPp36cpL4aGeK87caqTfq63WZAujoTZpr9Lp
+BRbkL7w/xG7jpQ/clpA8sHzHGQs/nelxoOtC7E118FiRgvD/jdhlMyL9AoGBANfX
+vyoN1pplfT2xR8QOjSZ+Q35S/+SAtMuBnHx3l0qH2bbBjcvM1MNDWjnRDyaYhiRu
+i+KA7tqfib09+XpB3g5D6Ov7ls/Ldx0S/VcmVWtia2HK8y8iLGtokoBZKQ5AaFX2
+iQU8+tC4h69GnJYQKqNwgCUzh8+gHX5Y46oDiTmRAoGAYpOx8lX+czB8/Da6MNrW
+mIZNT8atZLEsDs2ANEVRxDSIcTCZJId7+m1W+nRoaycLTWNowZ1+2ErLvR10+AGY
+b7Ys79Wg9idYaY9yGn9lnZsMzAiuLeyIvXcSqgjvAKlVWrhOQFOughvNWvFl85Yy
+oWSCMlPiTLtt7CCsCKsgKuECgYBgdIp6GZsIfkgclKe0hqgvRoeU4TR3gcjJlM9A
+lBTo+pKhaBectplx9RxR8AnsPobbqwcaHnIfAuKDzjk5mEvKZjClnFXF4HAHbyAF
+nRzZEy9XkWFhc80T5rRpZO7C7qdxmu2aiKixM3V3L3/0U58qULEDbubHMw9bEhAT
+PudI8QKBgHEEiMm/hr9T41hbQi/LYanWnlFw1ue+osKuF8bXQuxnnHNuFT/c+9/A
+vWhgqG6bOEHu+p/IPrYm4tBMYlwsyh4nXCyGgDJLbLIfzKwKAWCtH9LwnyDVhOow
+GH9shdR+sW3Ew97xef02KAH4VlNANEmBV4sQNqWWvsYrcFm2rOdL
+-----END RSA PRIVATE KEY-----
diff --git a/fs_mgr/libfs_avb/tests/data/testkey_rsa4096.pem b/fs_mgr/libfs_avb/tests/data/testkey_rsa4096.pem
new file mode 100644
index 0000000..26db5c3
--- /dev/null
+++ b/fs_mgr/libfs_avb/tests/data/testkey_rsa4096.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEA2ASv49OEbH4NiT3CjNMSVeliyfEPXswWcqtEfCxlSpS1FisA
+uwbvEwdTTPlkuSh6G4SYiNhnpCP5p0vcSg/3OhiuVKgV/rCtrDXaO60nvK/o0y83
+NNZRK2xaJ9eWBq9ruIDK+jC0sYWzTaqqwxY0Grjnx/r5CXerl5PrRK7PILzwgBHb
+IwxHcblt1ntgR4cWVpO3wiqasEwBDDDYk4fw7W6LvjBb9qav3YB8RV6PkZNeRP64
+ggfuecq/MXNiWOPNxLzCER2hSr/+J32h9jWjXsrcVy8+8Mldhmr4r2an7c247aFf
+upuFGtUJrpROO8/LXMl5gPfMpkqoatjTMRH59gJjKhot0RpmGxZBvb33TcBK5SdJ
+X39Y4yct5clmDlI4Fjj7FutTP+b96aJeJVnYeUX/A0wmogBajsJRoRX5e/RcgZsY
+RzXYLQXprQ81dBWjjovMJ9p8XeT6BNMFC7o6sklFL0fHDUE/l4BNP8G1u3Bfpzev
+SCISRS71D4eS4oQB+RIPFBUkzomZ7rnEF3BwFeq+xmwfYrP0LRaH+1YeRauuMuRe
+ke1TZl697a3mEjkNg8noa2wtpe7EWmaujJfXDWxJx/XEkjGLCe4z2qk3tkkY+A5g
+Rcgzke8gVxC+eC2DJtbKYfkv4L8FMFJaEhwAp13MfC7FlYujO/BDLl7dANsCAwEA
+AQKCAgAWoL8P/WsktjuSwb5sY/vKtgzcHH1Ar942GsysuTXPDy686LpF3R8T/jNy
+n7k2UBAia8xSoWCR6BbRuHeV5oA+PLGeOpE7QaSfonB+yc+cy0x3Or3ssfqEsu/q
+toGHp75/8DXS6WE0K04x94u1rdC9b9sPrrGBlWCLGzqM0kbuJfyHXdd3n2SofAUO
+b5QRSgxD+2tHUpEroHqHnWJCaf4J0QegX45yktlfOYNK/PHLDQXV8ly/ejc32M4Y
+Tv7hUtOOJTuq8VCg9OWZm2Zo1QuM9XEJTPCp5l3+o5vzO6yhk2gotDvD32CdA+3k
+tLJRP54M1Sn+IXb1gGKN9rKAtGJbenWIPlNObhQgkbwG89Qd+5rfMXsiPv1Hl1tK
++tqwjD82/H3/ElaaMnwHCpeoGSp95OblAoBjzjMP2KsbvKSdL8O/rf1c3uOw9+DF
+cth0SA8y3ZzI11gJtb2QMGUrCny5n4sPGGbc3x38NdLhwbkPKZy60OiT4g2kNpdY
+dIitmAML2otttiF4AJM6AraPk8YVzkPLTksoL3azPBya5lIoDI2H3QvTtSvpXkXP
+yKchsDSWYbdqfplqC/X0Djp2/Zd8jpN5I6+1aSmpTmbwx/JTllY1N89FRZLIdxoh
+2k81LPiXhE6uRbjioJUlbnEWIpY2y2N2Clmxpjh0/IcXd1XImQKCAQEA7Zai+yjj
+8xit24aO9Tf3mZBXBjSaDodjC2KS1yCcAIXp6S7aH0wZipyZpQjys3zaBQyMRYFG
+bQqIfVAa6inWyDoofbAJHMu5BVcHFBPZvSS5YhDjc8XZ5dqSCxzIz9opIqAbm+b4
+aEV/3A3Jki5Dy8y/5j21GAK4Y4mqQOYzne7bDGi3Hyu041MGM4qfIcIkS5N1eHW4
+sDZJh6+K5tuxN5TX3nDZSpm9luNH8mLGgKAZ15b1LqXAtM5ycoBY9Hv082suPPom
+O+r0ybdRX6nDSH8+11y2KiP2kdVIUHCGkwlqgrux5YZyjCZPwOvEPhzSoOS+vBiF
+UVXA8idnxNLk1QKCAQEA6MIihDSXx+350fWqhQ/3Qc6gA/t2C15JwJ9+uFWA+gjd
+c/hn5HcmnmBJN4R04nLG/aU9SQur87a4mnC/Mp9JIARjHlZ/WNT4U0sJyPEVRg5U
+Z9VajAucWwi0JyJYCO1EMMy68Jp8qlTriK/L7nbD86JJ5ASxjojiN/0psK/Pk60F
+Rr+shKPi3jRQ1BDjDtAxOfo4ctf/nFbUM4bY0FNPQMP7WesoSKU0NBCRR6d0d2tq
+YflMjIQHx+N74P5jEdSCHTVGQm+dj47pUt3lLPLWc0bX1G/GekwXP4NUsR/70Hsi
+bwxkNnK2TSGzkt2rcOnutP125rJu6WpV7SNrq9rm7wKCAQAfMROcnbWviKHqnDPQ
+hdR/2K9UJTvEhInASOS2UZWpi+s1rez9BuSjigOx4wbaAZ4t44PW7C3uyt84dHfU
+HkIQb3I5bg8ENMrJpK9NN33ykwuzkDwMSwFcZ+Gci97hSubzoMl/IkeiiN1MapL4
+GhLUgsD+3UMVL+Y9SymK8637IgyoCGdiND6/SXsa8SwLJo3VTjqx4eKpX7cvlSBL
+RrRxc50TmwUsAhsd4CDl9YnSATLjVvJBeYlfM2tbFPaYwl1aR8v+PWkfnK0efm60
+fHki33HEnGteBPKuGq4vwVYpn6bYGwQz+f6335/A2DMfZHFSpjVURHPcRcHbCMla
+0cUxAoIBAQC25eYNkO478mo+bBbEXJlkoqLmvjAyGrNFo48F9lpVH6Y0vNuWkXJN
+PUgLUhAu6RYotjGENqG17rz8zt/PPY9Ok2P3sOx8t00y1mIn/hlDZXs55FM0fOMu
+PZaiscAPs7HDzvyOmDah+fzi+ZD8H2M3DS2W+YE0iaeJa2vZJS2t02W0BGXiDI33
+IZDqMyLYvwwPjOnShJydEzXID4xLl0tNjzLxo3GSNA7jYqlmbtV8CXIc7rMSL6WV
+ktIDKKJcnmpn3TcKeX6MEjaSIT82pNOS3fY3PmXuL+CMzfw8+u77Eecq78fHaTiL
+P5JGM93F6mzi19EY0tmInUBMCWtQLcENAoIBAQCg0KaOkb8T36qzPrtgbfou0E2D
+ufdpL1ugmD4edOFKQB5fDFQhLnSEVSJq3KUg4kWsXapQdsBd6kLdxS+K6MQrLBzr
+4tf0c7UCF1AzWk6wXMExZ8mRb2RkGZYQB2DdyhFB3TPmnq9CW8JCq+6kxg/wkU4s
+vM4JXzgcqVoSf42QJl+B9waeWhg0BTWx01lal4ds88HvEKmE0ik5GwiDbr7EvDDw
+E6UbZtQcIoSTIIZDgYqVFfR2DAho3wXJRsOXh433lEJ8X7cCDzrngFbQnlKrpwML
+Xgm0SIUc+Nf5poMM3rfLFK77t/ob4w+5PwRKcoSniyAxrHd6bwykYA8Vuydv
+-----END RSA PRIVATE KEY-----
diff --git a/fs_mgr/libfs_avb/tests/data/testkey_rsa8192.pem b/fs_mgr/libfs_avb/tests/data/testkey_rsa8192.pem
new file mode 100644
index 0000000..a383428
--- /dev/null
+++ b/fs_mgr/libfs_avb/tests/data/testkey_rsa8192.pem
@@ -0,0 +1,99 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIISKgIBAAKCBAEA0D3T+dISsmCHm797wsX0vVfqUWDJ/3mvDYozlCabDhnGLlSE
+pAQbf1Z8Ts+OM4pVRHOJUJL0WebNdmPPGjsyWQz6zZE96lQZL3avCEXqYVQR66V5
+3wdK/ohaMSRnGyEMBrqkVVbF3gCr+/irxD3YK+VowO2WKs/6GrMdqTA8Y5CTF/Je
+ptwsSg5MMjr6UaK4qDcrej3hkgBVGvRV3cj1snK6Br8HuYdFnpGGTS0d7UJlHFgl
+trGHU/CBO923hkHgJaWEjC0giSGjhKKtLzrVcpDV2y/lWQP9T/T4djEAIaHqQ++P
+SdOSR6psIGR6hVgSigt7HCnE7nW711/rfV5Ur9EiVpB040mDImKZcy8//TMnXydN
+1KYTVd/34fdpzMpSw5iblErbwOLXVTUmOztYnpl41feHSv/jPesHstPlfklIF2vo
+GZEohf9scQvcuM7wEBfC/aTA9K39zMmkBbcvSZjLyhmcSZWMPPOZyIcl3zY53QhW
+QC/abmIcBfI1S4+r7mC4i2Jn++oEvuGNVGr2SY2Z0ZZxXGL1HI/08D/3+Tcumrcn
+4YjPK/DMFi0F+e+1x41lipuf+cx/2qRNQX/m02STrLYdM6e0g33KvlnFdi2b752y
+/OIaMwxDaJvunMh6EMDWKM1AHbY/ioAoK7eS26HeJLEDllqO4+SWP37c8lMvSEWy
+1GiErR0HcsOj/QwWGPFseoVroMiA2sUQ0Ic/tgVjCTlXg+12XpUnouIweCi8KcL/
+ad2zJkju9hBhJLBQ/2GnivJi3lFgF4Gd//TSJ6rgWuXFfMKt/9z2Sz35ohEX4yA0
+flqlCeLInFEoevbz+XT9aRfDe65MZ79yw3TfP9CrV74hf1RRzveD4zpi3F+hcY2i
+JWsH7gROZeCm6fAX5Trecd3hOxJOfA4N4rvSSCq6BwCvebT8FY25Z/VF7cQrHYDS
+ij5w6lqhMzXHeUEY90Ga9AK4XzaWwGgezq+R7Zs00YSKqFv9qYNKdR7tz3cjijWf
+9q/3R1uh6EQKTMZKo4SEClJiGyjOBvmPK09jMFZTJv00hDxagDPZBl7XpLDJ5/Ln
+1uppvLCNWWY1zeJfaElMyq3/PqKZLidF9rVoA1SIwk2lpdUvPote2oFiwCZoXlwZ
+J2ncjmXgQNs76/8unDJA0rj4JPqccw4M5GxQ7okbgm3F4rmzriCuv8BeMSCkr2ry
+0mY3UhpohX4wCMq0G4x5sEUAz9FVVPZKjxnYBmLDzrJAR+4+G7gZsct01XDJYgDd
+JVYInFP22/cIre8VrFWYtHbgOFdNqUiVq58de6PdZG/E+uaWmEThSlRrgEjTxupi
+OXfgdKW/20j1qAtjOlqFwsY094Q5rqULQ6wPxQIDAQABAoIEAQChmkmlhrRBv42d
+fYUiyxK52b8ath0saJdDz6tlXmxYDgJxM9/XlORt9oTzeDknoEO5olu+rrx4BBgQ
+tzYiaiwRVXRREVTWQ7tjzRvaNL/GFkLt93XTccpuKwyrNE/bitLVagRbwcI+HZFa
+MknCOihHMHoRto8h3FKAY94xzSAgODMek1WG8jhgpCXXmVNnBPt+d4oDDIDAGAfz
+qgf03J5nhIb+80KgZOzPOKnbvJaL6EmlLHbgB3c42dzAw7hHtVmofYGWcvLb2MIY
+DVKO435/sQx1U/8NDH6JjVdACZjLgObXH9K3/Tt46DWPEcrPLmD8xhoc6gFM+Qr0
+AhkzKoBYDNk0CljbhdIBXjktXU6wRQFZ45uP2e4JZ4zrzGBLr/t4lTavZ0SQtLld
+A6kOsGh+dCWFDtnshxYnl/xad/yR+3a5zmDJbo/fJTBXrlf1B4rfQkFtK20etOPQ
+B++FC/rjh3Mm/Kb/p9Gz/2upZdArH97ZvD2LBFfj77lFmAhqAi3wCRlN+ekuYxaZ
+t1pBV9yXig8Dyldg1d7X8pOn2kyrF3rQUDDf4pa7x9vpnbkUlEUifoV9gnYsmdni
+qDzYBtTv2g6MKqwQySXaIUW0YOBPbOellWEwxJqGYQ7y4IfVHfM0iyHnehk2tZcr
++XazLnwGe+Bz4vcguFhJXLyIu//lAOhZtbk6r1QJEUuxaOOQX3wzyceE6nkDsgmr
+P5dj3Zpd7fS2VV2vyGHIFnBJ88LRxreVvgr6Q28UT27SB82zMb7mRZTVE2zeuubT
+5D2D1XbZ0wBo6WiK6eRRrDQ2Haeetkj/uoRy6PWXwnAaTmmIrrXwLqaoJh/U1e+D
+tfsDLWd6IxLjfXvGglrHsrtAz0oprpixUTeVhgTrGk9IQRd5rvxuGUYhFujVaYI6
++QUf+33AFdtncb8y9C9jZmgx8AKbJk+e73SLhB5JVos+WteU7b8d/Mim5mALjnO6
+Z1n/uimsT79sSDqy3XSymtKWXo/22UlrvGCpoEuELPMb6dSFWR7vwrsvhFngY4/K
+UnitnvxboEflQnaIQ4IfRLRzZsX+sC5Esqw9U5tHt4oI+91Dv3KbdbcERgV73K6B
+ZQgC4lkAQquFXiZ5AICkxjiMyZwTtU9KJ7xv17Xu6oywF/3AtbVGETW1D+3maHsD
+y3DASWojyqZdLj+WGzKQRa+swgCDAYKeek2fIAXFSdF63zxJ2RxOJ4GijSaoh+mr
+4HVvcpDaTj+A8T1+QdByM4s98gu4GD7kVtVQGBZdWjutyHvh0hWv1gtVmbhQ/413
+gDMFFDzHIjLTYGYes4hHL22169jVR9sZ1eQxwvTIg3N4pD5cFm0rRuZZTS+oJToF
+G27aBFihAoICAQDyVB62ZDnbxQthk+zITKIzRUrJbLoXrUcANcSHfaN7inF87Ova
+ze7ejT9DNSEhbtfZFJ1G6diOYoSw+2MzFXv0gEkLKY0dETydKgHEu6nVq5eivMgv
+D4hc9YkJMHDSlmv2FDkpL3AXCAmnW9rKp+ddttBZECnmlPEpHLoj6xgBw3pNa1Xs
+IcLVfdugH86Hexj6o0oKgYfcqrX8UUHtUI2/XQqgFrIj8ksjf1fFVWJRJFWmBXqp
+nMEsYarzATeM1kQ/kDeT1ZUpoGPQt02/XqXT4B5A3ATiEtpM2u+l48xtogWWg2Ry
+G9l938StAmhUiW1m7GnKE6EIFvQY85WvbzxOR0JYVUSr7MrasF6nnQlhYxFuIJoJ
+2h/KJQao5GCTvG4+GtbJJm4c2nyZgwyhizMsdgsdcls79aXiMkrZZkamLVUZWOtE
+3pA/oBuz2qnO9HwjbH1HGOccq0TXfmpFScEV3CQGYJdno6Fy7cbmupaL4U9agQ4e
+w+ygL18nq5HV++LStFnVrgs5YijjskfRdE9GUMVDh5pCsd9Y23Fymaad4O/2SRCC
+YkSsyH5OvyDOLpoyUJ6g6Q+45Hqm/3lG4YjNpzFUiMcnp7+3xU35qC0LK8xEfeei
+Ms1mTVEiHNIp6xH/TqRdX73WD7+YuKZSLIfRG7dgrirU6w+mhhvxD51uHQKCAgEA
+2/1mBCR5qm3/0Lt++RQbeyE3tiw40UeyQqucG/+VvY77sSLkI/Lx8iwRlywXcLBn
++A4TvgukmAdWzCs8ndgKNxPA+gfohvBsMOGN9KOB1Ug5vvg2J2kiI64vwYCwzhdZ
+NTUUmL+GMFHUqSsWYg6i7iBFcZmznr4W2T3bBxyTMZki7JStB86e35KXrzc2/W/b
++/p5U2HCSazDHI5mMyuClHc6GmUSVJ7f7LHjL94jviNqobp0Vj603tScHISmNrZw
+TBavkvZGYXsoWKvqavk7jBB9QzaBL+unaFRslg5jTaiKnISj44Us1fjFKu84xifL
+nJaEzjDPt7PBxko7LPgEY7wF39nM9VpoetI7bwR6NwDLSX8UU97MGd+HY+MO1Wi1
+pd2Lapwrx/EK7Oxz335VRK4Je0aZna4j2TyQdMJac9fsGPXv4ZsLfDLj/wD6l1j+
+lLLbBv3ImdSj32LBbhsgF4iCGeXO8HpPO+Q/h9XVsnY52Um2XdNMn03PCGm6ZvtM
+7DXiS+lPF90HjolJVHZTBNtdVRrLr53zLuWEfqT4FeKrDaxdtiXkxLjrB+5/VYu7
+ntyk01ZQ63VNfEwS1irmKl9+qZkTHk3HHV9jNV5RzWViwmJI7Wpr1YzBwmcKCB1O
+oGUADDs8QpnkCz0xkMVtYwHj9qKZlqfbHzrFDUUcF8kCggIAdYvUcgjf//ju8mA8
+5VQ3AcPE6TvycPW+kR2DvW12VcDsF/sc1UA7dHzziPhGn98SmNxlBjb8suSbFPZ8
+QhVT0WBBDkcTilwIGPx9ax7U3S6lGW2VdS6FqQH5fRmgQKZyrCVXLOEz8BgYBrSJ
+xu/3TQAWxH0QtibdbGHg8Pdi58gYlWFRhn9B8Slh1aRYHGPb1AhNLBd0/ddY+5G2
+9xSyDXdmZg1cUA+B3zAwNSqbzFxhp2zU+V1uXsbpk4KtnYV6CZM9QlrCRjTk9iNU
+dVXF/qaiRjfzrm4SsmEpCkEbsrp7F22Y1bkooORglMOsNAWNqfVXw4wN+syXj1ro
+6vZ8PERYrFyAOR1dsQMIhymnmTPjCpaJ4emKrhWTy20sY71thHakZWJc22YoNpbZ
+E6tgIVsJPTlxg/4+fyCCKj5wWr92nhsB1KBZPGO/zFhvMlJpvQ0tH8W2pbN2a0mI
+5x9FqALm/qjwCHfZItSwPM+ZozSht3cOkGHdcD5KXAXfcfsDJc4SHZKVIzq4NusN
+504R/jvD1GP8sglyG7omp75ckgzAmakLdxOP2HhQvIX9tcXpSirNJ6Sl2bwKuuMF
+wxo3r/o/9Y97e4LlfpEYp9eqMdcG+NpR993IwK0UhAWS9H5wdnWBSUHd5e4xtDUt
+iILNRuO46g7R/AIhz1cSSraWWQkCggIBAMhhPP5C9yt9PIm1b0eTwCBctnFSQIKo
+KsA9rll2ab+bMLk9jc8M6MLszy0CtWso09sHf4YY9tifvrkEHRethEh8zscwUuYu
+sm2n1fTixk0ul6LSVgl54uXbMJayENn4PIKRkew8cA8tSma43497w37hmD+MgCb1
+ALzqcco9hfmkgkI6fo1g8Ce3UEECKy2YKSmREdgYcK9JFQO61W6AkFWJcDxAmfzI
+JjFkKwsb7TSw79zWiEdSoM9jm7sCPKATd6Bm/ZAAkUUTuEFkfobn9Ax1rJN/Xxb2
+MKuAUtQv0NYY0gEVdG62jItuKLId6nncH8PG+rsRjPLIYpWqYdJpKx5pUnR+4AkQ
+S6CsRASwcF4PdBvDDBIFG6XpjFo4pPdQhDzL2sTF8b8SWSBLlJQbb7G6UNqgCSau
+SusCFpazvU5NfDmUMuctob2EYVaSXq9jGaj6bTUmDwXHwWilfIk9XfLxnYfXYrJ6
+xhdIpXGmHhuLQtAgK2O1JtLoPc9s9qP8/SkfP7xjjG6xHsP/WvL7QE1pPs9ZM/UI
+C01JNHFi9LKCn8o5mbZjN8jUowi7ffK+76wZUG1L7zM5ytWQOYwo0TQBfc8fpmFw
++RBRJX2kJyDO27ExczoGOKjwqEDaODIB9+9zcCK0BgSoRibSm4ZBvoxzWWD65Kls
+xdPhZUHcFGW5AoICAQC8iG27aD8aRUt94Oek66gFOJx84QVZehWPqtZjWyVenDuc
+T8dink8oejGjcK2UJuQDa83azv90ocVqE0n0ronYyszt9Ib1jlYC+CK1Ar9TYGFg
+WU5OWEDyCzCpqW/w/aG68U8qhKm0MvkLJR+G6evan9TwEhFEVAm3iWllNXs9x29s
+BucwyMMC23zsimxYlS7dA4DtyvVA+zL1omLpSWHbU/qtuI3HV1NeJzsy+gC4mwPh
+j52tdl669fyWLzHzBRLeq6dVOedjnCo+jlU3dL20DEk9SaW08D1CPuZekV1jVPMw
+JoaDcIRh4KLtQ0BYZ7UJeFUTsx1CS/+UqzqYSPOi57a5kvr0Y8YwRnSB8dHVFttX
+JTv83wTQXHPFSBgfnHNe7lsRTfIQfuIkr2bpiU7h85UQ7LsqcI6YHaC07URcsGFF
+FrLWGh91qzAd1diSHla2RnY3n8PPuMnCkguNhLUrYdmyMol7FfWFa9lwplsuTzBq
+B6yj8iaiE3LL+Q/eulJ7S6QPfAI2bU0UJO23Y4koeoIibEEDMSCQ6KYZ2NClRRRT
+ga5fS1YfkDFEcHUQ1/KIkdYHGBKBjoKGExzi8+CgiSySVSYDZl6wIOhLjH2OZ3ol
+ldPN7iNAHirrxg9v8QO6OQlpLUk5Lhp/1dSlZ6sy3UjFqvax3tw6ZjrL88YP5g==
+-----END RSA PRIVATE KEY-----
diff --git a/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp b/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
new file mode 100644
index 0000000..95b17d8
--- /dev/null
+++ b/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
@@ -0,0 +1,220 @@
+/*
+ * 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_avb_test_util.h"
+
+#include <stdlib.h>
+
+#include <android-base/file.h>
+#include <base/files/file_util.h>
+#include <base/strings/string_util.h>
+
+namespace fs_avb_host_test {
+
+// Need to match the data setting in Android.bp:
+// data: ["tests/data/*"]
+base::FilePath BaseFsAvbTest::data_dir_ = base::FilePath("tests/data");
+
+void BaseFsAvbTest::SetUp() {
+ // Changes current directory to test executable directory so that relative path
+ // references to test dependencies don't rely on being manually run from
+ // the executable directory. With this, we can just open "./tests/data/testkey_rsa2048.pem"
+ // from the source.
+ base::SetCurrentDirectory(base::FilePath(android::base::GetExecutableDirectory()));
+
+ // Creates a temporary directory, e.g., /tmp/libfs_avb-tests.XXXXXX to stash images in.
+ base::FilePath tmp_dir;
+ ASSERT_TRUE(GetTempDir(&tmp_dir));
+ base::CreateTemporaryDirInDir(tmp_dir, "libfs_avb-tests.", &test_dir_);
+}
+
+void BaseFsAvbTest::TearDown() {
+ // Nukes temporary directory.
+ ASSERT_NE(std::string::npos, test_dir_.value().find("libfs_avb-tests"));
+ ASSERT_TRUE(base::DeleteFile(test_dir_, true /* recursive */));
+}
+
+std::string BaseFsAvbTest::CalcVBMetaDigest(const std::string& file_name,
+ const std::string& hash_algorithm) {
+ auto iter = vbmeta_images_.find(file_name);
+ EXPECT_NE(iter, vbmeta_images_.end()); // ensures file_name is generated before.
+
+ // Gets the image path from iterator->second.path: VBMetaImage.path.
+ base::FilePath image_path = iter->second.path;
+ base::FilePath vbmeta_digest_path = test_dir_.Append("vbmeta_digest");
+ EXPECT_COMMAND(0,
+ "avbtool calculate_vbmeta_digest --image %s --hash_algorithm %s"
+ " --output %s",
+ image_path.value().c_str(), hash_algorithm.c_str(),
+ vbmeta_digest_path.value().c_str());
+ // Reads the content of the output digest file.
+ std::string vbmeta_digest_data;
+ EXPECT_TRUE(base::ReadFileToString(vbmeta_digest_path, &vbmeta_digest_data));
+ // Returns the trimmed digest.
+ std::string trimmed_digest_data;
+ base::TrimString(vbmeta_digest_data, " \t\n", &trimmed_digest_data);
+ return trimmed_digest_data;
+}
+
+void BaseFsAvbTest::GenerateVBMetaImage(
+ const std::string& file_name, const std::string& avb_algorithm, uint64_t rollback_index,
+ const base::FilePath& key_path,
+ const std::vector<base::FilePath>& include_descriptor_image_paths,
+ const std::vector<ChainPartitionConfig>& chain_partitions,
+ const std::string& additional_options) {
+ // --algorithm and --key
+ std::string signing_options;
+ if (avb_algorithm == "") {
+ signing_options = " --algorithm NONE ";
+ } else {
+ signing_options =
+ std::string(" --algorithm ") + avb_algorithm + " --key " + key_path.value() + " ";
+ }
+ // --include_descriptors_from_image
+ std::string include_descriptor_options;
+ for (const auto& path : include_descriptor_image_paths) {
+ include_descriptor_options += " --include_descriptors_from_image " + path.value();
+ }
+ // --chain_partitions
+ std::string chain_partition_options;
+ for (const auto& partition : chain_partitions) {
+ chain_partition_options += base::StringPrintf(
+ " --chain_partition %s:%u:%s", partition.partition_name.c_str(),
+ partition.rollback_index_location, partition.key_blob_path.value().c_str());
+ }
+ // Starts to 'make_vbmeta_image'.
+ VBMetaImage vbmeta_image;
+ vbmeta_image.path = test_dir_.Append(file_name);
+ EXPECT_COMMAND(0,
+ "avbtool make_vbmeta_image"
+ " --rollback_index %" PRIu64
+ " %s %s %s %s"
+ " --output %s",
+ rollback_index, signing_options.c_str(), include_descriptor_options.c_str(),
+ chain_partition_options.c_str(), additional_options.c_str(),
+ vbmeta_image.path.value().c_str());
+ int64_t file_size;
+ ASSERT_TRUE(base::GetFileSize(vbmeta_image.path, &file_size));
+ vbmeta_image.content.resize(file_size);
+ ASSERT_TRUE(base::ReadFile(vbmeta_image.path,
+ reinterpret_cast<char*>(vbmeta_image.content.data()), file_size));
+ // Stores the generated vbmeta image into vbmeta_images_ member object.
+ vbmeta_images_.emplace(file_name, std::move(vbmeta_image));
+}
+
+void BaseFsAvbTest::ExtractVBMetaImage(const base::FilePath& image_path,
+ const std::string& output_file_name,
+ const size_t padding_size) {
+ VBMetaImage vbmeta_image;
+ vbmeta_image.path = test_dir_.Append(output_file_name);
+ EXPECT_COMMAND(0,
+ "avbtool extract_vbmeta_image"
+ " --image %s"
+ " --output %s"
+ " --padding_size %zu",
+ image_path.value().c_str(), vbmeta_image.path.value().c_str(), padding_size);
+ int64_t file_size;
+ ASSERT_TRUE(base::GetFileSize(vbmeta_image.path, &file_size));
+ vbmeta_image.content.resize(file_size);
+ ASSERT_TRUE(base::ReadFile(vbmeta_image.path,
+ reinterpret_cast<char*>(vbmeta_image.content.data()), file_size));
+ // Stores the extracted vbmeta image into vbmeta_images_ member object.
+ vbmeta_images_.emplace(output_file_name, std::move(vbmeta_image));
+}
+
+// Generates a file with name |file_name| of size |image_size| with
+// known content (0x00 0x01 0x02 .. 0xff 0x00 0x01 ..).
+base::FilePath BaseFsAvbTest::GenerateImage(const std::string& file_name, size_t image_size,
+ uint8_t start_byte) {
+ std::vector<uint8_t> image;
+ image.resize(image_size);
+ for (size_t n = 0; n < image_size; n++) {
+ image[n] = uint8_t(n + start_byte);
+ }
+ base::FilePath image_path = test_dir_.Append(file_name);
+ EXPECT_EQ(image_size,
+ static_cast<const size_t>(base::WriteFile(
+ image_path, reinterpret_cast<const char*>(image.data()), image.size())));
+ return image_path;
+}
+
+void BaseFsAvbTest::AddAvbFooter(const base::FilePath& image_path, const std::string& footer_type,
+ const std::string& partition_name, const uint64_t partition_size,
+ const std::string& avb_algorithm, uint64_t rollback_index,
+ const base::FilePath& key_path, const std::string& salt,
+ const std::string& additional_options) {
+ // 'add_hash_footer' or 'add_hashtree_footer'.
+ EXPECT_TRUE(footer_type == "hash" or footer_type == "hashtree");
+ std::string add_footer_option = "add_" + footer_type + "_footer";
+
+ std::string signing_options;
+ if (avb_algorithm == "") {
+ signing_options = " --algorithm NONE ";
+ } else {
+ signing_options =
+ std::string(" --algorithm ") + avb_algorithm + " --key " + key_path.value() + " ";
+ }
+ EXPECT_COMMAND(0,
+ "avbtool %s"
+ " --image %s"
+ " --partition_name %s "
+ " --partition_size %" PRIu64 " --rollback_index %" PRIu64
+ " --salt %s"
+ " %s %s",
+ add_footer_option.c_str(), image_path.value().c_str(), partition_name.c_str(),
+ partition_size, rollback_index, salt.c_str(), signing_options.c_str(),
+ additional_options.c_str());
+}
+
+std::string BaseFsAvbTest::InfoImage(const base::FilePath& image_path) {
+ base::FilePath tmp_path = test_dir_.Append("info_output.txt");
+ EXPECT_COMMAND(0, "avbtool info_image --image %s --output %s", image_path.value().c_str(),
+ tmp_path.value().c_str());
+ std::string info_data;
+ EXPECT_TRUE(base::ReadFileToString(tmp_path, &info_data));
+ return info_data;
+}
+
+std::string BaseFsAvbTest::InfoImage(const std::string& file_name) {
+ auto iter = vbmeta_images_.find(file_name);
+ EXPECT_NE(iter, vbmeta_images_.end()); // ensures file_name is generated before.
+ // Gets the image path from iterator->second.path: VBMetaImage.path.
+ base::FilePath image_path = iter->second.path;
+ return InfoImage(image_path);
+}
+
+base::FilePath BaseFsAvbTest::ExtractPublicKeyAvb(const base::FilePath& key_path) {
+ std::string file_name = key_path.RemoveExtension().BaseName().value();
+ base::FilePath tmp_path = test_dir_.Append(file_name + "public_key.bin");
+ EXPECT_COMMAND(0,
+ "avbtool extract_public_key --key %s"
+ " --output %s",
+ key_path.value().c_str(), tmp_path.value().c_str());
+ return tmp_path;
+}
+
+std::string BaseFsAvbTest::ExtractPublicKeyAvbBlob(const base::FilePath& key_path) {
+ base::FilePath tmp_path = test_dir_.Append("public_key.bin");
+ EXPECT_COMMAND(0,
+ "avbtool extract_public_key --key %s"
+ " --output %s",
+ key_path.value().c_str(), tmp_path.value().c_str());
+ std::string key_data;
+ EXPECT_TRUE(base::ReadFileToString(tmp_path, &key_data));
+ return key_data;
+}
+
+} // namespace fs_avb_host_test
diff --git a/fs_mgr/libfs_avb/tests/fs_avb_test_util.h b/fs_mgr/libfs_avb/tests/fs_avb_test_util.h
new file mode 100644
index 0000000..f80dc5f
--- /dev/null
+++ b/fs_mgr/libfs_avb/tests/fs_avb_test_util.h
@@ -0,0 +1,114 @@
+/*
+ * 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 <inttypes.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <string>
+#include <vector>
+
+#include <base/files/file_path.h>
+#include <base/strings/stringprintf.h>
+#include <gtest/gtest.h>
+
+// Utility macro to run the command expressed by the printf()-style string
+// |command_format| using the system(3) utility function. Will assert unless
+// the command exits normally with exit status |expected_exit_status|.
+#define EXPECT_COMMAND(expected_exit_status, command_format, ...) \
+ do { \
+ int rc = system(base::StringPrintf(command_format, ##__VA_ARGS__).c_str()); \
+ EXPECT_TRUE(WIFEXITED(rc)); \
+ EXPECT_EQ(WEXITSTATUS(rc), expected_exit_status); \
+ } while (0);
+
+namespace fs_avb_host_test {
+
+struct VBMetaImage {
+ // Path to vbmeta image generated with GenerateVBMetaImage().
+ base::FilePath path;
+ // Contents of the image generated with GenerateVBMetaImage().
+ std::vector<uint8_t> content;
+};
+
+struct ChainPartitionConfig {
+ std::string partition_name;
+ uint32_t rollback_index_location;
+ base::FilePath key_blob_path;
+};
+
+/* Base-class used for unit test. */
+class BaseFsAvbTest : public ::testing::Test {
+ public:
+ BaseFsAvbTest() {}
+
+ protected:
+ virtual ~BaseFsAvbTest() {}
+
+ // Calculates the vbmeta digest using 'avbtool calc_vbmeta_digest' command.
+ // Note that the calculation includes chained vbmeta images.
+ std::string CalcVBMetaDigest(const std::string& file_name, const std::string& hash_algorithm);
+
+ // Generates a vbmeta image with |file_name| by avbtool.
+ // The generated vbmeta image will be written to disk, see the
+ // |vbmeta_images_| variable for its path and the content.
+ void GenerateVBMetaImage(const std::string& file_name, const std::string& avb_algorithm,
+ uint64_t rollback_index, const base::FilePath& key_path,
+ const std::vector<base::FilePath>& include_descriptor_image_paths,
+ const std::vector<ChainPartitionConfig>& chain_partitions,
+ const std::string& additional_options = "");
+ // Similar to above, but extracts a vbmeta image from the given image_path.
+ // The extracted vbmeta image will be written to disk, with |output_file_name|.
+ // See the |vbmeta_images_| variable for its path and the content.
+ void ExtractVBMetaImage(const base::FilePath& image_path, const std::string& output_file_name,
+ const size_t padding_size = 0);
+
+ // Generate a file with name |file_name| of size |image_size| with
+ // known content (0x00 0x01 0x02 .. 0xff 0x00 0x01 ..).
+ base::FilePath GenerateImage(const std::string& file_name, size_t image_size,
+ uint8_t start_byte = 0);
+ // Invokes 'avbtool add_hash_footer' or 'avbtool add_hashtree_footer' to sign
+ // the |image_path|. The |footer_type| can be either "hash" or "hashtree".
+ void AddAvbFooter(const base::FilePath& image_path, const std::string& footer_type,
+ const std::string& partition_name, const uint64_t partition_size,
+ const std::string& avb_algorithm, uint64_t rollback_index,
+ const base::FilePath& key_path, const std::string& salt = "d00df00d",
+ const std::string& additional_options = "");
+
+ // Returns the output of 'avbtool info_image' for the |image_path|.
+ std::string InfoImage(const base::FilePath& image_path);
+ // Same as above, but for an internal vbmeta image with |file_name| in |vbmeta_images_|.
+ std::string InfoImage(const std::string& file_name);
+
+ // Extracts public key blob in AVB format for a .pem key, then returns the
+ // file path: a .bin file.
+ base::FilePath ExtractPublicKeyAvb(const base::FilePath& key_path);
+ // Same as above, but returns the key blob binary instead.
+ std::string ExtractPublicKeyAvbBlob(const base::FilePath& key_path);
+
+ void SetUp() override;
+ void TearDown() override;
+
+ // Temporary directory created in SetUp().
+ base::FilePath test_dir_;
+ // Maps vbmeta image name (e.g., vbmeta_a.img, system_a.img) to VBMetaImage.
+ std::map<std::string, VBMetaImage> vbmeta_images_;
+
+ static base::FilePath data_dir_;
+};
+
+} // namespace fs_avb_host_test
diff --git a/fs_mgr/libfs_avb/tests/util_test.cpp b/fs_mgr/libfs_avb/tests/util_test.cpp
new file mode 100644
index 0000000..835e8fd
--- /dev/null
+++ b/fs_mgr/libfs_avb/tests/util_test.cpp
@@ -0,0 +1,211 @@
+/*
+ * 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 <unistd.h>
+#include <future>
+#include <string>
+#include <thread>
+
+#include <base/files/file_util.h>
+
+#include "fs_avb_test_util.h"
+#include "util.h"
+
+// Target functions to test:
+using android::fs_mgr::BytesToHex;
+using android::fs_mgr::HexToBytes;
+using android::fs_mgr::NibbleValue;
+using android::fs_mgr::WaitForFile;
+
+namespace fs_avb_host_test {
+
+TEST(BasicUtilTest, NibbleValue09) {
+ uint8_t value;
+
+ EXPECT_TRUE(NibbleValue('0', &value));
+ EXPECT_EQ(0, value);
+ EXPECT_TRUE(NibbleValue('1', &value));
+ EXPECT_EQ(1, value);
+ EXPECT_TRUE(NibbleValue('2', &value));
+ EXPECT_EQ(2, value);
+ EXPECT_TRUE(NibbleValue('3', &value));
+ EXPECT_EQ(3, value);
+ EXPECT_TRUE(NibbleValue('4', &value));
+ EXPECT_EQ(4, value);
+ EXPECT_TRUE(NibbleValue('5', &value));
+ EXPECT_EQ(5, value);
+ EXPECT_TRUE(NibbleValue('6', &value));
+ EXPECT_EQ(6, value);
+ EXPECT_TRUE(NibbleValue('7', &value));
+ EXPECT_EQ(7, value);
+ EXPECT_TRUE(NibbleValue('8', &value));
+ EXPECT_EQ(8, value);
+ EXPECT_TRUE(NibbleValue('9', &value));
+ EXPECT_EQ(9, value);
+}
+
+TEST(BasicUtilTest, NibbleValueAF) {
+ uint8_t value;
+
+ EXPECT_TRUE(NibbleValue('a', &value));
+ EXPECT_EQ(10, value);
+ EXPECT_TRUE(NibbleValue('b', &value));
+ EXPECT_EQ(11, value);
+ EXPECT_TRUE(NibbleValue('c', &value));
+ EXPECT_EQ(12, value);
+ EXPECT_TRUE(NibbleValue('d', &value));
+ EXPECT_EQ(13, value);
+ EXPECT_TRUE(NibbleValue('e', &value));
+ EXPECT_EQ(14, value);
+ EXPECT_TRUE(NibbleValue('f', &value));
+ EXPECT_EQ(15, value);
+
+ EXPECT_TRUE(NibbleValue('A', &value));
+ EXPECT_EQ(10, value);
+ EXPECT_TRUE(NibbleValue('B', &value));
+ EXPECT_EQ(11, value);
+ EXPECT_TRUE(NibbleValue('C', &value));
+ EXPECT_EQ(12, value);
+ EXPECT_TRUE(NibbleValue('D', &value));
+ EXPECT_EQ(13, value);
+ EXPECT_TRUE(NibbleValue('E', &value));
+ EXPECT_EQ(14, value);
+ EXPECT_TRUE(NibbleValue('F', &value));
+ EXPECT_EQ(15, value);
+}
+
+TEST(BasicUtilTest, NibbleValueInvalid) {
+ uint8_t value;
+
+ EXPECT_FALSE(NibbleValue('G', &value));
+ EXPECT_FALSE(NibbleValue('H', &value));
+ EXPECT_FALSE(NibbleValue('I', &value));
+ EXPECT_FALSE(NibbleValue('x', &value));
+ EXPECT_FALSE(NibbleValue('y', &value));
+ EXPECT_FALSE(NibbleValue('z', &value));
+}
+
+TEST(BasicUtilTest, HexToBytes) {
+ std::string hex = "000102030405060708090A0B0C0D0E0F";
+ uint8_t bytes[16];
+
+ EXPECT_TRUE(HexToBytes((uint8_t*)bytes, sizeof(bytes), hex));
+ for (size_t i = 0; i < sizeof(bytes); i++) {
+ EXPECT_EQ(i, bytes[i]);
+ }
+}
+
+TEST(BasicUtilTest, HexToBytes2) {
+ std::string hex = "101112131415161718191A1B1C1D1E1F";
+ uint8_t bytes[16];
+
+ EXPECT_TRUE(HexToBytes((uint8_t*)bytes, sizeof(bytes), hex));
+ for (size_t i = 0; i < sizeof(bytes); i++) {
+ EXPECT_EQ(16 + i, bytes[i]);
+ }
+}
+
+TEST(BasicUtilTest, BytesToHex) {
+ const uint8_t bytes[16]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+
+ EXPECT_EQ("0102", BytesToHex((uint8_t*)bytes, 2));
+ EXPECT_EQ("01020304", BytesToHex((uint8_t*)bytes, 4));
+ EXPECT_EQ("0102030405060708", BytesToHex((uint8_t*)bytes, 8));
+ EXPECT_EQ("0102030405060708090a0b0c0d0e0f10", BytesToHex((uint8_t*)bytes, 16));
+
+ EXPECT_EQ("01", BytesToHex((uint8_t*)bytes, 1));
+ EXPECT_EQ("010203", BytesToHex((uint8_t*)bytes, 3));
+ EXPECT_EQ("0102030405", BytesToHex((uint8_t*)bytes, 5));
+}
+
+TEST(BasicUtilTest, HexToBytesInValidOddLenHex) {
+ std::string hex = "12345";
+ uint8_t bytes[16];
+
+ EXPECT_FALSE(HexToBytes((uint8_t*)bytes, sizeof(bytes), hex));
+}
+
+TEST(BasicUtilTest, HexToBytesInsufficientByteLen) {
+ std::string hex = "101112131415161718191A1B1C1D1E1F";
+ uint8_t bytes[8];
+
+ EXPECT_FALSE(HexToBytes((uint8_t*)bytes, sizeof(bytes), hex));
+}
+
+TEST(BasicUtilTest, WaitForFile) {
+ // Gets system tmp dir.
+ base::FilePath tmp_dir;
+ ASSERT_TRUE(GetTempDir(&tmp_dir));
+
+ // Waits this path.
+ base::FilePath wait_path = tmp_dir.Append("libfs_avb-test-exist-dir");
+ ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
+
+ EXPECT_TRUE(base::CreateDirectory(wait_path));
+ EXPECT_TRUE(WaitForFile(wait_path.value(), 1s));
+
+ // Removes the wait_path.
+ ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
+}
+
+TEST(BasicUtilTest, WaitForFileNonExist) {
+ base::FilePath wait_path("/path/not/exist");
+ EXPECT_FALSE(WaitForFile(wait_path.value(), 200ms));
+}
+
+TEST(BasicUtilTest, WaitForFileDeferCreation) {
+ // Gets system tmp dir.
+ base::FilePath tmp_dir;
+ ASSERT_TRUE(GetTempDir(&tmp_dir));
+
+ // Waits this path.
+ base::FilePath wait_path = tmp_dir.Append("libfs_avb-test-exist-dir");
+ ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
+ auto wait_file = std::async(WaitForFile, wait_path.value(), 500ms);
+
+ // Sleeps 100ms before creating the wait_path.
+ std::this_thread::sleep_for(100ms);
+ EXPECT_TRUE(base::CreateDirectory(wait_path));
+
+ // Checks WaitForFile() returns success.
+ EXPECT_TRUE(wait_file.get());
+
+ // Removes the wait_path.
+ ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
+}
+
+TEST(BasicUtilTest, WaitForFileDeferCreationFailure) {
+ // Gets system tmp dir.
+ base::FilePath tmp_dir;
+ ASSERT_TRUE(GetTempDir(&tmp_dir));
+
+ // Waits this path.
+ base::FilePath wait_path = tmp_dir.Append("libfs_avb-test-exist-dir");
+ ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
+ auto wait_file = std::async(WaitForFile, wait_path.value(), 50ms);
+
+ // Sleeps 100ms before creating the wait_path.
+ std::this_thread::sleep_for(100ms);
+ EXPECT_TRUE(base::CreateDirectory(wait_path));
+
+ // Checks WaitForFile() returns failure, because it only waits 50ms.
+ EXPECT_FALSE(wait_file.get());
+
+ // Removes the wait_path.
+ ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
+}
+
+} // namespace fs_avb_host_test
diff --git a/fs_mgr/libfs_avb/util.cpp b/fs_mgr/libfs_avb/util.cpp
new file mode 100644
index 0000000..17d47d9
--- /dev/null
+++ b/fs_mgr/libfs_avb/util.cpp
@@ -0,0 +1,120 @@
+/*
+ * 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 "util.h"
+
+#include <sys/ioctl.h>
+#include <thread>
+
+#include <android-base/unique_fd.h>
+#include <linux/fs.h>
+
+namespace android {
+namespace fs_mgr {
+
+bool NibbleValue(const char& c, uint8_t* value) {
+ CHECK(value != nullptr);
+
+ switch (c) {
+ case '0' ... '9':
+ *value = c - '0';
+ break;
+ case 'a' ... 'f':
+ *value = c - 'a' + 10;
+ break;
+ case 'A' ... 'F':
+ *value = c - 'A' + 10;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool HexToBytes(uint8_t* bytes, size_t bytes_len, const std::string& hex) {
+ CHECK(bytes != nullptr);
+
+ if (hex.size() % 2 != 0) {
+ return false;
+ }
+ if (hex.size() / 2 > bytes_len) {
+ return false;
+ }
+ for (size_t i = 0, j = 0, n = hex.size(); i < n; i += 2, ++j) {
+ uint8_t high;
+ if (!NibbleValue(hex[i], &high)) {
+ return false;
+ }
+ uint8_t low;
+ if (!NibbleValue(hex[i + 1], &low)) {
+ return false;
+ }
+ bytes[j] = (high << 4) | low;
+ }
+ return true;
+}
+
+std::string BytesToHex(const uint8_t* bytes, size_t bytes_len) {
+ CHECK(bytes != nullptr);
+
+ static const char* hex_digits = "0123456789abcdef";
+ std::string hex;
+
+ for (size_t i = 0; i < bytes_len; i++) {
+ hex.push_back(hex_digits[(bytes[i] & 0xF0) >> 4]);
+ hex.push_back(hex_digits[bytes[i] & 0x0F]);
+ }
+ return hex;
+}
+
+bool WaitForFile(const std::string& filename, const std::chrono::milliseconds relative_timeout) {
+ auto start_time = std::chrono::steady_clock::now();
+
+ while (true) {
+ if (0 == access(filename.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 IsDeviceUnlocked() {
+ std::string verified_boot_state;
+
+ if (fs_mgr_get_boot_config("verifiedbootstate", &verified_boot_state)) {
+ return verified_boot_state == "orange";
+ }
+ return false;
+}
+
+bool SetBlockDeviceReadOnly(const std::string& blockdev) {
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blockdev.c_str(), O_RDONLY | O_CLOEXEC)));
+ if (fd < 0) {
+ return false;
+ }
+
+ int ON = 1;
+ return ioctl(fd, BLKROSET, &ON) == 0;
+}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/libfs_avb/util.h b/fs_mgr/libfs_avb/util.h
new file mode 100644
index 0000000..cb861f4
--- /dev/null
+++ b/fs_mgr/libfs_avb/util.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 <chrono>
+#include <string>
+
+#ifdef HOST_TEST
+#include <base/logging.h>
+#else
+#include <android-base/logging.h>
+#endif
+
+#define FS_AVB_TAG "[libfs_avb]"
+
+// Logs a message to kernel
+#define LINFO LOG(INFO) << FS_AVB_TAG
+#define LWARNING LOG(WARNING) << FS_AVB_TAG
+#define LERROR LOG(ERROR) << FS_AVB_TAG
+#define LFATAL LOG(FATAL) << FS_AVB_TAG
+
+// Logs a message with strerror(errno) at the end
+#define PINFO PLOG(INFO) << FS_AVB_TAG
+#define PWARNING PLOG(WARNING) << FS_AVB_TAG
+#define PERROR PLOG(ERROR) << FS_AVB_TAG
+#define PFATAL PLOG(FATAL) << FS_AVB_TAG
+
+extern bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val);
+
+using namespace std::chrono_literals;
+
+namespace android {
+namespace fs_mgr {
+
+bool NibbleValue(const char& c, uint8_t* value);
+
+bool HexToBytes(uint8_t* bytes, size_t bytes_len, const std::string& hex);
+
+std::string BytesToHex(const uint8_t* bytes, size_t bytes_len);
+
+bool WaitForFile(const std::string& filename, const std::chrono::milliseconds relative_timeout);
+
+bool IsDeviceUnlocked();
+
+bool SetBlockDeviceReadOnly(const std::string& blockdev);
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index 89282db..355b7a1 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -25,6 +25,7 @@
srcs: [
"builder.cpp",
"images.cpp",
+ "partition_opener.cpp",
"reader.cpp",
"utility.cpp",
"writer.cpp",
@@ -35,10 +36,14 @@
"libcrypto",
"libcrypto_utils",
"libsparse",
- "libext2_uuid",
"libext4_utils",
"libz",
],
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
export_include_dirs: ["include"],
}
@@ -48,14 +53,19 @@
cppflags: [
"-Wno-unused-parameter",
],
+ static_libs: [
+ "libgmock",
+ ],
shared_libs: [
"liblp",
"libbase",
"libfs_mgr",
+ "libsparse",
],
srcs: [
"builder_test.cpp",
"io_test.cpp",
+ "test_partition_opener.cpp",
"utility_test.cpp",
],
}
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 2015e4d..110d56e 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -16,16 +16,12 @@
#include "liblp/builder.h"
-#if defined(__linux__)
-#include <linux/fs.h>
-#endif
#include <string.h>
-#include <sys/ioctl.h>
#include <algorithm>
+#include <android-base/properties.h>
#include <android-base/unique_fd.h>
-#include <uuid/uuid.h>
#include "liblp/liblp.h"
#include "reader.h"
@@ -34,67 +30,44 @@
namespace android {
namespace fs_mgr {
-bool GetBlockDeviceInfo(const std::string& block_device, BlockDeviceInfo* device_info) {
-#if defined(__linux__)
- android::base::unique_fd fd(open(block_device.c_str(), O_RDONLY));
- if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << "open '" << block_device << "' failed";
- return false;
- }
- if (!GetDescriptorSize(fd, &device_info->size)) {
- return false;
- }
- if (ioctl(fd, BLKIOMIN, &device_info->alignment) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed";
- return false;
- }
+bool MetadataBuilder::sABOverrideSet;
+bool MetadataBuilder::sABOverrideValue;
- int alignment_offset;
- if (ioctl(fd, BLKALIGNOFF, &alignment_offset) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed";
- return false;
- }
- int logical_block_size;
- if (ioctl(fd, BLKSSZGET, &logical_block_size) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "BLKSSZGET failed";
- return false;
- }
+static const std::string kDefaultGroup = "default";
- device_info->alignment_offset = static_cast<uint32_t>(alignment_offset);
- device_info->logical_block_size = static_cast<uint32_t>(logical_block_size);
+bool LinearExtent::AddTo(LpMetadata* out) const {
+ if (device_index_ >= out->block_devices.size()) {
+ LERROR << "Extent references unknown block device.";
+ return false;
+ }
+ out->extents.emplace_back(
+ LpMetadataExtent{num_sectors_, LP_TARGET_TYPE_LINEAR, physical_sector_, device_index_});
return true;
-#else
- (void)block_device;
- (void)device_info;
- LERROR << __PRETTY_FUNCTION__ << ": Not supported on this operating system.";
- return false;
-#endif
}
-void LinearExtent::AddTo(LpMetadata* out) const {
- out->extents.push_back(LpMetadataExtent{num_sectors_, LP_TARGET_TYPE_LINEAR, physical_sector_});
+bool ZeroExtent::AddTo(LpMetadata* out) const {
+ out->extents.emplace_back(LpMetadataExtent{num_sectors_, LP_TARGET_TYPE_ZERO, 0, 0});
+ return true;
}
-void ZeroExtent::AddTo(LpMetadata* out) const {
- out->extents.push_back(LpMetadataExtent{num_sectors_, LP_TARGET_TYPE_ZERO, 0});
-}
-
-Partition::Partition(const std::string& name, const std::string& guid, uint32_t attributes)
- : name_(name), guid_(guid), attributes_(attributes), size_(0) {}
+Partition::Partition(const std::string& name, const std::string& group_name, uint32_t attributes)
+ : name_(name), group_name_(group_name), attributes_(attributes), size_(0) {}
void Partition::AddExtent(std::unique_ptr<Extent>&& extent) {
size_ += extent->num_sectors() * LP_SECTOR_SIZE;
if (LinearExtent* new_extent = extent->AsLinearExtent()) {
- if (!extents_.empty() && extents_.back()->AsLinearExtent() &&
- extents_.back()->AsLinearExtent()->end_sector() == new_extent->physical_sector()) {
- // If the previous extent can be merged into this new one, do so
- // to avoid creating unnecessary extents.
+ if (!extents_.empty() && extents_.back()->AsLinearExtent()) {
LinearExtent* prev_extent = extents_.back()->AsLinearExtent();
- extent = std::make_unique<LinearExtent>(
- prev_extent->num_sectors() + new_extent->num_sectors(),
- prev_extent->physical_sector());
- extents_.pop_back();
+ if (prev_extent->end_sector() == new_extent->physical_sector() &&
+ prev_extent->device_index() == new_extent->device_index()) {
+ // If the previous extent can be merged into this new one, do so
+ // to avoid creating unnecessary extents.
+ extent = std::make_unique<LinearExtent>(
+ prev_extent->num_sectors() + new_extent->num_sectors(),
+ prev_extent->device_index(), prev_extent->physical_sector());
+ extents_.pop_back();
+ }
}
}
extents_.push_back(std::move(extent));
@@ -128,42 +101,120 @@
DCHECK(size_ == aligned_size);
}
-std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const std::string& block_device,
+uint64_t Partition::BytesOnDisk() const {
+ uint64_t sectors = 0;
+ for (const auto& extent : extents_) {
+ if (!extent->AsLinearExtent()) {
+ continue;
+ }
+ sectors += extent->num_sectors();
+ }
+ return sectors * LP_SECTOR_SIZE;
+}
+
+std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const IPartitionOpener& opener,
+ const std::string& super_partition,
uint32_t slot_number) {
- std::unique_ptr<LpMetadata> metadata = ReadMetadata(block_device.c_str(), slot_number);
+ std::unique_ptr<LpMetadata> metadata = ReadMetadata(opener, super_partition, slot_number);
if (!metadata) {
return nullptr;
}
- std::unique_ptr<MetadataBuilder> builder = New(*metadata.get());
- if (!builder) {
- return nullptr;
- }
- BlockDeviceInfo device_info;
- if (fs_mgr::GetBlockDeviceInfo(block_device, &device_info)) {
- builder->set_block_device_info(device_info);
- }
- return builder;
+ return New(*metadata.get(), &opener);
}
-std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const BlockDeviceInfo& device_info,
- uint32_t metadata_max_size,
- uint32_t metadata_slot_count) {
+std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const std::string& super_partition,
+ uint32_t slot_number) {
+ return New(PartitionOpener(), super_partition, slot_number);
+}
+
+std::unique_ptr<MetadataBuilder> MetadataBuilder::New(
+ const std::vector<BlockDeviceInfo>& block_devices, const std::string& super_partition,
+ uint32_t metadata_max_size, uint32_t metadata_slot_count) {
std::unique_ptr<MetadataBuilder> builder(new MetadataBuilder());
- if (!builder->Init(device_info, metadata_max_size, metadata_slot_count)) {
+ if (!builder->Init(block_devices, super_partition, metadata_max_size, metadata_slot_count)) {
return nullptr;
}
return builder;
}
-std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const LpMetadata& metadata) {
+std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const LpMetadata& metadata,
+ const IPartitionOpener* opener) {
std::unique_ptr<MetadataBuilder> builder(new MetadataBuilder());
if (!builder->Init(metadata)) {
return nullptr;
}
+ if (opener) {
+ for (size_t i = 0; i < builder->block_devices_.size(); i++) {
+ std::string partition_name = GetBlockDevicePartitionName(builder->block_devices_[i]);
+ BlockDeviceInfo device_info;
+ if (opener->GetInfo(partition_name, &device_info)) {
+ builder->UpdateBlockDeviceInfo(i, device_info);
+ }
+ }
+ }
return builder;
}
-MetadataBuilder::MetadataBuilder() {
+std::unique_ptr<MetadataBuilder> MetadataBuilder::NewForUpdate(const IPartitionOpener& opener,
+ const std::string& source_partition,
+ uint32_t source_slot_number,
+ uint32_t target_slot_number) {
+ 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.
+ auto super_device = GetMetadataSuperBlockDevice(*metadata.get());
+ if (GetBlockDevicePartitionName(*super_device) == "super") {
+ return New(*metadata.get(), &opener);
+ }
+
+ // 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();
+ metadata->extents.clear();
+ metadata->groups.clear();
+
+ std::string source_slot_suffix = SlotSuffixForSlotNumber(source_slot_number);
+ std::string target_slot_suffix = SlotSuffixForSlotNumber(target_slot_number);
+
+ // 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 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;
+ }
+ std::string new_name =
+ partition_name.substr(0, partition_name.size() - slot_suffix.size()) +
+ target_slot_suffix;
+
+ auto new_device = source_block_device;
+ if (!UpdateBlockDevicePartitionName(&new_device, new_name)) {
+ LERROR << "Partition name too long: " << new_name;
+ return nullptr;
+ }
+ metadata->block_devices.emplace_back(new_device);
+ }
+
+ return New(*metadata.get(), &opener);
+}
+
+void MetadataBuilder::OverrideABForTesting(bool ab_device) {
+ sABOverrideSet = true;
+ sABOverrideValue = ab_device;
+}
+
+MetadataBuilder::MetadataBuilder() : auto_slot_suffixing_(false), ignore_slot_suffixing_(false) {
memset(&geometry_, 0, sizeof(geometry_));
geometry_.magic = LP_METADATA_GEOMETRY_MAGIC;
geometry_.struct_size = sizeof(geometry_);
@@ -175,37 +226,84 @@
header_.header_size = sizeof(header_);
header_.partitions.entry_size = sizeof(LpMetadataPartition);
header_.extents.entry_size = sizeof(LpMetadataExtent);
+ header_.groups.entry_size = sizeof(LpMetadataPartitionGroup);
+ header_.block_devices.entry_size = sizeof(LpMetadataBlockDevice);
}
bool MetadataBuilder::Init(const LpMetadata& metadata) {
geometry_ = metadata.geometry;
+ block_devices_ = metadata.block_devices;
- for (const auto& partition : metadata.partitions) {
- Partition* builder = AddPartition(GetPartitionName(partition), GetPartitionGuid(partition),
- partition.attributes);
- if (!builder) {
+ for (const auto& group : metadata.groups) {
+ std::string group_name = GetPartitionGroupName(group);
+ if (!AddGroup(group_name, group.maximum_size)) {
return false;
}
-
- for (size_t i = 0; i < partition.num_extents; i++) {
- const LpMetadataExtent& extent = metadata.extents[partition.first_extent_index + i];
- if (extent.target_type == LP_TARGET_TYPE_LINEAR) {
- auto copy = std::make_unique<LinearExtent>(extent.num_sectors, extent.target_data);
- builder->AddExtent(std::move(copy));
- } else if (extent.target_type == LP_TARGET_TYPE_ZERO) {
- auto copy = std::make_unique<ZeroExtent>(extent.num_sectors);
- builder->AddExtent(std::move(copy));
- }
- }
}
- device_info_.alignment = geometry_.alignment;
- device_info_.alignment_offset = geometry_.alignment_offset;
- device_info_.logical_block_size = geometry_.logical_block_size;
+ for (const auto& partition : metadata.partitions) {
+ std::string group_name = GetPartitionGroupName(metadata.groups[partition.group_index]);
+ Partition* builder =
+ AddPartition(GetPartitionName(partition), group_name, partition.attributes);
+ if (!builder) {
+ return false;
+ }
+ ImportExtents(builder, metadata, partition);
+ }
return true;
}
-bool MetadataBuilder::Init(const BlockDeviceInfo& device_info, uint32_t metadata_max_size,
+void MetadataBuilder::ImportExtents(Partition* dest, const LpMetadata& metadata,
+ const LpMetadataPartition& source) {
+ for (size_t i = 0; i < source.num_extents; i++) {
+ const LpMetadataExtent& extent = metadata.extents[source.first_extent_index + i];
+ if (extent.target_type == LP_TARGET_TYPE_LINEAR) {
+ auto copy = std::make_unique<LinearExtent>(extent.num_sectors, extent.target_source,
+ extent.target_data);
+ dest->AddExtent(std::move(copy));
+ } else if (extent.target_type == LP_TARGET_TYPE_ZERO) {
+ auto copy = std::make_unique<ZeroExtent>(extent.num_sectors);
+ dest->AddExtent(std::move(copy));
+ }
+ }
+}
+
+static bool VerifyDeviceProperties(const BlockDeviceInfo& device_info) {
+ if (device_info.logical_block_size == 0) {
+ LERROR << "Block device " << device_info.partition_name
+ << " logical block size must not be zero.";
+ return false;
+ }
+ if (device_info.logical_block_size % LP_SECTOR_SIZE != 0) {
+ LERROR << "Block device " << device_info.partition_name
+ << " logical block size must be a multiple of 512.";
+ return false;
+ }
+ if (device_info.size % device_info.logical_block_size != 0) {
+ LERROR << "Block device " << device_info.partition_name
+ << " size must be a multiple of its block size.";
+ return false;
+ }
+ if (device_info.alignment_offset % LP_SECTOR_SIZE != 0) {
+ LERROR << "Block device " << device_info.partition_name
+ << " alignment offset is not sector-aligned.";
+ return false;
+ }
+ if (device_info.alignment % LP_SECTOR_SIZE != 0) {
+ LERROR << "Block device " << device_info.partition_name
+ << " partition alignment is not sector-aligned.";
+ return false;
+ }
+ if (device_info.alignment_offset > device_info.alignment) {
+ LERROR << "Block device " << device_info.partition_name
+ << " partition alignment offset is greater than its alignment.";
+ return false;
+ }
+ return true;
+}
+
+bool MetadataBuilder::Init(const std::vector<BlockDeviceInfo>& block_devices,
+ const std::string& super_partition, uint32_t metadata_max_size,
uint32_t metadata_slot_count) {
if (metadata_max_size < sizeof(LpMetadataHeader)) {
LERROR << "Invalid metadata maximum size.";
@@ -215,87 +313,123 @@
LERROR << "Invalid metadata slot count.";
return false;
}
+ if (block_devices.empty()) {
+ LERROR << "No block devices were specified.";
+ return false;
+ }
// Align the metadata size up to the nearest sector.
metadata_max_size = AlignTo(metadata_max_size, LP_SECTOR_SIZE);
- // Check that device properties are sane.
- device_info_ = device_info;
- if (device_info_.size % LP_SECTOR_SIZE != 0) {
- LERROR << "Block device size must be a multiple of 512.";
+ // Validate and build the block device list.
+ uint32_t logical_block_size = 0;
+ for (const auto& device_info : block_devices) {
+ if (!VerifyDeviceProperties(device_info)) {
+ return false;
+ }
+
+ if (!logical_block_size) {
+ logical_block_size = device_info.logical_block_size;
+ }
+ if (logical_block_size != device_info.logical_block_size) {
+ LERROR << "All partitions must have the same logical block size.";
+ return false;
+ }
+
+ LpMetadataBlockDevice out = {};
+ out.alignment = device_info.alignment;
+ out.alignment_offset = device_info.alignment_offset;
+ out.size = device_info.size;
+ if (device_info.partition_name.size() > sizeof(out.partition_name)) {
+ LERROR << "Partition name " << device_info.partition_name << " exceeds maximum length.";
+ return false;
+ }
+ strncpy(out.partition_name, device_info.partition_name.c_str(), sizeof(out.partition_name));
+
+ // In the case of the super partition, this field will be adjusted
+ // later. For all partitions, the first 512 bytes are considered
+ // untouched to be compatible code that looks for an MBR. Thus we
+ // start counting free sectors at sector 1, not 0.
+ uint64_t free_area_start = LP_SECTOR_SIZE;
+ if (out.alignment || out.alignment_offset) {
+ free_area_start = AlignTo(free_area_start, out.alignment, out.alignment_offset);
+ } else {
+ free_area_start = AlignTo(free_area_start, logical_block_size);
+ }
+ out.first_logical_sector = free_area_start / LP_SECTOR_SIZE;
+
+ // There must be one logical block of space available.
+ uint64_t minimum_size = out.first_logical_sector * LP_SECTOR_SIZE + logical_block_size;
+ if (device_info.size < minimum_size) {
+ LERROR << "Block device " << device_info.partition_name
+ << " is too small to hold any logical partitions.";
+ return false;
+ }
+
+ // The "root" of the super partition is always listed first.
+ if (device_info.partition_name == super_partition) {
+ block_devices_.emplace(block_devices_.begin(), out);
+ } else {
+ block_devices_.emplace_back(out);
+ }
+ }
+ if (GetBlockDevicePartitionName(block_devices_[0]) != super_partition) {
+ LERROR << "No super partition was specified.";
return false;
}
- if (device_info_.logical_block_size % LP_SECTOR_SIZE != 0) {
- LERROR << "Logical block size must be a multiple of 512.";
- return false;
- }
- if (device_info_.alignment_offset % LP_SECTOR_SIZE != 0) {
- LERROR << "Alignment offset is not sector-aligned.";
- return false;
- }
- if (device_info_.alignment % LP_SECTOR_SIZE != 0) {
- LERROR << "Partition alignment is not sector-aligned.";
- return false;
- }
- if (device_info_.alignment_offset > device_info_.alignment) {
- LERROR << "Partition alignment offset is greater than its alignment.";
- return false;
- }
+
+ LpMetadataBlockDevice& super = block_devices_[0];
// We reserve a geometry block (4KB) plus space for each copy of the
// maximum size of a metadata blob. Then, we double that space since
// we store a backup copy of everything.
- uint64_t reserved =
- LP_METADATA_GEOMETRY_SIZE + (uint64_t(metadata_max_size) * metadata_slot_count);
- uint64_t total_reserved = reserved * 2;
- if (device_info_.size < total_reserved) {
+ uint64_t total_reserved = GetTotalMetadataSize(metadata_max_size, metadata_slot_count);
+ if (super.size < total_reserved) {
LERROR << "Attempting to create metadata on a block device that is too small.";
return false;
}
// Compute the first free sector, factoring in alignment.
- uint64_t free_area = AlignTo(reserved, device_info_.alignment, device_info_.alignment_offset);
- uint64_t first_sector = free_area / LP_SECTOR_SIZE;
+ uint64_t free_area_start = total_reserved;
+ if (super.alignment || super.alignment_offset) {
+ free_area_start = AlignTo(free_area_start, super.alignment, super.alignment_offset);
+ } else {
+ free_area_start = AlignTo(free_area_start, logical_block_size);
+ }
+ super.first_logical_sector = free_area_start / LP_SECTOR_SIZE;
- // Compute the last free sector, which is inclusive. We subtract 1 to make
- // sure that logical partitions won't overlap with the same sector as the
- // backup metadata, which could happen if the block device was not aligned
- // to LP_SECTOR_SIZE.
- uint64_t last_sector = ((device_info_.size - reserved) / LP_SECTOR_SIZE) - 1;
-
- // If this check fails, it means either (1) we did not have free space to
- // allocate a single sector, or (2) we did, but the alignment was high
- // enough to bump the first sector out of range. Either way, we cannot
- // continue.
- if (first_sector > last_sector) {
- LERROR << "Not enough space to allocate any partition tables.";
+ // There must be one logical block of free space remaining (enough for one partition).
+ uint64_t minimum_disk_size = (super.first_logical_sector * LP_SECTOR_SIZE) + logical_block_size;
+ if (super.size < minimum_disk_size) {
+ LERROR << "Device must be at least " << minimum_disk_size << " bytes, only has "
+ << super.size;
return false;
}
- // Finally, the size of the allocatable space must be a multiple of the
- // logical block size. If we have no more free space after this
- // computation, then we abort. Note that the last sector is inclusive,
- // so we have to account for that.
- uint64_t num_free_sectors = last_sector - first_sector + 1;
- uint64_t sectors_per_block = device_info_.logical_block_size / LP_SECTOR_SIZE;
- if (num_free_sectors < sectors_per_block) {
- LERROR << "Not enough space to allocate any partition tables.";
- return false;
- }
- last_sector = first_sector + (num_free_sectors / sectors_per_block) * sectors_per_block - 1;
-
- geometry_.first_logical_sector = first_sector;
- geometry_.last_logical_sector = last_sector;
geometry_.metadata_max_size = metadata_max_size;
geometry_.metadata_slot_count = metadata_slot_count;
- geometry_.alignment = device_info_.alignment;
- geometry_.alignment_offset = device_info_.alignment_offset;
- geometry_.block_device_size = device_info_.size;
- geometry_.logical_block_size = device_info.logical_block_size;
+ geometry_.logical_block_size = logical_block_size;
+
+ if (!AddGroup(kDefaultGroup, 0)) {
+ return false;
+ }
return true;
}
-Partition* MetadataBuilder::AddPartition(const std::string& name, const std::string& guid,
+bool MetadataBuilder::AddGroup(const std::string& group_name, uint64_t maximum_size) {
+ if (FindGroup(group_name)) {
+ LERROR << "Group already exists: " << group_name;
+ return false;
+ }
+ groups_.push_back(std::make_unique<PartitionGroup>(group_name, maximum_size));
+ return true;
+}
+
+Partition* MetadataBuilder::AddPartition(const std::string& name, uint32_t attributes) {
+ return AddPartition(name, kDefaultGroup, attributes);
+}
+
+Partition* MetadataBuilder::AddPartition(const std::string& name, const std::string& group_name,
uint32_t attributes) {
if (name.empty()) {
LERROR << "Partition must have a non-empty name.";
@@ -305,7 +439,16 @@
LERROR << "Attempting to create duplication partition with name: " << name;
return nullptr;
}
- partitions_.push_back(std::make_unique<Partition>(name, guid, attributes));
+ if (!FindGroup(group_name)) {
+ 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();
}
@@ -318,6 +461,26 @@
return nullptr;
}
+PartitionGroup* MetadataBuilder::FindGroup(const std::string& group_name) {
+ for (const auto& group : groups_) {
+ if (group->name() == group_name) {
+ return group.get();
+ }
+ }
+ return nullptr;
+}
+
+uint64_t MetadataBuilder::TotalSizeOfGroup(PartitionGroup* group) const {
+ uint64_t total = 0;
+ for (const auto& partition : partitions_) {
+ if (partition->group_name() != group->name()) {
+ continue;
+ }
+ total += partition->BytesOnDisk();
+ }
+ return total;
+}
+
void MetadataBuilder::RemovePartition(const std::string& name) {
for (auto iter = partitions_.begin(); iter != partitions_.end(); iter++) {
if ((*iter)->name() == name) {
@@ -327,44 +490,16 @@
}
}
-bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) {
- // Figure out how much we need to allocate.
- 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);
-
- struct Interval {
- uint64_t start;
- uint64_t end;
-
- Interval(uint64_t start, uint64_t end) : start(start), end(end) {}
- uint64_t length() const { return end - start; }
- bool operator<(const Interval& other) const { return start < other.start; }
- };
-
- // Collect all extents in the partition table, then sort them by starting
- // sector.
- std::vector<Interval> extents;
- for (const auto& partition : partitions_) {
- for (const auto& extent : partition->extents()) {
- LinearExtent* linear = extent->AsLinearExtent();
- if (!linear) {
- continue;
- }
- extents.emplace_back(linear->physical_sector(),
- linear->physical_sector() + extent->num_sectors());
- }
- }
- std::sort(extents.begin(), extents.end());
-
+void MetadataBuilder::ExtentsToFreeList(const std::vector<Interval>& extents,
+ std::vector<Interval>* free_regions) const {
// Convert the extent list into a list of gaps between the extents; i.e.,
// the list of ranges that are free on the disk.
- std::vector<Interval> free_regions;
for (size_t i = 1; i < extents.size(); i++) {
const Interval& previous = extents[i - 1];
const Interval& current = extents[i];
+ DCHECK(previous.device_index == current.device_index);
- uint64_t aligned = AlignSector(previous.end);
+ uint64_t aligned = AlignSector(block_devices_[current.device_index], previous.end);
if (aligned >= current.start) {
// There is no gap between these two extents, try the next one.
// Note that we check with >= instead of >, since alignment may
@@ -374,20 +509,88 @@
// The new interval represents the free space starting at the end of
// the previous interval, and ending at the start of the next interval.
- free_regions.emplace_back(aligned, current.start);
+ free_regions->emplace_back(current.device_index, aligned, current.start);
+ }
+}
+
+auto MetadataBuilder::GetFreeRegions() const -> std::vector<Interval> {
+ std::vector<Interval> free_regions;
+
+ // Collect all extents in the partition table, per-device, then sort them
+ // by starting sector.
+ std::vector<std::vector<Interval>> device_extents(block_devices_.size());
+ for (const auto& partition : partitions_) {
+ for (const auto& extent : partition->extents()) {
+ LinearExtent* linear = extent->AsLinearExtent();
+ if (!linear) {
+ continue;
+ }
+ CHECK(linear->device_index() < device_extents.size());
+ auto& extents = device_extents[linear->device_index()];
+ extents.emplace_back(linear->device_index(), linear->physical_sector(),
+ linear->physical_sector() + extent->num_sectors());
+ }
}
- // Add a final interval representing the remainder of the free space.
- uint64_t last_free_extent_start =
- extents.empty() ? geometry_.first_logical_sector : extents.back().end;
- last_free_extent_start = AlignSector(last_free_extent_start);
- if (last_free_extent_start <= geometry_.last_logical_sector) {
- free_regions.emplace_back(last_free_extent_start, geometry_.last_logical_sector + 1);
+ // Add 0-length intervals for the first and last sectors. This will cause
+ // ExtentToFreeList() to treat the space in between as available.
+ for (size_t i = 0; i < device_extents.size(); i++) {
+ auto& extents = device_extents[i];
+ const auto& block_device = block_devices_[i];
+
+ uint64_t first_sector = block_device.first_logical_sector;
+ uint64_t last_sector = block_device.size / LP_SECTOR_SIZE;
+ extents.emplace_back(i, first_sector, first_sector);
+ extents.emplace_back(i, last_sector, last_sector);
+
+ std::sort(extents.begin(), extents.end());
+ ExtentsToFreeList(extents, &free_regions);
+ }
+ return free_regions;
+}
+
+bool MetadataBuilder::ValidatePartitionSizeChange(Partition* partition, uint64_t old_size,
+ uint64_t new_size) {
+ PartitionGroup* group = FindGroup(partition->group_name());
+ CHECK(group);
+
+ if (new_size <= old_size) {
+ return true;
}
- const uint64_t sectors_per_block = device_info_.logical_block_size / LP_SECTOR_SIZE;
+ // Figure out how much we need to allocate, and whether our group has
+ // enough space remaining.
+ uint64_t space_needed = new_size - old_size;
+ if (group->maximum_size() > 0) {
+ uint64_t group_size = TotalSizeOfGroup(group);
+ if (group_size >= group->maximum_size() ||
+ group->maximum_size() - group_size < space_needed) {
+ LERROR << "Partition " << partition->name() << " is part of group " << group->name()
+ << " which does not have enough space free (" << space_needed << " requested, "
+ << group_size << " used out of " << group->maximum_size() << ")";
+ return false;
+ }
+ }
+ return true;
+}
+
+bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) {
+ 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();
+
+ 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") {
+ // Allocate "a" partitions top-down and "b" partitions bottom-up, to
+ // minimize fragmentation during OTA.
+ free_regions = PrioritizeSecondHalfOfSuper(free_regions);
+ }
+
// Find gaps that we can use for new extents. Note we store new extents in a
// temporary vector, and only commit them if we are guaranteed enough free
// space.
@@ -410,14 +613,23 @@
}
uint64_t sectors = std::min(sectors_needed, region.length());
+ if (sectors < region.length()) {
+ const auto& block_device = block_devices_[region.device_index];
+ if (block_device.alignment) {
+ const uint64_t alignment = block_device.alignment / LP_SECTOR_SIZE;
+ sectors = AlignTo(sectors, alignment);
+ sectors = std::min(sectors, region.length());
+ }
+ }
CHECK(sectors % sectors_per_block == 0);
- auto extent = std::make_unique<LinearExtent>(sectors, region.start);
+ auto extent = std::make_unique<LinearExtent>(sectors, region.device_index, region.start);
new_extents.push_back(std::move(extent));
- sectors_needed -= sectors;
- if (!sectors_needed) {
+ if (sectors >= sectors_needed) {
+ sectors_needed = 0;
break;
}
+ sectors_needed -= sectors;
}
if (sectors_needed) {
LERROR << "Not enough free space to expand partition: " << partition->name();
@@ -431,15 +643,79 @@
return true;
}
+std::vector<MetadataBuilder::Interval> MetadataBuilder::PrioritizeSecondHalfOfSuper(
+ const std::vector<Interval>& free_list) {
+ const auto& super = block_devices_[0];
+ uint64_t first_sector = super.first_logical_sector;
+ uint64_t last_sector = super.size / LP_SECTOR_SIZE;
+ uint64_t midpoint = first_sector + (last_sector - first_sector) / 2;
+
+ // Choose an aligned sector for the midpoint. This could lead to one half
+ // being slightly larger than the other, but this will not restrict the
+ // size of partitions (it might lead to one extra extent if "B" overflows).
+ midpoint = AlignSector(super, midpoint);
+
+ std::vector<Interval> first_half;
+ std::vector<Interval> second_half;
+ for (const auto& region : free_list) {
+ // Note: deprioritze if not the main super partition. Even though we
+ // don't call this for retrofit devices, we will allow adding additional
+ // block devices on non-retrofit devices.
+ if (region.device_index != 0 || region.end <= midpoint) {
+ first_half.emplace_back(region);
+ continue;
+ }
+ if (region.start < midpoint && region.end > midpoint) {
+ // Split this into two regions.
+ first_half.emplace_back(region.device_index, region.start, midpoint);
+ second_half.emplace_back(region.device_index, midpoint, region.end);
+ } else {
+ second_half.emplace_back(region);
+ }
+ }
+ second_half.insert(second_half.end(), first_half.begin(), first_half.end());
+ return second_half;
+}
+
void MetadataBuilder::ShrinkPartition(Partition* partition, uint64_t aligned_size) {
partition->ShrinkTo(aligned_size);
}
std::unique_ptr<LpMetadata> MetadataBuilder::Export() {
+ if (!ValidatePartitionGroups()) {
+ return nullptr;
+ }
+
std::unique_ptr<LpMetadata> metadata = std::make_unique<LpMetadata>();
metadata->header = header_;
metadata->geometry = geometry_;
+ // Assign this early so the extent table can read it.
+ for (const auto& block_device : block_devices_) {
+ metadata->block_devices.emplace_back(block_device);
+ if (auto_slot_suffixing_) {
+ metadata->block_devices.back().flags |= LP_BLOCK_DEVICE_SLOT_SUFFIXED;
+ }
+ }
+
+ std::map<std::string, size_t> group_indices;
+ for (const auto& group : groups_) {
+ LpMetadataPartitionGroup out = {};
+
+ if (group->name().size() > sizeof(out.name)) {
+ LERROR << "Partition group name is too long: " << group->name();
+ return nullptr;
+ }
+ if (auto_slot_suffixing_ && group->name() != kDefaultGroup) {
+ out.flags |= LP_GROUP_SLOT_SUFFIXED;
+ }
+ strncpy(out.name, group->name().c_str(), sizeof(out.name));
+ out.maximum_size = group->maximum_size();
+
+ group_indices[group->name()] = metadata->groups.size();
+ metadata->groups.push_back(out);
+ }
+
// Flatten the partition and extent structures into an LpMetadata, which
// makes it very easy to validate, serialize, or pass on to device-mapper.
for (const auto& partition : partitions_) {
@@ -456,63 +732,138 @@
}
strncpy(part.name, partition->name().c_str(), sizeof(part.name));
- if (uuid_parse(partition->guid().c_str(), part.guid) != 0) {
- LERROR << "Could not parse guid " << partition->guid() << " for partition "
- << partition->name();
- return nullptr;
- }
-
part.first_extent_index = static_cast<uint32_t>(metadata->extents.size());
part.num_extents = static_cast<uint32_t>(partition->extents().size());
part.attributes = partition->attributes();
+ if (auto_slot_suffixing_) {
+ part.attributes |= LP_PARTITION_ATTR_SLOT_SUFFIXED;
+ }
+
+ auto iter = group_indices.find(partition->group_name());
+ if (iter == group_indices.end()) {
+ LERROR << "Partition " << partition->name() << " is a member of unknown group "
+ << partition->group_name();
+ return nullptr;
+ }
+ part.group_index = iter->second;
for (const auto& extent : partition->extents()) {
- extent->AddTo(metadata.get());
+ if (!extent->AddTo(metadata.get())) {
+ return nullptr;
+ }
}
metadata->partitions.push_back(part);
}
metadata->header.partitions.num_entries = static_cast<uint32_t>(metadata->partitions.size());
metadata->header.extents.num_entries = static_cast<uint32_t>(metadata->extents.size());
+ metadata->header.groups.num_entries = static_cast<uint32_t>(metadata->groups.size());
+ metadata->header.block_devices.num_entries =
+ static_cast<uint32_t>(metadata->block_devices.size());
return metadata;
}
uint64_t MetadataBuilder::AllocatableSpace() const {
- return (geometry_.last_logical_sector - geometry_.first_logical_sector + 1) * LP_SECTOR_SIZE;
+ uint64_t total_size = 0;
+ for (const auto& block_device : block_devices_) {
+ total_size += block_device.size - (block_device.first_logical_sector * LP_SECTOR_SIZE);
+ }
+ return total_size;
}
-uint64_t MetadataBuilder::AlignSector(uint64_t sector) {
+uint64_t MetadataBuilder::UsedSpace() const {
+ uint64_t size = 0;
+ for (const auto& partition : partitions_) {
+ size += partition->size();
+ }
+ return size;
+}
+
+uint64_t MetadataBuilder::AlignSector(const LpMetadataBlockDevice& block_device,
+ uint64_t sector) const {
// Note: when reading alignment info from the Kernel, we don't assume it
// is aligned to the sector size, so we round up to the nearest sector.
uint64_t lba = sector * LP_SECTOR_SIZE;
- uint64_t aligned = AlignTo(lba, device_info_.alignment, device_info_.alignment_offset);
+ uint64_t aligned = AlignTo(lba, block_device.alignment, block_device.alignment_offset);
return AlignTo(aligned, LP_SECTOR_SIZE) / LP_SECTOR_SIZE;
}
-void MetadataBuilder::set_block_device_info(const BlockDeviceInfo& device_info) {
- device_info_.size = device_info.size;
+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) {
+ *index = i;
+ return true;
+ }
+ }
+ return false;
+}
- // Note that if the logical block size changes, we're probably in trouble:
- // we could have already built extents that will only work on the previous
- // size.
- DCHECK(partitions_.empty() ||
- device_info_.logical_block_size == device_info.logical_block_size);
+bool MetadataBuilder::HasBlockDevice(const std::string& partition_name) const {
+ uint32_t index;
+ return FindBlockDeviceByName(partition_name, &index);
+}
+
+bool MetadataBuilder::GetBlockDeviceInfo(const std::string& partition_name,
+ BlockDeviceInfo* info) const {
+ uint32_t index;
+ if (!FindBlockDeviceByName(partition_name, &index)) {
+ LERROR << "No device named " << partition_name;
+ return false;
+ }
+ info->size = block_devices_[index].size;
+ info->alignment = block_devices_[index].alignment;
+ info->alignment_offset = block_devices_[index].alignment_offset;
+ info->logical_block_size = geometry_.logical_block_size;
+ info->partition_name = partition_name;
+ return true;
+}
+
+bool MetadataBuilder::UpdateBlockDeviceInfo(const std::string& partition_name,
+ const BlockDeviceInfo& device_info) {
+ uint32_t index;
+ if (!FindBlockDeviceByName(partition_name, &index)) {
+ LERROR << "No device named " << partition_name;
+ return false;
+ }
+ return UpdateBlockDeviceInfo(index, device_info);
+}
+
+bool MetadataBuilder::UpdateBlockDeviceInfo(size_t index, const BlockDeviceInfo& device_info) {
+ CHECK(index < block_devices_.size());
+
+ LpMetadataBlockDevice& block_device = block_devices_[index];
+ if (device_info.size != block_device.size) {
+ LERROR << "Device size does not match (got " << device_info.size << ", expected "
+ << block_device.size << ")";
+ return false;
+ }
+ if (device_info.logical_block_size != geometry_.logical_block_size) {
+ LERROR << "Device logical block size does not match (got " << device_info.logical_block_size
+ << ", expected " << geometry_.logical_block_size << ")";
+ return false;
+ }
// The kernel does not guarantee these values are present, so we only
// replace existing values if the new values are non-zero.
if (device_info.alignment) {
- device_info_.alignment = device_info.alignment;
+ block_device.alignment = device_info.alignment;
}
if (device_info.alignment_offset) {
- device_info_.alignment_offset = device_info.alignment_offset;
+ block_device.alignment_offset = device_info.alignment_offset;
}
+ return true;
}
bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size) {
// Align the space needed up to the nearest sector.
- uint64_t aligned_size = AlignTo(requested_size, device_info_.logical_block_size);
+ uint64_t aligned_size = AlignTo(requested_size, geometry_.logical_block_size);
uint64_t old_size = partition->size();
+ if (!ValidatePartitionSizeChange(partition, old_size, aligned_size)) {
+ return false;
+ }
+
if (aligned_size > old_size) {
if (!GrowPartition(partition, aligned_size)) {
return false;
@@ -521,8 +872,190 @@
ShrinkPartition(partition, aligned_size);
}
- LINFO << "Partition " << partition->name() << " will resize from " << old_size << " bytes to "
- << aligned_size << " bytes";
+ if (partition->size() != old_size) {
+ LINFO << "Partition " << partition->name() << " will resize from " << old_size
+ << " bytes to " << aligned_size << " bytes";
+ }
+ return true;
+}
+
+std::vector<std::string> MetadataBuilder::ListGroups() const {
+ std::vector<std::string> names;
+ for (const auto& group : groups_) {
+ names.emplace_back(group->name());
+ }
+ return names;
+}
+
+void MetadataBuilder::RemoveGroupAndPartitions(const std::string& group_name) {
+ if (group_name == kDefaultGroup) {
+ // Cannot remove the default group.
+ return;
+ }
+ std::vector<std::string> partition_names;
+ for (const auto& partition : partitions_) {
+ if (partition->group_name() == group_name) {
+ partition_names.emplace_back(partition->name());
+ }
+ }
+
+ for (const auto& partition_name : partition_names) {
+ RemovePartition(partition_name);
+ }
+ for (auto iter = groups_.begin(); iter != groups_.end(); iter++) {
+ if ((*iter)->name() == group_name) {
+ groups_.erase(iter);
+ break;
+ }
+ }
+}
+
+static bool CompareBlockDevices(const LpMetadataBlockDevice& first,
+ const LpMetadataBlockDevice& second) {
+ // 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);
+}
+
+bool MetadataBuilder::ImportPartitions(const LpMetadata& metadata,
+ const std::set<std::string>& partition_names) {
+ // The block device list must be identical. We do not try to be clever and
+ // allow ordering changes or changes that don't affect partitions. This
+ // process is designed to allow the most common flashing scenarios and more
+ // complex ones should require a wipe.
+ if (metadata.block_devices.size() != block_devices_.size()) {
+ LINFO << "Block device tables does not match.";
+ return false;
+ }
+ for (size_t i = 0; i < metadata.block_devices.size(); i++) {
+ const LpMetadataBlockDevice& old_device = metadata.block_devices[i];
+ const LpMetadataBlockDevice& new_device = block_devices_[i];
+ if (!CompareBlockDevices(old_device, new_device)) {
+ LINFO << "Block device tables do not match";
+ return false;
+ }
+ }
+
+ // Import named partitions. Note that we do not attempt to merge group
+ // information here. If the device changed its group names, the old
+ // partitions will fail to merge. The same could happen if the group
+ // allocation sizes change.
+ for (const auto& partition : metadata.partitions) {
+ std::string partition_name = GetPartitionName(partition);
+ if (partition_names.find(partition_name) == partition_names.end()) {
+ continue;
+ }
+ if (!ImportPartition(metadata, partition)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool MetadataBuilder::ImportPartition(const LpMetadata& metadata,
+ const LpMetadataPartition& source) {
+ std::string partition_name = GetPartitionName(source);
+ Partition* partition = FindPartition(partition_name);
+ if (!partition) {
+ std::string group_name = GetPartitionGroupName(metadata.groups[source.group_index]);
+ partition = AddPartition(partition_name, group_name, source.attributes);
+ if (!partition) {
+ return false;
+ }
+ }
+ if (partition->size() > 0) {
+ LINFO << "Importing partition table would overwrite non-empty partition: "
+ << partition_name;
+ return false;
+ }
+
+ ImportExtents(partition, metadata, source);
+
+ if (!ValidatePartitionSizeChange(partition, 0, partition->size())) {
+ partition->RemoveExtents();
+ return false;
+ }
+ return true;
+}
+
+void MetadataBuilder::SetAutoSlotSuffixing() {
+ auto_slot_suffixing_ = true;
+}
+
+void MetadataBuilder::IgnoreSlotSuffixing() {
+ ignore_slot_suffixing_ = true;
+}
+
+bool MetadataBuilder::IsABDevice() const {
+ if (sABOverrideSet) {
+ return sABOverrideValue;
+ }
+ return android::base::GetBoolProperty("ro.build.ab_update", false);
+}
+
+bool MetadataBuilder::IsRetrofitDevice() const {
+ return GetBlockDevicePartitionName(block_devices_[0]) != LP_METADATA_DEFAULT_PARTITION_NAME;
+}
+
+bool MetadataBuilder::AddLinearExtent(Partition* partition, const std::string& block_device,
+ uint64_t num_sectors, uint64_t physical_sector) {
+ uint32_t device_index;
+ if (!FindBlockDeviceByName(block_device, &device_index)) {
+ LERROR << "Could not find backing block device for extent: " << block_device;
+ return false;
+ }
+
+ auto extent = std::make_unique<LinearExtent>(num_sectors, device_index, physical_sector);
+ partition->AddExtent(std::move(extent));
+ return true;
+}
+
+std::vector<Partition*> MetadataBuilder::ListPartitionsInGroup(const std::string& group_name) {
+ std::vector<Partition*> partitions;
+ for (const auto& partition : partitions_) {
+ if (partition->group_name() == group_name) {
+ partitions.emplace_back(partition.get());
+ }
+ }
+ return partitions;
+}
+
+bool MetadataBuilder::ChangePartitionGroup(Partition* partition, const std::string& group_name) {
+ if (!FindGroup(group_name)) {
+ LERROR << "Partition cannot change to unknown group: " << group_name;
+ return false;
+ }
+ partition->set_group_name(group_name);
+ return true;
+}
+
+bool MetadataBuilder::ValidatePartitionGroups() const {
+ for (const auto& group : groups_) {
+ if (!group->maximum_size()) {
+ continue;
+ }
+ uint64_t used = TotalSizeOfGroup(group.get());
+ if (used > group->maximum_size()) {
+ LERROR << "Partition group " << group->name() << " exceeds maximum size (" << used
+ << " bytes used, maximum " << group->maximum_size() << ")";
+ return false;
+ }
+ }
+ return true;
+}
+
+bool MetadataBuilder::ChangeGroupSize(const std::string& group_name, uint64_t maximum_size) {
+ if (group_name == kDefaultGroup) {
+ LERROR << "Cannot change the size of the default group";
+ return false;
+ }
+ PartitionGroup* group = FindGroup(group_name);
+ if (!group) {
+ LERROR << "Cannot change size of unknown partition group: " << group_name;
+ return false;
+ }
+ group->set_maximum_size(maximum_size);
return true;
}
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index da9c8f3..7d615a3 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -14,24 +14,42 @@
* limitations under the License.
*/
+#include <fs_mgr.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <liblp/builder.h>
-#include "fs_mgr.h"
+
#include "utility.h"
using namespace std;
using namespace android::fs_mgr;
+using ::testing::ElementsAre;
-static const char* TEST_GUID = "A799D1D6-669F-41D8-A3F0-EBB7572D8302";
-static const char* TEST_GUID2 = "A799D1D6-669F-41D8-A3F0-EBB7572D8303";
+class Environment : public ::testing::Environment {
+ public:
+ void SetUp() override { MetadataBuilder::OverrideABForTesting(false); }
+};
-TEST(liblp, BuildBasic) {
+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); }
+};
+
+TEST_F(BuilderTest, BuildBasic) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
+ ASSERT_NE(builder, nullptr);
- Partition* partition = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ Partition* partition = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(partition, nullptr);
EXPECT_EQ(partition->name(), "system");
- EXPECT_EQ(partition->guid(), TEST_GUID);
EXPECT_EQ(partition->attributes(), LP_PARTITION_ATTR_READONLY);
EXPECT_EQ(partition->size(), 0);
EXPECT_EQ(builder->FindPartition("system"), partition);
@@ -40,10 +58,11 @@
EXPECT_EQ(builder->FindPartition("system"), nullptr);
}
-TEST(liblp, ResizePartition) {
+TEST_F(BuilderTest, ResizePartition) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
+ ASSERT_NE(builder, nullptr);
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
EXPECT_EQ(builder->ResizePartition(system, 65536), true);
EXPECT_EQ(system->size(), 65536);
@@ -52,8 +71,11 @@
LinearExtent* extent = system->extents()[0]->AsLinearExtent();
ASSERT_NE(extent, nullptr);
EXPECT_EQ(extent->num_sectors(), 65536 / LP_SECTOR_SIZE);
- // The first logical sector will be (4096+1024*2)/512 = 12.
- EXPECT_EQ(extent->physical_sector(), 12);
+ // The first logical sector will be:
+ // (LP_PARTITION_RESERVED_BYTES + 4096*2 + 1024*4) / 512
+ // Or, in terms of sectors (reserved + geometry + metadata):
+ // (8 + 16 + 8) = 32
+ EXPECT_EQ(extent->physical_sector(), 32);
// Test resizing to the same size.
EXPECT_EQ(builder->ResizePartition(system, 65536), true);
@@ -82,7 +104,7 @@
extent = system->extents()[0]->AsLinearExtent();
ASSERT_NE(extent, nullptr);
EXPECT_EQ(extent->num_sectors(), 32768 / LP_SECTOR_SIZE);
- EXPECT_EQ(extent->physical_sector(), 12);
+ EXPECT_EQ(extent->physical_sector(), 32);
// Test shrinking to 0.
builder->ResizePartition(system, 0);
@@ -90,11 +112,12 @@
EXPECT_EQ(system->extents().size(), 0);
}
-TEST(liblp, PartitionAlignment) {
+TEST_F(BuilderTest, PartitionAlignment) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
+ ASSERT_NE(builder, nullptr);
// Test that we align up to one sector.
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
EXPECT_EQ(builder->ResizePartition(system, 10000), true);
EXPECT_EQ(system->size(), 12288);
@@ -105,7 +128,7 @@
EXPECT_EQ(system->extents().size(), 1);
}
-TEST(liblp, DiskAlignment) {
+TEST_F(BuilderTest, DiskAlignment) {
static const uint64_t kDiskSize = 1000000;
static const uint32_t kMetadataSize = 1024;
static const uint32_t kMetadataSlots = 2;
@@ -115,23 +138,25 @@
ASSERT_EQ(builder, nullptr);
}
-TEST(liblp, MetadataAlignment) {
+TEST_F(BuilderTest, MetadataAlignment) {
// Make sure metadata sizes get aligned up.
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1000, 2);
+ ASSERT_NE(builder, nullptr);
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
EXPECT_EQ(exported->geometry.metadata_max_size, 1024);
}
-TEST(liblp, InternalAlignment) {
+TEST_F(BuilderTest, InternalAlignment) {
// Test the metadata fitting within alignment.
- BlockDeviceInfo device_info(1024 * 1024, 768 * 1024, 0, 4096);
+ BlockDeviceInfo device_info("super", 1024 * 1024, 768 * 1024, 0, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 2);
ASSERT_NE(builder, nullptr);
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
- EXPECT_EQ(exported->geometry.first_logical_sector, 1536);
- EXPECT_EQ(exported->geometry.last_logical_sector, 2031);
+ auto super_device = GetMetadataSuperBlockDevice(*exported.get());
+ ASSERT_NE(super_device, nullptr);
+ EXPECT_EQ(super_device->first_logical_sector, 1536);
// Test a large alignment offset thrown in.
device_info.alignment_offset = 753664;
@@ -139,8 +164,9 @@
ASSERT_NE(builder, nullptr);
exported = builder->Export();
ASSERT_NE(exported, nullptr);
- EXPECT_EQ(exported->geometry.first_logical_sector, 1472);
- EXPECT_EQ(exported->geometry.last_logical_sector, 2031);
+ super_device = GetMetadataSuperBlockDevice(*exported.get());
+ ASSERT_NE(super_device, nullptr);
+ EXPECT_EQ(super_device->first_logical_sector, 1472);
// Alignment offset without alignment doesn't mean anything.
device_info.alignment = 0;
@@ -154,8 +180,9 @@
ASSERT_NE(builder, nullptr);
exported = builder->Export();
ASSERT_NE(exported, nullptr);
- EXPECT_EQ(exported->geometry.first_logical_sector, 78);
- EXPECT_EQ(exported->geometry.last_logical_sector, 1973);
+ super_device = GetMetadataSuperBlockDevice(*exported.get());
+ ASSERT_NE(super_device, nullptr);
+ EXPECT_EQ(super_device->first_logical_sector, 174);
// Test a small alignment with no alignment offset.
device_info.alignment = 11 * 1024;
@@ -163,17 +190,18 @@
ASSERT_NE(builder, nullptr);
exported = builder->Export();
ASSERT_NE(exported, nullptr);
- EXPECT_EQ(exported->geometry.first_logical_sector, 72);
- EXPECT_EQ(exported->geometry.last_logical_sector, 1975);
+ super_device = GetMetadataSuperBlockDevice(*exported.get());
+ ASSERT_NE(super_device, nullptr);
+ EXPECT_EQ(super_device->first_logical_sector, 160);
}
-TEST(liblp, InternalPartitionAlignment) {
- BlockDeviceInfo device_info(512 * 1024 * 1024, 768 * 1024, 753664, 4096);
+TEST_F(BuilderTest, InternalPartitionAlignment) {
+ BlockDeviceInfo device_info("super", 512 * 1024 * 1024, 768 * 1024, 753664, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 32 * 1024, 2);
- Partition* a = builder->AddPartition("a", TEST_GUID, 0);
+ Partition* a = builder->AddPartition("a", 0);
ASSERT_NE(a, nullptr);
- Partition* b = builder->AddPartition("b", TEST_GUID2, 0);
+ Partition* b = builder->AddPartition("b", 0);
ASSERT_NE(b, nullptr);
// Add a bunch of small extents to each, interleaving.
@@ -181,8 +209,8 @@
ASSERT_TRUE(builder->ResizePartition(a, a->size() + 4096));
ASSERT_TRUE(builder->ResizePartition(b, b->size() + 4096));
}
- EXPECT_EQ(a->size(), 40960);
- EXPECT_EQ(b->size(), 40960);
+ EXPECT_EQ(a->size(), 7864320);
+ EXPECT_EQ(b->size(), 7864320);
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
@@ -190,7 +218,7 @@
// Check that each starting sector is aligned.
for (const auto& extent : exported->extents) {
ASSERT_EQ(extent.target_type, LP_TARGET_TYPE_LINEAR);
- EXPECT_EQ(extent.num_sectors, 8);
+ EXPECT_EQ(extent.num_sectors, 1536);
uint64_t lba = extent.target_data * LP_SECTOR_SIZE;
uint64_t aligned_lba = AlignTo(lba, device_info.alignment, device_info.alignment_offset);
@@ -201,22 +229,37 @@
EXPECT_EQ(exported->extents.back().target_data, 30656);
}
-TEST(liblp, UseAllDiskSpace) {
- unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
- EXPECT_EQ(builder->AllocatableSpace(), 1036288);
+TEST_F(BuilderTest, UseAllDiskSpace) {
+ static constexpr uint64_t total = 1024 * 1024;
+ static constexpr uint64_t metadata = 1024;
+ static constexpr uint64_t slots = 2;
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(total, metadata, slots);
+ // We reserve a geometry block (4KB) plus space for each copy of the
+ // maximum size of a metadata blob. Then, we double that space since
+ // we store a backup copy of everything.
+ static constexpr uint64_t geometry = 4 * 1024;
+ static constexpr uint64_t allocatable =
+ total - (metadata * slots + geometry) * 2 - LP_PARTITION_RESERVED_BYTES;
+ EXPECT_EQ(builder->AllocatableSpace(), allocatable);
+ EXPECT_EQ(builder->UsedSpace(), 0);
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
- EXPECT_EQ(builder->ResizePartition(system, 1036288), true);
- EXPECT_EQ(system->size(), 1036288);
- EXPECT_EQ(builder->ResizePartition(system, 1036289), false);
+ EXPECT_EQ(builder->ResizePartition(system, allocatable), true);
+ EXPECT_EQ(system->size(), allocatable);
+ EXPECT_EQ(builder->UsedSpace(), allocatable);
+ EXPECT_EQ(builder->AllocatableSpace(), allocatable);
+ EXPECT_EQ(builder->ResizePartition(system, allocatable + 1), false);
+ EXPECT_EQ(system->size(), allocatable);
+ EXPECT_EQ(builder->UsedSpace(), allocatable);
+ EXPECT_EQ(builder->AllocatableSpace(), allocatable);
}
-TEST(liblp, BuildComplex) {
+TEST_F(BuilderTest, BuildComplex) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
- Partition* vendor = builder->AddPartition("vendor", TEST_GUID2, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
+ Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
ASSERT_NE(vendor, nullptr);
EXPECT_EQ(builder->ResizePartition(system, 65536), true);
@@ -237,39 +280,39 @@
ASSERT_NE(system2, nullptr);
ASSERT_NE(vendor1, nullptr);
EXPECT_EQ(system1->num_sectors(), 65536 / LP_SECTOR_SIZE);
- EXPECT_EQ(system1->physical_sector(), 12);
+ EXPECT_EQ(system1->physical_sector(), 32);
EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE);
- EXPECT_EQ(system2->physical_sector(), 204);
+ EXPECT_EQ(system2->physical_sector(), 224);
EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE);
- EXPECT_EQ(vendor1->physical_sector(), 140);
+ EXPECT_EQ(vendor1->physical_sector(), 160);
EXPECT_EQ(system1->physical_sector() + system1->num_sectors(), vendor1->physical_sector());
EXPECT_EQ(vendor1->physical_sector() + vendor1->num_sectors(), system2->physical_sector());
}
-TEST(liblp, AddInvalidPartition) {
+TEST_F(BuilderTest, AddInvalidPartition) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
- Partition* partition = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ Partition* partition = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(partition, nullptr);
// Duplicate name.
- partition = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ partition = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
EXPECT_EQ(partition, nullptr);
// Empty name.
- partition = builder->AddPartition("", TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ partition = builder->AddPartition("", LP_PARTITION_ATTR_READONLY);
EXPECT_EQ(partition, nullptr);
}
-TEST(liblp, BuilderExport) {
+TEST_F(BuilderTest, BuilderExport) {
static const uint64_t kDiskSize = 1024 * 1024;
static const uint32_t kMetadataSize = 1024;
static const uint32_t kMetadataSlots = 2;
unique_ptr<MetadataBuilder> builder =
MetadataBuilder::New(kDiskSize, kMetadataSize, kMetadataSlots);
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
- Partition* vendor = builder->AddPartition("vendor", TEST_GUID2, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
+ Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
ASSERT_NE(vendor, nullptr);
EXPECT_EQ(builder->ResizePartition(system, 65536), true);
@@ -279,6 +322,9 @@
unique_ptr<LpMetadata> exported = builder->Export();
EXPECT_NE(exported, nullptr);
+ auto super_device = GetMetadataSuperBlockDevice(*exported.get());
+ ASSERT_NE(super_device, nullptr);
+
// Verify geometry. Some details of this may change if we change the
// metadata structures. So in addition to checking the exact values, we
// also check that they are internally consistent after.
@@ -287,14 +333,11 @@
EXPECT_EQ(geometry.struct_size, sizeof(geometry));
EXPECT_EQ(geometry.metadata_max_size, 1024);
EXPECT_EQ(geometry.metadata_slot_count, 2);
- EXPECT_EQ(geometry.first_logical_sector, 12);
- EXPECT_EQ(geometry.last_logical_sector, 2035);
+ EXPECT_EQ(super_device->first_logical_sector, 32);
static const size_t kMetadataSpace =
- (kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE;
- uint64_t space_at_end = kDiskSize - (geometry.last_logical_sector + 1) * LP_SECTOR_SIZE;
- EXPECT_GE(space_at_end, kMetadataSpace);
- EXPECT_GE(geometry.first_logical_sector * LP_SECTOR_SIZE, kMetadataSpace);
+ ((kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE) * 2;
+ EXPECT_GE(super_device->first_logical_sector * LP_SECTOR_SIZE, kMetadataSpace);
// Verify header.
const LpMetadataHeader& header = exported->header;
@@ -308,7 +351,6 @@
for (const auto& partition : exported->partitions) {
Partition* original = builder->FindPartition(GetPartitionName(partition));
ASSERT_NE(original, nullptr);
- EXPECT_EQ(original->guid(), GetPartitionGuid(partition));
for (size_t i = 0; i < partition.num_extents; i++) {
const auto& extent = exported->extents[partition.first_extent_index + i];
LinearExtent* original_extent = original->extents()[i]->AsLinearExtent();
@@ -320,11 +362,11 @@
}
}
-TEST(liblp, BuilderImport) {
+TEST_F(BuilderTest, BuilderImport) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
- Partition* vendor = builder->AddPartition("vendor", TEST_GUID2, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
+ Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
ASSERT_NE(vendor, nullptr);
EXPECT_EQ(builder->ResizePartition(system, 65536), true);
@@ -343,55 +385,43 @@
EXPECT_EQ(system->size(), 98304);
ASSERT_EQ(system->extents().size(), 2);
- EXPECT_EQ(system->guid(), TEST_GUID);
EXPECT_EQ(system->attributes(), LP_PARTITION_ATTR_READONLY);
EXPECT_EQ(vendor->size(), 32768);
ASSERT_EQ(vendor->extents().size(), 1);
- EXPECT_EQ(vendor->guid(), TEST_GUID2);
EXPECT_EQ(vendor->attributes(), LP_PARTITION_ATTR_READONLY);
LinearExtent* system1 = system->extents()[0]->AsLinearExtent();
LinearExtent* system2 = system->extents()[1]->AsLinearExtent();
LinearExtent* vendor1 = vendor->extents()[0]->AsLinearExtent();
EXPECT_EQ(system1->num_sectors(), 65536 / LP_SECTOR_SIZE);
- EXPECT_EQ(system1->physical_sector(), 12);
+ EXPECT_EQ(system1->physical_sector(), 32);
EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE);
- EXPECT_EQ(system2->physical_sector(), 204);
+ EXPECT_EQ(system2->physical_sector(), 224);
EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE);
}
-TEST(liblp, ExportNameTooLong) {
+TEST_F(BuilderTest, ExportNameTooLong) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
std::string name = "abcdefghijklmnopqrstuvwxyz0123456789";
- Partition* system = builder->AddPartition(name + name, TEST_GUID, LP_PARTITION_ATTR_READONLY);
+ Partition* system = builder->AddPartition(name + name, LP_PARTITION_ATTR_READONLY);
EXPECT_NE(system, nullptr);
unique_ptr<LpMetadata> exported = builder->Export();
EXPECT_EQ(exported, nullptr);
}
-TEST(liblp, ExportInvalidGuid) {
- unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
-
- Partition* system = builder->AddPartition("system", "bad", LP_PARTITION_ATTR_READONLY);
- EXPECT_NE(system, nullptr);
-
- unique_ptr<LpMetadata> exported = builder->Export();
- EXPECT_EQ(exported, nullptr);
-}
-
-TEST(liblp, MetadataTooLarge) {
+TEST_F(BuilderTest, MetadataTooLarge) {
static const size_t kDiskSize = 128 * 1024;
static const size_t kMetadataSize = 64 * 1024;
// No space to store metadata + geometry.
- BlockDeviceInfo device_info(kDiskSize, 0, 0, 4096);
+ BlockDeviceInfo device_info("super", kDiskSize, 0, 0, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
EXPECT_EQ(builder, nullptr);
// No space to store metadata + geometry + one free sector.
- device_info.size += LP_METADATA_GEOMETRY_SIZE * 2;
+ device_info.size += LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2);
builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
EXPECT_EQ(builder, nullptr);
@@ -411,18 +441,15 @@
EXPECT_EQ(builder, nullptr);
}
-TEST(liblp, block_device_info) {
+TEST_F(BuilderTest, block_device_info) {
std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
fs_mgr_free_fstab);
ASSERT_NE(fstab, nullptr);
- // This should read from the "super" partition once we have a well-defined
- // way to access it.
- struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab.get(), "/data");
- ASSERT_NE(rec, nullptr);
+ PartitionOpener opener;
BlockDeviceInfo device_info;
- ASSERT_TRUE(GetBlockDeviceInfo(rec->blk_device, &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.
@@ -435,49 +462,375 @@
ASSERT_LT(device_info.alignment_offset, device_info.alignment);
}
-TEST(liblp, UpdateBlockDeviceInfo) {
- BlockDeviceInfo device_info(1024 * 1024, 4096, 1024, 4096);
+TEST_F(BuilderTest, UpdateBlockDeviceInfo) {
+ BlockDeviceInfo device_info("super", 1024 * 1024, 4096, 1024, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
ASSERT_NE(builder, nullptr);
- EXPECT_EQ(builder->block_device_info().size, device_info.size);
- EXPECT_EQ(builder->block_device_info().alignment, device_info.alignment);
- EXPECT_EQ(builder->block_device_info().alignment_offset, device_info.alignment_offset);
- EXPECT_EQ(builder->block_device_info().logical_block_size, device_info.logical_block_size);
+ BlockDeviceInfo new_info;
+ ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
+
+ EXPECT_EQ(new_info.size, device_info.size);
+ EXPECT_EQ(new_info.alignment, device_info.alignment);
+ EXPECT_EQ(new_info.alignment_offset, device_info.alignment_offset);
+ EXPECT_EQ(new_info.logical_block_size, device_info.logical_block_size);
device_info.alignment = 0;
device_info.alignment_offset = 2048;
- builder->set_block_device_info(device_info);
- EXPECT_EQ(builder->block_device_info().alignment, 4096);
- EXPECT_EQ(builder->block_device_info().alignment_offset, device_info.alignment_offset);
+ ASSERT_TRUE(builder->UpdateBlockDeviceInfo("super", device_info));
+ ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
+ EXPECT_EQ(new_info.alignment, 4096);
+ EXPECT_EQ(new_info.alignment_offset, device_info.alignment_offset);
device_info.alignment = 8192;
device_info.alignment_offset = 0;
- builder->set_block_device_info(device_info);
- EXPECT_EQ(builder->block_device_info().alignment, 8192);
- EXPECT_EQ(builder->block_device_info().alignment_offset, 2048);
+ ASSERT_TRUE(builder->UpdateBlockDeviceInfo("super", device_info));
+ ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
+ EXPECT_EQ(new_info.alignment, 8192);
+ EXPECT_EQ(new_info.alignment_offset, 2048);
+
+ new_info.size += 4096;
+ ASSERT_FALSE(builder->UpdateBlockDeviceInfo("super", new_info));
+ ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
+ EXPECT_EQ(new_info.size, 1024 * 1024);
+
+ new_info.logical_block_size = 512;
+ ASSERT_FALSE(builder->UpdateBlockDeviceInfo("super", new_info));
+ ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
+ EXPECT_EQ(new_info.logical_block_size, 4096);
}
-TEST(liblp, InvalidBlockSize) {
- BlockDeviceInfo device_info(1024 * 1024, 0, 0, 513);
+TEST_F(BuilderTest, InvalidBlockSize) {
+ BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 513);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
EXPECT_EQ(builder, nullptr);
}
-TEST(liblp, AlignedExtentSize) {
- BlockDeviceInfo device_info(1024 * 1024, 0, 0, 4096);
+TEST_F(BuilderTest, AlignedExtentSize) {
+ BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
ASSERT_NE(builder, nullptr);
- Partition* partition = builder->AddPartition("system", TEST_GUID, 0);
+ Partition* partition = builder->AddPartition("system", 0);
ASSERT_NE(partition, nullptr);
ASSERT_TRUE(builder->ResizePartition(partition, 512));
EXPECT_EQ(partition->size(), 4096);
}
-TEST(liblp, AlignedFreeSpace) {
+TEST_F(BuilderTest, AlignedFreeSpace) {
// Only one sector free - at least one block is required.
- BlockDeviceInfo device_info(10240, 0, 0, 4096);
+ BlockDeviceInfo device_info("super", 10240, 0, 0, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 512, 1);
ASSERT_EQ(builder, nullptr);
}
+
+TEST_F(BuilderTest, HasDefaultGroup) {
+ BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+ ASSERT_NE(builder, nullptr);
+
+ EXPECT_FALSE(builder->AddGroup("default", 0));
+}
+
+TEST_F(BuilderTest, GroupSizeLimits) {
+ BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+ ASSERT_NE(builder, nullptr);
+
+ ASSERT_TRUE(builder->AddGroup("google", 16384));
+
+ Partition* partition = builder->AddPartition("system", "google", 0);
+ ASSERT_NE(partition, nullptr);
+ EXPECT_TRUE(builder->ResizePartition(partition, 8192));
+ EXPECT_EQ(partition->size(), 8192);
+ EXPECT_TRUE(builder->ResizePartition(partition, 16384));
+ EXPECT_EQ(partition->size(), 16384);
+ EXPECT_FALSE(builder->ResizePartition(partition, 32768));
+ EXPECT_EQ(partition->size(), 16384);
+}
+
+TEST_F(BuilderTest, ListPartitionsInGroup) {
+ BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+ ASSERT_NE(builder, nullptr);
+
+ ASSERT_TRUE(builder->AddGroup("groupA", 16384));
+ ASSERT_TRUE(builder->AddGroup("groupB", 16384));
+
+ Partition* system = builder->AddPartition("system", "groupA", 0);
+ Partition* vendor = builder->AddPartition("vendor", "groupA", 0);
+ Partition* product = builder->AddPartition("product", "groupB", 0);
+ ASSERT_NE(system, nullptr);
+ ASSERT_NE(vendor, nullptr);
+ ASSERT_NE(product, nullptr);
+
+ auto groupA = builder->ListPartitionsInGroup("groupA");
+ auto groupB = builder->ListPartitionsInGroup("groupB");
+ auto groupC = builder->ListPartitionsInGroup("groupC");
+ ASSERT_THAT(groupA, ElementsAre(system, vendor));
+ ASSERT_THAT(groupB, ElementsAre(product));
+ ASSERT_TRUE(groupC.empty());
+}
+
+TEST_F(BuilderTest, ChangeGroups) {
+ BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+ ASSERT_NE(builder, nullptr);
+
+ ASSERT_TRUE(builder->AddGroup("groupA", 16384));
+ ASSERT_TRUE(builder->AddGroup("groupB", 32768));
+
+ Partition* system = builder->AddPartition("system", "groupA", 0);
+ Partition* vendor = builder->AddPartition("vendor", "groupB", 0);
+ ASSERT_NE(system, nullptr);
+ ASSERT_NE(vendor, nullptr);
+ ASSERT_NE(builder->Export(), nullptr);
+
+ ASSERT_FALSE(builder->ChangePartitionGroup(system, "groupXYZ"));
+ ASSERT_TRUE(builder->ChangePartitionGroup(system, "groupB"));
+ ASSERT_NE(builder->Export(), nullptr);
+
+ // Violate group constraint by reassigning groups.
+ ASSERT_TRUE(builder->ResizePartition(system, 16384 + 4096));
+ ASSERT_TRUE(builder->ChangePartitionGroup(system, "groupA"));
+ ASSERT_EQ(builder->Export(), nullptr);
+
+ ASSERT_FALSE(builder->ChangeGroupSize("default", 2));
+ ASSERT_FALSE(builder->ChangeGroupSize("unknown", 2));
+ ASSERT_TRUE(builder->ChangeGroupSize("groupA", 32768));
+ 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);
+ ASSERT_TRUE(builder->AddGroup("foo_a", 5_GiB));
+ ASSERT_TRUE(builder->AddGroup("foo_b", 5_GiB));
+ android::fs_mgr::Partition* p;
+ p = builder->AddPartition("system_a", "foo_a", 0);
+ ASSERT_TRUE(p && builder->ResizePartition(p, 2_GiB));
+ p = builder->AddPartition("vendor_a", "foo_a", 0);
+ ASSERT_TRUE(p && builder->ResizePartition(p, 1_GiB));
+ p = builder->AddPartition("system_b", "foo_b", 0);
+ ASSERT_TRUE(p && builder->ResizePartition(p, 2_GiB));
+ p = builder->AddPartition("vendor_b", "foo_b", 0);
+ ASSERT_TRUE(p && builder->ResizePartition(p, 1_GiB));
+
+ builder->RemovePartition("system_a");
+ builder->RemovePartition("vendor_a");
+ p = builder->AddPartition("system_a", "foo_a", 0);
+ ASSERT_TRUE(p && builder->ResizePartition(p, 3_GiB));
+ p = builder->AddPartition("vendor_a", "foo_a", 0);
+ ASSERT_TRUE(p && builder->ResizePartition(p, 1_GiB));
+}
+
+TEST_F(BuilderTest, ListGroups) {
+ BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+ ASSERT_NE(builder, nullptr);
+ ASSERT_TRUE(builder->AddGroup("example", 0));
+
+ std::vector<std::string> groups = builder->ListGroups();
+ ASSERT_THAT(groups, ElementsAre("default", "example"));
+}
+
+TEST_F(BuilderTest, RemoveGroupAndPartitions) {
+ BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+ ASSERT_NE(builder, nullptr);
+ ASSERT_TRUE(builder->AddGroup("example", 0));
+ ASSERT_NE(builder->AddPartition("system", "default", 0), nullptr);
+ ASSERT_NE(builder->AddPartition("vendor", "example", 0), nullptr);
+
+ builder->RemoveGroupAndPartitions("example");
+ ASSERT_NE(builder->FindPartition("system"), nullptr);
+ ASSERT_EQ(builder->FindPartition("vendor"), nullptr);
+ ASSERT_THAT(builder->ListGroups(), ElementsAre("default"));
+
+ builder->RemoveGroupAndPartitions("default");
+ ASSERT_NE(builder->FindPartition("system"), nullptr);
+}
+
+TEST_F(BuilderTest, MultipleBlockDevices) {
+ std::vector<BlockDeviceInfo> partitions = {
+ BlockDeviceInfo("system_a", 256_MiB, 786432, 229376, 4096),
+ BlockDeviceInfo("vendor_a", 128_MiB, 786432, 753664, 4096),
+ BlockDeviceInfo("product_a", 64_MiB, 786432, 753664, 4096),
+ };
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(partitions, "system_a", 65536, 2);
+ ASSERT_NE(builder, nullptr);
+ EXPECT_EQ(builder->AllocatableSpace(), 467238912);
+
+ // Create a partition that spans 3 devices.
+ Partition* p = builder->AddPartition("system_a", 0);
+ ASSERT_NE(p, nullptr);
+ ASSERT_TRUE(builder->ResizePartition(p, 466976768));
+
+ unique_ptr<LpMetadata> metadata = builder->Export();
+ ASSERT_NE(metadata, nullptr);
+ ASSERT_EQ(metadata->block_devices.size(), 3);
+ EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[0]), "system_a");
+ EXPECT_EQ(metadata->block_devices[0].size, 256_MiB);
+ EXPECT_EQ(metadata->block_devices[0].alignment, 786432);
+ EXPECT_EQ(metadata->block_devices[0].alignment_offset, 229376);
+ EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[1]), "vendor_a");
+ EXPECT_EQ(metadata->block_devices[1].size, 128_MiB);
+ EXPECT_EQ(metadata->block_devices[1].alignment, 786432);
+ EXPECT_EQ(metadata->block_devices[1].alignment_offset, 753664);
+ EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[2]), "product_a");
+ EXPECT_EQ(metadata->block_devices[2].size, 64_MiB);
+ EXPECT_EQ(metadata->block_devices[2].alignment, 786432);
+ EXPECT_EQ(metadata->block_devices[2].alignment_offset, 753664);
+ ASSERT_EQ(metadata->extents.size(), 3);
+ EXPECT_EQ(metadata->extents[0].num_sectors, 522304);
+ EXPECT_EQ(metadata->extents[0].target_type, LP_TARGET_TYPE_LINEAR);
+ EXPECT_EQ(metadata->extents[0].target_data, 1984);
+ EXPECT_EQ(metadata->extents[0].target_source, 0);
+ EXPECT_EQ(metadata->extents[1].num_sectors, 260672);
+ EXPECT_EQ(metadata->extents[1].target_type, LP_TARGET_TYPE_LINEAR);
+ EXPECT_EQ(metadata->extents[1].target_data, 1472);
+ EXPECT_EQ(metadata->extents[1].target_source, 1);
+ EXPECT_EQ(metadata->extents[2].num_sectors, 129600);
+ EXPECT_EQ(metadata->extents[2].target_type, LP_TARGET_TYPE_LINEAR);
+ EXPECT_EQ(metadata->extents[2].target_data, 1472);
+ EXPECT_EQ(metadata->extents[2].target_source, 2);
+}
+
+TEST_F(BuilderTest, ImportPartitionsOk) {
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
+ ASSERT_NE(builder, nullptr);
+
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
+ Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
+ ASSERT_NE(system, nullptr);
+ ASSERT_NE(vendor, nullptr);
+ EXPECT_EQ(builder->ResizePartition(system, 65536), true);
+ EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
+ EXPECT_EQ(builder->ResizePartition(system, 98304), true);
+
+ unique_ptr<LpMetadata> exported = builder->Export();
+ ASSERT_NE(exported, nullptr);
+
+ builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
+ ASSERT_NE(builder, nullptr);
+
+ ASSERT_TRUE(builder->ImportPartitions(*exported.get(), {"vendor"}));
+ EXPECT_NE(builder->FindPartition("vendor"), nullptr);
+ EXPECT_EQ(builder->FindPartition("system"), nullptr);
+
+ unique_ptr<LpMetadata> new_metadata = builder->Export();
+ ASSERT_NE(new_metadata, nullptr);
+
+ ASSERT_EQ(exported->partitions.size(), static_cast<size_t>(2));
+ ASSERT_EQ(GetPartitionName(exported->partitions[1]), "vendor");
+ ASSERT_EQ(new_metadata->partitions.size(), static_cast<size_t>(1));
+ ASSERT_EQ(GetPartitionName(new_metadata->partitions[0]), "vendor");
+
+ const LpMetadataExtent& extent_a =
+ exported->extents[exported->partitions[1].first_extent_index];
+ const LpMetadataExtent& extent_b =
+ new_metadata->extents[new_metadata->partitions[0].first_extent_index];
+ EXPECT_EQ(extent_a.num_sectors, extent_b.num_sectors);
+ EXPECT_EQ(extent_a.target_type, extent_b.target_type);
+ EXPECT_EQ(extent_a.target_data, extent_b.target_data);
+ EXPECT_EQ(extent_a.target_source, extent_b.target_source);
+}
+
+TEST_F(BuilderTest, ImportPartitionsFail) {
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
+ ASSERT_NE(builder, nullptr);
+
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
+ Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
+ ASSERT_NE(system, nullptr);
+ ASSERT_NE(vendor, nullptr);
+ EXPECT_EQ(builder->ResizePartition(system, 65536), true);
+ EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
+ EXPECT_EQ(builder->ResizePartition(system, 98304), true);
+
+ unique_ptr<LpMetadata> exported = builder->Export();
+ ASSERT_NE(exported, nullptr);
+
+ // Different device size.
+ builder = MetadataBuilder::New(1024 * 2048, 1024, 2);
+ ASSERT_NE(builder, nullptr);
+ 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);
+ auto builder = MetadataBuilder::New(device_info, 65536, 2);
+ ASSERT_NE(builder, nullptr);
+ Partition* system_a = builder->AddPartition("system_a", 0);
+ ASSERT_NE(system_a, nullptr);
+ Partition* system_b = builder->AddPartition("system_b", 0);
+ ASSERT_NE(system_b, nullptr);
+ ASSERT_TRUE(builder->ResizePartition(system_a, 2_GiB));
+ ASSERT_TRUE(builder->ResizePartition(system_b, 2_GiB));
+
+ builder->RemovePartition("system_a");
+ system_a = builder->AddPartition("system_a", 0);
+ ASSERT_NE(system_a, nullptr);
+ ASSERT_TRUE(builder->ResizePartition(system_a, 3_GiB));
+
+ EXPECT_EQ(system_a->extents().size(), static_cast<size_t>(1));
+ EXPECT_EQ(system_b->extents().size(), static_cast<size_t>(1));
+ ASSERT_TRUE(builder->ResizePartition(system_b, 6_GiB));
+ EXPECT_EQ(system_b->extents().size(), static_cast<size_t>(2));
+
+ unique_ptr<LpMetadata> exported = builder->Export();
+ ASSERT_NE(exported, nullptr);
+ ASSERT_EQ(exported->extents.size(), static_cast<size_t>(3));
+ EXPECT_EQ(exported->extents[0].target_data, 10487808);
+ EXPECT_EQ(exported->extents[0].num_sectors, 10483712);
+ EXPECT_EQ(exported->extents[1].target_data, 6292992);
+ EXPECT_EQ(exported->extents[1].num_sectors, 2099712);
+ EXPECT_EQ(exported->extents[2].target_data, 1536);
+ EXPECT_EQ(exported->extents[2].num_sectors, 6291456);
+}
+
+TEST_F(BuilderTest, PartialExtents) {
+ // super has a minimum extent size of 768KiB.
+ BlockDeviceInfo device_info("super", 1_GiB, 768 * 1024, 0, 4096);
+ auto builder = MetadataBuilder::New(device_info, 65536, 1);
+ ASSERT_NE(builder, nullptr);
+ Partition* system = builder->AddPartition("system", 0);
+ ASSERT_NE(system, nullptr);
+ Partition* vendor = builder->AddPartition("vendor", 0);
+ ASSERT_NE(vendor, nullptr);
+ ASSERT_TRUE(builder->ResizePartition(system, device_info.alignment + 4096));
+ ASSERT_TRUE(builder->ResizePartition(vendor, device_info.alignment));
+ ASSERT_EQ(system->size(), device_info.alignment * 2);
+ ASSERT_EQ(vendor->size(), device_info.alignment);
+
+ ASSERT_TRUE(builder->ResizePartition(system, device_info.alignment * 2));
+ ASSERT_EQ(system->extents().size(), static_cast<size_t>(1));
+
+ unique_ptr<LpMetadata> exported = builder->Export();
+ ASSERT_NE(exported, nullptr);
+ ASSERT_EQ(exported->extents.size(), static_cast<size_t>(2));
+ EXPECT_EQ(exported->extents[0].target_data, 1536);
+ EXPECT_EQ(exported->extents[0].num_sectors, 3072);
+ EXPECT_EQ(exported->extents[1].target_data, 4608);
+ EXPECT_EQ(exported->extents[1].num_sectors, 1536);
+}
diff --git a/fs_mgr/liblp/images.cpp b/fs_mgr/liblp/images.cpp
index 742b1d0..5a498f9 100644
--- a/fs_mgr/liblp/images.cpp
+++ b/fs_mgr/liblp/images.cpp
@@ -19,8 +19,6 @@
#include <limits.h>
#include <android-base/file.h>
-#include <android-base/unique_fd.h>
-#include <sparse/sparse.h>
#include "reader.h"
#include "utility.h"
@@ -29,13 +27,24 @@
namespace android {
namespace fs_mgr {
+using android::base::unique_fd;
+
+#if defined(_WIN32)
+static const int O_NOFOLLOW = 0;
+#endif
+
std::unique_ptr<LpMetadata> ReadFromImageFile(int fd) {
- LpMetadataGeometry geometry;
- if (!ReadLogicalPartitionGeometry(fd, &geometry)) {
+ std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(LP_METADATA_GEOMETRY_SIZE);
+ if (SeekFile64(fd, 0, SEEK_SET) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed";
return nullptr;
}
- if (SeekFile64(fd, LP_METADATA_GEOMETRY_SIZE, SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << LP_METADATA_GEOMETRY_SIZE;
+ if (!android::base::ReadFully(fd, buffer.get(), LP_METADATA_GEOMETRY_SIZE)) {
+ PERROR << __PRETTY_FUNCTION__ << " read failed";
+ return nullptr;
+ }
+ LpMetadataGeometry geometry;
+ if (!ParseGeometry(buffer.get(), &geometry)) {
return nullptr;
}
return ParseMetadata(geometry, fd);
@@ -58,10 +67,10 @@
return ParseMetadata(geometry, metadata_buffer, metadata_buffer_size);
}
-std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file) {
- android::base::unique_fd fd(open(file, O_RDONLY));
+std::unique_ptr<LpMetadata> ReadFromImageFile(const std::string& image_file) {
+ unique_fd fd(open(image_file.c_str(), O_RDONLY | O_CLOEXEC));
if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << "open failed: " << file;
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << image_file;
return nullptr;
}
return ReadFromImageFile(fd);
@@ -74,65 +83,83 @@
std::string everything = geometry + metadata;
if (!android::base::WriteFully(fd, everything.data(), everything.size())) {
- PERROR << __PRETTY_FUNCTION__ << "write " << everything.size() << " bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " write " << everything.size() << " bytes failed";
return false;
}
return true;
}
bool WriteToImageFile(const char* file, const LpMetadata& input) {
- android::base::unique_fd fd(open(file, O_CREAT | O_RDWR | O_TRUNC, 0644));
+ unique_fd fd(open(file, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, 0644));
if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << "open failed: " << file;
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << file;
return false;
}
return WriteToImageFile(fd, input);
}
-// We use an object to build the sparse file since it requires that data
-// pointers be held alive until the sparse file is destroyed. It's easier
-// to do this when the data pointers are all in one place.
-class SparseBuilder {
- public:
- SparseBuilder(const LpMetadata& metadata, uint32_t block_size,
- const std::map<std::string, std::string>& images);
-
- bool Build();
- bool Export(const char* file);
- bool IsValid() const { return file_ != nullptr; }
-
- private:
- bool AddData(const std::string& blob, uint64_t sector);
- bool AddPartitionImage(const LpMetadataPartition& partition, const std::string& file);
- int OpenImageFile(const std::string& file);
- bool SectorToBlock(uint64_t sector, uint32_t* block);
-
- const LpMetadata& metadata_;
- const LpMetadataGeometry& geometry_;
- uint32_t block_size_;
- std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)> file_;
- std::string primary_blob_;
- std::string backup_blob_;
- std::map<std::string, std::string> images_;
- std::vector<android::base::unique_fd> temp_fds_;
-};
-
SparseBuilder::SparseBuilder(const LpMetadata& metadata, uint32_t block_size,
const std::map<std::string, std::string>& images)
: metadata_(metadata),
geometry_(metadata.geometry),
block_size_(block_size),
- file_(sparse_file_new(block_size_, geometry_.block_device_size), sparse_file_destroy),
- images_(images) {}
+ images_(images) {
+ uint64_t total_size = GetTotalSuperPartitionSize(metadata);
+ if (block_size % LP_SECTOR_SIZE != 0) {
+ LERROR << "Block size must be a multiple of the sector size, " << LP_SECTOR_SIZE;
+ return;
+ }
+ if (total_size % block_size != 0) {
+ LERROR << "Device size must be a multiple of the block size, " << block_size;
+ return;
+ }
+ if (metadata.geometry.metadata_max_size % block_size != 0) {
+ LERROR << "Metadata max size must be a multiple of the block size, " << block_size;
+ return;
+ }
+ if (LP_METADATA_GEOMETRY_SIZE % block_size != 0) {
+ LERROR << "Geometry size is not a multiple of the block size, " << block_size;
+ return;
+ }
+ if (LP_PARTITION_RESERVED_BYTES % block_size != 0) {
+ LERROR << "Reserved size is not a multiple of the block size, " << block_size;
+ return;
+ }
+
+ uint64_t num_blocks = total_size / block_size;
+ if (num_blocks >= UINT_MAX) {
+ // libsparse counts blocks in unsigned 32-bit integers, so we check to
+ // make sure we're not going to overflow.
+ LERROR << "Block device is too large to encode with libsparse.";
+ return;
+ }
+
+ for (const auto& block_device : metadata.block_devices) {
+ SparsePtr file(sparse_file_new(block_size_, block_device.size), sparse_file_destroy);
+ if (!file) {
+ LERROR << "Could not allocate sparse file of size " << block_device.size;
+ return;
+ }
+ device_images_.emplace_back(std::move(file));
+ }
+}
+
+bool SparseBuilder::IsValid() const {
+ return device_images_.size() == metadata_.block_devices.size();
+}
bool SparseBuilder::Export(const char* file) {
- android::base::unique_fd fd(open(file, O_CREAT | O_RDWR | O_TRUNC, 0644));
+ unique_fd fd(open(file, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, 0644));
if (fd < 0) {
PERROR << "open failed: " << file;
return false;
}
+ if (device_images_.size() > 1) {
+ LERROR << "Cannot export to a single image on retrofit builds.";
+ return false;
+ }
// No gzip compression; sparseify; no checksum.
- int ret = sparse_file_write(file_.get(), fd, false, true, false);
+ int ret = sparse_file_write(device_images_[0].get(), fd, false, true, false);
if (ret != 0) {
LERROR << "sparse_file_write failed (error code " << ret << ")";
return false;
@@ -140,13 +167,35 @@
return true;
}
-bool SparseBuilder::AddData(const std::string& blob, uint64_t sector) {
+bool SparseBuilder::ExportFiles(const std::string& output_dir) {
+ for (size_t i = 0; i < device_images_.size(); i++) {
+ std::string name = GetBlockDevicePartitionName(metadata_.block_devices[i]);
+ std::string file_name = "super_" + name + ".img";
+ std::string file_path = output_dir + "/" + file_name;
+
+ static const int kOpenFlags = O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_NOFOLLOW;
+ unique_fd fd(open(file_path.c_str(), kOpenFlags, 0644));
+ if (fd < 0) {
+ PERROR << "open failed: " << file_path;
+ return false;
+ }
+ // No gzip compression; sparseify; no checksum.
+ int ret = sparse_file_write(device_images_[i].get(), fd, false, true, false);
+ if (ret != 0) {
+ LERROR << "sparse_file_write failed (error code " << ret << ")";
+ return false;
+ }
+ }
+ return true;
+}
+
+bool SparseBuilder::AddData(sparse_file* file, const std::string& blob, uint64_t sector) {
uint32_t block;
if (!SectorToBlock(sector, &block)) {
return false;
}
void* data = const_cast<char*>(blob.data());
- int ret = sparse_file_add_data(file_.get(), data, blob.size(), block);
+ int ret = sparse_file_add_data(file, data, blob.size(), block);
if (ret != 0) {
LERROR << "sparse_file_add_data failed (error code " << ret << ")";
return false;
@@ -169,21 +218,32 @@
return true;
}
+uint64_t SparseBuilder::BlockToSector(uint64_t block) const {
+ return (block * block_size_) / LP_SECTOR_SIZE;
+}
+
bool SparseBuilder::Build() {
+ if (sparse_file_add_fill(device_images_[0].get(), 0, LP_PARTITION_RESERVED_BYTES, 0) < 0) {
+ LERROR << "Could not add initial sparse block for reserved zeroes";
+ return false;
+ }
+
std::string geometry_blob = SerializeGeometry(geometry_);
std::string metadata_blob = SerializeMetadata(metadata_);
metadata_blob.resize(geometry_.metadata_max_size);
- std::string all_metadata;
- for (size_t i = 0; i < geometry_.metadata_slot_count; i++) {
- all_metadata += metadata_blob;
+ // Two copies of geometry, then two copies of each metadata slot.
+ all_metadata_ += geometry_blob + geometry_blob;
+ for (size_t i = 0; i < geometry_.metadata_slot_count * 2; i++) {
+ all_metadata_ += metadata_blob;
}
- // Metadata immediately follows geometry, and we write the same metadata
- // to all slots. Note that we don't bother trying to write skip chunks
- // here since it's a small amount of data.
- primary_blob_ = geometry_blob + all_metadata;
- if (!AddData(primary_blob_, 0)) {
+ uint64_t first_sector = LP_PARTITION_RESERVED_BYTES / LP_SECTOR_SIZE;
+ if (!AddData(device_images_[0].get(), all_metadata_, first_sector)) {
+ return false;
+ }
+
+ if (!CheckExtentOrdering()) {
return false;
}
@@ -202,17 +262,6 @@
LERROR << "Partition image was specified but no partition was found.";
return false;
}
-
- // The backup area contains all metadata slots, and then geometry. Similar
- // to before we write the metadata to every slot.
- int64_t backup_offset = GetBackupMetadataOffset(geometry_, 0);
- uint64_t backups_start = geometry_.block_device_size + backup_offset;
- uint64_t backup_sector = backups_start / LP_SECTOR_SIZE;
-
- backup_blob_ = all_metadata + geometry_blob;
- if (!AddData(backup_blob_, backup_sector)) {
- return false;
- }
return true;
}
@@ -228,13 +277,10 @@
bool SparseBuilder::AddPartitionImage(const LpMetadataPartition& partition,
const std::string& file) {
- if (partition.num_extents != 1) {
- LERROR << "Partition for new tables should not have more than one extent: "
- << GetPartitionName(partition);
- return false;
- }
+ // Track which extent we're processing.
+ uint32_t extent_index = partition.first_extent_index;
- const LpMetadataExtent& extent = metadata_.extents[partition.first_extent_index];
+ const LpMetadataExtent& extent = metadata_.extents[extent_index];
if (extent.target_type != LP_TARGET_TYPE_LINEAR) {
LERROR << "Partition should only have linear extents: " << GetPartitionName(partition);
return false;
@@ -252,9 +298,11 @@
LERROR << "Could not compute image size";
return false;
}
- if (file_length > extent.num_sectors * LP_SECTOR_SIZE) {
+ uint64_t partition_size = ComputePartitionSize(partition);
+ if (file_length > partition_size) {
LERROR << "Image for partition '" << GetPartitionName(partition)
- << "' is greater than its size";
+ << "' is greater than its size (" << file_length << ", expected " << partition_size
+ << ")";
return false;
}
if (SeekFile64(fd, 0, SEEK_SET)) {
@@ -262,14 +310,39 @@
return false;
}
+ // We track the current logical sector and the position the current extent
+ // ends at.
+ uint64_t output_sector = 0;
+ uint64_t extent_last_sector = extent.num_sectors;
+
+ // We also track the output device and the current output block within that
+ // device.
uint32_t output_block;
if (!SectorToBlock(extent.target_data, &output_block)) {
return false;
}
+ sparse_file* output_device = device_images_[extent.target_source].get();
+ // Proceed to read the file and build sparse images.
uint64_t pos = 0;
uint64_t remaining = file_length;
while (remaining) {
+ // Check if we need to advance to the next extent.
+ if (output_sector == extent_last_sector) {
+ extent_index++;
+ if (extent_index >= partition.first_extent_index + partition.num_extents) {
+ LERROR << "image is larger than extent table";
+ return false;
+ }
+
+ const LpMetadataExtent& extent = metadata_.extents[extent_index];
+ extent_last_sector += extent.num_sectors;
+ output_device = device_images_[extent.target_source].get();
+ if (!SectorToBlock(extent.target_data, &output_block)) {
+ return false;
+ }
+ }
+
uint32_t buffer[block_size_ / sizeof(uint32_t)];
size_t read_size = remaining >= sizeof(buffer) ? sizeof(buffer) : size_t(remaining);
if (!android::base::ReadFully(fd, buffer, sizeof(buffer))) {
@@ -277,13 +350,13 @@
return false;
}
if (read_size != sizeof(buffer) || !HasFillValue(buffer, read_size / sizeof(uint32_t))) {
- int rv = sparse_file_add_fd(file_.get(), fd, pos, read_size, output_block);
+ int rv = sparse_file_add_fd(output_device, fd, pos, read_size, output_block);
if (rv) {
LERROR << "sparse_file_add_fd failed with code: " << rv;
return false;
}
} else {
- int rv = sparse_file_add_fill(file_.get(), buffer[0], read_size, output_block);
+ int rv = sparse_file_add_fill(output_device, buffer[0], read_size, output_block);
if (rv) {
LERROR << "sparse_file_add_fill failed with code: " << rv;
return false;
@@ -291,76 +364,89 @@
}
pos += read_size;
remaining -= read_size;
+ output_sector += block_size_ / LP_SECTOR_SIZE;
output_block++;
}
return true;
}
+uint64_t SparseBuilder::ComputePartitionSize(const LpMetadataPartition& partition) const {
+ uint64_t sectors = 0;
+ for (size_t i = 0; i < partition.num_extents; i++) {
+ sectors += metadata_.extents[partition.first_extent_index + i].num_sectors;
+ }
+ return sectors * LP_SECTOR_SIZE;
+}
+
+// For simplicity, we don't allow serializing any configuration: extents must
+// be ordered, such that any extent at position I in the table occurs *before*
+// any extent after position I, for the same block device. We validate that
+// here.
+//
+// Without this, it would be more difficult to find the appropriate extent for
+// an output block. With this guarantee it is a linear walk.
+bool SparseBuilder::CheckExtentOrdering() {
+ std::vector<uint64_t> last_sectors(metadata_.block_devices.size());
+
+ for (const auto& extent : metadata_.extents) {
+ if (extent.target_type != LP_TARGET_TYPE_LINEAR) {
+ LERROR << "Extents must all be type linear.";
+ return false;
+ }
+ if (extent.target_data <= last_sectors[extent.target_source]) {
+ LERROR << "Extents must appear in increasing order.";
+ return false;
+ }
+ if ((extent.num_sectors * LP_SECTOR_SIZE) % block_size_ != 0) {
+ LERROR << "Extents must be aligned to the block size.";
+ return false;
+ }
+ last_sectors[extent.target_source] = extent.target_data;
+ }
+ return true;
+}
+
int SparseBuilder::OpenImageFile(const std::string& file) {
- android::base::unique_fd source_fd(open(file.c_str(), O_RDONLY));
+ android::base::unique_fd source_fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
if (source_fd < 0) {
PERROR << "open image file failed: " << file;
return -1;
}
- std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)> source(
- sparse_file_import(source_fd, true, true), sparse_file_destroy);
+ SparsePtr source(sparse_file_import(source_fd, true, true), sparse_file_destroy);
if (!source) {
int fd = source_fd.get();
temp_fds_.push_back(std::move(source_fd));
return fd;
}
- char temp_file[PATH_MAX];
- snprintf(temp_file, sizeof(temp_file), "%s/imageXXXXXX", P_tmpdir);
- android::base::unique_fd temp_fd(mkstemp(temp_file));
- if (temp_fd < 0) {
- PERROR << "mkstemp failed";
- return -1;
- }
- if (unlink(temp_file) < 0) {
- PERROR << "unlink failed";
+ TemporaryFile tf;
+ if (tf.fd < 0) {
+ PERROR << "make temporary file failed";
return -1;
}
// We temporarily unsparse the file, rather than try to merge its chunks.
- int rv = sparse_file_write(source.get(), temp_fd, false, false, false);
+ int rv = sparse_file_write(source.get(), tf.fd, false, false, false);
if (rv) {
LERROR << "sparse_file_write failed with code: " << rv;
return -1;
}
- temp_fds_.push_back(std::move(temp_fd));
+ temp_fds_.push_back(android::base::unique_fd(tf.release()));
return temp_fds_.back().get();
}
bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size,
const std::map<std::string, std::string>& images) {
- if (block_size % LP_SECTOR_SIZE != 0) {
- LERROR << "Block size must be a multiple of the sector size, " << LP_SECTOR_SIZE;
- return false;
- }
- if (metadata.geometry.block_device_size % block_size != 0) {
- LERROR << "Device size must be a multiple of the block size, " << block_size;
- return false;
- }
- uint64_t num_blocks = metadata.geometry.block_device_size % block_size;
- if (num_blocks >= UINT_MAX) {
- // libsparse counts blocks in unsigned 32-bit integers, so we check to
- // make sure we're not going to overflow.
- LERROR << "Block device is too large to encode with libsparse.";
- return false;
- }
-
SparseBuilder builder(metadata, block_size, images);
- if (!builder.IsValid()) {
- LERROR << "Could not allocate sparse file of size " << metadata.geometry.block_device_size;
- return false;
- }
- if (!builder.Build()) {
- return false;
- }
- return builder.Export(file);
+ return builder.IsValid() && builder.Build() && builder.Export(file);
+}
+
+bool WriteSplitSparseFiles(const std::string& output_dir, const LpMetadata& metadata,
+ uint32_t block_size, const std::map<std::string, std::string>& images) {
+ SparseBuilder builder(metadata, block_size, images);
+ return builder.IsValid() && builder.Build() && builder.ExportFiles(output_dir);
}
} // namespace fs_mgr
diff --git a/fs_mgr/liblp/images.h b/fs_mgr/liblp/images.h
index 3a999b8..44217a0 100644
--- a/fs_mgr/liblp/images.h
+++ b/fs_mgr/liblp/images.h
@@ -14,7 +14,14 @@
* limitations under the License.
*/
+#include <stdint.h>
+#include <map>
+#include <memory>
+#include <string>
+
+#include <android-base/unique_fd.h>
#include <liblp/liblp.h>
+#include <sparse/sparse.h>
namespace android {
namespace fs_mgr {
@@ -25,5 +32,40 @@
bool WriteToImageFile(const char* file, const LpMetadata& metadata);
bool WriteToImageFile(int fd, const LpMetadata& metadata);
+// We use an object to build the sparse file since it requires that data
+// pointers be held alive until the sparse file is destroyed. It's easier
+// to do this when the data pointers are all in one place.
+class SparseBuilder {
+ public:
+ SparseBuilder(const LpMetadata& metadata, uint32_t block_size,
+ const std::map<std::string, std::string>& images);
+
+ bool Build();
+ bool Export(const char* file);
+ bool ExportFiles(const std::string& dir);
+ bool IsValid() const;
+
+ using SparsePtr = std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)>;
+ const std::vector<SparsePtr>& device_images() const { return device_images_; }
+
+ private:
+ bool AddData(sparse_file* file, const std::string& blob, uint64_t sector);
+ bool AddPartitionImage(const LpMetadataPartition& partition, const std::string& file);
+ int OpenImageFile(const std::string& file);
+ bool SectorToBlock(uint64_t sector, uint32_t* block);
+ uint64_t BlockToSector(uint64_t block) const;
+ bool CheckExtentOrdering();
+ uint64_t ComputePartitionSize(const LpMetadataPartition& partition) const;
+
+ const LpMetadata& metadata_;
+ const LpMetadataGeometry& geometry_;
+ uint32_t block_size_;
+
+ std::vector<SparsePtr> device_images_;
+ std::string all_metadata_;
+ std::map<std::string, std::string> images_;
+ std::vector<android::base::unique_fd> temp_fds_;
+};
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index a35cf8e..53f480f 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -22,8 +22,11 @@
#include <map>
#include <memory>
+#include <optional>
+#include <set>
#include "liblp.h"
+#include "partition_opener.h"
namespace android {
namespace fs_mgr {
@@ -34,34 +37,13 @@
static const uint32_t kDefaultPartitionAlignment = 1024 * 1024;
static const uint32_t kDefaultBlockSize = 4096;
-struct BlockDeviceInfo {
- BlockDeviceInfo() : size(0), alignment(0), alignment_offset(0), logical_block_size(0) {}
- BlockDeviceInfo(uint64_t size, uint32_t alignment, uint32_t alignment_offset,
- uint32_t logical_block_size)
- : size(size),
- alignment(alignment),
- alignment_offset(alignment_offset),
- logical_block_size(logical_block_size) {}
- // Size of the block device, in bytes.
- uint64_t size;
- // Optimal target alignment, in bytes. Partition extents will be aligned to
- // this value by default. This value must be 0 or a multiple of 512.
- uint32_t alignment;
- // Alignment offset to parent device (if any), in bytes. The sector at
- // |alignment_offset| on the target device is correctly aligned on its
- // parent device. This value must be 0 or a multiple of 512.
- uint32_t alignment_offset;
- // Block size, for aligning extent sizes and partition sizes.
- uint32_t logical_block_size;
-};
-
// Abstraction around dm-targets that can be encoded into logical partition tables.
class Extent {
public:
explicit Extent(uint64_t num_sectors) : num_sectors_(num_sectors) {}
virtual ~Extent() {}
- virtual void AddTo(LpMetadata* out) const = 0;
+ virtual bool AddTo(LpMetadata* out) const = 0;
virtual LinearExtent* AsLinearExtent() { return nullptr; }
uint64_t num_sectors() const { return num_sectors_; }
@@ -74,16 +56,18 @@
// This corresponds to a dm-linear target.
class LinearExtent final : public Extent {
public:
- LinearExtent(uint64_t num_sectors, uint64_t physical_sector)
- : Extent(num_sectors), physical_sector_(physical_sector) {}
+ LinearExtent(uint64_t num_sectors, uint32_t device_index, uint64_t physical_sector)
+ : Extent(num_sectors), device_index_(device_index), physical_sector_(physical_sector) {}
- void AddTo(LpMetadata* metadata) const override;
+ bool AddTo(LpMetadata* metadata) const override;
LinearExtent* AsLinearExtent() override { return this; }
uint64_t physical_sector() const { return physical_sector_; }
uint64_t end_sector() const { return physical_sector_ + num_sectors_; }
+ uint32_t device_index() const { return device_index_; }
private:
+ uint32_t device_index_;
uint64_t physical_sector_;
};
@@ -92,14 +76,31 @@
public:
explicit ZeroExtent(uint64_t num_sectors) : Extent(num_sectors) {}
- void AddTo(LpMetadata* out) const override;
+ bool AddTo(LpMetadata* out) const override;
+};
+
+class PartitionGroup final {
+ friend class MetadataBuilder;
+
+ public:
+ explicit PartitionGroup(const std::string& name, uint64_t maximum_size)
+ : name_(name), maximum_size_(maximum_size) {}
+
+ const std::string& name() const { return name_; }
+ uint64_t maximum_size() const { return maximum_size_; }
+
+ private:
+ void set_maximum_size(uint64_t maximum_size) { maximum_size_ = maximum_size; }
+
+ std::string name_;
+ uint64_t maximum_size_;
};
class Partition final {
friend class MetadataBuilder;
public:
- Partition(const std::string& name, const std::string& guid, uint32_t attributes);
+ Partition(const std::string& name, const std::string& group_name, uint32_t attributes);
// Add a raw extent.
void AddExtent(std::unique_ptr<Extent>&& extent);
@@ -107,17 +108,22 @@
// Remove all extents from this partition.
void RemoveExtents();
+ // Compute the size used by linear extents. This is the same as size(),
+ // but does not factor in extents which do not take up space.
+ uint64_t BytesOnDisk() const;
+
const std::string& name() const { return name_; }
+ const std::string& group_name() const { return group_name_; }
uint32_t attributes() const { return attributes_; }
- const std::string& guid() const { return guid_; }
const std::vector<std::unique_ptr<Extent>>& extents() const { return extents_; }
uint64_t size() const { return size_; }
private:
void ShrinkTo(uint64_t aligned_size);
+ void set_group_name(const std::string& group_name) { group_name_ = group_name; }
std::string name_;
- std::string guid_;
+ std::string group_name_;
std::vector<std::unique_ptr<Extent>> extents_;
uint32_t attributes_;
uint64_t size_;
@@ -125,44 +131,89 @@
class MetadataBuilder {
public:
- // Construct an empty logical partition table builder. The block device size
- // and maximum metadata size must be specified, as this will determine which
- // areas of the physical partition can be flashed for metadata vs for logical
- // partitions.
+ // Construct an empty logical partition table builder given the specified
+ // map of partitions that are available for storing logical partitions.
+ //
+ // At least one partition in the list must be the "super" device, where
+ // metadata will be stored.
//
// If the parameters would yield invalid metadata, nullptr is returned. This
- // could happen if the block device size is too small to store the metadata
- // and backup copies.
- static std::unique_ptr<MetadataBuilder> New(const BlockDeviceInfo& device_info,
+ // could happen if the super device is too small to store all required
+ // metadata.
+ static std::unique_ptr<MetadataBuilder> New(const std::vector<BlockDeviceInfo>& block_devices,
+ const std::string& super_partition,
uint32_t metadata_max_size,
uint32_t metadata_slot_count);
// Import an existing table for modification. This reads metadata off the
// given block device and imports it. It also adjusts alignment information
// based on run-time values in the operating system.
- static std::unique_ptr<MetadataBuilder> New(const std::string& block_device,
+ static std::unique_ptr<MetadataBuilder> New(const IPartitionOpener& opener,
+ const std::string& super_partition,
uint32_t slot_number);
+ // Same as above, but use the default PartitionOpener.
+ static std::unique_ptr<MetadataBuilder> New(const std::string& super_partition,
+ uint32_t slot_number);
+
+ // This is when performing an A/B update. The source partition must be a
+ // super partition. On a normal device, the metadata for the source slot
+ // is imported and the target slot is ignored. On a retrofit device, the
+ // metadata may not have the target slot's devices listed yet, in which
+ // case, it is automatically upgraded to include all available block
+ // devices.
+ static std::unique_ptr<MetadataBuilder> NewForUpdate(const IPartitionOpener& opener,
+ const std::string& source_partition,
+ uint32_t source_slot_number,
+ uint32_t target_slot_number);
+
// Import an existing table for modification. If the table is not valid, for
// example it contains duplicate partition names, then nullptr is returned.
- // This method is for testing or changing off-line tables.
- static std::unique_ptr<MetadataBuilder> New(const LpMetadata& metadata);
+ //
+ // If an IPartitionOpener is specified, then block device informatiom will
+ // be updated.
+ static std::unique_ptr<MetadataBuilder> New(const LpMetadata& metadata,
+ const IPartitionOpener* opener = nullptr);
+
+ // Helper function for a single super partition, for tests.
+ static std::unique_ptr<MetadataBuilder> New(const BlockDeviceInfo& device_info,
+ uint32_t metadata_max_size,
+ uint32_t metadata_slot_count) {
+ return New({device_info}, device_info.partition_name, metadata_max_size,
+ metadata_slot_count);
+ }
// Wrapper around New() with a BlockDeviceInfo that only specifies a device
// size. This is a convenience method for tests.
static std::unique_ptr<MetadataBuilder> New(uint64_t blockdev_size, uint32_t metadata_max_size,
uint32_t metadata_slot_count) {
- BlockDeviceInfo device_info(blockdev_size, 0, 0, kDefaultBlockSize);
+ BlockDeviceInfo device_info(LP_METADATA_DEFAULT_PARTITION_NAME, blockdev_size, 0, 0,
+ kDefaultBlockSize);
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);
+
// Export metadata so it can be serialized to an image, to disk, or mounted
// via device-mapper.
std::unique_ptr<LpMetadata> Export();
// 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& guid, uint32_t attributes);
+ Partition* AddPartition(const std::string& name, const std::string& group_name,
+ uint32_t attributes);
+
+ // Same as AddPartition above, but uses the default partition group which
+ // has no size restrictions.
+ Partition* AddPartition(const std::string& name, uint32_t attributes);
// Delete a partition by name if it exists.
void RemovePartition(const std::string& name);
@@ -170,6 +221,13 @@
// Find a partition by name. If no partition is found, nullptr is returned.
Partition* FindPartition(const std::string& name);
+ // Find a group by name. If no group is found, nullptr is returned.
+ PartitionGroup* FindGroup(const std::string& name);
+
+ // Add a predetermined extent to a partition.
+ bool AddLinearExtent(Partition* partition, const std::string& block_device,
+ uint64_t num_sectors, uint64_t physical_sector);
+
// Grow or shrink a partition to the requested size. This size will be
// rounded UP to the nearest block (512 bytes).
//
@@ -182,26 +240,101 @@
// underlying filesystem or contents of the partition on disk.
bool ResizePartition(Partition* partition, uint64_t requested_size);
+ // Return the list of partitions belonging to a group.
+ std::vector<Partition*> ListPartitionsInGroup(const std::string& 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);
+
+ // Changes the size of a partition group. Size constraints will not be
+ // checked until metadata is exported, to avoid errors during group
+ // reshuffling. This will return false if the group does not exist, or if
+ // the group name is "default".
+ bool ChangeGroupSize(const std::string& group_name, uint64_t maximum_size);
+
// Amount of space that can be allocated to logical partitions.
uint64_t AllocatableSpace() const;
+ uint64_t UsedSpace() const;
- // Merge new block device information into previous values. Alignment values
- // are only overwritten if the new values are non-zero.
- void set_block_device_info(const BlockDeviceInfo& device_info);
- const BlockDeviceInfo& block_device_info() const { return device_info_; }
+ // Return a list of all group names.
+ std::vector<std::string> ListGroups() const;
+
+ // Remove all partitions belonging to a group, then remove the group.
+ void RemoveGroupAndPartitions(const std::string& group_name);
+
+ // Set the LP_METADATA_AUTO_SLOT_SUFFIXING flag.
+ void SetAutoSlotSuffixing();
+
+ // If set, checks for slot suffixes will be ignored internally.
+ void IgnoreSlotSuffixing();
+
+ bool GetBlockDeviceInfo(const std::string& partition_name, BlockDeviceInfo* info) const;
+ bool UpdateBlockDeviceInfo(const std::string& partition_name, const BlockDeviceInfo& info);
+
+ // 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.
+ bool ImportPartitions(const LpMetadata& metadata, const std::set<std::string>& partition_names);
+
+ // Return true if a block device is found, else false.
+ bool HasBlockDevice(const std::string& partition_name) const;
private:
MetadataBuilder();
- bool Init(const BlockDeviceInfo& info, uint32_t metadata_max_size, uint32_t metadata_slot_count);
+ MetadataBuilder(const MetadataBuilder&) = delete;
+ MetadataBuilder(MetadataBuilder&&) = delete;
+ MetadataBuilder& operator=(const MetadataBuilder&) = delete;
+ MetadataBuilder& operator=(MetadataBuilder&&) = delete;
+ 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);
void ShrinkPartition(Partition* partition, uint64_t aligned_size);
- uint64_t AlignSector(uint64_t sector);
+ uint64_t AlignSector(const LpMetadataBlockDevice& device, uint64_t sector) const;
+ uint64_t TotalSizeOfGroup(PartitionGroup* group) const;
+ bool UpdateBlockDeviceInfo(size_t index, const BlockDeviceInfo& info);
+ bool FindBlockDeviceByName(const std::string& partition_name, uint32_t* index) const;
+ bool ValidatePartitionSizeChange(Partition* partition, uint64_t old_size, uint64_t new_size);
+ void ImportExtents(Partition* dest, const LpMetadata& metadata,
+ const LpMetadataPartition& source);
+ bool ImportPartition(const LpMetadata& metadata, const LpMetadataPartition& source);
+ bool IsABDevice() const;
+ bool IsRetrofitDevice() 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;
+ void ExtentsToFreeList(const std::vector<Interval>& extents,
+ std::vector<Interval>* free_regions) const;
+ std::vector<Interval> PrioritizeSecondHalfOfSuper(const std::vector<Interval>& free_list);
+
+ static bool sABOverrideValue;
+ static bool sABOverrideSet;
LpMetadataGeometry geometry_;
LpMetadataHeader header_;
std::vector<std::unique_ptr<Partition>> partitions_;
- BlockDeviceInfo device_info_;
+ 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 6da24f6..6348f55 100644
--- a/fs_mgr/liblp/include/liblp/liblp.h
+++ b/fs_mgr/liblp/include/liblp/liblp.h
@@ -24,7 +24,10 @@
#include <memory>
#include <string>
+#include <android-base/unique_fd.h>
+
#include "metadata_format.h"
+#include "partition_opener.h"
namespace android {
namespace fs_mgr {
@@ -36,13 +39,16 @@
LpMetadataHeader header;
std::vector<LpMetadataPartition> partitions;
std::vector<LpMetadataExtent> extents;
+ std::vector<LpMetadataPartitionGroup> groups;
+ std::vector<LpMetadataBlockDevice> block_devices;
};
// Place an initial partition table on the device. This will overwrite the
// existing geometry, and should not be used for normal partition table
// updates. False can be returned if the geometry is incompatible with the
// block device or an I/O error occurs.
-bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata);
+bool FlashPartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
+ const LpMetadata& metadata);
// Update the partition table for a given metadata slot number. False is
// returned if an error occurs, which can include:
@@ -50,27 +56,55 @@
// - I/O error.
// - Corrupt or missing metadata geometry on disk.
// - Incompatible geometry.
-bool UpdatePartitionTable(const std::string& block_device, const LpMetadata& metadata,
- uint32_t slot_number);
+bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
+ const LpMetadata& metadata, uint32_t slot_number);
// Read logical partition metadata from its predetermined location on a block
// device. If readback fails, we also attempt to load from a backup copy.
-std::unique_ptr<LpMetadata> ReadMetadata(const char* block_device, uint32_t slot_number);
+std::unique_ptr<LpMetadata> ReadMetadata(const IPartitionOpener& opener,
+ const std::string& super_partition, uint32_t slot_number);
+
+// Helper functions that use the default PartitionOpener.
+bool FlashPartitionTable(const std::string& super_partition, const LpMetadata& metadata);
+bool UpdatePartitionTable(const std::string& super_partition, const LpMetadata& metadata,
+ 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
// flashing.
bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size,
const std::map<std::string, std::string>& images);
bool WriteToImageFile(const char* file, const LpMetadata& metadata);
-std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file);
+std::unique_ptr<LpMetadata> ReadFromImageFile(const std::string& image_file);
std::unique_ptr<LpMetadata> ReadFromImageBlob(const void* data, size_t bytes);
+// Similar to WriteToSparseFile, this will generate an image that can be
+// flashed to a device directly. However unlike WriteToSparseFile, it
+// is intended for retrofit devices, and will generate one sparse file per
+// block device (each named super_<name>.img) and placed in the specified
+// output folder.
+bool WriteSplitSparseFiles(const std::string& output_dir, const LpMetadata& metadata,
+ uint32_t block_size, const std::map<std::string, std::string>& images);
+
// Helper to extract safe C++ strings from partition info.
std::string GetPartitionName(const LpMetadataPartition& partition);
-std::string GetPartitionGuid(const LpMetadataPartition& partition);
+std::string GetPartitionGroupName(const LpMetadataPartitionGroup& group);
+std::string GetBlockDevicePartitionName(const LpMetadataBlockDevice& block_device);
-// Helper to return a slot number for a slot suffix.
+// Return the block device that houses the super partition metadata; returns
+// null on failure.
+const LpMetadataBlockDevice* GetMetadataSuperBlockDevice(const LpMetadata& metadata);
+
+// Return the total size of all partitions comprising the super partition.
+uint64_t GetTotalSuperPartitionSize(const LpMetadata& metadata);
+
+// Get the list of block device names required by the given metadata.
+std::vector<std::string> GetBlockDevicePartitionNames(const LpMetadata& metadata);
+
+// Slot suffix helpers.
uint32_t SlotNumberForSlotSuffix(const std::string& suffix);
+std::string SlotSuffixForSlotNumber(uint32_t slot_number);
+std::string GetPartitionSlotSuffix(const std::string& partition_name);
} // 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 52c80f7..8934aaf 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -38,7 +38,7 @@
#define LP_METADATA_HEADER_MAGIC 0x414C5030
/* Current metadata version. */
-#define LP_METADATA_MAJOR_VERSION 1
+#define LP_METADATA_MAJOR_VERSION 10
#define LP_METADATA_MINOR_VERSION 0
/* Attributes for the LpMetadataPartition::attributes field.
@@ -47,10 +47,19 @@
* device mapper, the block device will be created as read-only.
*/
#define LP_PARTITION_ATTR_NONE 0x0
-#define LP_PARTITION_ATTR_READONLY 0x1
+#define LP_PARTITION_ATTR_READONLY (1 << 0)
+
+/* This flag is only intended to be used with super_empty.img and super.img on
+ * retrofit devices. On these devices there are A and B super partitions, and
+ * we don't know ahead of time which slot the image will be applied to.
+ *
+ * If set, the partition name needs a slot suffix applied. The slot suffix is
+ * determined by the metadata slot number (0 = _a, 1 = _b).
+ */
+#define LP_PARTITION_ATTR_SLOT_SUFFIXED (1 << 1)
/* Mask that defines all valid attributes. */
-#define LP_PARTITION_ATTRIBUTE_MASK (LP_PARTITION_ATTR_READONLY)
+#define LP_PARTITION_ATTRIBUTE_MASK (LP_PARTITION_ATTR_READONLY | LP_PARTITION_ATTR_SLOT_SUFFIXED)
/* Default name of the physical partition that holds logical partition entries.
* The layout of this partition will look like:
@@ -58,22 +67,27 @@
* +--------------------+
* | Disk Geometry |
* +--------------------+
- * | Metadata |
+ * | Geometry Backup |
* +--------------------+
- * | Logical Partitions |
+ * | Metadata |
* +--------------------+
* | Backup Metadata |
* +--------------------+
- * | Geometry Backup |
+ * | Logical Partitions |
* +--------------------+
*/
-#define LP_METADATA_PARTITION_NAME "super"
+#define LP_METADATA_DEFAULT_PARTITION_NAME "super"
/* Size of a sector is always 512 bytes for compatibility with the Linux kernel. */
#define LP_SECTOR_SIZE 512
-/* This structure is stored at sector 0 in the first 4096 bytes of the
- * partition, and again in the very last 4096 bytes. It is never modified and
+/* Amount of space reserved at the start of every super partition to avoid
+ * creating an accidental boot sector.
+ */
+#define LP_PARTITION_RESERVED_BYTES 4096
+
+/* This structure is stored at block 0 in the first 4096 bytes of the
+ * partition, and again in the following block. It is never modified and
* describes how logical partition information can be located.
*/
typedef struct LpMetadataGeometry {
@@ -98,48 +112,10 @@
*/
uint32_t metadata_slot_count;
- /* 48: First usable sector for allocating logical partitions. this will be
- * the first sector after the initial 4096 geometry block, followed by the
- * space consumed by metadata_max_size*metadata_slot_count.
- */
- uint64_t first_logical_sector;
-
- /* 56: Last usable sector, inclusive, for allocating logical partitions.
- * At the end of this sector will follow backup metadata slots and the
- * backup geometry block at the very end.
- */
- uint64_t last_logical_sector;
-
- /* 64: Alignment for defining partitions or partition extents. For example,
- * an alignment of 1MiB will require that all partitions have a size evenly
- * divisible by 1MiB, and that the smallest unit the partition can grow by
- * is 1MiB.
- *
- * Alignment is normally determined at runtime when growing or adding
- * partitions. If for some reason the alignment cannot be determined, then
- * this predefined alignment in the geometry is used instead. By default
- * it is set to 1MiB.
- */
- uint32_t alignment;
-
- /* 68: Alignment offset for "stacked" devices. For example, if the "super"
- * partition itself is not aligned within the parent block device's
- * partition table, then we adjust for this in deciding where to place
- * |first_logical_sector|.
- *
- * Similar to |alignment|, this will be derived from the operating system.
- * If it cannot be determined, it is assumed to be 0.
- */
- uint32_t alignment_offset;
-
- /* 72: Block device size, as specified when the metadata was created. This
- * can be used to verify the geometry against a target device.
- */
- uint64_t block_device_size;
-
- /* 76: Logical block size of the super partition block device. This is the
- * minimal alignment for partition and extent sizes, and it must be a
- * multiple of LP_SECTOR_SIZE.
+ /* 48: Logical block size. This is the minimal alignment for partition and
+ * extent sizes, and it must be a multiple of LP_SECTOR_SIZE. Note that
+ * this must be equal across all LUNs that comprise the super partition,
+ * and thus this field is stored in the geometry, not per-device.
*/
uint32_t logical_block_size;
} __attribute__((packed)) LpMetadataGeometry;
@@ -151,7 +127,7 @@
* num_entries, and the result must not overflow a 32-bit signed integer.
*/
typedef struct LpMetadataTableDescriptor {
- /* 0: Location of the table, relative to the metadata header. */
+ /* 0: Location of the table, relative to end of the metadata header. */
uint32_t offset;
/* 4: Number of entries in the table. */
uint32_t num_entries;
@@ -216,6 +192,10 @@
LpMetadataTableDescriptor partitions;
/* 92: Extent table descriptor. */
LpMetadataTableDescriptor extents;
+ /* 104: Updateable group descriptor. */
+ LpMetadataTableDescriptor groups;
+ /* 116: Block device table. */
+ LpMetadataTableDescriptor block_devices;
} __attribute__((packed)) LpMetadataHeader;
/* This struct defines a logical partition entry, similar to what would be
@@ -230,21 +210,21 @@
*/
char name[36];
- /* 36: Globally unique identifier (GUID) of this partition. */
- uint8_t guid[16];
-
- /* 52: Attributes for the partition (see LP_PARTITION_ATTR_* flags above). */
+ /* 36: Attributes for the partition (see LP_PARTITION_ATTR_* flags above). */
uint32_t attributes;
- /* 56: Index of the first extent owned by this partition. The extent will
+ /* 40: Index of the first extent owned by this partition. The extent will
* start at logical sector 0. Gaps between extents are not allowed.
*/
uint32_t first_extent_index;
- /* 60: Number of extents in the partition. Every partition must have at
+ /* 44: Number of extents in the partition. Every partition must have at
* least one extent.
*/
uint32_t num_extents;
+
+ /* 48: Group this partition belongs to. */
+ uint32_t group_index;
} __attribute__((packed)) LpMetadataPartition;
/* This extent is a dm-linear target, and the index is an index into the
@@ -269,8 +249,92 @@
* ZERO: This field must be 0.
*/
uint64_t target_data;
+
+ /* 20: Contents depends on target_type.
+ *
+ * LINEAR: Must be an index into the block devices table.
+ * ZERO: This field must be 0.
+ */
+ uint32_t target_source;
} __attribute__((packed)) LpMetadataExtent;
+/* This struct defines an entry in the groups table. Each group has a maximum
+ * size, and partitions in a group must not exceed that size. There is always
+ * a "default" group of unlimited size, which is used when not using update
+ * groups or when using overlayfs or fastbootd.
+ */
+typedef struct LpMetadataPartitionGroup {
+ /* 0: Name of this group. Any unused characters must be 0. */
+ char name[36];
+
+ /* 36: Flags (see LP_GROUP_*). */
+ uint32_t flags;
+
+ /* 40: Maximum size in bytes. If 0, the group has no maximum size. */
+ uint64_t maximum_size;
+} __attribute__((packed)) LpMetadataPartitionGroup;
+
+/* This flag is only intended to be used with super_empty.img and super.img on
+ * retrofit devices. If set, the group needs a slot suffix to be interpreted
+ * correctly. The suffix is automatically applied by ReadMetadata().
+ */
+#define LP_GROUP_SLOT_SUFFIXED (1 << 0)
+
+/* This struct defines an entry in the block_devices table. There must be at
+ * least one device, and the first device must represent the partition holding
+ * the super metadata.
+ */
+typedef struct LpMetadataBlockDevice {
+ /* 0: First usable sector for allocating logical partitions. this will be
+ * the first sector after the initial geometry blocks, followed by the
+ * space consumed by metadata_max_size*metadata_slot_count*2.
+ */
+ uint64_t first_logical_sector;
+
+ /* 8: Alignment for defining partitions or partition extents. For example,
+ * an alignment of 1MiB will require that all partitions have a size evenly
+ * divisible by 1MiB, and that the smallest unit the partition can grow by
+ * is 1MiB.
+ *
+ * Alignment is normally determined at runtime when growing or adding
+ * partitions. If for some reason the alignment cannot be determined, then
+ * this predefined alignment in the geometry is used instead. By default
+ * it is set to 1MiB.
+ */
+ uint32_t alignment;
+
+ /* 12: Alignment offset for "stacked" devices. For example, if the "super"
+ * partition itself is not aligned within the parent block device's
+ * partition table, then we adjust for this in deciding where to place
+ * |first_logical_sector|.
+ *
+ * Similar to |alignment|, this will be derived from the operating system.
+ * If it cannot be determined, it is assumed to be 0.
+ */
+ uint32_t alignment_offset;
+
+ /* 16: Block device size, as specified when the metadata was created. This
+ * can be used to verify the geometry against a target device.
+ */
+ uint64_t size;
+
+ /* 24: Partition name in the GPT. Any unused characters must be 0. */
+ char partition_name[36];
+
+ /* 60: Flags (see LP_BLOCK_DEVICE_* flags below). */
+ uint32_t flags;
+} __attribute__((packed)) LpMetadataBlockDevice;
+
+/* This flag is only intended to be used with super_empty.img and super.img on
+ * retrofit devices. On these devices there are A and B super partitions, and
+ * we don't know ahead of time which slot the image will be applied to.
+ *
+ * If set, the block device needs a slot suffix applied before being used with
+ * IPartitionOpener. The slot suffix is determined by the metadata slot number
+ * (0 = _a, 1 = _b).
+ */
+#define LP_BLOCK_DEVICE_SLOT_SUFFIXED (1 << 0)
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/fs_mgr/liblp/include/liblp/partition_opener.h b/fs_mgr/liblp/include/liblp/partition_opener.h
new file mode 100644
index 0000000..e506bd5
--- /dev/null
+++ b/fs_mgr/liblp/include/liblp/partition_opener.h
@@ -0,0 +1,77 @@
+//
+// 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 <string>
+
+#include <android-base/unique_fd.h>
+
+namespace android {
+namespace fs_mgr {
+
+struct BlockDeviceInfo {
+ BlockDeviceInfo() : size(0), alignment(0), alignment_offset(0), logical_block_size(0) {}
+ BlockDeviceInfo(const std::string& partition_name, uint64_t size, uint32_t alignment,
+ uint32_t alignment_offset, uint32_t logical_block_size)
+ : size(size),
+ alignment(alignment),
+ alignment_offset(alignment_offset),
+ logical_block_size(logical_block_size),
+ partition_name(partition_name) {}
+ // Size of the block device, in bytes.
+ uint64_t size;
+ // Optimal target alignment, in bytes. Partition extents will be aligned to
+ // this value by default. This value must be 0 or a multiple of 512.
+ uint32_t alignment;
+ // Alignment offset to parent device (if any), in bytes. The sector at
+ // |alignment_offset| on the target device is correctly aligned on its
+ // parent device. This value must be 0 or a multiple of 512.
+ uint32_t alignment_offset;
+ // Block size, for aligning extent sizes and partition sizes.
+ uint32_t logical_block_size;
+ // The physical partition name for this block device, as it would appear in
+ // the GPT or under /dev/block/by-name.
+ std::string partition_name;
+};
+
+// Test-friendly interface for interacting with partitions.
+class IPartitionOpener {
+ public:
+ virtual ~IPartitionOpener() = default;
+
+ // Open the given named physical partition with the provided open() flags.
+ // The name can be an absolute path if the full path is already known.
+ virtual android::base::unique_fd Open(const std::string& partition_name, int flags) const = 0;
+
+ // 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;
+};
+
+// Helper class to implement IPartitionOpener. If |partition_name| is not an
+// absolute path, /dev/block/by-name/ will be prepended.
+class PartitionOpener : public IPartitionOpener {
+ public:
+ 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;
+};
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index 329a901..9f3314d 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -26,6 +26,7 @@
#include "images.h"
#include "reader.h"
+#include "test_partition_opener.h"
#include "utility.h"
#include "writer.h"
@@ -37,8 +38,7 @@
static const size_t kDiskSize = 131072;
static const size_t kMetadataSize = 512;
static const size_t kMetadataSlots = 2;
-static const char* TEST_GUID_BASE = "A799D1D6-669F-41D8-A3F0-EBB7572D830";
-static const char* TEST_GUID = "A799D1D6-669F-41D8-A3F0-EBB7572D8302";
+static const BlockDeviceInfo kSuperInfo{"super", kDiskSize, 0, 0, 4096};
// Helper function for creating an in-memory file descriptor. This lets us
// simulate read/writing logical partition metadata as if we had a block device
@@ -80,8 +80,14 @@
return builder;
}
+class DefaultPartitionOpener final : public TestPartitionOpener {
+ public:
+ explicit DefaultPartitionOpener(int fd)
+ : TestPartitionOpener({{"super", fd}}, {{"super", kSuperInfo}}) {}
+};
+
static bool AddDefaultPartitions(MetadataBuilder* builder) {
- Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_NONE);
+ Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_NONE);
if (!system) {
return false;
}
@@ -103,7 +109,9 @@
if (!exported) {
return {};
}
- if (!FlashPartitionTable(fd, *exported.get())) {
+
+ DefaultPartitionOpener opener(fd);
+ if (!FlashPartitionTable(opener, "super", *exported.get())) {
return {};
}
return fd;
@@ -117,12 +125,17 @@
uint64_t size;
ASSERT_TRUE(GetDescriptorSize(fd, &size));
ASSERT_EQ(size, kDiskSize);
+
+ DefaultPartitionOpener opener(fd);
+
+ // Verify that we can't read unwritten metadata.
+ ASSERT_EQ(ReadMetadata(opener, "super", 1), nullptr);
}
// Flashing metadata should not work if the metadata was created for a larger
// disk than the destination disk.
TEST(liblp, ExportDiskTooSmall) {
- unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(kDiskSize + 1024, 512, 2);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(kDiskSize + 4096, 512, 2);
ASSERT_NE(builder, nullptr);
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
@@ -132,7 +145,9 @@
unique_fd fd = CreateFakeDisk();
ASSERT_GE(fd, 0);
- EXPECT_FALSE(FlashPartitionTable(fd, *exported.get()));
+ DefaultPartitionOpener opener(fd);
+
+ EXPECT_FALSE(FlashPartitionTable(opener, "super", *exported.get()));
}
// Test the basics of flashing a partition and reading it back.
@@ -144,23 +159,23 @@
unique_fd fd = CreateFakeDisk();
ASSERT_GE(fd, 0);
+ DefaultPartitionOpener opener(fd);
+
// Export and flash.
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
- ASSERT_TRUE(FlashPartitionTable(fd, *exported.get()));
+ ASSERT_TRUE(FlashPartitionTable(opener, "super", *exported.get()));
// Read back. Note that some fields are only filled in during
// serialization, so exported and imported will not be identical. For
// example, table sizes and checksums are computed in WritePartitionTable.
// Therefore we check on a field-by-field basis.
- unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
// Check geometry and header.
EXPECT_EQ(exported->geometry.metadata_max_size, imported->geometry.metadata_max_size);
EXPECT_EQ(exported->geometry.metadata_slot_count, imported->geometry.metadata_slot_count);
- EXPECT_EQ(exported->geometry.first_logical_sector, imported->geometry.first_logical_sector);
- EXPECT_EQ(exported->geometry.last_logical_sector, imported->geometry.last_logical_sector);
EXPECT_EQ(exported->header.major_version, imported->header.major_version);
EXPECT_EQ(exported->header.minor_version, imported->header.minor_version);
EXPECT_EQ(exported->header.header_size, imported->header.header_size);
@@ -168,7 +183,6 @@
// Check partition tables.
ASSERT_EQ(exported->partitions.size(), imported->partitions.size());
EXPECT_EQ(GetPartitionName(exported->partitions[0]), GetPartitionName(imported->partitions[0]));
- EXPECT_EQ(GetPartitionGuid(exported->partitions[0]), GetPartitionGuid(imported->partitions[0]));
EXPECT_EQ(exported->partitions[0].attributes, imported->partitions[0].attributes);
EXPECT_EQ(exported->partitions[0].first_extent_index,
imported->partitions[0].first_extent_index);
@@ -179,6 +193,11 @@
EXPECT_EQ(exported->extents[0].num_sectors, imported->extents[0].num_sectors);
EXPECT_EQ(exported->extents[0].target_type, imported->extents[0].target_type);
EXPECT_EQ(exported->extents[0].target_data, imported->extents[0].target_data);
+
+ // Check block devices table.
+ ASSERT_EQ(exported->block_devices.size(), imported->block_devices.size());
+ EXPECT_EQ(exported->block_devices[0].first_logical_sector,
+ imported->block_devices[0].first_logical_sector);
}
// Test that we can update metadata slots without disturbing others.
@@ -186,37 +205,40 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
- unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
+ DefaultPartitionOpener opener(fd);
+
+ unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
ASSERT_EQ(imported->partitions.size(), 1);
EXPECT_EQ(GetPartitionName(imported->partitions[0]), "system");
- // Verify that we can't read unwritten metadata.
- ASSERT_EQ(ReadMetadata(fd, 1), nullptr);
-
// Change the name before writing to the next slot.
strncpy(imported->partitions[0].name, "vendor", sizeof(imported->partitions[0].name));
- ASSERT_TRUE(UpdatePartitionTable(fd, *imported.get(), 1));
+ ASSERT_TRUE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
// Read back the original slot, make sure it hasn't changed.
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
ASSERT_EQ(imported->partitions.size(), 1);
EXPECT_EQ(GetPartitionName(imported->partitions[0]), "system");
// Now read back the new slot, and verify that it has a different name.
- imported = ReadMetadata(fd, 1);
+ imported = ReadMetadata(opener, "super", 1);
ASSERT_NE(imported, nullptr);
ASSERT_EQ(imported->partitions.size(), 1);
EXPECT_EQ(GetPartitionName(imported->partitions[0]), "vendor");
+ auto super_device = GetMetadataSuperBlockDevice(*imported.get());
+ ASSERT_NE(super_device, nullptr);
+
+ uint64_t last_sector = super_device->size / LP_SECTOR_SIZE;
+
// Verify that we didn't overwrite anything in the logical paritition area.
// We expect the disk to be filled with 0xcc on creation so we can read
// this back and compare it.
char expected[LP_SECTOR_SIZE];
memset(expected, 0xcc, sizeof(expected));
- for (uint64_t i = imported->geometry.first_logical_sector;
- i <= imported->geometry.last_logical_sector; i++) {
+ for (uint64_t i = super_device->first_logical_sector; i < last_sector; i++) {
char buffer[LP_SECTOR_SIZE];
ASSERT_GE(lseek(fd, i * LP_SECTOR_SIZE, SEEK_SET), 0);
ASSERT_TRUE(android::base::ReadFully(fd, buffer, sizeof(buffer)));
@@ -228,15 +250,17 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
+ DefaultPartitionOpener opener(fd);
+
// Make sure all slots are filled.
- unique_ptr<LpMetadata> metadata = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> metadata = ReadMetadata(opener, "super", 0);
ASSERT_NE(metadata, nullptr);
for (uint32_t i = 1; i < kMetadataSlots; i++) {
- ASSERT_TRUE(UpdatePartitionTable(fd, *metadata.get(), i));
+ ASSERT_TRUE(UpdatePartitionTable(opener, "super", *metadata.get(), i));
}
// Verify that we can't read unavailable slots.
- EXPECT_EQ(ReadMetadata(fd, kMetadataSlots), nullptr);
+ EXPECT_EQ(ReadMetadata(opener, "super", kMetadataSlots), nullptr);
}
// Test that updating a metadata slot does not allow it to be computed based
@@ -245,27 +269,28 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
- unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
+ DefaultPartitionOpener opener(fd);
+
+ unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
- ASSERT_TRUE(UpdatePartitionTable(fd, *imported.get(), 1));
+ ASSERT_TRUE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
imported->geometry.metadata_max_size += LP_SECTOR_SIZE;
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 1));
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
imported->geometry.metadata_slot_count++;
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 1));
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
- imported->geometry.first_logical_sector++;
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 1));
+ ASSERT_EQ(imported->block_devices.size(), 1);
+ imported->block_devices[0].first_logical_sector++;
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
- imported->geometry.last_logical_sector--;
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 1));
}
// Test that changing one bit of metadata is enough to break the checksum.
@@ -273,6 +298,8 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
+ DefaultPartitionOpener opener(fd);
+
LpMetadataGeometry geometry;
ASSERT_GE(lseek(fd, 0, SEEK_SET), 0);
ASSERT_TRUE(android::base::ReadFully(fd, &geometry, sizeof(geometry)));
@@ -281,7 +308,7 @@
bad_geometry.metadata_slot_count++;
ASSERT_TRUE(android::base::WriteFully(fd, &bad_geometry, sizeof(bad_geometry)));
- unique_ptr<LpMetadata> metadata = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> metadata = ReadMetadata(opener, "super", 0);
ASSERT_NE(metadata, nullptr);
EXPECT_EQ(metadata->geometry.metadata_slot_count, 2);
}
@@ -290,39 +317,45 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
+ DefaultPartitionOpener opener(fd);
+
char corruption[LP_METADATA_GEOMETRY_SIZE];
memset(corruption, 0xff, sizeof(corruption));
- // Corrupt the first 4096 bytes of the disk.
- ASSERT_GE(lseek(fd, 0, SEEK_SET), 0);
+ // Corrupt the primary geometry.
+ ASSERT_GE(lseek(fd, GetPrimaryGeometryOffset(), SEEK_SET), 0);
ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
- EXPECT_NE(ReadMetadata(fd, 0), nullptr);
+ EXPECT_NE(ReadMetadata(opener, "super", 0), nullptr);
- // Corrupt the last 4096 bytes too.
- ASSERT_GE(lseek(fd, -LP_METADATA_GEOMETRY_SIZE, SEEK_END), 0);
+ // Corrupt the backup geometry.
+ ASSERT_GE(lseek(fd, GetBackupGeometryOffset(), SEEK_SET), 0);
ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
- EXPECT_EQ(ReadMetadata(fd, 0), nullptr);
+ EXPECT_EQ(ReadMetadata(opener, "super", 0), nullptr);
}
TEST(liblp, ReadBackupMetadata) {
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
- unique_ptr<LpMetadata> metadata = ReadMetadata(fd, 0);
+ DefaultPartitionOpener opener(fd);
+
+ unique_ptr<LpMetadata> metadata = ReadMetadata(opener, "super", 0);
char corruption[kMetadataSize];
memset(corruption, 0xff, sizeof(corruption));
- ASSERT_GE(lseek(fd, LP_METADATA_GEOMETRY_SIZE, SEEK_SET), 0);
- ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
- EXPECT_NE(ReadMetadata(fd, 0), nullptr);
+ off_t offset = GetPrimaryMetadataOffset(metadata->geometry, 0);
- off_t offset = LP_METADATA_GEOMETRY_SIZE + kMetadataSize * 2;
+ ASSERT_GE(lseek(fd, offset, SEEK_SET), 0);
+ ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
+ EXPECT_NE(ReadMetadata(opener, "super", 0), nullptr);
+
+ offset = GetBackupMetadataOffset(metadata->geometry, 0);
// Corrupt the backup metadata.
- ASSERT_GE(lseek(fd, -offset, SEEK_END), 0);
+ ASSERT_GE(lseek(fd, offset, SEEK_SET), 0);
ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
- EXPECT_EQ(ReadMetadata(fd, 0), nullptr);
+ EXPECT_EQ(ReadMetadata(opener, "super", 0), nullptr);
}
// Test that we don't attempt to write metadata if it would overflow its
@@ -331,21 +364,20 @@
unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
ASSERT_NE(builder, nullptr);
- // Compute the maximum number of partitions we can fit in 1024 bytes of metadata.
- size_t max_partitions = (kMetadataSize - sizeof(LpMetadataHeader)) / sizeof(LpMetadataPartition);
- EXPECT_LT(max_partitions, 10);
+ // 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) -
+ sizeof(LpMetadataPartitionGroup) -
+ sizeof(LpMetadataBlockDevice);
+ size_t max_partitions = kMaxPartitionTableSize / sizeof(LpMetadataPartition);
// Add this number of partitions.
Partition* partition = nullptr;
for (size_t i = 0; i < max_partitions; i++) {
- std::string guid = std::string(TEST_GUID) + to_string(i);
- partition = builder->AddPartition(to_string(i), TEST_GUID, LP_PARTITION_ATTR_NONE);
+ partition = builder->AddPartition(to_string(i), LP_PARTITION_ATTR_NONE);
ASSERT_NE(partition, nullptr);
}
- ASSERT_NE(partition, nullptr);
- // Add one extent to any partition to fill up more space - we're at 508
- // bytes after this, out of 512.
- ASSERT_TRUE(builder->ResizePartition(partition, 1024));
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
@@ -353,28 +385,30 @@
unique_fd fd = CreateFakeDisk();
ASSERT_GE(fd, 0);
+ DefaultPartitionOpener opener(fd);
+
// Check that we are able to write our table.
- ASSERT_TRUE(FlashPartitionTable(fd, *exported.get()));
+ ASSERT_TRUE(FlashPartitionTable(opener, "super", *exported.get()));
// Check that adding one more partition overflows the metadata allotment.
- partition = builder->AddPartition("final", TEST_GUID, LP_PARTITION_ATTR_NONE);
+ partition = builder->AddPartition("final", LP_PARTITION_ATTR_NONE);
EXPECT_NE(partition, nullptr);
exported = builder->Export();
ASSERT_NE(exported, nullptr);
// The new table should be too large to be written.
- ASSERT_FALSE(UpdatePartitionTable(fd, *exported.get(), 1));
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *exported.get(), 1));
+
+ auto super_device = GetMetadataSuperBlockDevice(*exported.get());
+ ASSERT_NE(super_device, nullptr);
// Check that the first and last logical sectors weren't touched when we
// wrote this almost-full metadata.
char expected[LP_SECTOR_SIZE];
memset(expected, 0xcc, sizeof(expected));
char buffer[LP_SECTOR_SIZE];
- ASSERT_GE(lseek(fd, exported->geometry.first_logical_sector * LP_SECTOR_SIZE, SEEK_SET), 0);
- ASSERT_TRUE(android::base::ReadFully(fd, buffer, sizeof(buffer)));
- EXPECT_EQ(memcmp(expected, buffer, LP_SECTOR_SIZE), 0);
- ASSERT_GE(lseek(fd, exported->geometry.last_logical_sector * LP_SECTOR_SIZE, SEEK_SET), 0);
+ ASSERT_GE(lseek(fd, super_device->first_logical_sector * LP_SECTOR_SIZE, SEEK_SET), 0);
ASSERT_TRUE(android::base::ReadFully(fd, buffer, sizeof(buffer)));
EXPECT_EQ(memcmp(expected, buffer, LP_SECTOR_SIZE), 0);
}
@@ -385,6 +419,7 @@
ASSERT_NE(builder, nullptr);
ASSERT_TRUE(AddDefaultPartitions(builder.get()));
unique_ptr<LpMetadata> exported = builder->Export();
+ ASSERT_NE(exported, nullptr);
unique_fd fd(syscall(__NR_memfd_create, "image_file", 0));
ASSERT_GE(fd, 0);
@@ -459,23 +494,25 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
+ DefaultPartitionOpener opener(fd);
+
BadWriter writer;
// Read and write it back.
writer.FailOnWrite(1);
- unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 0, writer));
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 0, writer));
// We should still be able to read the backup copy.
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
// Flash again, this time fail the backup copy. We should still be able
// to read the primary.
writer.FailOnWrite(3);
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 0, writer));
- imported = ReadMetadata(fd, 0);
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 0, writer));
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
}
@@ -485,23 +522,25 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
+ DefaultPartitionOpener opener(fd);
+
BadWriter writer;
// Read and write it back.
writer.FailOnWrite(2);
- unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 0, writer));
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 0, writer));
// We should still be able to read the primary copy.
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
// Flash again, this time fail the primary copy. We should still be able
// to read the primary.
writer.FailOnWrite(2);
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 0, writer));
- imported = ReadMetadata(fd, 0);
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 0, writer));
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
}
@@ -512,20 +551,22 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
+ DefaultPartitionOpener opener(fd);
+
BadWriter writer;
// Change the name of the existing partition.
- unique_ptr<LpMetadata> new_table = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> new_table = ReadMetadata(opener, "super", 0);
ASSERT_NE(new_table, nullptr);
ASSERT_GE(new_table->partitions.size(), 1);
new_table->partitions[0].name[0]++;
// Flash it, but fail to write the backup copy.
writer.FailAfterWrite(2);
- ASSERT_FALSE(UpdatePartitionTable(fd, *new_table.get(), 0, writer));
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *new_table.get(), 0, writer));
// When we read back, we should get the updated primary copy.
- unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
ASSERT_GE(new_table->partitions.size(), 1);
ASSERT_EQ(GetPartitionName(new_table->partitions[0]), GetPartitionName(imported->partitions[0]));
@@ -534,10 +575,130 @@
// Note that the sync step should have used the primary to sync, not
// the backup.
writer.Reset();
- ASSERT_TRUE(UpdatePartitionTable(fd, *new_table.get(), 0, writer));
+ ASSERT_TRUE(UpdatePartitionTable(opener, "super", *new_table.get(), 0, writer));
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
ASSERT_GE(new_table->partitions.size(), 1);
ASSERT_EQ(GetPartitionName(new_table->partitions[0]), GetPartitionName(imported->partitions[0]));
}
+
+// Test that writing a sparse image can be read back.
+TEST(liblp, FlashSparseImage) {
+ unique_fd fd = CreateFakeDisk();
+ ASSERT_GE(fd, 0);
+
+ BlockDeviceInfo device_info("super", kDiskSize, 0, 0, 512);
+ unique_ptr<MetadataBuilder> builder =
+ MetadataBuilder::New(device_info, kMetadataSize, kMetadataSlots);
+ ASSERT_NE(builder, nullptr);
+ ASSERT_TRUE(AddDefaultPartitions(builder.get()));
+
+ unique_ptr<LpMetadata> exported = builder->Export();
+ ASSERT_NE(exported, nullptr);
+
+ // Build the sparse file.
+ SparseBuilder sparse(*exported.get(), 512, {});
+ ASSERT_TRUE(sparse.IsValid());
+ ASSERT_TRUE(sparse.Build());
+
+ const auto& images = sparse.device_images();
+ ASSERT_EQ(images.size(), static_cast<size_t>(1));
+
+ // Write it to the fake disk.
+ ASSERT_NE(lseek(fd.get(), 0, SEEK_SET), -1);
+ int ret = sparse_file_write(images[0].get(), fd.get(), false, false, false);
+ ASSERT_EQ(ret, 0);
+
+ // Verify that we can read both sets of metadata.
+ LpMetadataGeometry geometry;
+ ASSERT_TRUE(ReadPrimaryGeometry(fd.get(), &geometry));
+ ASSERT_TRUE(ReadBackupGeometry(fd.get(), &geometry));
+ ASSERT_NE(ReadPrimaryMetadata(fd.get(), geometry, 0), nullptr);
+ ASSERT_NE(ReadBackupMetadata(fd.get(), geometry, 0), nullptr);
+}
+
+TEST(liblp, AutoSlotSuffixing) {
+ unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
+ ASSERT_NE(builder, nullptr);
+ ASSERT_TRUE(AddDefaultPartitions(builder.get()));
+ ASSERT_TRUE(builder->AddGroup("example", 0));
+ builder->SetAutoSlotSuffixing();
+
+ auto fd = CreateFakeDisk();
+ ASSERT_GE(fd, 0);
+
+ // Note: we bind the same fd to both names, since we want to make sure the
+ // exact same bits are getting read back in each test.
+ TestPartitionOpener opener({{"super_a", fd}, {"super_b", fd}},
+ {{"super_a", kSuperInfo}, {"super_b", kSuperInfo}});
+ auto exported = builder->Export();
+ ASSERT_NE(exported, nullptr);
+ ASSERT_TRUE(FlashPartitionTable(opener, "super_a", *exported.get()));
+
+ auto metadata = ReadMetadata(opener, "super_b", 1);
+ ASSERT_NE(metadata, nullptr);
+ ASSERT_EQ(metadata->partitions.size(), static_cast<size_t>(1));
+ EXPECT_EQ(GetPartitionName(metadata->partitions[0]), "system_b");
+ ASSERT_EQ(metadata->block_devices.size(), static_cast<size_t>(1));
+ EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[0]), "super_b");
+ ASSERT_EQ(metadata->groups.size(), static_cast<size_t>(2));
+ EXPECT_EQ(GetPartitionGroupName(metadata->groups[0]), "default");
+ EXPECT_EQ(GetPartitionGroupName(metadata->groups[1]), "example_b");
+ EXPECT_EQ(metadata->groups[0].flags, 0);
+ EXPECT_EQ(metadata->groups[1].flags, 0);
+
+ metadata = ReadMetadata(opener, "super_a", 0);
+ ASSERT_NE(metadata, nullptr);
+ ASSERT_EQ(metadata->partitions.size(), static_cast<size_t>(1));
+ EXPECT_EQ(GetPartitionName(metadata->partitions[0]), "system_a");
+ ASSERT_EQ(metadata->block_devices.size(), static_cast<size_t>(1));
+ EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[0]), "super_a");
+ ASSERT_EQ(metadata->groups.size(), static_cast<size_t>(2));
+ EXPECT_EQ(GetPartitionGroupName(metadata->groups[0]), "default");
+ EXPECT_EQ(GetPartitionGroupName(metadata->groups[1]), "example_a");
+ EXPECT_EQ(metadata->groups[0].flags, 0);
+ EXPECT_EQ(metadata->groups[1].flags, 0);
+}
+
+TEST(liblp, UpdateRetrofit) {
+ unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
+ ASSERT_NE(builder, nullptr);
+ ASSERT_TRUE(AddDefaultPartitions(builder.get()));
+ ASSERT_TRUE(builder->AddGroup("example", 0));
+ builder->SetAutoSlotSuffixing();
+
+ auto fd = CreateFakeDisk();
+ ASSERT_GE(fd, 0);
+
+ // Note: we bind the same fd to both names, since we want to make sure the
+ // exact same bits are getting read back in each test.
+ TestPartitionOpener opener({{"super_a", fd}, {"super_b", fd}},
+ {{"super_a", kSuperInfo}, {"super_b", kSuperInfo}});
+ auto exported = builder->Export();
+ ASSERT_NE(exported, nullptr);
+ ASSERT_TRUE(FlashPartitionTable(opener, "super_a", *exported.get()));
+
+ builder = MetadataBuilder::NewForUpdate(opener, "super_a", 0, 1);
+ ASSERT_NE(builder, nullptr);
+ auto updated = builder->Export();
+ ASSERT_NE(updated, nullptr);
+ ASSERT_EQ(updated->block_devices.size(), static_cast<size_t>(1));
+ EXPECT_EQ(GetBlockDevicePartitionName(updated->block_devices[0]), "super_b");
+ ASSERT_TRUE(updated->groups.empty());
+ ASSERT_TRUE(updated->partitions.empty());
+ ASSERT_TRUE(updated->extents.empty());
+}
+
+TEST(liblp, UpdateNonRetrofit) {
+ 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_EQ(updated->block_devices.size(), static_cast<size_t>(1));
+ EXPECT_EQ(GetBlockDevicePartitionName(updated->block_devices[0]), "super");
+}
diff --git a/fs_mgr/liblp/partition_opener.cpp b/fs_mgr/liblp/partition_opener.cpp
new file mode 100644
index 0000000..898f241
--- /dev/null
+++ b/fs_mgr/liblp/partition_opener.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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 "liblp/partition_opener.h"
+
+#if defined(__linux__)
+#include <linux/fs.h>
+#endif
+#if !defined(_WIN32)
+#include <sys/ioctl.h>
+#endif
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android-base/file.h>
+
+#include "utility.h"
+
+namespace android {
+namespace fs_mgr {
+
+using android::base::unique_fd;
+
+namespace {
+
+std::string GetPartitionAbsolutePath(const std::string& path) {
+ if (path[0] == '/') {
+ return path;
+ }
+ return "/dev/block/by-name/" + path;
+}
+
+bool GetBlockDeviceInfo(const std::string& block_device, BlockDeviceInfo* device_info) {
+#if defined(__linux__)
+ unique_fd fd(open(block_device.c_str(), O_RDONLY));
+ if (fd < 0) {
+ PERROR << __PRETTY_FUNCTION__ << "open '" << block_device << "' failed";
+ return false;
+ }
+ if (!GetDescriptorSize(fd, &device_info->size)) {
+ return false;
+ }
+ if (ioctl(fd, BLKIOMIN, &device_info->alignment) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed on " << block_device;
+ return false;
+ }
+
+ int alignment_offset;
+ if (ioctl(fd, BLKALIGNOFF, &alignment_offset) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << "BLKALIGNOFF failed on " << block_device;
+ return false;
+ }
+ int logical_block_size;
+ if (ioctl(fd, BLKSSZGET, &logical_block_size) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << "BLKSSZGET failed on " << block_device;
+ return false;
+ }
+
+ device_info->alignment_offset = static_cast<uint32_t>(alignment_offset);
+ device_info->logical_block_size = static_cast<uint32_t>(logical_block_size);
+ device_info->partition_name = android::base::Basename(block_device);
+ return true;
+#else
+ (void)block_device;
+ (void)device_info;
+ LERROR << __PRETTY_FUNCTION__ << ": Not supported on this operating system.";
+ return false;
+#endif
+}
+
+} // namespace
+
+unique_fd PartitionOpener::Open(const std::string& partition_name, int flags) const {
+ std::string path = GetPartitionAbsolutePath(partition_name);
+ return unique_fd{open(path.c_str(), flags | O_CLOEXEC)};
+}
+
+bool PartitionOpener::GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const {
+ std::string path = GetPartitionAbsolutePath(partition_name);
+ return GetBlockDeviceInfo(path, info);
+}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index 117f5d5..dcee6d2 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -108,47 +108,44 @@
LERROR << "Metadata max size is not sector-aligned.";
return false;
}
+ return true;
+}
- // Check that the metadata area and logical partition areas don't overlap.
- int64_t end_of_metadata =
- GetPrimaryMetadataOffset(*geometry, geometry->metadata_slot_count - 1) +
- geometry->metadata_max_size;
- if (uint64_t(end_of_metadata) > geometry->first_logical_sector * LP_SECTOR_SIZE) {
- LERROR << "Logical partition metadata overlaps with logical partition contents.";
+bool ReadPrimaryGeometry(int fd, LpMetadataGeometry* geometry) {
+ std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(LP_METADATA_GEOMETRY_SIZE);
+ if (SeekFile64(fd, GetPrimaryGeometryOffset(), SEEK_SET) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed";
return false;
}
- return true;
+ if (!android::base::ReadFully(fd, buffer.get(), LP_METADATA_GEOMETRY_SIZE)) {
+ PERROR << __PRETTY_FUNCTION__ << " read " << LP_METADATA_GEOMETRY_SIZE << " bytes failed";
+ return false;
+ }
+ return ParseGeometry(buffer.get(), geometry);
+}
+
+bool ReadBackupGeometry(int fd, LpMetadataGeometry* geometry) {
+ std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(LP_METADATA_GEOMETRY_SIZE);
+ if (SeekFile64(fd, GetBackupGeometryOffset(), SEEK_SET) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed";
+ return false;
+ }
+ if (!android::base::ReadFully(fd, buffer.get(), LP_METADATA_GEOMETRY_SIZE)) {
+ PERROR << __PRETTY_FUNCTION__ << " backup read " << LP_METADATA_GEOMETRY_SIZE
+ << " bytes failed";
+ return false;
+ }
+ return ParseGeometry(buffer.get(), geometry);
}
// Read and validate geometry information from a block device that holds
// logical partitions. If the information is corrupted, this will attempt
// to read it from a secondary backup location.
bool ReadLogicalPartitionGeometry(int fd, LpMetadataGeometry* geometry) {
- // Read the first 4096 bytes.
- std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(LP_METADATA_GEOMETRY_SIZE);
- if (SeekFile64(fd, 0, SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed";
- return false;
- }
- if (!android::base::ReadFully(fd, buffer.get(), LP_METADATA_GEOMETRY_SIZE)) {
- PERROR << __PRETTY_FUNCTION__ << "read " << LP_METADATA_GEOMETRY_SIZE << " bytes failed";
- return false;
- }
- if (ParseGeometry(buffer.get(), geometry)) {
+ if (ReadPrimaryGeometry(fd, geometry)) {
return true;
}
-
- // Try the backup copy in the last 4096 bytes.
- if (SeekFile64(fd, -LP_METADATA_GEOMETRY_SIZE, SEEK_END) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed, offset " << -LP_METADATA_GEOMETRY_SIZE;
- return false;
- }
- if (!android::base::ReadFully(fd, buffer.get(), LP_METADATA_GEOMETRY_SIZE)) {
- PERROR << __PRETTY_FUNCTION__ << "backup read " << LP_METADATA_GEOMETRY_SIZE
- << " bytes failed";
- return false;
- }
- return ParseGeometry(buffer.get(), geometry);
+ return ReadBackupGeometry(fd, geometry);
}
static bool ValidateTableBounds(const LpMetadataHeader& header,
@@ -188,7 +185,9 @@
return false;
}
if (!ValidateTableBounds(header, header.partitions) ||
- !ValidateTableBounds(header, header.extents)) {
+ !ValidateTableBounds(header, header.extents) ||
+ !ValidateTableBounds(header, header.groups) ||
+ !ValidateTableBounds(header, header.block_devices)) {
LERROR << "Logical partition metadata has invalid table bounds.";
return false;
}
@@ -202,6 +201,10 @@
LERROR << "Logical partition metadata has invalid extent table entry size.";
return false;
}
+ if (header.groups.entry_size != sizeof(LpMetadataPartitionGroup)) {
+ LERROR << "Logical partition metadata has invalid group table entry size.";
+ return false;
+ }
return true;
}
@@ -212,7 +215,7 @@
// 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";
+ PERROR << __PRETTY_FUNCTION__ << " read " << sizeof(metadata->header) << "bytes failed";
return nullptr;
}
if (!ValidateMetadataHeader(metadata->header)) {
@@ -230,7 +233,7 @@
return nullptr;
}
if (!reader->ReadFully(buffer.get(), header.tables_size)) {
- PERROR << __PRETTY_FUNCTION__ << "read " << header.tables_size << "bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " read " << header.tables_size << "bytes failed";
return nullptr;
}
@@ -253,10 +256,18 @@
LERROR << "Logical partition has invalid attribute set.";
return nullptr;
}
+ if (partition.first_extent_index + partition.num_extents < partition.first_extent_index) {
+ LERROR << "Logical partition first_extent_index + num_extents overflowed.";
+ return nullptr;
+ }
if (partition.first_extent_index + partition.num_extents > header.extents.num_entries) {
LERROR << "Logical partition has invalid extent list.";
return nullptr;
}
+ if (partition.group_index >= header.groups.num_entries) {
+ LERROR << "Logical partition has invalid group index.";
+ return nullptr;
+ }
metadata->partitions.push_back(partition);
}
@@ -267,8 +278,46 @@
memcpy(&extent, cursor, sizeof(extent));
cursor += header.extents.entry_size;
+ if (extent.target_type == LP_TARGET_TYPE_LINEAR &&
+ extent.target_source >= header.block_devices.num_entries) {
+ LERROR << "Logical partition extent has invalid block device.";
+ return nullptr;
+ }
+
metadata->extents.push_back(extent);
}
+
+ cursor = buffer.get() + header.groups.offset;
+ for (size_t i = 0; i < header.groups.num_entries; i++) {
+ LpMetadataPartitionGroup group = {};
+ memcpy(&group, cursor, sizeof(group));
+ cursor += header.groups.entry_size;
+
+ metadata->groups.push_back(group);
+ }
+
+ cursor = buffer.get() + header.block_devices.offset;
+ for (size_t i = 0; i < header.block_devices.num_entries; i++) {
+ LpMetadataBlockDevice device = {};
+ memcpy(&device, cursor, sizeof(device));
+ cursor += header.block_devices.entry_size;
+
+ metadata->block_devices.push_back(device);
+ }
+
+ const LpMetadataBlockDevice* super_device = GetMetadataSuperBlockDevice(*metadata.get());
+ if (!super_device) {
+ LERROR << "Metadata does not specify a super device.";
+ return nullptr;
+ }
+
+ // Check that the metadata area and logical partition areas don't overlap.
+ uint64_t metadata_region =
+ GetTotalMetadataSize(geometry.metadata_max_size, geometry.metadata_slot_count);
+ if (metadata_region > super_device->first_logical_sector * LP_SECTOR_SIZE) {
+ LERROR << "Logical partition metadata overlaps with logical partition contents.";
+ return nullptr;
+ }
return metadata;
}
@@ -287,7 +336,7 @@
uint32_t slot_number) {
int64_t offset = GetPrimaryMetadataOffset(geometry, slot_number);
if (SeekFile64(fd, offset, SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << offset;
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << offset;
return nullptr;
}
return ParseMetadata(geometry, fd);
@@ -296,39 +345,96 @@
std::unique_ptr<LpMetadata> ReadBackupMetadata(int fd, const LpMetadataGeometry& geometry,
uint32_t slot_number) {
int64_t offset = GetBackupMetadataOffset(geometry, slot_number);
- if (SeekFile64(fd, offset, SEEK_END) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << offset;
+ if (SeekFile64(fd, offset, SEEK_SET) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << offset;
return nullptr;
}
return ParseMetadata(geometry, fd);
}
-std::unique_ptr<LpMetadata> ReadMetadata(int fd, uint32_t slot_number) {
+namespace {
+
+bool AdjustMetadataForSlot(LpMetadata* metadata, uint32_t slot_number) {
+ std::string slot_suffix = SlotSuffixForSlotNumber(slot_number);
+ for (auto& partition : metadata->partitions) {
+ if (!(partition.attributes & LP_PARTITION_ATTR_SLOT_SUFFIXED)) {
+ continue;
+ }
+ std::string partition_name = GetPartitionName(partition) + slot_suffix;
+ if (partition_name.size() > sizeof(partition.name)) {
+ LERROR << __PRETTY_FUNCTION__ << " partition name too long: " << partition_name;
+ return false;
+ }
+ strncpy(partition.name, partition_name.c_str(), sizeof(partition.name));
+ partition.attributes &= ~LP_PARTITION_ATTR_SLOT_SUFFIXED;
+ }
+ for (auto& block_device : metadata->block_devices) {
+ if (!(block_device.flags & LP_BLOCK_DEVICE_SLOT_SUFFIXED)) {
+ continue;
+ }
+ std::string partition_name = GetBlockDevicePartitionName(block_device) + slot_suffix;
+ if (!UpdateBlockDevicePartitionName(&block_device, partition_name)) {
+ LERROR << __PRETTY_FUNCTION__ << " partition name too long: " << partition_name;
+ return false;
+ }
+ block_device.flags &= ~LP_BLOCK_DEVICE_SLOT_SUFFIXED;
+ }
+ for (auto& group : metadata->groups) {
+ if (!(group.flags & LP_GROUP_SLOT_SUFFIXED)) {
+ continue;
+ }
+ std::string group_name = GetPartitionGroupName(group) + slot_suffix;
+ if (!UpdatePartitionGroupName(&group, group_name)) {
+ LERROR << __PRETTY_FUNCTION__ << " group name too long: " << group_name;
+ return false;
+ }
+ group.flags &= ~LP_GROUP_SLOT_SUFFIXED;
+ }
+ return true;
+}
+
+} // namespace
+
+std::unique_ptr<LpMetadata> ReadMetadata(const IPartitionOpener& opener,
+ const std::string& super_partition, uint32_t slot_number) {
+ android::base::unique_fd fd = opener.Open(super_partition, O_RDONLY);
+ if (fd < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << super_partition;
+ return nullptr;
+ }
+
LpMetadataGeometry geometry;
if (!ReadLogicalPartitionGeometry(fd, &geometry)) {
return nullptr;
}
-
if (slot_number >= geometry.metadata_slot_count) {
- LERROR << __PRETTY_FUNCTION__ << "invalid metadata slot number";
+ LERROR << __PRETTY_FUNCTION__ << " invalid metadata slot number";
return nullptr;
}
- // Read the priamry copy, and if that fails, try the backup.
- std::unique_ptr<LpMetadata> metadata = ReadPrimaryMetadata(fd, geometry, slot_number);
- if (metadata) {
- return metadata;
+ std::vector<int64_t> offsets = {
+ GetPrimaryMetadataOffset(geometry, slot_number),
+ GetBackupMetadataOffset(geometry, slot_number),
+ };
+ std::unique_ptr<LpMetadata> metadata;
+
+ for (const auto& offset : offsets) {
+ if (SeekFile64(fd, offset, SEEK_SET) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed, offset " << offset;
+ continue;
+ }
+ if ((metadata = ParseMetadata(geometry, fd)) != nullptr) {
+ break;
+ }
}
- return ReadBackupMetadata(fd, geometry, slot_number);
+ if (!metadata || !AdjustMetadataForSlot(metadata.get(), slot_number)) {
+ return nullptr;
+ }
+ return metadata;
}
-std::unique_ptr<LpMetadata> ReadMetadata(const char* block_device, uint32_t slot_number) {
- android::base::unique_fd fd(open(block_device, O_RDONLY));
- if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << "open failed: " << block_device;
- return nullptr;
- }
- return ReadMetadata(fd, slot_number);
+std::unique_ptr<LpMetadata> ReadMetadata(const std::string& super_partition, uint32_t slot_number) {
+ return ReadMetadata(PartitionOpener(), super_partition, slot_number);
}
static std::string NameFromFixedArray(const char* name, size_t buffer_size) {
@@ -345,5 +451,13 @@
return NameFromFixedArray(partition.name, sizeof(partition.name));
}
+std::string GetPartitionGroupName(const LpMetadataPartitionGroup& group) {
+ return NameFromFixedArray(group.name, sizeof(group.name));
+}
+
+std::string GetBlockDevicePartitionName(const LpMetadataBlockDevice& block_device) {
+ return NameFromFixedArray(block_device.partition_name, sizeof(block_device.partition_name));
+}
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/liblp/reader.h b/fs_mgr/liblp/reader.h
index 9f6ca6e..7a2490b 100644
--- a/fs_mgr/liblp/reader.h
+++ b/fs_mgr/liblp/reader.h
@@ -31,13 +31,16 @@
bool ParseGeometry(const void* buffer, LpMetadataGeometry* geometry);
// Helper functions for manually reading geometry and metadata.
-std::unique_ptr<LpMetadata> ReadMetadata(int fd, uint32_t slot_number);
std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry, int fd);
std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry, const void* buffer,
size_t size);
bool ReadLogicalPartitionGeometry(int fd, LpMetadataGeometry* geometry);
+bool ReadPrimaryGeometry(int fd, LpMetadataGeometry* geometry);
+bool ReadBackupGeometry(int fd, LpMetadataGeometry* geometry);
-// These functions assume a valid geometry and slot number.
+// These functions assume a valid geometry and slot number, and do not obey
+// auto-slot-suffixing. They are used for tests and for checking whether
+// the metadata is coherent across primary and backup copies.
std::unique_ptr<LpMetadata> ReadPrimaryMetadata(int fd, const LpMetadataGeometry& geometry,
uint32_t slot_number);
std::unique_ptr<LpMetadata> ReadBackupMetadata(int fd, const LpMetadataGeometry& geometry,
diff --git a/fs_mgr/liblp/test_partition_opener.cpp b/fs_mgr/liblp/test_partition_opener.cpp
new file mode 100644
index 0000000..c796f6c
--- /dev/null
+++ b/fs_mgr/liblp/test_partition_opener.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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 "test_partition_opener.h"
+
+#include <errno.h>
+
+namespace android {
+namespace fs_mgr {
+
+using android::base::unique_fd;
+
+TestPartitionOpener::TestPartitionOpener(
+ const std::map<std::string, int>& partition_map,
+ const std::map<std::string, BlockDeviceInfo>& partition_info)
+ : partition_map_(partition_map), partition_info_(partition_info) {}
+
+unique_fd TestPartitionOpener::Open(const std::string& partition_name, int flags) const {
+ auto iter = partition_map_.find(partition_name);
+ if (iter == partition_map_.end()) {
+ errno = ENOENT;
+ return {};
+ }
+ return unique_fd{dup(iter->second)};
+}
+
+bool TestPartitionOpener::GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const {
+ auto iter = partition_info_.find(partition_name);
+ if (iter == partition_info_.end()) {
+ errno = ENOENT;
+ return false;
+ }
+ *info = iter->second;
+ return true;
+}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/test_partition_opener.h b/fs_mgr/liblp/test_partition_opener.h
new file mode 100644
index 0000000..b90fee7
--- /dev/null
+++ b/fs_mgr/liblp/test_partition_opener.h
@@ -0,0 +1,42 @@
+/*
+ * 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 <map>
+#include <string>
+
+#include <android-base/unique_fd.h>
+#include <liblp/partition_opener.h>
+
+namespace android {
+namespace fs_mgr {
+
+class TestPartitionOpener : public PartitionOpener {
+ public:
+ explicit TestPartitionOpener(const std::map<std::string, int>& partition_map,
+ const std::map<std::string, BlockDeviceInfo>& partition_info = {});
+
+ android::base::unique_fd Open(const std::string& partition_name, int flags) const override;
+ bool GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const override;
+
+ private:
+ std::map<std::string, int> partition_map_;
+ std::map<std::string, BlockDeviceInfo> partition_info_;
+};
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/utility.cpp b/fs_mgr/liblp/utility.cpp
index a590037..ecf94a4 100644
--- a/fs_mgr/liblp/utility.cpp
+++ b/fs_mgr/liblp/utility.cpp
@@ -16,14 +16,17 @@
#include <fcntl.h>
#include <stdint.h>
-#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
+#if defined(__linux__)
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#endif
+
#include <android-base/file.h>
#include <ext4_utils/ext4_utils.h>
#include <openssl/sha.h>
-#include <uuid/uuid.h>
#include "utility.h"
@@ -31,6 +34,7 @@
namespace fs_mgr {
bool GetDescriptorSize(int fd, uint64_t* size) {
+#if !defined(_WIN32)
struct stat s;
if (fstat(fd, &s) < 0) {
PERROR << __PRETTY_FUNCTION__ << "fstat failed";
@@ -41,6 +45,7 @@
*size = get_block_device_size(fd);
return *size != 0;
}
+#endif
int64_t result = SeekFile64(fd, 0, SEEK_END);
if (result == -1) {
@@ -57,22 +62,40 @@
return lseek(fd, offset, whence);
}
+int64_t GetPrimaryGeometryOffset() {
+ return LP_PARTITION_RESERVED_BYTES;
+}
+
+int64_t GetBackupGeometryOffset() {
+ return GetPrimaryGeometryOffset() + LP_METADATA_GEOMETRY_SIZE;
+}
+
int64_t GetPrimaryMetadataOffset(const LpMetadataGeometry& geometry, uint32_t slot_number) {
CHECK(slot_number < geometry.metadata_slot_count);
-
- int64_t offset = LP_METADATA_GEOMETRY_SIZE + geometry.metadata_max_size * slot_number;
- CHECK(offset + geometry.metadata_max_size <=
- int64_t(geometry.first_logical_sector * LP_SECTOR_SIZE));
+ int64_t offset = LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2) +
+ geometry.metadata_max_size * slot_number;
return offset;
}
int64_t GetBackupMetadataOffset(const LpMetadataGeometry& geometry, uint32_t slot_number) {
CHECK(slot_number < geometry.metadata_slot_count);
- int64_t start = int64_t(-LP_METADATA_GEOMETRY_SIZE) -
+ int64_t start = LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2) +
int64_t(geometry.metadata_max_size) * geometry.metadata_slot_count;
return start + int64_t(geometry.metadata_max_size * slot_number);
}
+uint64_t GetTotalMetadataSize(uint32_t metadata_max_size, uint32_t max_slots) {
+ return LP_PARTITION_RESERVED_BYTES +
+ (LP_METADATA_GEOMETRY_SIZE + metadata_max_size * max_slots) * 2;
+}
+
+const LpMetadataBlockDevice* GetMetadataSuperBlockDevice(const LpMetadata& metadata) {
+ if (metadata.block_devices.empty()) {
+ return nullptr;
+ }
+ return &metadata.block_devices[0];
+}
+
void SHA256(const void* data, size_t length, uint8_t out[32]) {
SHA256_CTX c;
SHA256_Init(&c);
@@ -80,25 +103,72 @@
SHA256_Final(out, &c);
}
-std::string GetPartitionGuid(const LpMetadataPartition& partition) {
- // 32 hex characters, four hyphens. Unfortunately libext2_uuid provides no
- // macro to assist with buffer sizing.
- static const size_t kGuidLen = 36;
- char buffer[kGuidLen + 1];
- uuid_unparse_upper(partition.guid, buffer);
- return buffer;
-}
-
uint32_t SlotNumberForSlotSuffix(const std::string& suffix) {
- if (suffix.empty()) {
+ if (suffix.empty() || suffix == "a" || suffix == "_a") {
return 0;
- }
- if (suffix.size() != 2 || suffix[0] != '_' || suffix[1] < 'a') {
+ } else if (suffix == "b" || suffix == "_b") {
+ return 1;
+ } else {
LERROR << __PRETTY_FUNCTION__ << "slot '" << suffix
<< "' does not have a recognized format.";
return 0;
}
- return suffix[1] - 'a';
+}
+
+uint64_t GetTotalSuperPartitionSize(const LpMetadata& metadata) {
+ uint64_t size = 0;
+ for (const auto& block_device : metadata.block_devices) {
+ size += block_device.size;
+ }
+ return size;
+}
+
+std::vector<std::string> GetBlockDevicePartitionNames(const LpMetadata& metadata) {
+ std::vector<std::string> list;
+ for (const auto& block_device : metadata.block_devices) {
+ list.emplace_back(GetBlockDevicePartitionName(block_device));
+ }
+ return list;
+}
+
+std::string GetPartitionSlotSuffix(const std::string& partition_name) {
+ if (partition_name.size() <= 2) {
+ return "";
+ }
+ std::string suffix = partition_name.substr(partition_name.size() - 2);
+ return (suffix == "_a" || suffix == "_b") ? suffix : "";
+}
+
+std::string SlotSuffixForSlotNumber(uint32_t slot_number) {
+ CHECK(slot_number == 0 || slot_number == 1);
+ return (slot_number == 0) ? "_a" : "_b";
+}
+
+bool UpdateBlockDevicePartitionName(LpMetadataBlockDevice* device, const std::string& name) {
+ if (name.size() > sizeof(device->partition_name)) {
+ return false;
+ }
+ strncpy(device->partition_name, name.c_str(), sizeof(device->partition_name));
+ return true;
+}
+
+bool UpdatePartitionGroupName(LpMetadataPartitionGroup* group, const std::string& name) {
+ if (name.size() > sizeof(group->name)) {
+ return false;
+ }
+ strncpy(group->name, name.c_str(), sizeof(group->name));
+ return true;
+}
+
+bool SetBlockReadonly(int fd, bool readonly) {
+#if defined(__linux__)
+ int val = readonly;
+ return ioctl(fd, BLKROSET, &val) == 0;
+#else
+ (void)fd;
+ (void)readonly;
+ return true;
+#endif
}
} // namespace fs_mgr
diff --git a/fs_mgr/liblp/utility.h b/fs_mgr/liblp/utility.h
index 6ef5124..e8b2ca9 100644
--- a/fs_mgr/liblp/utility.h
+++ b/fs_mgr/liblp/utility.h
@@ -23,12 +23,13 @@
#include <android-base/logging.h>
-#include "liblp/metadata_format.h"
+#include "liblp/liblp.h"
#define LP_TAG "[liblp]"
#define LWARN LOG(WARNING) << LP_TAG
#define LINFO LOG(INFO) << LP_TAG
#define LERROR LOG(ERROR) << LP_TAG
+#define PWARNING PLOG(WARNING) << LP_TAG
#define PERROR PLOG(ERROR) << LP_TAG
namespace android {
@@ -38,6 +39,10 @@
// error. After calling this, the position of |fd| may have changed.
bool GetDescriptorSize(int fd, uint64_t* size);
+// Return the offset of the primary or backup geometry.
+int64_t GetPrimaryGeometryOffset();
+int64_t GetBackupGeometryOffset();
+
// Return the offset of a primary metadata slot, relative to the start of the
// device.
int64_t GetPrimaryMetadataOffset(const LpMetadataGeometry& geometry, uint32_t slot_number);
@@ -46,6 +51,10 @@
// device.
int64_t GetBackupMetadataOffset(const LpMetadataGeometry& geometry, uint32_t slot_number);
+// Return the total space at the start of the super partition that must be set
+// aside from headers/metadata and backups.
+uint64_t GetTotalMetadataSize(uint32_t metadata_max_size, uint32_t max_slots);
+
// Cross-platform helper for lseek64().
int64_t SeekFile64(int fd, int64_t offset, int whence);
@@ -76,6 +85,13 @@
return aligned;
}
+// Update names from C++ strings.
+bool UpdateBlockDevicePartitionName(LpMetadataBlockDevice* device, const std::string& name);
+bool UpdatePartitionGroupName(LpMetadataPartitionGroup* group, const std::string& name);
+
+// Call BLKROSET ioctl on fd so that fd is readonly / read-writable.
+bool SetBlockReadonly(int fd, bool readonly);
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/liblp/utility_test.cpp b/fs_mgr/liblp/utility_test.cpp
index 7bf42ae..15f7fff 100644
--- a/fs_mgr/liblp/utility_test.cpp
+++ b/fs_mgr/liblp/utility_test.cpp
@@ -24,10 +24,17 @@
TEST(liblp, SlotNumberForSlotSuffix) {
EXPECT_EQ(SlotNumberForSlotSuffix(""), 0);
+ EXPECT_EQ(SlotNumberForSlotSuffix("a"), 0);
EXPECT_EQ(SlotNumberForSlotSuffix("_a"), 0);
+ EXPECT_EQ(SlotNumberForSlotSuffix("b"), 1);
EXPECT_EQ(SlotNumberForSlotSuffix("_b"), 1);
- EXPECT_EQ(SlotNumberForSlotSuffix("_c"), 2);
- EXPECT_EQ(SlotNumberForSlotSuffix("_d"), 3);
+ EXPECT_EQ(SlotNumberForSlotSuffix("_c"), 0);
+ EXPECT_EQ(SlotNumberForSlotSuffix("_d"), 0);
+}
+
+TEST(liblp, SlotSuffixForSlotNumber) {
+ EXPECT_EQ(SlotSuffixForSlotNumber(0), "_a");
+ EXPECT_EQ(SlotSuffixForSlotNumber(1), "_b");
}
TEST(liblp, GetMetadataOffset) {
@@ -36,21 +43,18 @@
{0},
16384,
4,
- 10000,
- 80000,
- 0,
- 0,
- 1024 * 1024,
4096};
- EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 0), 4096);
- EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 1), 4096 + 16384);
- EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 2), 4096 + 16384 * 2);
- EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 3), 4096 + 16384 * 3);
+ static const uint64_t start = LP_PARTITION_RESERVED_BYTES;
+ EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 0), start + 8192);
+ EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 1), start + 8192 + 16384);
+ EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 2), start + 8192 + 16384 * 2);
+ EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 3), start + 8192 + 16384 * 3);
- EXPECT_EQ(GetBackupMetadataOffset(geometry, 3), -4096 - 16384 * 1);
- EXPECT_EQ(GetBackupMetadataOffset(geometry, 2), -4096 - 16384 * 2);
- EXPECT_EQ(GetBackupMetadataOffset(geometry, 1), -4096 - 16384 * 3);
- EXPECT_EQ(GetBackupMetadataOffset(geometry, 0), -4096 - 16384 * 4);
+ static const uint64_t backup_start = start + 8192 + 16384 * 4;
+ EXPECT_EQ(GetBackupMetadataOffset(geometry, 3), backup_start + 16384 * 3);
+ EXPECT_EQ(GetBackupMetadataOffset(geometry, 2), backup_start + 16384 * 2);
+ EXPECT_EQ(GetBackupMetadataOffset(geometry, 1), backup_start + 16384 * 1);
+ EXPECT_EQ(GetBackupMetadataOffset(geometry, 0), backup_start + 16384 * 0);
}
TEST(liblp, AlignTo) {
@@ -63,3 +67,11 @@
EXPECT_EQ(AlignTo(32, 32, 30), 62);
EXPECT_EQ(AlignTo(17, 32, 30), 30);
}
+
+TEST(liblp, GetPartitionSlotSuffix) {
+ EXPECT_EQ(GetPartitionSlotSuffix("system"), "");
+ EXPECT_EQ(GetPartitionSlotSuffix("_"), "");
+ EXPECT_EQ(GetPartitionSlotSuffix("_a"), "");
+ EXPECT_EQ(GetPartitionSlotSuffix("system_a"), "_a");
+ EXPECT_EQ(GetPartitionSlotSuffix("system_b"), "_b");
+}
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index ad84b22..bffcb7e 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -43,8 +43,7 @@
static bool CompareGeometry(const LpMetadataGeometry& g1, const LpMetadataGeometry& g2) {
return g1.metadata_max_size == g2.metadata_max_size &&
g1.metadata_slot_count == g2.metadata_slot_count &&
- g1.first_logical_sector == g2.first_logical_sector &&
- g1.last_logical_sector == g2.last_logical_sector;
+ g1.logical_block_size == g2.logical_block_size;
}
std::string SerializeMetadata(const LpMetadata& input) {
@@ -56,14 +55,20 @@
metadata.partitions.size() * sizeof(LpMetadataPartition));
std::string extents(reinterpret_cast<const char*>(metadata.extents.data()),
metadata.extents.size() * sizeof(LpMetadataExtent));
+ std::string groups(reinterpret_cast<const char*>(metadata.groups.data()),
+ metadata.groups.size() * sizeof(LpMetadataPartitionGroup));
+ std::string block_devices(reinterpret_cast<const char*>(metadata.block_devices.data()),
+ metadata.block_devices.size() * sizeof(LpMetadataBlockDevice));
// Compute positions of tables.
header.partitions.offset = 0;
header.extents.offset = header.partitions.offset + partitions.size();
- header.tables_size = header.extents.offset + extents.size();
+ header.groups.offset = header.extents.offset + extents.size();
+ header.block_devices.offset = header.groups.offset + groups.size();
+ header.tables_size = header.block_devices.offset + block_devices.size();
// Compute payload checksum.
- std::string tables = partitions + extents;
+ std::string tables = partitions + extents + groups + block_devices;
SHA256(tables.data(), tables.size(), header.tables_checksum);
// Compute header checksum.
@@ -77,24 +82,16 @@
// Perform sanity checks so we don't accidentally overwrite valid metadata
// with potentially invalid metadata, or random partition data with metadata.
-static bool ValidateAndSerializeMetadata(int fd, const LpMetadata& metadata, std::string* blob) {
- uint64_t blockdevice_size;
- if (!GetDescriptorSize(fd, &blockdevice_size)) {
- return false;
- }
+static bool ValidateAndSerializeMetadata(const IPartitionOpener& opener, const LpMetadata& metadata,
+ const std::string& slot_suffix, std::string* blob) {
+ const LpMetadataGeometry& geometry = metadata.geometry;
*blob = SerializeMetadata(metadata);
- const LpMetadataHeader& header = metadata.header;
- const LpMetadataGeometry& geometry = metadata.geometry;
- // Validate the usable sector range.
- if (geometry.first_logical_sector > geometry.last_logical_sector) {
- LERROR << "Logical partition metadata has invalid sector range.";
- return false;
- }
// Make sure we're writing within the space reserved.
if (blob->size() > geometry.metadata_max_size) {
- LERROR << "Logical partition metadata is too large.";
+ LERROR << "Logical partition metadata is too large. " << blob->size() << " > "
+ << geometry.metadata_max_size;
return false;
}
@@ -102,19 +99,44 @@
// metadata.
uint64_t reserved_size = LP_METADATA_GEOMETRY_SIZE +
uint64_t(geometry.metadata_max_size) * geometry.metadata_slot_count;
- if (reserved_size > blockdevice_size ||
- reserved_size > geometry.first_logical_sector * LP_SECTOR_SIZE) {
+ uint64_t total_reserved = LP_PARTITION_RESERVED_BYTES + reserved_size * 2;
+
+ const LpMetadataBlockDevice* super_device = GetMetadataSuperBlockDevice(metadata);
+ if (!super_device) {
+ LERROR << "Logical partition metadata does not have a super block device.";
+ return false;
+ }
+
+ if (total_reserved > super_device->first_logical_sector * LP_SECTOR_SIZE) {
LERROR << "Not enough space to store all logical partition metadata slots.";
return false;
}
- if (blockdevice_size - reserved_size < (geometry.last_logical_sector + 1) * LP_SECTOR_SIZE) {
- LERROR << "Not enough space to backup all logical partition metadata slots.";
- return false;
- }
- if (blockdevice_size != metadata.geometry.block_device_size) {
- LERROR << "Block device size " << blockdevice_size
- << " does not match metadata requested size " << metadata.geometry.block_device_size;
- return false;
+ for (const auto& block_device : metadata.block_devices) {
+ std::string partition_name = GetBlockDevicePartitionName(block_device);
+ if (block_device.flags & LP_BLOCK_DEVICE_SLOT_SUFFIXED) {
+ if (slot_suffix.empty()) {
+ LERROR << "Block device " << partition_name << " requires a slot suffix,"
+ << " which could not be derived from the super partition name.";
+ return false;
+ }
+ partition_name += slot_suffix;
+ }
+
+ if ((block_device.first_logical_sector + 1) * LP_SECTOR_SIZE > block_device.size) {
+ LERROR << "Block device " << partition_name << " has invalid first sector "
+ << block_device.first_logical_sector << " for size " << block_device.size;
+ return false;
+ }
+ BlockDeviceInfo info;
+ if (!opener.GetInfo(partition_name, &info)) {
+ PERROR << partition_name << ": ioctl";
+ return false;
+ }
+ if (info.size != block_device.size) {
+ LERROR << "Block device " << partition_name << " size mismatch (expected"
+ << block_device.size << ", got " << info.size << ")";
+ return false;
+ }
}
// Make sure all partition entries reference valid extents.
@@ -126,11 +148,12 @@
}
// Make sure all linear extents have a valid range.
+ uint64_t last_sector = super_device->size / LP_SECTOR_SIZE;
for (const auto& extent : metadata.extents) {
if (extent.target_type == LP_TARGET_TYPE_LINEAR) {
uint64_t physical_sector = extent.target_data;
- if (physical_sector < geometry.first_logical_sector ||
- physical_sector + extent.num_sectors > geometry.last_logical_sector) {
+ if (physical_sector < super_device->first_logical_sector ||
+ physical_sector + extent.num_sectors > last_sector) {
LERROR << "Extent table entry is out of bounds.";
return false;
}
@@ -139,54 +162,69 @@
return true;
}
-static bool WritePrimaryMetadata(int fd, const LpMetadataGeometry& geometry, uint32_t slot_number,
+// Check that the given region is within metadata bounds.
+static bool ValidateMetadataRegion(const LpMetadata& metadata, uint64_t start, size_t size) {
+ const LpMetadataBlockDevice* super_device = GetMetadataSuperBlockDevice(metadata);
+ if (!super_device) {
+ LERROR << __PRETTY_FUNCTION__ << " could not locate super block device in metadata";
+ return false;
+ }
+ if (start + size >= super_device->first_logical_sector * LP_SECTOR_SIZE) {
+ LERROR << __PRETTY_FUNCTION__ << " write of " << size << " bytes at " << start
+ << " overlaps with logical partition contents";
+ return false;
+ }
+ return true;
+}
+
+static bool WritePrimaryMetadata(int fd, const LpMetadata& metadata, uint32_t slot_number,
const std::string& blob,
const std::function<bool(int, const std::string&)>& writer) {
- int64_t primary_offset = GetPrimaryMetadataOffset(geometry, slot_number);
+ int64_t primary_offset = GetPrimaryMetadataOffset(metadata.geometry, slot_number);
+ if (!ValidateMetadataRegion(metadata, primary_offset, blob.size())) {
+ return false;
+ }
if (SeekFile64(fd, primary_offset, SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << primary_offset;
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << primary_offset;
return false;
}
if (!writer(fd, blob)) {
- PERROR << __PRETTY_FUNCTION__ << "write " << blob.size() << " bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " write " << blob.size() << " bytes failed";
return false;
}
return true;
}
-static bool WriteBackupMetadata(int fd, const LpMetadataGeometry& geometry, uint32_t slot_number,
+static bool WriteBackupMetadata(int fd, const LpMetadata& metadata, uint32_t slot_number,
const std::string& blob,
const std::function<bool(int, const std::string&)>& writer) {
- int64_t backup_offset = GetBackupMetadataOffset(geometry, slot_number);
- int64_t abs_offset = SeekFile64(fd, backup_offset, SEEK_END);
- if (abs_offset == (int64_t)-1) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << backup_offset;
+ int64_t backup_offset = GetBackupMetadataOffset(metadata.geometry, slot_number);
+ if (!ValidateMetadataRegion(metadata, backup_offset, blob.size())) {
return false;
}
- if (abs_offset < int64_t((geometry.last_logical_sector + 1) * LP_SECTOR_SIZE)) {
- PERROR << __PRETTY_FUNCTION__ << "backup offset " << abs_offset
- << " is within logical partition bounds, sector " << geometry.last_logical_sector;
+ if (SeekFile64(fd, backup_offset, SEEK_SET) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << backup_offset;
return false;
}
if (!writer(fd, blob)) {
- PERROR << __PRETTY_FUNCTION__ << "backup write " << blob.size() << " bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " backup write " << blob.size() << " bytes failed";
return false;
}
return true;
}
-static bool WriteMetadata(int fd, const LpMetadataGeometry& geometry, uint32_t slot_number,
+static bool WriteMetadata(int fd, const LpMetadata& metadata, uint32_t slot_number,
const std::string& blob,
const std::function<bool(int, const std::string&)>& writer) {
// Make sure we're writing to a valid metadata slot.
- if (slot_number >= geometry.metadata_slot_count) {
+ if (slot_number >= metadata.geometry.metadata_slot_count) {
LERROR << "Invalid logical partition metadata slot number.";
return false;
}
- if (!WritePrimaryMetadata(fd, geometry, slot_number, blob, writer)) {
+ if (!WritePrimaryMetadata(fd, metadata, slot_number, blob, writer)) {
return false;
}
- if (!WriteBackupMetadata(fd, geometry, slot_number, blob, writer)) {
+ if (!WriteBackupMetadata(fd, metadata, slot_number, blob, writer)) {
return false;
}
return true;
@@ -196,53 +234,101 @@
return android::base::WriteFully(fd, blob.data(), blob.size());
}
-bool FlashPartitionTable(int fd, const LpMetadata& metadata) {
+#if defined(_WIN32)
+static const int O_SYNC = 0;
+#endif
+
+bool FlashPartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
+ const LpMetadata& metadata) {
+ android::base::unique_fd fd = opener.Open(super_partition, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << super_partition;
+ return false;
+ }
+
+ // This is only used in update_engine and fastbootd, where the super
+ // partition should be specified as a name (or by-name link), and
+ // therefore, we should be able to extract a slot suffix.
+ std::string slot_suffix = GetPartitionSlotSuffix(super_partition);
+
// Before writing geometry and/or logical partition tables, perform some
// basic checks that the geometry and tables are coherent, and will fit
// on the given block device.
std::string metadata_blob;
- if (!ValidateAndSerializeMetadata(fd, metadata, &metadata_blob)) {
+ if (!ValidateAndSerializeMetadata(opener, metadata, slot_suffix, &metadata_blob)) {
return false;
}
- // Write geometry to the first and last 4096 bytes of the device.
- std::string blob = SerializeGeometry(metadata.geometry);
+ // On retrofit devices, super_partition is system_other and might be set to readonly by
+ // fs_mgr_set_blk_ro(). Unset readonly so that fd can be written to.
+ if (!SetBlockReadonly(fd.get(), false)) {
+ PWARNING << __PRETTY_FUNCTION__ << " BLKROSET 0 failed: " << super_partition;
+ }
+
+ // Write zeroes to the first block.
+ std::string zeroes(LP_PARTITION_RESERVED_BYTES, 0);
if (SeekFile64(fd, 0, SEEK_SET) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset 0";
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset 0";
+ return false;
+ }
+ if (!android::base::WriteFully(fd, zeroes.data(), zeroes.size())) {
+ PERROR << __PRETTY_FUNCTION__ << " write " << zeroes.size() << " bytes failed";
+ return false;
+ }
+
+ LWARN << "Flashing new logical partition geometry to " << super_partition;
+
+ // Write geometry to the primary and backup locations.
+ std::string blob = SerializeGeometry(metadata.geometry);
+ if (SeekFile64(fd, GetPrimaryGeometryOffset(), SEEK_SET) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: primary geometry";
return false;
}
if (!android::base::WriteFully(fd, blob.data(), blob.size())) {
- PERROR << __PRETTY_FUNCTION__ << "write " << blob.size() << " bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " write " << blob.size() << " bytes failed";
return false;
}
- if (SeekFile64(fd, -LP_METADATA_GEOMETRY_SIZE, SEEK_END) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << -LP_METADATA_GEOMETRY_SIZE;
+ if (SeekFile64(fd, GetBackupGeometryOffset(), SEEK_SET) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: backup geometry";
return false;
}
if (!android::base::WriteFully(fd, blob.data(), blob.size())) {
- PERROR << __PRETTY_FUNCTION__ << "backup write " << blob.size() << " bytes failed";
+ PERROR << __PRETTY_FUNCTION__ << " backup write " << blob.size() << " bytes failed";
return false;
}
bool ok = true;
for (size_t i = 0; i < metadata.geometry.metadata_slot_count; i++) {
- ok &= WriteMetadata(fd, metadata.geometry, i, metadata_blob, DefaultWriter);
+ ok &= WriteMetadata(fd, metadata, i, metadata_blob, DefaultWriter);
}
return ok;
}
+bool FlashPartitionTable(const std::string& super_partition, const LpMetadata& metadata) {
+ return FlashPartitionTable(PartitionOpener(), super_partition, metadata);
+}
+
static bool CompareMetadata(const LpMetadata& a, const LpMetadata& b) {
return !memcmp(a.header.header_checksum, b.header.header_checksum,
sizeof(a.header.header_checksum));
}
-bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number,
+bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
+ const LpMetadata& metadata, uint32_t slot_number,
const std::function<bool(int, const std::string&)>& writer) {
+ android::base::unique_fd fd = opener.Open(super_partition, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << super_partition;
+ return false;
+ }
+
+ std::string slot_suffix = SlotSuffixForSlotNumber(slot_number);
+
// Before writing geometry and/or logical partition tables, perform some
// basic checks that the geometry and tables are coherent, and will fit
// on the given block device.
std::string blob;
- if (!ValidateAndSerializeMetadata(fd, metadata, &blob)) {
+ if (!ValidateAndSerializeMetadata(opener, metadata, slot_suffix, &blob)) {
return false;
}
@@ -274,11 +360,11 @@
// synchronize the backup copy. This guarantees that a partial write
// still leaves one copy intact.
std::string old_blob;
- if (!ValidateAndSerializeMetadata(fd, *primary.get(), &old_blob)) {
+ if (!ValidateAndSerializeMetadata(opener, *primary.get(), slot_suffix, &old_blob)) {
LERROR << "Error serializing primary metadata to repair corrupted backup";
return false;
}
- if (!WriteBackupMetadata(fd, geometry, slot_number, old_blob, writer)) {
+ if (!WriteBackupMetadata(fd, metadata, slot_number, old_blob, writer)) {
LERROR << "Error writing primary metadata to repair corrupted backup";
return false;
}
@@ -286,50 +372,35 @@
// The backup copy is coherent, and the primary is not. Sync it for
// safety.
std::string old_blob;
- if (!ValidateAndSerializeMetadata(fd, *backup.get(), &old_blob)) {
- LERROR << "Error serializing primary metadata to repair corrupted backup";
+ if (!ValidateAndSerializeMetadata(opener, *backup.get(), slot_suffix, &old_blob)) {
+ LERROR << "Error serializing backup metadata to repair corrupted primary";
return false;
}
- if (!WritePrimaryMetadata(fd, geometry, slot_number, old_blob, writer)) {
- LERROR << "Error writing primary metadata to repair corrupted backup";
+ if (!WritePrimaryMetadata(fd, metadata, slot_number, old_blob, writer)) {
+ LERROR << "Error writing backup metadata to repair corrupted primary";
return false;
}
}
// Both copies should now be in sync, so we can continue the update.
- return WriteMetadata(fd, geometry, slot_number, blob, writer);
-}
+ if (!WriteMetadata(fd, metadata, slot_number, blob, writer)) {
+ return false;
+ }
-bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata) {
- android::base::unique_fd fd(open(block_device.c_str(), O_RDWR | O_SYNC));
- if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << "open failed: " << block_device;
- return false;
- }
- if (!FlashPartitionTable(fd, metadata)) {
- return false;
- }
- LWARN << "Flashed new logical partition geometry to " << block_device;
- return true;
-}
-
-bool UpdatePartitionTable(const std::string& block_device, const LpMetadata& metadata,
- uint32_t slot_number) {
- android::base::unique_fd fd(open(block_device.c_str(), O_RDWR | O_SYNC));
- if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << "open failed: " << block_device;
- return false;
- }
- if (!UpdatePartitionTable(fd, metadata, slot_number)) {
- return false;
- }
LINFO << "Updated logical partition table at slot " << slot_number << " on device "
- << block_device;
+ << super_partition;
return true;
}
-bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number) {
- return UpdatePartitionTable(fd, metadata, slot_number, DefaultWriter);
+bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
+ const LpMetadata& metadata, uint32_t slot_number) {
+ return UpdatePartitionTable(opener, super_partition, metadata, slot_number, DefaultWriter);
+}
+
+bool UpdatePartitionTable(const std::string& super_partition, const LpMetadata& metadata,
+ uint32_t slot_number) {
+ PartitionOpener opener;
+ return UpdatePartitionTable(opener, super_partition, metadata, slot_number, DefaultWriter);
}
} // namespace fs_mgr
diff --git a/fs_mgr/liblp/writer.h b/fs_mgr/liblp/writer.h
index ab18d45..6f1da0f 100644
--- a/fs_mgr/liblp/writer.h
+++ b/fs_mgr/liblp/writer.h
@@ -30,10 +30,8 @@
// These variants are for testing only. The path-based functions should be used
// for actual operation, so that open() is called with the correct flags.
-bool FlashPartitionTable(int fd, const LpMetadata& metadata);
-bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number);
-
-bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number,
+bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
+ const LpMetadata& metadata, uint32_t slot_number,
const std::function<bool(int, const std::string&)>& writer);
} // namespace fs_mgr
diff --git a/fs_mgr/tests/Android.bp b/fs_mgr/tests/Android.bp
index 5497223..ea12e96 100644
--- a/fs_mgr/tests/Android.bp
+++ b/fs_mgr/tests/Android.bp
@@ -23,7 +23,9 @@
"libfs_mgr",
"libfstab",
],
-
+ data: [
+ "data/*",
+ ],
srcs: [
"fs_mgr_test.cpp",
],
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
new file mode 100755
index 0000000..0765f04
--- /dev/null
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -0,0 +1,714 @@
+#! /bin/bash
+
+USAGE="USAGE: `basename ${0}` [-s <SerialNumber>]
+
+adb remount tests (overlayfs focus)
+
+Conditions:
+ - Must be a userdebug build.
+ - Must be in adb mode.
+ - Kernel must have overlayfs enabled and patched to support override_creds.
+ - Must have either squashfs, ext4-dedupe or right-sized partitions.
+ - Minimum expectation system and vender are overlayfs covered partitions.
+"
+
+if [ X"${1}" = X"--help" -o X"${1}" = X"-h" -o X"${1}" = X"-?" ]; then
+ echo "${USAGE}" >&2
+ exit 0
+fi
+
+# Helper Variables
+
+SPACE=" "
+# A _real_ embedded tab character
+TAB="`echo | tr '\n' '\t'`"
+# A _real_ embedded escape character
+ESCAPE="`echo | tr '\n' '\033'`"
+GREEN="${ESCAPE}[38;5;40m"
+RED="${ESCAPE}[38;5;196m"
+ORANGE="${ESCAPE}[38;5;255:165:0m"
+BLUE="${ESCAPE}[35m"
+NORMAL="${ESCAPE}[0m"
+
+# Helper functions
+
+[ "USAGE: inFastboot
+
+Returns: true if device is in fastboot mode" ]
+inFastboot() {
+ fastboot devices |
+ if [ -n "${ANDROID_SERIAL}" ]; then
+ grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
+ else
+ wc -l | grep '^1$' >/dev/null
+ fi
+}
+
+[ "USAGE: inAdb
+
+Returns: true if device is in adb mode" ]
+inAdb() {
+ adb devices |
+ grep -v -e 'List of devices attached' -e '^$' |
+ if [ -n "${ANDROID_SERIAL}" ]; then
+ grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
+ else
+ wc -l | grep '^1$' >/dev/null
+ fi
+}
+
+[ "USAGE: adb_sh <commands> </dev/stdin >/dev/stdout 2>/dev/stderr
+
+Returns: true if the command succeeded" ]
+adb_sh() {
+ args=
+ for i in ${@}; do
+ if [ X"${i}" != X"${i#\'}" ]; then
+ args="${args} ${i}"
+ elif [ X"${i}" != X"${i#* }" ]; then
+ args="${args} '${i}'"
+ else
+ args="${args} ${i}"
+ fi
+ done
+ adb shell ${args}
+}
+
+[ "USAGE: adb_date >/dev/stdout
+
+Returns: report device epoch time (suitable for logcat -t)" ]
+adb_date() {
+ adb_sh date +%s.%N </dev/null
+}
+
+[ "USAGE: adb_logcat [arguments] >/dev/stdout
+
+Returns: the logcat output" ]
+adb_logcat() {
+ echo "${RED}[ INFO ]${NORMAL} logcat ${@}" >&2 &&
+ adb logcat "${@}" </dev/null |
+ grep -v 'logd : logdr: UID=' |
+ sed -e '${/------- beginning of kernel/d}' -e 's/^[0-1][0-9]-[0-3][0-9] //'
+}
+
+[ "USAGE: get_property <prop>
+
+Returns the property value" ]
+get_property() {
+ adb_sh getprop ${1} </dev/null
+}
+
+[ "USAGE: isDebuggable
+
+Returns: true if device is (likely) a debug build" ]
+isDebuggable() {
+ if inAdb && [ 1 != "`get_property ro.debuggable`" ]; then
+ false
+ fi
+}
+
+[ "USAGE: adb_su <commands> </dev/stdin >/dev/stdout 2>/dev/stderr
+
+Returns: true if the command running as root succeeded" ]
+adb_su() {
+ adb_sh su root "${@}"
+}
+
+[ "USAGE: adb_cat <file> >stdout
+
+Returns: content of file to stdout with carriage returns skipped,
+ true of the file exists" ]
+adb_cat() {
+ OUTPUT="`adb_sh cat ${1} </dev/null 2>&1`"
+ retval=${?}
+ echo "${OUTPUT}" | tr -d '\r'
+ return ${retval}
+}
+
+[ "USAGE: adb_reboot
+
+Returns: true if the reboot command succeeded" ]
+adb_reboot() {
+ adb reboot remount-test &&
+ sleep 2
+}
+
+[ "USAGE: adb_wait [timeout]
+
+Returns: waits until the device has returned for adb or optional timeout" ]
+adb_wait() {
+ if [ -n "${1}" ]; then
+ timeout --preserve-status --signal=KILL ${1} adb wait-for-device
+ else
+ adb wait-for-device
+ fi
+}
+
+[ "USAGE: fastboot_wait [timeout]
+
+Returns: waits until the device has returned for fastboot or optional timeout" ]
+fastboot_wait() {
+ # 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
+ timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device
+ else
+ fastboot wait-for-device >/dev/null
+ fi >/dev/null 2>/dev/null ||
+ inFastboot
+}
+
+[ "USAGE: adb_root
+
+NB: This can be flakey on devices due to USB state
+
+Returns: true if device in root state" ]
+adb_root() {
+ [ `adb_sh echo '${USER}'` != root ] || return 0
+ adb root >/dev/null </dev/null 2>/dev/null
+ sleep 2
+ adb_wait 2m &&
+ [ `adb_sh echo '${USER}'` = root ]
+}
+
+[ "USAGE: adb_unroot
+
+NB: This can be flakey on devices due to USB state
+
+Returns: true if device in un root state" ]
+adb_unroot() {
+ [ `adb_sh echo '${USER}'` = root ] || return 0
+ adb unroot >/dev/null </dev/null 2>/dev/null
+ sleep 2
+ adb_wait 2m &&
+ [ `adb_sh echo '${USER}'` != root ]
+}
+
+[ "USAGE: fastboot_getvar var expected
+
+Returns: true if var output matches expected" ]
+fastboot_getvar() {
+ O=`fastboot getvar ${1} 2>&1`
+ err=${?}
+ O="${O#< waiting for * >?}"
+ O="${O%%?Finished. Total time: *}"
+ if [ 0 -ne ${err} ]; then
+ echo ${O} >&2
+ false
+ return
+ fi
+ if [ "${O}" != "${O#*FAILED}" ]; then
+ O="${1}: <empty>"
+ fi
+ if [ -n "${2}" -a "${1}: ${2}" != "${O}" ]; then
+ echo "${2} != ${O}" >&2
+ false
+ return
+ fi
+ echo ${O} >&2
+}
+
+[ "USAGE: cleanup
+
+Do nothing: should be redefined when necessary
+
+Returns: cleans up any latent resources, reverses configurations" ]
+cleanup () {
+ :
+}
+
+[ "USAGE: die [-d|-t <epoch>] [message] >/dev/stderr
+
+If -d, or -t <epoch> argument is supplied, dump logcat.
+
+Returns: exit failure, report status" ]
+die() {
+ if [ X"-d" = X"${1}" ]; then
+ adb_logcat -b all -v nsec -d >&2
+ shift
+ elif [ X"-t" = X"${1}" ]; then
+ if [ -n "${2}" ]; then
+ adb_logcat -b all -v nsec -t ${2} >&2
+ else
+ adb_logcat -b all -v nsec -d >&2
+ fi
+ shift 2
+ fi
+ echo "${RED}[ FAILED ]${NORMAL} ${@}" >&2
+ cleanup
+ exit 1
+}
+
+[ "USAGE: EXPECT_EQ <lval> <rval> [message]
+
+Returns true if (regex) lval matches rval" ]
+EXPECT_EQ() {
+ lval="${1}"
+ rval="${2}"
+ shift 2
+ 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 "ERROR: expected \"${lval}\"" >&2
+ echo " got \"${rval}\"" |
+ sed ': again
+ N
+ s/\(\n\)\([^ ]\)/\1 \2/
+ t again' >&2
+ if [ -n "${*}" ] ; then
+ echo " ${*}" >&2
+ fi
+ else
+ echo "ERROR: expected \"${lval}\" got \"${rval}\" ${*}" >&2
+ fi
+ return 1
+ fi
+ if [ -n "${*}" ] ; then
+ if [ X"${lval}" != X"${rval}" ]; then
+ if [ `echo ${lval}${rval}${*} | wc -c` -gt 60 -o "${rval}" != "${rval% *}" ]; then
+ echo "INFO: ok \"${lval}\"" >&2
+ echo " = \"${rval}\"" |
+ sed ': again
+ N
+ s/\(\n\)\([^ ]\)/\1 \2/
+ t again' >&2
+ if [ -n "${*}" ] ; then
+ echo " ${*}" >&2
+ fi
+ else
+ echo "INFO: ok \"${lval}\" = \"${rval}\" ${*}" >&2
+ fi
+ else
+ echo "INFO: ok \"${lval}\" ${*}" >&2
+ fi
+ fi
+ return 0
+}
+
+[ "USAGE: check_eq <lval> <rval> [message]
+
+Exits if (regex) lval mismatches rval" ]
+check_eq() {
+ left="${1}"
+ right="${2}"
+ shift 2
+ EXPECT_EQ "${left}" "${right}" ||
+ die "${@}"
+}
+
+[ "USAGE: skip_administrative_mounts [data] < /proc/mounts
+
+Filters out all administrative (eg: sysfs) mounts uninteresting to the test" ]
+skip_administrative_mounts() {
+ if [ "data" = "${1}" ]; then
+ grep -v " /data "
+ else
+ cat -
+ fi |
+ grep -v \
+ -e "^\(overlay\|tmpfs\|none\|sysfs\|proc\|selinuxfs\|debugfs\) " \
+ -e "^\(bpf\|cg2_bpf\|pstore\|tracefs\|adb\|mtp\|ptp\|devpts\) " \
+ -e "^\(/data/media\|/dev/block/loop[0-9]*\) " \
+ -e " /\(cache\|mnt/scratch\|mnt/vendor/persist\|metadata\) "
+}
+
+if [ X"-s" = X"${1}" -a -n "${2}" ]; then
+ export ANDROID_SERIAL="${2}"
+ shift 2
+fi
+
+inFastboot && die "device in fastboot mode"
+if ! inAdb; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} device not in adb mode ... waiting 2 minutes"
+ adb_wait 2m
+fi
+inAdb || die "specified device not in adb mode"
+isDebuggable || die "device not a debug build"
+enforcing=true
+if ! adb_su getenforce </dev/null | grep 'Enforcing' >/dev/null; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} device does not have sepolicy in enforcing mode"
+ enforcing=false
+fi
+
+# Do something
+
+echo "${GREEN}[ RUN ]${NORMAL} Testing kernel support for overlayfs" >&2
+
+overlayfs_supported=true;
+adb_wait || die "wait for device failed"
+adb_sh ls -d /sys/module/overlay </dev/null >/dev/null &&
+ echo "${GREEN}[ OK ]${NORMAL} overlay module present" >&2 ||
+ (
+ echo "${ORANGE}[ WARNING ]${NORMAL} overlay module not present" >&2 &&
+ false
+ ) ||
+ overlayfs_supported=false
+if ${overlayfs_supported}; then
+ case `adb_sh uname -r </dev/null` in
+ 4.[6789].* | 4.[1-9][0-9]* | [56789].*)
+ adb_su ls /sys/module/overlay/parameters/override_creds </dev/null >/dev/null &&
+ echo "${GREEN}[ OK ]${NORMAL} overlay module supports override_creds" >&2 ||
+ (
+ echo "${ORANGE}[ WARNING ]${NORMAL} overlay module does not support override_creds" >&2 &&
+ false
+ ) ||
+ overlayfs_supported=false;
+ ;;
+ *)
+ echo "${GREEN}[ OK ]${NORMAL} overlay module uses callers creds" >&2
+ ;;
+ esac
+fi
+
+adb_root ||
+ die "initial setup"
+
+echo "${GREEN}[ RUN ]${NORMAL} Checking current overlayfs status" >&2
+
+# We can not universally use adb enable-verity to ensure device is
+# in a overlayfs disabled state since it can prevent reboot on
+# devices that remount the physical content rather than overlayfs.
+# 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
+ adb_sh rm -rf /${d}/overlay </dev/null ||
+ die "/${d}/overlay wipe"
+ reboot=true
+ fi
+done
+if ${reboot}; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} rebooting before test" >&2
+ adb_reboot &&
+ adb_wait 2m ||
+ die "lost device after reboot after wipe"
+ adb_root ||
+ die "lost device after elevation to root after wipe"
+fi
+D=`adb_sh df -k </dev/null` &&
+ H=`echo "${D}" | head -1` &&
+ D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` &&
+ echo "${H}" &&
+ echo "${D}" &&
+ echo "${ORANGE}[ WARNING ]${NORMAL} overlays present before setup" >&2 ||
+ echo "${GREEN}[ OK ]${NORMAL} no overlay present before setup" >&2
+overlayfs_needed=true
+D=`adb_sh cat /proc/mounts </dev/null |
+ skip_administrative_mounts data`
+if echo "${D}" | grep /dev/root >/dev/null; then
+ D=`echo / /
+ echo "${D}" | grep -v /dev/root`
+fi
+D=`echo "${D}" | cut -s -d' ' -f1 | sort -u`
+D=`adb_sh df -k ${D} </dev/null`
+echo "${D}"
+if [ X"${D}" = X"${D##* 100[%] }" ]; then
+ overlayfs_needed=false
+elif ! ${overlayfs_supported}; then
+ die "need overlayfs, but do not have it"
+fi
+
+echo "${GREEN}[ RUN ]${NORMAL} disable verity" >&2
+
+T=`adb_date`
+H=`adb disable-verity 2>&1`
+err=${?}
+L=
+D="${H%?Now reboot your device for settings to take effect}"
+if [ X"${D}" != X"${D##*using overlayfs}" ]; then
+ echo "${GREEN}[ OK ]${NORMAL} using overlayfs" >&2
+fi
+if [ ${err} != 0 ]; then
+ echo "${H}"
+ ( [ -n "${L}" ] && echo "${L}" && false ) ||
+ die -t "${T}" "disable-verity"
+fi
+rebooted=false
+if [ X"${D}" != X"${H}" ]; then
+ echo "${H}"
+ if [ X"${D}" != X"${D##*setup failed}" ]; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} overlayfs setup whined" >&2
+ fi
+ D=`adb_sh df -k </dev/null` &&
+ H=`echo "${D}" | head -1` &&
+ D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay " || true` &&
+ [ -z "${D}" ] ||
+ ( echo "${H}" && echo "${D}" && false ) ||
+ die -t ${T} "overlay takeover unexpected at this phase"
+ echo "${GREEN}[ INFO ]${NORMAL} rebooting as requested" >&2
+ L=`adb_logcat -b all -v nsec -t ${T} 2>&1`
+ adb_reboot &&
+ adb_wait 2m ||
+ die "lost device after reboot requested"
+ adb_root ||
+ die "lost device after elevation to root"
+ rebooted=true
+ # re-disable verity to see the setup remarks expected
+ T=`adb_date`
+ H=`adb disable-verity 2>&1`
+ err=${?}
+ D="${H%?Now reboot your device for settings to take effect}"
+ if [ X"${D}" != X"${D##*using overlayfs}" ]; then
+ echo "${GREEN}[ OK ]${NORMAL} using overlayfs" >&2
+ fi
+ if [ ${err} != 0 ]; then
+ T=
+ fi
+fi
+if ${overlayfs_supported} && ${overlayfs_needed} && [ X"${D}" != X"${D##*setup failed}" ]; then
+ echo "${D}"
+ ( [ -n "${L}" ] && echo "${L}" && false ) ||
+ die -t "${T}" "setup for overlay"
+fi
+if [ X"${D}" != X"${D##*Successfully disabled verity}" ]; then
+ echo "${H}"
+ D=`adb_sh df -k </dev/null` &&
+ H=`echo "${D}" | head -1` &&
+ D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay " || true` &&
+ [ -z "${D}" ] ||
+ ( echo "${H}" && echo "${D}" && false ) ||
+ ( [ -n "${L}" ] && echo "${L}" && false ) ||
+ die -t "${T}" "overlay takeover unexpected"
+ [ -n "${L}" ] && echo "${L}"
+ die -t "${T}" "unexpected report of verity being disabled a second time"
+elif ${rebooted}; then
+ echo "${GREEN}[ OK ]${NORMAL} verity already disabled" >&2
+else
+ echo "${ORANGE}[ WARNING ]${NORMAL} verity already disabled" >&2
+fi
+
+echo "${GREEN}[ RUN ]${NORMAL} remount" >&2
+
+adb remount ||
+ ( [ -n "${L}" ] && echo "${L}" && false ) ||
+ die -t "${T}" "adb remount failed"
+D=`adb_sh df -k </dev/null` &&
+ H=`echo "${D}" | head -1` &&
+ D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` ||
+ ( [ -n "${L}" ] && echo "${L}" && false )
+ret=${?}
+uses_dynamic_scratch=false
+scratch_partition=
+if ${overlayfs_needed}; then
+ if [ ${ret} != 0 ]; then
+ die -t ${T} "overlay takeover failed"
+ fi
+ echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
+ echo "${ORANGE}[ WARNING ]${NORMAL} overlay takeover not complete" >&2
+ scratch_partition=scratch
+ if echo "${D}" | grep " /mnt/scratch" >/dev/null; then
+ echo "${BLUE}[ INFO ]${NORMAL} using ${scratch_partition} dynamic partition for overrides" >&2
+ fi
+ M=`adb_sh cat /proc/mounts </dev/null |
+ sed -n 's@\([^ ]*\) /mnt/scratch \([^ ]*\) .*@\2 on \1@p'`
+ [ -n "${M}" ] &&
+ echo "${BLUE}[ INFO ]${NORMAL} scratch filesystem ${M}"
+ uses_dynamic_scratch=true
+ if [ "${M}" != "${M##*/dev/block/by-name/}" ]; then
+ uses_dynamic_scratch=false
+ scratch_partition="${M##*/dev/block/by-name/}"
+ fi
+ scratch_size=`adb_sh df -k /mnt/scratch </dev/null 2>/dev/null |
+ while read device kblocks used available use mounted on; do
+ if [ "/mnt/scratch" = "\${mounted}" ]; then
+ echo \${kblocks}
+ fi
+ done` &&
+ [ -n "${scratch_size}" ] ||
+ die "scratch size"
+ echo "${BLUE}[ INFO ]${NORMAL} scratch size ${scratch_size}KB" >&2
+ for d in ${OVERLAYFS_BACKING}; do
+ if adb_sh ls -d /${d}/overlay/system/upper </dev/null >/dev/null 2>/dev/null; then
+ echo "${BLUE}[ INFO ]${NORMAL} /${d}/overlay is setup" >&2
+ fi
+ done
+
+ echo "${H}" &&
+ echo "${D}" &&
+ echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
+ die "overlay takeover after remount"
+ !(adb_sh grep "^overlay " /proc/mounts </dev/null |
+ grep -v "^overlay /\(vendor\|system\)/..* overlay ro," |
+ grep " overlay ro,") &&
+ !(adb_sh grep " rw," /proc/mounts </dev/null |
+ skip_administrative_mounts data) ||
+ die "remount overlayfs missed a spot (ro)"
+else
+ if [ ${ret} = 0 ]; then
+ die -t ${T} "unexpected overlay takeover"
+ fi
+fi
+
+# Check something
+
+echo "${GREEN}[ RUN ]${NORMAL} push content to /system and /vendor" >&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
+
+echo "${GREEN}[ RUN ]${NORMAL} reboot to confirm content persistent" >&2
+
+adb_reboot &&
+ adb_wait 2m ||
+ die "reboot after override content added failed"
+
+if ${overlayfs_needed}; then
+ D=`adb_su df -k </dev/null` &&
+ H=`echo "${D}" | head -1` &&
+ D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` ||
+ ( echo "${L}" && false ) ||
+ die -d "overlay takeover failed after reboot"
+
+ adb_su "sed -n '1,/overlay \\/system/p' /proc/mounts" </dev/null |
+ skip_administrative_mounts |
+ grep -v ' \(squashfs\|ext4\|f2fs\) ' &&
+ echo "${ORANGE}[ WARNING ]${NORMAL} overlay takeover after first stage init" >&2 ||
+ echo "${GREEN}[ OK ]${NORMAL} overlay takeover in first stage init" >&2
+fi
+
+B="`adb_cat /system/hello`" ||
+ die "re-read /system/hello after reboot"
+check_eq "${A}" "${B}" /system after reboot
+echo "${GREEN}[ OK ]${NORMAL} /system content remains after reboot" >&2
+# Only root can read vendor if sepolicy permissions are as expected
+if ${enforcing}; then
+ adb_unroot
+ B="`adb_cat /vendor/hello`" &&
+ die "re-read /vendor/hello after reboot w/o root"
+ 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
+fi
+adb_root &&
+ B="`adb_cat /vendor/hello`" ||
+ die "re-read /vendor/hello after reboot"
+check_eq "${A}" "${B}" vendor after reboot
+echo "${GREEN}[ OK ]${NORMAL} /vendor content remains after reboot" >&2
+
+echo "${GREEN}[ RUN ]${NORMAL} flash vendor, confirm its content disappears" >&2
+
+H=`adb_sh echo '${HOSTNAME}' </dev/null 2>/dev/null`
+if [ -z "${ANDROID_PRODUCT_OUT}" ]; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} build tree not setup, skipping"
+elif [ ! -s "${ANDROID_PRODUCT_OUT}/vendor.img" ]; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} vendor image missing, skipping"
+elif [ "${ANDROID_PRODUCT_OUT}" = "${ANDROID_PRODUCT_OUT%*/${H}}" ]; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} wrong vendor image, skipping"
+else
+ adb reboot-fastboot &&
+ fastboot_wait 2m &&
+ fastboot flash vendor ||
+ ( fastboot reboot && false) ||
+ die "fastboot flash vendor"
+ if [ -n "${scratch_paritition}" ]; then
+ fastboot_getvar partition-type:${scratch_partition} raw ||
+ ( fastboot reboot && false) ||
+ die "fastboot can not see ${scratch_partition} parameters"
+ if ${uses_dynamic_scratch}; then
+ # check ${scratch_partition} via fastboot
+ fastboot_getvar has-slot:${scratch_partition} no &&
+ fastboot_getvar is-logical:${scratch_partition} yes ||
+ ( fastboot reboot && false) ||
+ die "fastboot can not see ${scratch_partition} parameters"
+ else
+ fastboot_getvar is-logical:${scratch_partition} no ||
+ ( fastboot reboot && false) ||
+ die "fastboot can not see ${scratch_partition} parameters"
+ fi
+ if ! ${uses_dynamic_scratch}; then
+ fastboot reboot-bootloader ||
+ die "Reboot into fastboot"
+ fi
+ if ${uses_dynamic_scratch}; then
+ echo "${BLUE}[ INFO ]${NORMAL} expect fastboot erase ${scratch_partition} to fail" >&2
+ fastboot erase ${scratch_partition} &&
+ ( fastboot reboot || true) &&
+ die "fastboot can erase ${scratch_partition}"
+ fi
+ echo "${BLUE}[ INFO ]${NORMAL} expect fastboot format ${scratch_partition} to fail" >&2
+ fastboot format ${scratch_partition} &&
+ ( fastboot reboot || true) &&
+ die "fastboot can format ${scratch_partition}"
+ fi
+ fastboot reboot ||
+ die "can not reboot out of fastboot"
+ echo "${ORANGE}[ WARNING ]${NORMAL} adb after fastboot ... waiting 2 minutes"
+ adb_wait 2m ||
+ die "did not reboot after flash"
+ if ${overlayfs_needed}; then
+ adb_root &&
+ D=`adb_sh df -k </dev/null` &&
+ H=`echo "${D}" | head -1` &&
+ D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` &&
+ echo "${H}" &&
+ echo "${D}" &&
+ echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
+ die "overlay /system takeover after flash vendor"
+ echo "${D}" | grep "^overlay .* /vendor\$" >/dev/null &&
+ die "overlay supposed to be minus /vendor takeover after flash vendor"
+ fi
+ B="`adb_cat /system/hello`" ||
+ die "re-read /system/hello after flash vendor"
+ check_eq "${A}" "${B}" system after flash vendor
+ adb_root ||
+ die "adb root"
+ B="`adb_cat /vendor/hello`" &&
+ die "re-read /vendor/hello after flash vendor"
+ check_eq "cat: /vendor/hello: No such file or directory" "${B}" vendor after flash vendor
+fi
+
+echo "${GREEN}[ RUN ]${NORMAL} remove test content (cleanup)" >&2
+
+T=`adb_date`
+adb remount &&
+ ( adb_sh rm /vendor/hello </dev/null 2>/dev/null || true ) &&
+ adb_sh rm /system/hello </dev/null ||
+ die -t ${T} "cleanup hello"
+B="`adb_cat /system/hello`" &&
+ die "re-read /system/hello after rm"
+check_eq "cat: /system/hello: No such file or directory" "${B}" after flash rm
+B="`adb_cat /vendor/hello`" &&
+ die "re-read /vendor/hello after rm"
+check_eq "cat: /vendor/hello: No such file or directory" "${B}" after flash rm
+
+if [ -n "${scratch_partition}" ]; then
+
+ echo "${GREEN}[ RUN ]${NORMAL} test fastboot flash to ${scratch_partition}" >&2
+
+ adb reboot-fastboot ||
+ die "Reboot into fastbootd"
+ dd if=/dev/zero of=/tmp/adb-remount-test.img bs=4096 count=16 2>/dev/null &&
+ fastboot_wait 2m ||
+ ( rm /tmp/adb-remount-test.img && false) ||
+ die "reboot into fastboot"
+ fastboot flash --force ${scratch_partition} /tmp/adb-remount-test.img
+ err=${?}
+ rm /tmp/adb-remount-test.img
+ fastboot reboot ||
+ die "can not reboot out of fastboot"
+ [ 0 -eq ${err} ] ||
+ die "fastboot flash ${scratch_partition}"
+ adb_wait 2m &&
+ adb_root ||
+ die "did not reboot after flash"
+ T=`adb_date`
+ D=`adb disable-verity 2>&1`
+ err=${?}
+ echo "${D}"
+ [ ${err} = 0 ] &&
+ [ X"${D}" = X"${D##*setup failed}" ] &&
+ [ X"${D}" != X"${D##*using overlayfs}" ] &&
+ echo "${GREEN}[ OK ]${NORMAL} ${scratch_partition} recreated" >&2 ||
+ die -t ${T} "setup for overlayfs"
+fi
+
+echo "${GREEN}[ PASSED ]${NORMAL} adb remount" >&2
diff --git a/fs_mgr/tests/data/fstab.example b/fs_mgr/tests/data/fstab.example
new file mode 100644
index 0000000..1a3dfa1
--- /dev/null
+++ b/fs_mgr/tests/data/fstab.example
@@ -0,0 +1,11 @@
+# Android fstab file.
+
+#<src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
+
+/dev/block/bootdevice/by-name/system / ext4 ro,barrier=1 wait,slotselect,avb
+/dev/block/bootdevice/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,formattable
+/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier latemount,wait,check,fileencryption=ice,keydirectory=/metadata/vold/metadata_encryption,quota,formattable,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,reservedsize=128M
+/dev/block/bootdevice/by-name/misc /misc emmc defaults defaults
+/dev/block/bootdevice/by-name/modem /vendor/firmware_mnt vfat ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0 wait,slotselect
+/devices/platform/soc/a600000.ssusb/a600000.dwc3* auto vfat defaults voldmanaged=usb:auto
+/dev/block/zram0 none swap defaults zramsize=1073741824,max_comp_streams=8
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 8b1c55a..1922a69 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -24,6 +24,8 @@
#include <utility>
#include <vector>
+#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android-base/strings.h>
#include <fstab/fstab.h>
#include <gtest/gtest.h>
@@ -139,7 +141,7 @@
auto fstab = fs_mgr_read_fstab("/proc/mounts");
ASSERT_NE(fstab, nullptr);
- std::unique_ptr<std::FILE, int (*)(std::FILE*)> mounts(setmntent("/proc/mounts", "r"),
+ std::unique_ptr<std::FILE, int (*)(std::FILE*)> mounts(setmntent("/proc/mounts", "re"),
endmntent);
ASSERT_NE(mounts, nullptr);
@@ -201,3 +203,33 @@
++i;
}
}
+
+TEST(fs_mgr, ReadFstabFromFile_FsOptions) {
+ Fstab fstab;
+ std::string fstab_file = android::base::GetExecutableDirectory() + "/data/fstab.example";
+ EXPECT_TRUE(ReadFstabFromFile(fstab_file, &fstab));
+
+ EXPECT_EQ("/", fstab[0].mount_point);
+ EXPECT_EQ("barrier=1", fstab[0].fs_options);
+
+ EXPECT_EQ("/metadata", fstab[1].mount_point);
+ EXPECT_EQ("discard", fstab[1].fs_options);
+
+ EXPECT_EQ("/data", fstab[2].mount_point);
+ EXPECT_EQ("discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier", fstab[2].fs_options);
+
+ EXPECT_EQ("/misc", fstab[3].mount_point);
+ EXPECT_EQ("", fstab[3].fs_options);
+
+ EXPECT_EQ("/vendor/firmware_mnt", fstab[4].mount_point);
+ EXPECT_EQ(
+ "shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,"
+ "context=u:object_r:firmware_file:s0",
+ fstab[4].fs_options);
+
+ EXPECT_EQ("auto", fstab[5].mount_point);
+ EXPECT_EQ("", fstab[5].fs_options);
+
+ EXPECT_EQ("none", fstab[6].mount_point);
+ EXPECT_EQ("", fstab[6].fs_options);
+}
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 879ba21..3b6ff9b 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -36,12 +36,15 @@
#include <string>
#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 DmBlockDevice = ::android::dm::DeviceMapper::DmBlockDevice;
@@ -50,7 +53,7 @@
std::cerr << "commands:" << std::endl;
std::cerr << " create <dm-name> [-ro] <targets...>" << std::endl;
std::cerr << " delete <dm-name>" << std::endl;
- std::cerr << " list <devices | targets>" << std::endl;
+ std::cerr << " list <devices | targets> [-v]" << std::endl;
std::cerr << " getpath <dm-name>" << std::endl;
std::cerr << " table <dm-name>" << std::endl;
std::cerr << " help" << std::endl;
@@ -108,6 +111,13 @@
std::string block_device = NextArg();
return std::make_unique<DmTargetAndroidVerity>(start_sector, num_sectors, keyid,
block_device);
+ } else if (target_type == "bow") {
+ if (!HasArgs(1)) {
+ std::cerr << "Expected \"bow\" <block_device>" << std::endl;
+ return nullptr;
+ }
+ std::string block_device = NextArg();
+ return std::make_unique<DmTargetBow>(start_sector, num_sectors, block_device);
} else {
std::cerr << "Unrecognized target type: " << target_type << std::endl;
return nullptr;
@@ -189,7 +199,8 @@
return 0;
}
-static int DmListTargets(DeviceMapper& dm) {
+static int DmListTargets(DeviceMapper& dm, [[maybe_unused]] int argc,
+ [[maybe_unused]] char** argv) {
std::vector<DmTargetTypeInfo> targets;
if (!dm.GetAvailableTargets(&targets)) {
std::cerr << "Failed to read available device mapper targets" << std::endl;
@@ -210,7 +221,7 @@
return 0;
}
-static int DmListDevices(DeviceMapper& dm) {
+static int DmListDevices(DeviceMapper& dm, int argc, char** argv) {
std::vector<DmBlockDevice> devices;
if (!dm.GetAvailableDevices(&devices)) {
std::cerr << "Failed to read available device mapper devices" << std::endl;
@@ -222,15 +233,37 @@
return 0;
}
+ bool verbose = (argc && (argv[0] == "-v"s));
for (const auto& dev : devices) {
std::cout << std::left << std::setw(20) << dev.name() << " : " << dev.Major() << ":"
<< dev.Minor() << std::endl;
+ if (verbose) {
+ std::vector<DeviceMapper::TargetInfo> table;
+ if (!dm.GetTableInfo(dev.name(), &table)) {
+ std::cerr << "Could not query table status for device \"" << dev.name() << "\"."
+ << std::endl;
+ return -EINVAL;
+ }
+
+ uint32_t target_num = 1;
+ for (const auto& target : table) {
+ std::cout << " target#" << target_num << ": ";
+ std::cout << target.spec.sector_start << "-"
+ << (target.spec.sector_start + target.spec.length) << ": "
+ << target.spec.target_type;
+ if (!target.data.empty()) {
+ std::cout << ", " << target.data;
+ }
+ std::cout << std::endl;
+ target_num++;
+ }
+ }
}
return 0;
}
-static const std::map<std::string, std::function<int(DeviceMapper&)>> listmap = {
+static const std::map<std::string, std::function<int(DeviceMapper&, int, char**)>> listmap = {
{"targets", DmListTargets},
{"devices", DmListDevices},
};
@@ -243,7 +276,7 @@
DeviceMapper& dm = DeviceMapper::Instance();
for (const auto& l : listmap) {
- if (l.first == argv[0]) return l.second(dm);
+ if (l.first == argv[0]) return l.second(dm, argc - 1, argv + 1);
}
std::cerr << "Invalid argument to \'dmctl list\': " << argv[0] << std::endl;
diff --git a/gatekeeperd/Android.bp b/gatekeeperd/Android.bp
new file mode 100644
index 0000000..8e9c7ea
--- /dev/null
+++ b/gatekeeperd/Android.bp
@@ -0,0 +1,50 @@
+//
+// 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_binary {
+ name: "gatekeeperd",
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wunused",
+ ],
+ srcs: [
+ "SoftGateKeeperDevice.cpp",
+ "IGateKeeperService.cpp",
+ "gatekeeperd.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "libgatekeeper",
+ "liblog",
+ "libhardware",
+ "libbase",
+ "libutils",
+ "libcrypto",
+ "libkeystore_aidl",
+ "libkeystore_binder",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "android.hardware.gatekeeper@1.0",
+ ],
+
+ static_libs: ["libscrypt_static"],
+ include_dirs: ["external/scrypt/lib/crypto"],
+ init_rc: ["gatekeeperd.rc"],
+}
diff --git a/gatekeeperd/Android.mk b/gatekeeperd/Android.mk
deleted file mode 100644
index 6d5d1ea..0000000
--- a/gatekeeperd/Android.mk
+++ /dev/null
@@ -1,47 +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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused
-LOCAL_SRC_FILES := \
- SoftGateKeeperDevice.cpp \
- IGateKeeperService.cpp \
- gatekeeperd.cpp
-
-LOCAL_MODULE := gatekeeperd
-LOCAL_SHARED_LIBRARIES := \
- libbinder \
- libgatekeeper \
- liblog \
- libhardware \
- libbase \
- libutils \
- libcrypto \
- libkeystore_aidl \
- libkeystore_binder \
- libhidlbase \
- libhidltransport \
- libhwbinder \
- android.hardware.gatekeeper@1.0 \
-
-LOCAL_STATIC_LIBRARIES := libscrypt_static
-LOCAL_C_INCLUDES := external/scrypt/lib/crypto
-LOCAL_INIT_RC := gatekeeperd.rc
-include $(BUILD_EXECUTABLE)
-
-include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/gatekeeperd/IGateKeeperService.cpp b/gatekeeperd/IGateKeeperService.cpp
index 1c339f4..43d5708 100644
--- a/gatekeeperd/IGateKeeperService.cpp
+++ b/gatekeeperd/IGateKeeperService.cpp
@@ -70,7 +70,7 @@
} else {
reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
}
- return NO_ERROR;
+ return OK;
}
case VERIFY: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
@@ -102,7 +102,7 @@
} else {
reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
}
- return NO_ERROR;
+ return OK;
}
case VERIFY_CHALLENGE: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
@@ -141,7 +141,7 @@
} else {
reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
}
- return NO_ERROR;
+ return OK;
}
case GET_SECURE_USER_ID: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
@@ -149,20 +149,20 @@
uint64_t sid = getSecureUserId(uid);
reply->writeNoException();
reply->writeInt64(sid);
- return NO_ERROR;
+ return OK;
}
case CLEAR_SECURE_USER_ID: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
uint32_t uid = data.readInt32();
clearSecureUserId(uid);
reply->writeNoException();
- return NO_ERROR;
+ return OK;
}
case REPORT_DEVICE_SETUP_COMPLETE: {
CHECK_INTERFACE(IGateKeeperService, data, reply);
reportDeviceSetupComplete();
reply->writeNoException();
- return NO_ERROR;
+ return OK;
}
default:
return BBinder::onTransact(code, data, reply, flags);
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index 5f3ce36..446b66e 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -25,7 +25,7 @@
#include <unistd.h>
#include <memory>
-#include <android/security/IKeystoreService.h>
+#include <android/security/keystore/IKeystoreService.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
@@ -318,8 +318,8 @@
// TODO: cache service?
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
- sp<security::IKeystoreService> service =
- interface_cast<security::IKeystoreService>(binder);
+ 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);
@@ -386,7 +386,7 @@
write(fd, result, strlen(result) + 1);
}
- return NO_ERROR;
+ return OK;
}
private:
diff --git a/gatekeeperd/tests/Android.bp b/gatekeeperd/tests/Android.bp
new file mode 100644
index 0000000..d4cf93b
--- /dev/null
+++ b/gatekeeperd/tests/Android.bp
@@ -0,0 +1,34 @@
+//
+// 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/Android.mk b/gatekeeperd/tests/Android.mk
deleted file mode 100644
index c38c64b..0000000
--- a/gatekeeperd/tests/Android.mk
+++ /dev/null
@@ -1,29 +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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := gatekeeperd-unit-tests
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_CFLAGS += -g -Wall -Werror -Wno-missing-field-initializers
-LOCAL_SHARED_LIBRARIES := libgatekeeper libcrypto libbase
-LOCAL_STATIC_LIBRARIES := libscrypt_static
-LOCAL_C_INCLUDES := external/scrypt/lib/crypto
-LOCAL_SRC_FILES := \
- gatekeeper_test.cpp
-include $(BUILD_NATIVE_TEST)
-
diff --git a/healthd/Android.mk b/healthd/Android.mk
index f7214c6..2127b96 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -43,7 +43,7 @@
AnimationParser.cpp
LOCAL_MODULE := libhealthd_charger
-LOCAL_C_INCLUDES := bootable/recovery $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDE_DIRS := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/include
@@ -97,6 +97,7 @@
android.hardware.health@2.0 \
android.hardware.health@1.0 \
android.hardware.health@1.0-convert \
+ libbinderthreadstate \
libhidltransport \
libhidlbase \
libhwbinder_noltopgo \
@@ -108,6 +109,7 @@
libbase \
libutils \
libcutils \
+ libprocessgroup \
liblog \
libm \
libc \
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 80c5afe..06c8176 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -26,6 +26,8 @@
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
+
+#include <algorithm>
#include <memory>
#include <android-base/file.h>
@@ -240,10 +242,9 @@
if (readFromFile(mHealthdConfig->batteryTechnologyPath, &buf) > 0)
props.batteryTechnology = String8(buf.c_str());
- unsigned int i;
double MaxPower = 0;
- for (i = 0; i < mChargerNames.size(); i++) {
+ for (size_t i = 0; i < mChargerNames.size(); i++) {
String8 path;
path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH,
mChargerNames[i].string());
@@ -357,7 +358,7 @@
if (!mHealthdConfig->batteryChargeCounterPath.isEmpty()) {
val->valueInt64 =
getIntField(mHealthdConfig->batteryChargeCounterPath);
- ret = NO_ERROR;
+ ret = OK;
} else {
ret = NAME_NOT_FOUND;
}
@@ -367,7 +368,7 @@
if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
val->valueInt64 =
getIntField(mHealthdConfig->batteryCurrentNowPath);
- ret = NO_ERROR;
+ ret = OK;
} else {
ret = NAME_NOT_FOUND;
}
@@ -377,7 +378,7 @@
if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty()) {
val->valueInt64 =
getIntField(mHealthdConfig->batteryCurrentAvgPath);
- ret = NO_ERROR;
+ ret = OK;
} else {
ret = NAME_NOT_FOUND;
}
@@ -387,7 +388,7 @@
if (!mHealthdConfig->batteryCapacityPath.isEmpty()) {
val->valueInt64 =
getIntField(mHealthdConfig->batteryCapacityPath);
- ret = NO_ERROR;
+ ret = OK;
} else {
ret = NAME_NOT_FOUND;
}
@@ -403,7 +404,7 @@
case BATTERY_PROP_BATTERY_STATUS:
val->valueInt64 = getChargeStatus();
- ret = NO_ERROR;
+ ret = OK;
break;
default:
@@ -477,10 +478,16 @@
while ((entry = readdir(dir.get()))) {
const char* name = entry->d_name;
+ std::vector<String8>::iterator itIgnoreName;
if (!strcmp(name, ".") || !strcmp(name, ".."))
continue;
+ itIgnoreName = find(hc->ignorePowerSupplyNames.begin(),
+ hc->ignorePowerSupplyNames.end(), String8(name));
+ if (itIgnoreName != hc->ignorePowerSupplyNames.end())
+ continue;
+
// Look for "type" file in each subdirectory
path.clear();
path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
diff --git a/healthd/android.hardware.health@2.0-service.rc b/healthd/android.hardware.health@2.0-service.rc
index dca0ccc..6960c5d 100644
--- a/healthd/android.hardware.health@2.0-service.rc
+++ b/healthd/android.hardware.health@2.0-service.rc
@@ -2,4 +2,5 @@
class hal
user system
group system
+ capabilities WAKE_ALARM
file /dev/kmsg w
diff --git a/healthd/animation.h b/healthd/animation.h
index 562b689..f59fb38 100644
--- a/healthd/animation.h
+++ b/healthd/animation.h
@@ -20,7 +20,7 @@
#include <inttypes.h>
#include <string>
-struct GRSurface;
+class GRSurface;
struct GRFont;
namespace android {
diff --git a/healthd/include/healthd/healthd.h b/healthd/include/healthd/healthd.h
index c01e8d7..a900071 100644
--- a/healthd/include/healthd/healthd.h
+++ b/healthd/include/healthd/healthd.h
@@ -22,6 +22,8 @@
#include <utils/Errors.h>
#include <utils/String8.h>
+#include <vector>
+
// periodic_chores_interval_fast, periodic_chores_interval_slow: intervals at
// which healthd wakes up to poll health state and perform periodic chores,
// in units of seconds:
@@ -71,6 +73,7 @@
int (*energyCounter)(int64_t *);
int boot_min_cap;
bool (*screen_on)(android::BatteryProperties *props);
+ std::vector<android::String8> ignorePowerSupplyNames;
};
enum EventWakeup {
diff --git a/init/Android.bp b/init/Android.bp
index a2c49d0..9f5d17d 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -68,17 +68,24 @@
],
shared_libs: [
"libbase",
+ "libbinder",
"libbootloader_message",
"libcutils",
+ "libcrypto",
"libdl",
"libext4_utils",
"libfs_mgr",
+ "libfscrypt",
+ "libgsi",
"libhidl-gen-utils",
"libkeyutils",
"liblog",
"liblogwrap",
+ "liblp",
"libselinux",
+ "libutils",
],
+ bootstrap: true,
}
cc_library_static {
@@ -89,6 +96,7 @@
"action.cpp",
"action_manager.cpp",
"action_parser.cpp",
+ "boringssl_self_test.cpp",
"bootchart.cpp",
"builtins.cpp",
"capabilities.cpp",
@@ -96,6 +104,7 @@
"devices.cpp",
"epoll.cpp",
"firmware_handler.cpp",
+ "first_stage_init.cpp",
"first_stage_mount.cpp",
"import_parser.cpp",
"init.cpp",
@@ -114,6 +123,7 @@
"sigchld_handler.cpp",
"subcontext.cpp",
"subcontext.proto",
+ "switch_root.cpp",
"rlimit_parser.cpp",
"tokenizer.cpp",
"uevent_listener.cpp",
@@ -127,6 +137,13 @@
type: "lite",
export_proto_headers: true,
},
+
+ target: {
+ recovery: {
+ cflags: ["-DRECOVERY"],
+ exclude_shared_libs: ["libbinder", "libutils"],
+ },
+ },
}
cc_binary {
@@ -143,6 +160,12 @@
],
srcs: ["main.cpp"],
symlinks: ["ueventd"],
+ target: {
+ recovery: {
+ cflags: ["-DRECOVERY"],
+ exclude_shared_libs: ["libbinder", "libutils"],
+ },
+ },
}
// Tests
diff --git a/init/Android.mk b/init/Android.mk
index dc400ad..69c63e1 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -35,23 +35,26 @@
-Wall -Wextra \
-Wno-unused-parameter \
-Werror \
- -std=gnu++1z \
# --
+# Do not build this even with mmma if we're system-as-root, otherwise it will overwrite the symlink.
+ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
include $(CLEAR_VARS)
LOCAL_CPPFLAGS := $(init_cflags)
LOCAL_SRC_FILES := \
devices.cpp \
+ first_stage_init.cpp \
+ first_stage_main.cpp \
first_stage_mount.cpp \
- init_first_stage.cpp \
reboot_utils.cpp \
selinux.cpp \
switch_root.cpp \
uevent_listener.cpp \
util.cpp \
-LOCAL_MODULE := init
+LOCAL_MODULE := init_first_stage
+LOCAL_MODULE_STEM := init
LOCAL_FORCE_STATIC_EXECUTABLE := true
@@ -61,17 +64,19 @@
# Set up the same mount points on the ramdisk that system-as-root contains.
LOCAL_POST_INSTALL_CMD := \
mkdir -p $(TARGET_RAMDISK_OUT)/dev \
- mkdir -p $(TARGET_RAMDISK_OUT)/mnt \
- mkdir -p $(TARGET_RAMDISK_OUT)/proc \
- mkdir -p $(TARGET_RAMDISK_OUT)/sys \
+ $(TARGET_RAMDISK_OUT)/mnt \
+ $(TARGET_RAMDISK_OUT)/proc \
+ $(TARGET_RAMDISK_OUT)/sys \
LOCAL_STATIC_LIBRARIES := \
+ libfs_avb \
libfs_mgr \
libfec \
libfec_rs \
libsquashfs_utils \
liblogwrap \
libext4_utils \
+ libfscrypt \
libseccomp_policy \
libcrypto_utils \
libsparse \
@@ -86,9 +91,28 @@
libz \
libselinux \
libcap \
-
-LOCAL_REQUIRED_MODULES := \
- init_second_stage \
+ libgsi \
LOCAL_SANITIZE := signed-integer-overflow
+# First stage init is weird: it may start without stdout/stderr, and no /proc.
+LOCAL_NOSANITIZE := hwaddress
include $(BUILD_EXECUTABLE)
+endif
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := init_system
+LOCAL_REQUIRED_MODULES := \
+ init_second_stage \
+
+include $(BUILD_PHONY_PACKAGE)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := init_vendor
+ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+LOCAL_REQUIRED_MODULES := \
+ init_first_stage \
+
+endif
+include $(BUILD_PHONY_PACKAGE)
diff --git a/init/README.md b/init/README.md
index b45da21..3a7c71c 100644
--- a/init/README.md
+++ b/init/README.md
@@ -189,7 +189,7 @@
`critical`
> This is a device-critical service. If it exits more than four times in
- four minutes, the device will reboot into recovery mode.
+ four minutes, the device will reboot into bootloader.
`disabled`
> This service will not automatically start with its class.
@@ -213,7 +213,8 @@
`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.
+ 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>`
@@ -225,9 +226,25 @@
keycodes are pressed at once, the service will start. This is typically used to start the
bugreport service.
-`memcg.limit_in_bytes <value>`
-> Sets the child's memory.limit_in_bytes to the specified value (only if memcg is mounted),
- which must be equal or greater than 0.
+> This option may take a property instead of a list of keycodes. In this case, only one option is
+ provided: the property name in the typical property expansion format. The property must contain
+ a comma separated list of keycode values or the text 'none' to indicate that
+ this service does not respond to keycodes.
+
+> For example, `keycodes ${some.property.name:-none}` where some.property.name expands
+ to "123,124,125". Since keycodes are handled very early in init,
+ only PRODUCT_DEFAULT_PROPERTY_OVERRIDES properties can be used.
+
+`memcg.limit_in_bytes <value>` and `memcg.limit_percent <value>`
+> Sets the child's memory.limit_in_bytes to the minimum of `limit_in_bytes`
+ bytes and `limit_percent` which is interpreted as a percentage of the size
+ of the device's physical memory (only if memcg is mounted).
+ Values must be equal or greater than 0.
+
+`memcg.limit_property <value>`
+> Sets the child's memory.limit_in_bytes to the value of the specified property
+ (only if memcg is mounted). This property will override the values specified
+ via `memcg.limit_in_bytes` and `memcg.limit_percent`.
`memcg.soft_limit_in_bytes <value>`
> Sets the child's memory.soft_limit_in_bytes to the specified value (only if memcg is mounted),
@@ -258,10 +275,21 @@
since it has some peculiarities for backwards compatibility reasons. The 'imports' section of
this file has more details on the order.
+`parse_apex_configs`
+ Parses config file(s) from the mounted APEXes. Intented to be used only once
+ when apexd notifies the mount event by setting apexd.status to ready.
+
`priority <priority>`
> 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().
+`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.
+ This can be increased for services that are meant to run periodically. For
+ example, it may be set to 3600 to indicate that the service should run every hour
+ or 86400 to indicate that the service should run every day.
+
`rlimit <resource> <cur> <max>`
> This applies the given rlimit to the service. rlimits are inherited by child
processes, so this effectively applies the given rlimit to the process tree
@@ -298,6 +326,19 @@
seclabel or computed based on the service executable file security context.
For native executables see libcutils android\_get\_control\_socket().
+`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.
+ This is particularly useful for creating a periodic service combined with the restart_period
+ option described above.
+
+`updatable`
+> Mark that the service can be overridden (via the 'override' option) later in
+ the boot sequence by APEXes. When a service with updatable option is started
+ before APEXes are all activated, the execution is delayed until the activation
+ is finished. A service that is not marked as updatable cannot be overridden by
+ APEXes.
+
`user <username>`
> Change to 'username' before exec'ing this service.
Currently defaults to root. (??? probably should default to nobody)
@@ -441,9 +482,8 @@
-f: force installation of the module even if the version of the running kernel
and the version of the kernel for which the module was compiled do not match.
-`load_all_props`
-> Loads properties from /system, /vendor, et cetera.
- This is included in the default init.rc.
+`load_system_props`
+> (This action is deprecated and no-op.)
`load_persist_props`
> Loads persistent properties when /data has been decrypted.
@@ -772,3 +812,42 @@
SELinux would permit the operation, or if the UIDs and GIDs resolve.
2) No checking if a service exists or has a valid SELinux domain defined
3) No checking if a service has not been previously defined in a different init script.
+
+Early Init Boot Sequence
+------------------------
+The early init boot sequence is broken up into three stages: first stage init, SELinux setup, and
+second stage init.
+
+First stage init is responsible for setting up the bare minimum requirements to load the rest of the
+system. Specifically this includes mounting /dev, /proc, mounting 'early mount' partitions (which
+needs to include all partitions that contain system code, for example system and vendor), and moving
+the system.img mount to / for devices with a ramdisk.
+
+Note that in Android Q, system.img always contains TARGET_ROOT_OUT and always is mounted at / by the
+time first stage init finishes. Android Q will also require dynamic partitions and therefore will
+require using a ramdisk to boot Android. The recovery ramdisk can be used to boot to Android instead
+of a dedicated ramdisk as well.
+
+First stage init has three variations depending on the device configuration:
+1) For system-as-root devices, first stage init is part of /system/bin/init and a symlink at /init
+points to /system/bin/init for backwards compatibility. These devices do not need to do anything to
+mount system.img, since it is by definition already mounted as the rootfs by the kernel.
+
+2) For devices with a ramdisk, first stage init is a static executable located at /init. These
+devices mount system.img as /system then perform a switch root operation to move the mount at
+/system to /. The contents of the ramdisk are freed after mounting has completed.
+
+3) For devices that use recovery as a ramdisk, first stage init it contained within the shared init
+located at /init within the recovery ramdisk. These devices first switch root to
+/first_stage_ramdisk to remove the recovery components from the environment, then proceed the same
+as 2). Note that the decision to boot normally into Android instead of booting
+into recovery mode is made if androidboot.force_normal_boot=1 is present in the
+kernel commandline.
+
+Once first stage init finishes it execs /system/bin/init with the "selinux_setup" argument. This
+phase is where SELinux is optionally compiled and loaded onto the system. selinux.cpp contains more
+information on the specifics of this process.
+
+Lastly once that phase finishes, it execs /system/bin/init again with the "second_stage"
+argument. At this point the main phase of init runs and continues the boot process via the init.rc
+scripts.
diff --git a/init/action.cpp b/init/action.cpp
index 11335ca..94ccef2 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -44,9 +44,12 @@
return function(builtin_arguments);
}
-Command::Command(BuiltinFunction f, bool execute_in_subcontext,
- const std::vector<std::string>& args, int line)
- : func_(std::move(f)), execute_in_subcontext_(execute_in_subcontext), args_(args), line_(line) {}
+Command::Command(BuiltinFunction f, bool execute_in_subcontext, std::vector<std::string>&& args,
+ int line)
+ : func_(std::move(f)),
+ execute_in_subcontext_(execute_in_subcontext),
+ args_(std::move(args)),
+ line_(line) {}
Result<Success> Command::InvokeFunc(Subcontext* subcontext) const {
if (subcontext) {
@@ -80,7 +83,7 @@
const KeywordFunctionMap* Action::function_map_ = nullptr;
-Result<Success> Action::AddCommand(const std::vector<std::string>& args, int line) {
+Result<Success> Action::AddCommand(std::vector<std::string>&& args, int line) {
if (!function_map_) {
return Error() << "no function map available";
}
@@ -88,12 +91,12 @@
auto function = function_map_->FindFunction(args);
if (!function) return Error() << function.error();
- commands_.emplace_back(function->second, function->first, args, line);
+ commands_.emplace_back(function->second, function->first, std::move(args), line);
return Success();
}
-void Action::AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line) {
- commands_.emplace_back(f, false, args, line);
+void Action::AddCommand(BuiltinFunction f, std::vector<std::string>&& args, int line) {
+ commands_.emplace_back(f, false, std::move(args), line);
}
std::size_t Action::NumCommands() const {
diff --git a/init/action.h b/init/action.h
index 4f063cc..967c682 100644
--- a/init/action.h
+++ b/init/action.h
@@ -36,7 +36,7 @@
class Command {
public:
- Command(BuiltinFunction f, bool execute_in_subcontext, const std::vector<std::string>& args,
+ Command(BuiltinFunction f, bool execute_in_subcontext, std::vector<std::string>&& args,
int line);
Result<Success> InvokeFunc(Subcontext* subcontext) const;
@@ -61,8 +61,8 @@
const std::string& event_trigger,
const std::map<std::string, std::string>& property_triggers);
- Result<Success> AddCommand(const std::vector<std::string>& args, int line);
- void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line);
+ Result<Success> AddCommand(std::vector<std::string>&& args, int line);
+ void AddCommand(BuiltinFunction f, std::vector<std::string>&& args, int line);
std::size_t NumCommands() const;
void ExecuteOneCommand(std::size_t command) const;
void ExecuteAllCommands() const;
diff --git a/init/action_manager.cpp b/init/action_manager.cpp
index 22977bb..9de4085 100644
--- a/init/action_manager.cpp
+++ b/init/action_manager.cpp
@@ -47,9 +47,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>{});
- std::vector<std::string> name_vector{name};
-
- action->AddCommand(func, name_vector, 0);
+ action->AddCommand(func, {name}, 0);
event_queue_.emplace(action.get());
actions_.emplace_back(std::move(action));
diff --git a/init/action_parser.cpp b/init/action_parser.cpp
index 1481162..4f8bd16 100644
--- a/init/action_parser.cpp
+++ b/init/action_parser.cpp
@@ -19,7 +19,11 @@
#include <android-base/properties.h>
#include <android-base/strings.h>
-#include "stable_properties.h"
+#if defined(__ANDROID__)
+#include "property_service.h"
+#else
+#include "host_init_stubs.h"
+#endif
using android::base::GetBoolProperty;
using android::base::StartsWith;
@@ -36,15 +40,19 @@
return true;
}
- if (kExportedActionableProperties.count(prop_name) == 1) {
- return true;
- }
+ static constexpr const char* kPartnerPrefixes[] = {
+ "init.svc.vendor.", "ro.vendor.", "persist.vendor.",
+ "vendor.", "init.svc.odm.", "ro.odm.",
+ "persist.odm.", "odm.", "ro.boot.",
+ };
+
for (const auto& prefix : kPartnerPrefixes) {
if (android::base::StartsWith(prop_name, prefix)) {
return true;
}
}
- return false;
+
+ return CanReadProperty(subcontext->context(), prop_name);
}
Result<Success> ParsePropertyTrigger(const std::string& trigger, Subcontext* subcontext,
diff --git a/init/boringssl_self_test.cpp b/init/boringssl_self_test.cpp
new file mode 100644
index 0000000..0408d30
--- /dev/null
+++ b/init/boringssl_self_test.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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/libbacktrace/GetPss.h b/init/boringssl_self_test.h
similarity index 67%
copy from libbacktrace/GetPss.h
copy to init/boringssl_self_test.h
index 787c33d..b21fc78 100644
--- a/libbacktrace/GetPss.h
+++ b/init/boringssl_self_test.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,9 +14,15 @@
* limitations under the License.
*/
-#ifndef _LIBBACKTRACE_GET_PSS_H
-#define _LIBBACKTRACE_GET_PSS_H
+#pragma once
-size_t GetPssBytes();
+#include "builtin_arguments.h"
+#include "result.h"
-#endif // _LIBBACKTRACE_GET_PSS_H
+namespace android {
+namespace init {
+
+Result<Success> StartBoringSslSelfTest(const BuiltinArguments&);
+
+} // namespace init
+} // namespace android
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 17d34e1..169edbe 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -20,6 +20,7 @@
#include <errno.h>
#include <fcntl.h>
#include <fts.h>
+#include <glob.h>
#include <linux/loop.h>
#include <linux/module.h>
#include <mntent.h>
@@ -50,9 +51,10 @@
#include <android-base/unique_fd.h>
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
-#include <ext4_utils/ext4_crypt.h>
-#include <ext4_utils/ext4_crypt_init_extensions.h>
#include <fs_mgr.h>
+#include <fscrypt/fscrypt.h>
+#include <fscrypt/fscrypt_init_extensions.h>
+#include <libgsi/libgsi.h>
#include <selinux/android.h>
#include <selinux/label.h>
#include <selinux/selinux.h>
@@ -99,6 +101,9 @@
}
static Result<Success> 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();
// Starting a class does not start services which are explicitly disabled.
// They must be started individually.
for (const auto& service : ServiceList::GetInstance()) {
@@ -123,6 +128,9 @@
}
static Result<Success> 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();
ForEachServiceInClass(args[1], &Service::Restart);
return Success();
}
@@ -307,8 +315,8 @@
}
}
- if (e4crypt_is_native()) {
- if (e4crypt_set_directory_policy(args[1].c_str())) {
+ if (fscrypt_is_native()) {
+ if (fscrypt_set_directory_policy(args[1].c_str())) {
return reboot_into_recovery(
{"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + args[1]});
}
@@ -472,9 +480,10 @@
// Only needed if someone explicitly changes the default log level in their init.rc.
android::base::ScopedLogSeverity info(android::base::INFO);
- struct fstab* fstab = fs_mgr_read_fstab(fstabfile);
- int child_ret = fs_mgr_mount_all(fstab, mount_mode);
- fs_mgr_free_fstab(fstab);
+ Fstab fstab;
+ ReadFstabFromFile(fstabfile, &fstab);
+
+ int child_ret = fs_mgr_mount_all(&fstab, mount_mode);
if (child_ret == -1) {
PLOG(ERROR) << "fs_mgr_mount_all returned an error";
}
@@ -512,13 +521,16 @@
return Success();
} else if (code == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
/* Setup a wipe via recovery, and reboot into recovery */
+ if (android::gsi::IsGsiRunning()) {
+ return Error() << "cannot wipe within GSI";
+ }
PLOG(ERROR) << "fs_mgr_mount_all suggested recovery, so wiping data via recovery.";
const std::vector<std::string> options = {"--wipe_data", "--reason=fs_mgr_mount_all" };
return reboot_into_recovery(options);
/* If reboot worked, there is no return. */
} else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
- if (e4crypt_install_keyring()) {
- return Error() << "e4crypt_install_keyring() failed";
+ if (fscrypt_install_keyring()) {
+ return Error() << "fscrypt_install_keyring() failed";
}
property_set("ro.crypto.state", "encrypted");
property_set("ro.crypto.type", "file");
@@ -528,8 +540,8 @@
ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
return Success();
} else if (code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED) {
- if (e4crypt_install_keyring()) {
- return Error() << "e4crypt_install_keyring() failed";
+ if (fscrypt_install_keyring()) {
+ return Error() << "fscrypt_install_keyring() failed";
}
property_set("ro.crypto.state", "encrypted");
property_set("ro.crypto.type", "file");
@@ -539,8 +551,8 @@
ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
return Success();
} else if (code == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
- if (e4crypt_install_keyring()) {
- return Error() << "e4crypt_install_keyring() failed";
+ if (fscrypt_install_keyring()) {
+ return Error() << "fscrypt_install_keyring() failed";
}
property_set("ro.crypto.state", "encrypted");
property_set("ro.crypto.type", "file");
@@ -611,14 +623,15 @@
}
static Result<Success> do_swapon_all(const BuiltinArguments& args) {
- struct fstab *fstab;
- int ret;
+ Fstab fstab;
+ if (!ReadFstabFromFile(args[1], &fstab)) {
+ return Error() << "Could not read fstab '" << args[1] << "'";
+ }
- fstab = fs_mgr_read_fstab(args[1].c_str());
- ret = fs_mgr_swapon_all(fstab);
- fs_mgr_free_fstab(fstab);
+ if (!fs_mgr_swapon_all(fstab)) {
+ return Error() << "fs_mgr_swapon_all() failed";
+ }
- if (ret != 0) return Error() << "fs_mgr_swapon_all() failed";
return Success();
}
@@ -732,13 +745,10 @@
return Success();
}
-static void verity_update_property(fstab_rec *fstab, const char *mount_point,
- int mode, int status) {
- property_set("partition."s + mount_point + ".verified", std::to_string(mode));
-}
-
static Result<Success> do_verity_update_state(const BuiltinArguments& args) {
- if (!fs_mgr_update_verity_state(verity_update_property)) {
+ if (!fs_mgr_update_verity_state([](const std::string& mount_point, int mode) {
+ property_set("partition." + mount_point + ".verified", std::to_string(mode));
+ })) {
return Error() << "fs_mgr_update_verity_state() failed";
}
return Success();
@@ -966,7 +976,7 @@
}
static Result<Success> do_load_system_props(const BuiltinArguments& args) {
- load_system_props();
+ LOG(INFO) << "deprecated action `load_system_props` called.";
return Success();
}
@@ -1016,9 +1026,14 @@
}
service->AddReapCallback([reboot_reason](const siginfo_t& siginfo) {
if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) {
- if (e4crypt_is_native()) {
+ // TODO (b/122850122): support this in gsi
+ if (fscrypt_is_native() && !android::gsi::IsGsiRunning()) {
LOG(ERROR) << "Rebooting into recovery, reason: " << reboot_reason;
- reboot_into_recovery({"--prompt_and_wipe_data", "--reason="s + 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;
}
@@ -1034,7 +1049,7 @@
static Result<Success> do_installkey(const BuiltinArguments& args) {
if (!is_file_crypto()) return Success();
- auto unencrypted_dir = args[1] + e4crypt_unencrypted_folder;
+ auto unencrypted_dir = args[1] + fscrypt_unencrypted_folder;
if (!make_dir(unencrypted_dir, 0700) && errno != EEXIST) {
return ErrnoError() << "Failed to create " << unencrypted_dir;
}
@@ -1049,6 +1064,40 @@
{{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context});
}
+static Result<Success> do_parse_apex_configs(const BuiltinArguments& args) {
+ 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";
+ 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());
+ for (size_t i = 0; i < glob_result.gl_pathc; i++) {
+ configs.emplace_back(glob_result.gl_pathv[i]);
+ }
+ globfree(&glob_result);
+
+ bool success = true;
+ for (const auto& c : configs) {
+ if (c.back() == '/') {
+ // skip if directory
+ continue;
+ }
+ success &= parser.ParseConfigFile(c);
+ }
+ ServiceList::GetInstance().MarkServicesUpdate();
+ if (success) {
+ return Success();
+ } else {
+ return Error() << "Could not parse apex configs";
+ }
+}
+
// Builtin-function-map start
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
@@ -1086,6 +1135,7 @@
// 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}}},
{"umount", {1, 1, {false, do_umount}}},
{"readahead", {1, 2, {true, do_readahead}}},
{"restart", {1, 1, {false, do_restart}}},
diff --git a/init/devices.cpp b/init/devices.cpp
index 58c8b2e..1a77ba1 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -320,6 +320,7 @@
auto link_path = "/dev/block/" + type + "/" + device;
+ bool is_boot_device = boot_devices_.find(device) != boot_devices_.end();
if (!uevent.partition_name.empty()) {
std::string partition_name_sanitized(uevent.partition_name);
SanitizePartitionName(&partition_name_sanitized);
@@ -329,9 +330,13 @@
}
links.emplace_back(link_path + "/by-name/" + partition_name_sanitized);
// Adds symlink: /dev/block/by-name/<partition_name>.
- if (boot_devices_.find(device) != boot_devices_.end()) {
+ if (is_boot_device) {
links.emplace_back("/dev/block/by-name/" + partition_name_sanitized);
}
+ } else if (is_boot_device) {
+ // If we don't have a partition name but we are a partition on a boot device, create a
+ // symlink of /dev/block/by-name/<device_name> for symmetry.
+ links.emplace_back("/dev/block/by-name/" + uevent.device_name);
}
auto last_slash = uevent.path.rfind('/');
@@ -419,7 +424,7 @@
}
void DeviceHandler::ColdbootDone() {
- skip_restorecon_ = true;
+ skip_restorecon_ = false;
}
DeviceHandler::DeviceHandler(std::vector<Permissions> dev_permissions,
diff --git a/init/devices_test.cpp b/init/devices_test.cpp
index d658f4d..3e7c1a8 100644
--- a/init/devices_test.cpp
+++ b/init/devices_test.cpp
@@ -16,8 +16,8 @@
#include "devices.h"
+#include <android-base/file.h>
#include <android-base/scopeguard.h>
-#include <android-base/test_utils.h>
#include <gtest/gtest.h>
#include "util.h"
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
new file mode 100644
index 0000000..e11d897
--- /dev/null
+++ b/init/first_stage_init.cpp
@@ -0,0 +1,230 @@
+/*
+ * 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 "first_stage_init.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include <android-base/chrono_utils.h>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <cutils/android_reboot.h>
+#include <private/android_filesystem_config.h>
+
+#include "first_stage_mount.h"
+#include "reboot_utils.h"
+#include "switch_root.h"
+#include "util.h"
+
+using android::base::boot_clock;
+
+using namespace std::literals;
+
+namespace android {
+namespace init {
+
+namespace {
+
+void FreeRamdisk(DIR* dir, dev_t dev) {
+ int dfd = dirfd(dir);
+
+ dirent* de;
+ while ((de = readdir(dir)) != nullptr) {
+ if (de->d_name == "."s || de->d_name == ".."s) {
+ continue;
+ }
+
+ bool is_dir = false;
+
+ if (de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) {
+ struct stat info;
+ if (fstatat(dfd, de->d_name, &info, AT_SYMLINK_NOFOLLOW) != 0) {
+ continue;
+ }
+
+ if (info.st_dev != dev) {
+ continue;
+ }
+
+ if (S_ISDIR(info.st_mode)) {
+ is_dir = true;
+ auto fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
+ if (fd >= 0) {
+ auto subdir =
+ std::unique_ptr<DIR, decltype(&closedir)>{fdopendir(fd), closedir};
+ if (subdir) {
+ FreeRamdisk(subdir.get(), dev);
+ } else {
+ close(fd);
+ }
+ }
+ }
+ }
+ unlinkat(dfd, de->d_name, is_dir ? AT_REMOVEDIR : 0);
+ }
+}
+
+bool ForceNormalBoot() {
+ std::string cmdline;
+ android::base::ReadFileToString("/proc/cmdline", &cmdline);
+ return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos;
+}
+
+} // namespace
+
+int FirstStageMain(int argc, char** argv) {
+ if (REBOOT_BOOTLOADER_ON_PANIC) {
+ InstallRebootSignalHandlers();
+ }
+
+ boot_clock::time_point start_time = boot_clock::now();
+
+ std::vector<std::pair<std::string, int>> errors;
+#define CHECKCALL(x) \
+ if (x != 0) errors.emplace_back(#x " failed", errno);
+
+ // Clear the umask.
+ umask(0);
+
+ CHECKCALL(clearenv());
+ CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1));
+ // Get the basic filesystem setup we need put together in the initramdisk
+ // on / and then we'll let the rc file figure out the rest.
+ CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
+ CHECKCALL(mkdir("/dev/pts", 0755));
+ CHECKCALL(mkdir("/dev/socket", 0755));
+ CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));
+#define MAKE_STR(x) __STRING(x)
+ CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)));
+#undef MAKE_STR
+ // Don't expose the raw commandline to unprivileged processes.
+ CHECKCALL(chmod("/proc/cmdline", 0440));
+ gid_t groups[] = {AID_READPROC};
+ CHECKCALL(setgroups(arraysize(groups), groups));
+ CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
+ CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL));
+
+ CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11)));
+
+ if constexpr (WORLD_WRITABLE_KMSG) {
+ CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11)));
+ }
+
+ CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)));
+ CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)));
+
+ // This is needed for log wrapper, which gets called before ueventd runs.
+ CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2)));
+ CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3)));
+
+ // These below mounts are done in first stage init so that first stage mount can mount
+ // subdirectories of /mnt/{vendor,product}/. Other mounts, not required by first stage mount,
+ // should be done in rc files.
+ // Mount staging areas for devices managed by vold
+ // See storage config details at http://source.android.com/devices/storage/
+ CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
+ "mode=0755,uid=0,gid=1000"));
+ // /mnt/vendor is used to mount vendor-specific partitions that can not be
+ // part of the vendor partition, e.g. because they are mounted read-write.
+ CHECKCALL(mkdir("/mnt/vendor", 0755));
+ // /mnt/product is used to mount product-specific partitions that can not be
+ // part of the product partition, e.g. because they are mounted read-write.
+ CHECKCALL(mkdir("/mnt/product", 0755));
+
+#undef CHECKCALL
+
+ // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
+ // talk to the outside world...
+ // We need to set up stdin/stdout/stderr for child processes forked from first
+ // stage init as part of the mount process. This closes /dev/console if the
+ // kernel had previously opened it.
+ auto reboot_bootloader = [](const char*) { RebootSystem(ANDROID_RB_RESTART2, "bootloader"); };
+ InitKernelLogging(argv, reboot_bootloader);
+
+ if (!errors.empty()) {
+ for (const auto& [error_string, error_errno] : errors) {
+ LOG(ERROR) << error_string << " " << strerror(error_errno);
+ }
+ LOG(FATAL) << "Init encountered errors starting first stage, aborting";
+ }
+
+ LOG(INFO) << "init first stage started!";
+
+ auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir};
+ if (!old_root_dir) {
+ PLOG(ERROR) << "Could not opendir(\"/\"), not freeing ramdisk";
+ }
+
+ struct stat old_root_info;
+ if (stat("/", &old_root_info) != 0) {
+ PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
+ old_root_dir.reset();
+ }
+
+ if (ForceNormalBoot()) {
+ 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.
+ if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) {
+ LOG(FATAL) << "Could not bind mount /first_stage_ramdisk to itself";
+ }
+ SwitchRoot("/first_stage_ramdisk");
+ }
+
+ if (!DoFirstStageMount()) {
+ LOG(FATAL) << "Failed to mount required partitions early ...";
+ }
+
+ struct stat new_root_info;
+ if (stat("/", &new_root_info) != 0) {
+ PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
+ old_root_dir.reset();
+ }
+
+ if (old_root_dir && old_root_info.st_dev != new_root_info.st_dev) {
+ FreeRamdisk(old_root_dir.get(), old_root_info.st_dev);
+ }
+
+ 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);
+
+ const char* path = "/system/bin/init";
+ const char* args[] = {path, "selinux_setup", nullptr};
+ execv(path, const_cast<char**>(args));
+
+ // execv() only returns if an error happened, in which case we
+ // panic and never fall through this conditional.
+ PLOG(FATAL) << "execv(\"" << path << "\") failed";
+
+ return 1;
+}
+
+} // namespace init
+} // namespace android
diff --git a/libbacktrace/GetPss.h b/init/first_stage_init.h
similarity index 73%
copy from libbacktrace/GetPss.h
copy to init/first_stage_init.h
index 787c33d..0476e44 100644
--- a/libbacktrace/GetPss.h
+++ b/init/first_stage_init.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,9 +14,12 @@
* limitations under the License.
*/
-#ifndef _LIBBACKTRACE_GET_PSS_H
-#define _LIBBACKTRACE_GET_PSS_H
+#pragma once
-size_t GetPssBytes();
+namespace android {
+namespace init {
-#endif // _LIBBACKTRACE_GET_PSS_H
+int FirstStageMain(int argc, char** argv);
+
+} // namespace init
+} // namespace android
diff --git a/libbacktrace/GetPss.h b/init/first_stage_main.cpp
similarity index 75%
rename from libbacktrace/GetPss.h
rename to init/first_stage_main.cpp
index 787c33d..7bae84c 100644
--- a/libbacktrace/GetPss.h
+++ b/init/first_stage_main.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-#ifndef _LIBBACKTRACE_GET_PSS_H
-#define _LIBBACKTRACE_GET_PSS_H
+#include "first_stage_init.h"
-size_t GetPssBytes();
-
-#endif // _LIBBACKTRACE_GET_PSS_H
+int main(int argc, char** argv) {
+ return android::init::FirstStageMain(argc, argv);
+}
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index fa3392e..affa39e 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -17,6 +17,7 @@
#include "first_stage_mount.h"
#include <stdlib.h>
+#include <sys/mount.h>
#include <unistd.h>
#include <chrono>
@@ -29,11 +30,12 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
+#include <fs_avb/fs_avb.h>
#include <fs_mgr.h>
-#include <fs_mgr_avb.h>
#include <fs_mgr_dm_linear.h>
#include <fs_mgr_overlayfs.h>
-#include <liblp/metadata_format.h>
+#include <libgsi/libgsi.h>
+#include <liblp/liblp.h>
#include "devices.h"
#include "switch_root.h"
@@ -41,7 +43,12 @@
#include "uevent_listener.h"
#include "util.h"
+using android::base::ReadFileToString;
+using android::base::Split;
using android::base::Timer;
+using android::fs_mgr::AvbHandle;
+using android::fs_mgr::AvbHashtreeResult;
+using android::fs_mgr::AvbUniquePtr;
using namespace std::literals;
@@ -52,7 +59,7 @@
// ------------------
class FirstStageMount {
public:
- FirstStageMount();
+ FirstStageMount(Fstab fstab);
virtual ~FirstStageMount() = default;
// The factory method to create either FirstStageMountVBootV1 or FirstStageMountVBootV2
@@ -66,110 +73,110 @@
bool InitRequiredDevices();
bool InitMappedDevice(const std::string& verity_device);
bool CreateLogicalPartitions();
- bool MountPartition(fstab_rec* fstab_rec);
+ bool MountPartition(FstabEntry* fstab_entry);
bool MountPartitions();
- bool GetBackingDmLinearDevices();
+ bool TrySwitchSystemAsRoot();
+ bool TrySkipMountingPartitions();
+ bool IsDmLinearEnabled();
+ bool GetDmLinearMetadataDevice();
+ bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata);
+ void UseGsiIfPresent();
- virtual ListenerAction UeventCallback(const Uevent& uevent);
+ ListenerAction UeventCallback(const Uevent& uevent);
// Pure virtual functions.
virtual bool GetDmVerityDevices() = 0;
- virtual bool SetUpDmVerity(fstab_rec* fstab_rec) = 0;
+ virtual bool SetUpDmVerity(FstabEntry* fstab_entry) = 0;
bool need_dm_verity_;
- std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> device_tree_fstab_;
+ Fstab fstab_;
std::string lp_metadata_partition_;
- std::vector<fstab_rec*> mount_fstab_recs_;
std::set<std::string> required_devices_partition_names_;
+ std::string super_partition_name_;
std::unique_ptr<DeviceHandler> device_handler_;
UeventListener uevent_listener_;
};
class FirstStageMountVBootV1 : public FirstStageMount {
public:
- FirstStageMountVBootV1() = default;
+ FirstStageMountVBootV1(Fstab fstab) : FirstStageMount(std::move(fstab)) {}
~FirstStageMountVBootV1() override = default;
protected:
bool GetDmVerityDevices() override;
- bool SetUpDmVerity(fstab_rec* fstab_rec) override;
+ bool SetUpDmVerity(FstabEntry* fstab_entry) override;
};
class FirstStageMountVBootV2 : public FirstStageMount {
public:
friend void SetInitAvbVersionInRecovery();
- FirstStageMountVBootV2();
+ FirstStageMountVBootV2(Fstab fstab);
~FirstStageMountVBootV2() override = default;
protected:
- ListenerAction UeventCallback(const Uevent& uevent) override;
bool GetDmVerityDevices() override;
- bool SetUpDmVerity(fstab_rec* fstab_rec) override;
+ bool SetUpDmVerity(FstabEntry* fstab_entry) override;
bool InitAvbHandle();
- std::string device_tree_vbmeta_parts_;
- FsManagerAvbUniquePtr avb_handle_;
- ByNameSymlinkMap by_name_symlink_map_;
+ std::vector<std::string> vbmeta_partitions_;
+ AvbUniquePtr avb_handle_;
};
// Static Functions
// ----------------
-static inline bool IsDtVbmetaCompatible() {
+static inline bool IsDtVbmetaCompatible(const Fstab& fstab) {
+ if (std::any_of(fstab.begin(), fstab.end(),
+ [](const auto& entry) { return entry.fs_mgr_flags.avb; })) {
+ return true;
+ }
return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta");
}
-static bool inline IsRecoveryMode() {
+static bool IsRecoveryMode() {
return access("/system/bin/recovery", F_OK) == 0;
}
-static inline bool IsDmLinearEnabled() {
- static bool checked = false;
- static bool enabled = false;
- if (checked) {
- return enabled;
+static Fstab ReadFirstStageFstab() {
+ Fstab fstab;
+ if (!ReadFstabFromDt(&fstab)) {
+ if (ReadDefaultFstab(&fstab)) {
+ fstab.erase(std::remove_if(fstab.begin(), fstab.end(),
+ [](const auto& entry) {
+ return !entry.fs_mgr_flags.first_stage_mount;
+ }),
+ fstab.end());
+ } else {
+ LOG(INFO) << "Failed to fstab for first stage mount";
+ }
}
- import_kernel_cmdline(false,
- [](const std::string& key, const std::string& value, bool in_qemu) {
- if (key == "androidboot.logical_partitions" && value == "1") {
- enabled = true;
- }
- });
- checked = true;
- return enabled;
+ return fstab;
}
// Class Definitions
// -----------------
-FirstStageMount::FirstStageMount()
- : need_dm_verity_(false), device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) {
- if (device_tree_fstab_) {
- // Stores device_tree_fstab_->recs[] into mount_fstab_recs_ (vector<fstab_rec*>)
- // for easier manipulation later, e.g., range-base for loop.
- for (int i = 0; i < device_tree_fstab_->num_entries; i++) {
- mount_fstab_recs_.push_back(&device_tree_fstab_->recs[i]);
- }
- } else {
- LOG(INFO) << "Failed to read fstab from device tree";
- }
-
+FirstStageMount::FirstStageMount(Fstab fstab)
+ : need_dm_verity_(false), fstab_(std::move(fstab)), uevent_listener_(16 * 1024 * 1024) {
auto boot_devices = fs_mgr_get_boot_devices();
device_handler_ = std::make_unique<DeviceHandler>(
std::vector<Permissions>{}, std::vector<SysfsPermissions>{}, std::vector<Subsystem>{},
std::move(boot_devices), false);
+
+ super_partition_name_ = fs_mgr_get_super_partition_name();
}
std::unique_ptr<FirstStageMount> FirstStageMount::Create() {
- if (IsDtVbmetaCompatible()) {
- return std::make_unique<FirstStageMountVBootV2>();
+ auto fstab = ReadFirstStageFstab();
+ if (IsDtVbmetaCompatible(fstab)) {
+ return std::make_unique<FirstStageMountVBootV2>(std::move(fstab));
} else {
- return std::make_unique<FirstStageMountVBootV1>();
+ return std::make_unique<FirstStageMountVBootV1>(std::move(fstab));
}
}
bool FirstStageMount::DoFirstStageMount() {
- if (!IsDmLinearEnabled() && mount_fstab_recs_.empty()) {
+ if (!IsDmLinearEnabled() && fstab_.empty()) {
// Nothing to mount.
LOG(INFO) << "First stage mount skipped (missing/incompatible/empty fstab in device tree)";
return true;
@@ -185,16 +192,25 @@
}
bool FirstStageMount::InitDevices() {
- return GetBackingDmLinearDevices() && GetDmVerityDevices() && InitRequiredDevices();
+ return GetDmLinearMetadataDevice() && GetDmVerityDevices() && InitRequiredDevices();
}
-bool FirstStageMount::GetBackingDmLinearDevices() {
+bool FirstStageMount::IsDmLinearEnabled() {
+ for (const auto& entry : fstab_) {
+ if (entry.fs_mgr_flags.logical) return true;
+ }
+ return false;
+}
+
+bool FirstStageMount::GetDmLinearMetadataDevice() {
// Add any additional devices required for dm-linear mappings.
if (!IsDmLinearEnabled()) {
return true;
}
- required_devices_partition_names_.emplace(LP_METADATA_PARTITION_NAME);
+ required_devices_partition_names_.emplace(super_partition_name_);
+ // When booting from live GSI images, userdata is the super device.
+ required_devices_partition_names_.emplace("userdata");
return true;
}
@@ -253,17 +269,49 @@
return true;
}
+bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata) {
+ auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata);
+ for (const auto& partition_name : partition_names) {
+ const auto super_device = android::fs_mgr::GetMetadataSuperBlockDevice(metadata);
+ if (partition_name == android::fs_mgr::GetBlockDevicePartitionName(*super_device)) {
+ continue;
+ }
+ required_devices_partition_names_.emplace(partition_name);
+ }
+ if (required_devices_partition_names_.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;
+}
+
bool FirstStageMount::CreateLogicalPartitions() {
if (!IsDmLinearEnabled()) {
return true;
}
-
if (lp_metadata_partition_.empty()) {
LOG(ERROR) << "Could not locate logical partition tables in partition "
- << LP_METADATA_PARTITION_NAME;
+ << super_partition_name_;
return false;
}
- return android::fs_mgr::CreateLogicalPartitions(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_;
+ return false;
+ }
+ if (!InitDmLinearBackingDevices(*metadata.get())) {
+ return false;
+ }
+ return android::fs_mgr::CreateLogicalPartitions(*metadata.get(), lp_metadata_partition_);
}
ListenerAction FirstStageMount::HandleBlockDevice(const std::string& name, const Uevent& uevent) {
@@ -273,7 +321,7 @@
auto iter = required_devices_partition_names_.find(name);
if (iter != required_devices_partition_names_.end()) {
LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << *iter;
- if (IsDmLinearEnabled() && name == LP_METADATA_PARTITION_NAME) {
+ if (IsDmLinearEnabled() && name == super_partition_name_) {
std::vector<std::string> links = device_handler_->GetBlockDeviceSymlinks(uevent);
lp_metadata_partition_ = links[0];
}
@@ -337,77 +385,205 @@
return true;
}
-bool FirstStageMount::MountPartition(fstab_rec* fstab_rec) {
- if (fs_mgr_is_logical(fstab_rec)) {
- if (!fs_mgr_update_logical_partition(fstab_rec)) {
+bool FirstStageMount::MountPartition(FstabEntry* fstab_entry) {
+ if (fstab_entry->fs_mgr_flags.logical) {
+ if (!fs_mgr_update_logical_partition(fstab_entry)) {
return false;
}
- if (!InitMappedDevice(fstab_rec->blk_device)) {
+ if (!InitMappedDevice(fstab_entry->blk_device)) {
return false;
}
}
- if (!SetUpDmVerity(fstab_rec)) {
- PLOG(ERROR) << "Failed to setup verity for '" << fstab_rec->mount_point << "'";
+ if (!SetUpDmVerity(fstab_entry)) {
+ PLOG(ERROR) << "Failed to setup verity for '" << fstab_entry->mount_point << "'";
return false;
}
- if (fs_mgr_do_mount_one(fstab_rec)) {
- PLOG(ERROR) << "Failed to mount '" << fstab_rec->mount_point << "'";
+ if (fs_mgr_do_mount_one(*fstab_entry)) {
+ if (fstab_entry->fs_mgr_flags.formattable) {
+ PLOG(INFO) << "Failed to mount '" << fstab_entry->mount_point << "', "
+ << "ignoring mount for formattable partition";
+ return true;
+ }
+ PLOG(ERROR) << "Failed to mount '" << fstab_entry->mount_point << "'";
return false;
}
return true;
}
-bool FirstStageMount::MountPartitions() {
- // If system is in the fstab then we're not a system-as-root device, and in
- // this case, we mount system first then pivot to it. From that point on,
- // we are effectively identical to a system-as-root device.
- auto system_partition =
- std::find_if(mount_fstab_recs_.begin(), mount_fstab_recs_.end(),
- [](const auto& rec) { return rec->mount_point == "/system"s; });
- if (system_partition != mount_fstab_recs_.end()) {
- if (!MountPartition(*system_partition)) {
- return false;
- }
-
- SwitchRoot("/system");
-
- mount_fstab_recs_.erase(system_partition);
- }
-
- for (auto fstab_rec : mount_fstab_recs_) {
- if (!MountPartition(fstab_rec) && !fs_mgr_is_nofail(fstab_rec)) {
- return false;
+// If system is in the fstab then we're not a system-as-root device, and in
+// 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))) {
+ fstab_.erase(metadata_partition);
+ UseGsiIfPresent();
}
}
- fs_mgr_overlayfs_mount_all();
+ auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
+ return entry.mount_point == "/system";
+ });
+
+ if (system_partition == fstab_.end()) return true;
+
+ bool mounted = false;
+ bool no_fail = false;
+ for (auto it = system_partition; it != fstab_.end();) {
+ if (it->mount_point != "/system") {
+ break;
+ }
+ no_fail |= (it->fs_mgr_flags).no_fail;
+ if (MountPartition(&(*it))) {
+ mounted = true;
+ SwitchRoot("/system");
+ break;
+ }
+ it++;
+ }
+
+ if (!mounted && !no_fail) {
+ LOG(ERROR) << "Failed to mount /system";
+ return false;
+ }
+
+ auto it = std::remove_if(fstab_.begin(), fstab_.end(),
+ [](const auto& entry) { return entry.mount_point == "/system"; });
+ fstab_.erase(it, fstab_.end());
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.
+bool FirstStageMount::TrySkipMountingPartitions() {
+ constexpr const char kSkipMountConfig[] = "/system/etc/init/config/skip_mount.cfg";
+
+ std::string skip_config;
+ if (!ReadFileToString(kSkipMountConfig, &skip_config)) {
+ return true;
+ }
+
+ for (const auto& skip_mount_point : Split(skip_config, "\n")) {
+ if (skip_mount_point.empty()) {
+ continue;
+ }
+ auto it = std::remove_if(fstab_.begin(), fstab_.end(),
+ [&skip_mount_point](const auto& entry) {
+ return entry.mount_point == skip_mount_point;
+ });
+ fstab_.erase(it, fstab_.end());
+ LOG(INFO) << "Skip mounting partition: " << skip_mount_point;
+ }
+
+ return true;
+}
+
+bool FirstStageMount::MountPartitions() {
+ if (!TrySwitchSystemAsRoot()) return false;
+
+ if (!TrySkipMountingPartitions()) return false;
+
+ for (auto it = fstab_.begin(); it != fstab_.end();) {
+ bool mounted = false;
+ bool no_fail = false;
+ auto start_mount_point = it->mount_point;
+ do {
+ no_fail |= (it->fs_mgr_flags).no_fail;
+ if (!mounted)
+ mounted = MountPartition(&(*it));
+ else
+ LOG(INFO) << "Skip already-mounted partition: " << start_mount_point;
+ it++;
+ } while (it != fstab_.end() && it->mount_point == start_mount_point);
+
+ if (!mounted && !no_fail) {
+ LOG(ERROR) << start_mount_point << " mounted unsuccessfully but it is required!";
+ return false;
+ }
+ }
+
+ // heads up for instantiating required device(s) for overlayfs logic
+ 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);
+ uevent_listener_.Poll(uevent_callback, 10s);
+ } else {
+ InitMappedDevice(device);
+ }
+ }
+
+ fs_mgr_overlayfs_mount_all(&fstab_);
+
+ return true;
+}
+
+void FirstStageMount::UseGsiIfPresent() {
+ std::string metadata_file, error;
+
+ if (!android::gsi::CanBootIntoGsi(&metadata_file, &error)) {
+ LOG(INFO) << "GSI " << 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 (!android::fs_mgr::CreateLogicalPartitions(*metadata.get(), "/dev/block/by-name/userdata")) {
+ LOG(ERROR) << "GSI partition layout could not be instantiated";
+ return;
+ }
+
+ if (!android::gsi::MarkSystemAsGsi()) {
+ PLOG(ERROR) << "GSI 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);
+ }
+ fstab_.emplace_back(BuildGsiSystemFstabEntry());
+}
+
bool FirstStageMountVBootV1::GetDmVerityDevices() {
std::string verity_loc_device;
need_dm_verity_ = false;
- for (auto fstab_rec : mount_fstab_recs_) {
+ for (const auto& fstab_entry : fstab_) {
// Don't allow verifyatboot in the first stage.
- if (fs_mgr_is_verifyatboot(fstab_rec)) {
+ if (fstab_entry.fs_mgr_flags.verify_at_boot) {
LOG(ERROR) << "Partitions can't be verified at boot";
return false;
}
// Checks for verified partitions.
- if (fs_mgr_is_verified(fstab_rec)) {
+ 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_rec->verity_loc) {
+ if (!fstab_entry.verity_loc.empty()) {
if (verity_loc_device.empty()) {
- verity_loc_device = fstab_rec->verity_loc;
- } else if (verity_loc_device != fstab_rec->verity_loc) {
+ 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_rec->verity_loc;
+ << fstab_entry.verity_loc;
return false;
}
}
@@ -415,8 +591,10 @@
// Includes the partition names of fstab records and verity_loc_device (if any).
// Notes that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used.
- for (auto fstab_rec : mount_fstab_recs_) {
- required_devices_partition_names_.emplace(basename(fstab_rec->blk_device));
+ 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()));
+ }
}
if (!verity_loc_device.empty()) {
@@ -426,19 +604,19 @@
return true;
}
-bool FirstStageMountVBootV1::SetUpDmVerity(fstab_rec* fstab_rec) {
- if (fs_mgr_is_verified(fstab_rec)) {
- int ret = fs_mgr_setup_verity(fstab_rec, false /* wait_for_verity_dev */);
+bool FirstStageMountVBootV1::SetUpDmVerity(FstabEntry* fstab_entry) {
+ if (fstab_entry->fs_mgr_flags.verify) {
+ int ret = fs_mgr_setup_verity(fstab_entry, false /* wait_for_verity_dev */);
switch (ret) {
case FS_MGR_SETUP_VERITY_SKIPPED:
case FS_MGR_SETUP_VERITY_DISABLED:
- LOG(INFO) << "Verity disabled/skipped for '" << fstab_rec->mount_point << "'";
+ LOG(INFO) << "Verity disabled/skipped for '" << fstab_entry->mount_point << "'";
return true;
case FS_MGR_SETUP_VERITY_SUCCESS:
// The exact block device name (fstab_rec->blk_device) is changed to
// "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init
// first stage.
- return InitMappedDevice(fstab_rec->blk_device);
+ return InitMappedDevice(fstab_entry->blk_device);
default:
return false;
}
@@ -446,22 +624,27 @@
return true; // Returns true to mount the partition.
}
-// FirstStageMountVBootV2 constructor.
-// Gets the vbmeta partitions from device tree.
-// /{
-// firmware {
-// android {
-// vbmeta {
-// compatible = "android,vbmeta";
-// parts = "vbmeta,boot,system,vendor"
-// };
-// };
-// };
-// }
-FirstStageMountVBootV2::FirstStageMountVBootV2() : avb_handle_(nullptr) {
- if (!read_android_dt_file("vbmeta/parts", &device_tree_vbmeta_parts_)) {
- PLOG(ERROR) << "Failed to read vbmeta/parts from device tree";
- return;
+// First retrieve any vbmeta partitions from device tree (legacy) then read through the fstab
+// for any further vbmeta partitions.
+FirstStageMountVBootV2::FirstStageMountVBootV2(Fstab fstab)
+ : FirstStageMount(std::move(fstab)), avb_handle_(nullptr) {
+ std::string device_tree_vbmeta_parts;
+ read_android_dt_file("vbmeta/parts", &device_tree_vbmeta_parts);
+
+ for (auto&& partition : Split(device_tree_vbmeta_parts, ",")) {
+ if (!partition.empty()) {
+ vbmeta_partitions_.emplace_back(std::move(partition));
+ }
+ }
+
+ for (const auto& entry : fstab_) {
+ if (!entry.vbmeta_partition.empty()) {
+ vbmeta_partitions_.emplace_back(entry.vbmeta_partition);
+ }
+ }
+
+ if (vbmeta_partitions_.empty()) {
+ LOG(ERROR) << "Failed to read vbmeta partitions.";
}
}
@@ -471,30 +654,27 @@
std::set<std::string> logical_partitions;
// fstab_rec->blk_device has A/B suffix.
- for (auto fstab_rec : mount_fstab_recs_) {
- if (fs_mgr_is_avb(fstab_rec)) {
+ for (const auto& fstab_entry : fstab_) {
+ if (fstab_entry.fs_mgr_flags.avb) {
need_dm_verity_ = true;
}
- if (fs_mgr_is_logical(fstab_rec)) {
+ if (fstab_entry.fs_mgr_flags.logical) {
// Don't try to find logical partitions via uevent regeneration.
- logical_partitions.emplace(basename(fstab_rec->blk_device));
+ logical_partitions.emplace(basename(fstab_entry.blk_device.c_str()));
} else {
- required_devices_partition_names_.emplace(basename(fstab_rec->blk_device));
+ required_devices_partition_names_.emplace(basename(fstab_entry.blk_device.c_str()));
}
}
- // libavb verifies AVB metadata on all verified partitions at once.
- // e.g., The device_tree_vbmeta_parts_ will be "vbmeta,boot,system,vendor"
- // for libavb to verify metadata, even if there is only /vendor in the
- // above mount_fstab_recs_.
+ // Any partitions needed for verifying the partitions used in first stage mount, e.g. vbmeta
+ // must be provided as vbmeta_partitions.
if (need_dm_verity_) {
- if (device_tree_vbmeta_parts_.empty()) {
- LOG(ERROR) << "Missing vbmeta parts in device tree";
+ if (vbmeta_partitions_.empty()) {
+ LOG(ERROR) << "Missing vbmeta partitions";
return false;
}
- std::vector<std::string> partitions = android::base::Split(device_tree_vbmeta_parts_, ",");
std::string ab_suffix = fs_mgr_get_slot_suffix();
- for (const auto& partition : partitions) {
+ for (const auto& partition : vbmeta_partitions_) {
std::string partition_name = partition + ab_suffix;
if (logical_partitions.count(partition_name)) {
continue;
@@ -509,46 +689,19 @@
return true;
}
-ListenerAction FirstStageMountVBootV2::UeventCallback(const Uevent& uevent) {
- // Check if this uevent corresponds to one of the required partitions and store its symlinks if
- // so, in order to create FsManagerAvbHandle later.
- // Note that the parent callback removes partitions from the list of required partitions
- // as it finds them, so this must happen first.
- if (!uevent.partition_name.empty() &&
- required_devices_partition_names_.find(uevent.partition_name) !=
- required_devices_partition_names_.end()) {
- // GetBlockDeviceSymlinks() will return three symlinks at most, depending on
- // the content of uevent. by-name symlink will be at [0] if uevent->partition_name
- // is not empty. e.g.,
- // - /dev/block/platform/soc.0/f9824900.sdhci/by-name/modem
- // - /dev/block/platform/soc.0/f9824900.sdhci/mmcblk0p1
- std::vector<std::string> links = device_handler_->GetBlockDeviceSymlinks(uevent);
- if (!links.empty()) {
- auto [it, inserted] = by_name_symlink_map_.emplace(uevent.partition_name, links[0]);
- if (!inserted) {
- LOG(ERROR) << "Partition '" << uevent.partition_name
- << "' already existed in the by-name symlink map with a value of '"
- << it->second << "', new value '" << links[0] << "' will be ignored.";
- }
- }
- }
-
- return FirstStageMount::UeventCallback(uevent);
-}
-
-bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) {
- if (fs_mgr_is_avb(fstab_rec)) {
+bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) {
+ if (fstab_entry->fs_mgr_flags.avb) {
if (!InitAvbHandle()) return false;
- SetUpAvbHashtreeResult hashtree_result =
- avb_handle_->SetUpAvbHashtree(fstab_rec, false /* wait_for_verity_dev */);
+ AvbHashtreeResult hashtree_result =
+ avb_handle_->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */);
switch (hashtree_result) {
- case SetUpAvbHashtreeResult::kDisabled:
+ case AvbHashtreeResult::kDisabled:
return true; // Returns true to mount the partition.
- case SetUpAvbHashtreeResult::kSuccess:
+ case AvbHashtreeResult::kSuccess:
// The exact block device name (fstab_rec->blk_device) is changed to
// "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init
// first stage.
- return InitMappedDevice(fstab_rec->blk_device);
+ return InitMappedDevice(fstab_entry->blk_device);
default:
return false;
}
@@ -559,16 +712,10 @@
bool FirstStageMountVBootV2::InitAvbHandle() {
if (avb_handle_) return true; // Returns true if the handle is already initialized.
- if (by_name_symlink_map_.empty()) {
- LOG(ERROR) << "by_name_symlink_map_ is empty";
- return false;
- }
-
- avb_handle_ = FsManagerAvbHandle::Open(std::move(by_name_symlink_map_));
- by_name_symlink_map_.clear(); // Removes all elements after the above std::move().
+ avb_handle_ = AvbHandle::Open();
if (!avb_handle_) {
- PLOG(ERROR) << "Failed to open FsManagerAvbHandle";
+ PLOG(ERROR) << "Failed to open AvbHandle";
return false;
}
// Sets INIT_AVB_VERSION here for init to set ro.boot.avb_version in the second stage.
@@ -600,26 +747,27 @@
return;
}
- if (!IsDtVbmetaCompatible()) {
+ auto fstab = ReadFirstStageFstab();
+
+ if (!IsDtVbmetaCompatible(fstab)) {
LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not vbmeta compatible)";
return;
}
- // Initializes required devices for the subsequent FsManagerAvbHandle::Open()
+ // Initializes required devices for the subsequent AvbHandle::Open()
// to verify AVB metadata on all partitions in the verified chain.
// We only set INIT_AVB_VERSION when the AVB verification succeeds, i.e., the
// Open() function returns a valid handle.
// We don't need to mount partitions here in recovery mode.
- FirstStageMountVBootV2 avb_first_mount;
+ FirstStageMountVBootV2 avb_first_mount(std::move(fstab));
if (!avb_first_mount.InitDevices()) {
LOG(ERROR) << "Failed to init devices for INIT_AVB_VERSION";
return;
}
- FsManagerAvbUniquePtr avb_handle =
- FsManagerAvbHandle::Open(std::move(avb_first_mount.by_name_symlink_map_));
+ AvbUniquePtr avb_handle = AvbHandle::Open();
if (!avb_handle) {
- PLOG(ERROR) << "Failed to open FsManagerAvbHandle for INIT_AVB_VERSION";
+ PLOG(ERROR) << "Failed to open AvbHandle for INIT_AVB_VERSION";
return;
}
setenv("INIT_AVB_VERSION", avb_handle->avb_version().c_str(), 1);
diff --git a/init/grab-bootchart.sh b/init/grab-bootchart.sh
index c4ff6df..2c56698 100755
--- a/init/grab-bootchart.sh
+++ b/init/grab-bootchart.sh
@@ -17,6 +17,6 @@
adb "${@}" pull $LOGROOT/$f $TMPDIR/$f 2>&1 > /dev/null
done
(cd $TMPDIR && tar -czf $TARBALL $FILES)
-bootchart ${TMPDIR}/${TARBALL}
-gnome-open ${TARBALL%.tgz}.png
+pybootchartgui ${TMPDIR}/${TARBALL}
+xdg-open ${TARBALL%.tgz}.png
echo "Clean up ${TMPDIR}/ and ./${TARBALL%.tgz}.png when done"
diff --git a/init/host_init_stubs.cpp b/init/host_init_stubs.cpp
index 8866bdc..b85e54a 100644
--- a/init/host_init_stubs.cpp
+++ b/init/host_init_stubs.cpp
@@ -30,6 +30,9 @@
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;
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index 0af11f6..63ceead 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -39,6 +39,7 @@
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);
diff --git a/init/init.cpp b/init/init.cpp
index 16564f4..d360fdd 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -19,6 +19,7 @@
#include <dirent.h>
#include <fcntl.h>
#include <pthread.h>
+#include <seccomp_policy.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
@@ -38,10 +39,17 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <cutils/android_reboot.h>
+#include <fs_mgr_vendor_overlay.h>
#include <keyutils.h>
#include <libavb/libavb.h>
+#include <selinux/android.h>
+
+#ifndef RECOVERY
+#include <binder/ProcessState.h>
+#endif
#include "action_parser.h"
+#include "boringssl_self_test.h"
#include "epoll.h"
#include "first_stage_mount.h"
#include "import_parser.h"
@@ -52,7 +60,6 @@
#include "security.h"
#include "selinux.h"
#include "sigchld_handler.h"
-#include "ueventd.h"
#include "util.h"
using namespace std::chrono_literals;
@@ -102,6 +109,14 @@
return parser;
}
+// parser that only accepts new services
+Parser CreateServiceOnlyParser(ServiceList& service_list) {
+ Parser parser;
+
+ parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list, subcontexts));
+ return parser;
+}
+
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
Parser parser = CreateParser(action_manager, service_list);
@@ -181,23 +196,34 @@
}
}
-static std::optional<boot_clock::time_point> RestartProcesses() {
- std::optional<boot_clock::time_point> next_process_restart_time;
+static std::optional<boot_clock::time_point> HandleProcessActions() {
+ std::optional<boot_clock::time_point> next_process_action_time;
for (const auto& s : ServiceList::GetInstance()) {
+ if ((s->flags() & SVC_RUNNING) && s->timeout_period()) {
+ auto timeout_time = s->time_started() + *s->timeout_period();
+ if (boot_clock::now() > timeout_time) {
+ s->Timeout();
+ } else {
+ if (!next_process_action_time || timeout_time < *next_process_action_time) {
+ next_process_action_time = timeout_time;
+ }
+ }
+ }
+
if (!(s->flags() & SVC_RESTARTING)) continue;
- auto restart_time = s->time_started() + 5s;
+ auto restart_time = s->time_started() + s->restart_period();
if (boot_clock::now() > restart_time) {
if (auto result = s->Start(); !result) {
LOG(ERROR) << "Could not restart process '" << s->name() << "': " << result.error();
}
} else {
- if (!next_process_restart_time || restart_time < *next_process_restart_time) {
- next_process_restart_time = restart_time;
+ if (!next_process_action_time || restart_time < *next_process_action_time) {
+ next_process_action_time = restart_time;
}
}
}
- return next_process_restart_time;
+ return next_process_action_time;
}
static Result<Success> DoControlStart(Service* service) {
@@ -340,12 +366,12 @@
if (!android::base::GetBoolProperty("ro.oem_unlock_supported", false)) {
return;
}
-
- std::string value = GetProperty("ro.boot.verifiedbootstate", "");
-
- if (!value.empty()) {
- property_set("ro.boot.flash.locked", value == "orange" ? "0" : "1");
- }
+ 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() {
@@ -413,6 +439,24 @@
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();
+}
+
// Set the UDC controller for the ConfigFS USB Gadgets.
// Read the UDC controller in use from "/sys/class/udc".
// In case of multiple UDC controllers select the first one.
@@ -548,41 +592,27 @@
RebootSystem(ANDROID_RB_RESTART2, "bootloader");
}
-static void InitKernelLogging(char* argv[]) {
- // Make stdin/stdout/stderr all point to /dev/null.
- int fd = open("/sys/fs/selinux/null", O_RDWR);
- if (fd == -1) {
- int saved_errno = errno;
- android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
- errno = saved_errno;
- PLOG(FATAL) << "Couldn't open /sys/fs/selinux/null";
- }
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- if (fd > 2) close(fd);
-
- android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
+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!";
+ }
+ });
}
-int main(int argc, char** argv) {
- if (!strcmp(basename(argv[0]), "ueventd")) {
- return ueventd_main(argc, argv);
- }
-
- if (argc > 1 && !strcmp(argv[1], "subcontext")) {
- android::base::InitLogging(argv, &android::base::KernelLogger);
- const BuiltinFunctionMap function_map;
- return SubcontextMain(argc, argv, &function_map);
- }
-
+int SecondStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
}
- InitKernelLogging(argv);
+ // We need to set up stdin/stdout/stderr again now that we're running in init's context.
+ InitKernelLogging(argv, InitAborter);
LOG(INFO) << "init second stage started!";
+ // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
+ GlobalSeccomp();
+
// Set up a session keyring that all processes will have access to. It
// will hold things like FBE encryption keys. No process should override
// its session keyring.
@@ -628,6 +658,7 @@
InstallSignalFdHandler(&epoll);
property_load_boot_defaults();
+ fs_mgr_vendor_overlay_mount_all();
export_oem_lock_status();
StartPropertyService(&epoll);
set_usb_controller();
@@ -669,10 +700,16 @@
// 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") {
@@ -700,12 +737,12 @@
}
if (!(waiting_for_prop || Service::is_exec_service_running())) {
if (!shutting_down) {
- auto next_process_restart_time = RestartProcesses();
+ auto next_process_action_time = HandleProcessActions();
// If there's a process that needs restarting, wake up in time for that.
- if (next_process_restart_time) {
+ if (next_process_action_time) {
epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>(
- *next_process_restart_time - boot_clock::now());
+ *next_process_action_time - boot_clock::now());
if (*epoll_timeout < 0ms) epoll_timeout = 0ms;
}
}
diff --git a/init/init.h b/init/init.h
index f244ad7..a76da20 100644
--- a/init/init.h
+++ b/init/init.h
@@ -38,6 +38,7 @@
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);
@@ -49,7 +50,7 @@
void ResetWaitForProp();
-int main(int argc, char** argv);
+int SecondStageMain(int argc, char** argv);
} // namespace init
} // namespace android
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
deleted file mode 100644
index 466cde3..0000000
--- a/init/init_first_stage.cpp
+++ /dev/null
@@ -1,169 +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 <paths.h>
-#include <seccomp_policy.h>
-#include <stdlib.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <string>
-#include <vector>
-
-#include <android-base/chrono_utils.h>
-#include <android-base/logging.h>
-#include <cutils/android_reboot.h>
-#include <private/android_filesystem_config.h>
-#include <selinux/android.h>
-
-#include "first_stage_mount.h"
-#include "reboot_utils.h"
-#include "selinux.h"
-#include "util.h"
-
-using android::base::boot_clock;
-
-namespace android {
-namespace init {
-
-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!";
- }
- });
-}
-
-int main(int argc, char** argv) {
- if (REBOOT_BOOTLOADER_ON_PANIC) {
- InstallRebootSignalHandlers();
- }
-
- boot_clock::time_point start_time = boot_clock::now();
-
- std::vector<std::pair<std::string, int>> errors;
-#define CHECKCALL(x) \
- if (x != 0) errors.emplace_back(#x " failed", errno);
-
- // Clear the umask.
- umask(0);
-
- CHECKCALL(clearenv());
- CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1));
- // Get the basic filesystem setup we need put together in the initramdisk
- // on / and then we'll let the rc file figure out the rest.
- CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
- CHECKCALL(mkdir("/dev/pts", 0755));
- CHECKCALL(mkdir("/dev/socket", 0755));
- CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));
-#define MAKE_STR(x) __STRING(x)
- CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)));
-#undef MAKE_STR
- // Don't expose the raw commandline to unprivileged processes.
- CHECKCALL(chmod("/proc/cmdline", 0440));
- gid_t groups[] = {AID_READPROC};
- CHECKCALL(setgroups(arraysize(groups), groups));
- CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
- CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL));
-
- CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11)));
-
- if constexpr (WORLD_WRITABLE_KMSG) {
- CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11)));
- }
-
- CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)));
- CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)));
-
- // This is needed for log wrapper, which gets called before ueventd runs.
- CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2)));
- CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3)));
-
- // Mount staging areas for devices managed by vold
- // See storage config details at http://source.android.com/devices/storage/
- CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
- "mode=0755,uid=0,gid=1000"));
- // /mnt/vendor is used to mount vendor-specific partitions that can not be
- // part of the vendor partition, e.g. because they are mounted read-write.
- CHECKCALL(mkdir("/mnt/vendor", 0755));
- // /mnt/product is used to mount product-specific partitions that can not be
- // part of the product partition, e.g. because they are mounted read-write.
- CHECKCALL(mkdir("/mnt/product", 0755));
-
-#undef CHECKCALL
-
- // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
- // talk to the outside world...
- android::base::InitLogging(argv, &android::base::KernelLogger, [](const char*) {
- RebootSystem(ANDROID_RB_RESTART2, "bootloader");
- });
-
- if (!errors.empty()) {
- for (const auto& [error_string, error_errno] : errors) {
- LOG(ERROR) << error_string << " " << strerror(error_errno);
- }
- LOG(FATAL) << "Init encountered errors starting first stage, aborting";
- }
-
- LOG(INFO) << "init first stage started!";
-
- if (!DoFirstStageMount()) {
- LOG(FATAL) << "Failed to mount required partitions early ...";
- }
-
- SetInitAvbVersionInRecovery();
-
- // Does this need to be done in first stage init or can it be done later?
- // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
- GlobalSeccomp();
-
- // Set up SELinux, loading the SELinux policy.
- SelinuxSetupKernelLogging();
- SelinuxInitialize();
-
- // We're in the kernel domain and want to transition to the init domain when we exec second
- // stage init. File systems that store SELabels in their xattrs, such as ext4 do not need an
- // explicit restorecon here, but other file systems do. In particular, this is needed for
- // ramdisks such as the recovery image for A/B devices.
- if (selinux_android_restorecon("/system/bin/init", 0) == -1) {
- PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
- }
-
- 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);
-
- const char* path = "/system/bin/init";
- const char* args[] = {path, nullptr};
- execv(path, const_cast<char**>(args));
-
- // execv() only returns if an error happened, in which case we
- // panic and never fall through this conditional.
- PLOG(FATAL) << "execv(\"" << path << "\") failed";
-
- return 1;
-}
-
-} // namespace init
-} // namespace android
-
-int main(int argc, char** argv) {
- return android::init::main(argc, argv);
-}
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 0f9635f..c2f0c41 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -17,7 +17,6 @@
#include <functional>
#include <android-base/file.h>
-#include <android-base/test_utils.h>
#include <gtest/gtest.h>
#include "action.h"
diff --git a/init/keychords.cpp b/init/keychords.cpp
index b8c1cfd..f5ac44f 100644
--- a/init/keychords.cpp
+++ b/init/keychords.cpp
@@ -41,7 +41,7 @@
Keychords::~Keychords() noexcept {
if (inotify_fd_ >= 0) {
- epoll_->UnregisterHandler(inotify_fd_);
+ epoll_->UnregisterHandler(inotify_fd_).IgnoreError();
::close(inotify_fd_);
}
while (!registration_.empty()) GeteventCloseDevice(registration_.begin()->first);
@@ -186,7 +186,11 @@
current_ |= mask & available & set;
LambdaCheck();
}
- epoll_->RegisterHandler(fd, [this, fd]() { this->LambdaHandler(fd); });
+ if (auto result = epoll_->RegisterHandler(fd, [this, fd]() { this->LambdaHandler(fd); });
+ !result) {
+ LOG(WARNING) << "Could not register keychord epoll handler: " << result.error();
+ return false;
+ }
return true;
}
@@ -208,7 +212,7 @@
auto it = registration_.find(device);
if (it == registration_.end()) return;
auto fd = (*it).second;
- epoll_->UnregisterHandler(fd);
+ epoll_->UnregisterHandler(fd).IgnoreError();
registration_.erase(it);
::close(fd);
}
@@ -266,7 +270,11 @@
}
if (inotify_fd_ >= 0) {
- epoll_->RegisterHandler(inotify_fd_, [this]() { this->InotifyHandler(); });
+ if (auto result =
+ epoll_->RegisterHandler(inotify_fd_, [this]() { this->InotifyHandler(); });
+ !result) {
+ LOG(WARNING) << "Could not register keychord epoll handler: " << result.error();
+ }
}
}
diff --git a/init/keychords_test.cpp b/init/keychords_test.cpp
index c8c47a8..e5a6fd3 100644
--- a/init/keychords_test.cpp
+++ b/init/keychords_test.cpp
@@ -47,9 +47,9 @@
public:
EventHandler();
EventHandler(const EventHandler&) = delete;
- EventHandler(EventHandler&&);
+ EventHandler(EventHandler&&) noexcept;
EventHandler& operator=(const EventHandler&) = delete;
- EventHandler& operator=(EventHandler&&);
+ EventHandler& operator=(EventHandler&&) noexcept;
~EventHandler() noexcept;
bool init();
@@ -64,11 +64,11 @@
EventHandler::EventHandler() : fd_(-1) {}
-EventHandler::EventHandler(EventHandler&& rval) : fd_(rval.fd_) {
+EventHandler::EventHandler(EventHandler&& rval) noexcept : fd_(rval.fd_) {
rval.fd_ = -1;
}
-EventHandler& EventHandler::operator=(EventHandler&& rval) {
+EventHandler& EventHandler::operator=(EventHandler&& rval) noexcept {
fd_ = rval.fd_;
rval.fd_ = -1;
return *this;
@@ -213,7 +213,7 @@
}
void TestFrame::RelaxForMs(std::chrono::milliseconds wait) {
- epoll_.Wait(wait);
+ epoll_.Wait(wait).IgnoreError();
}
void TestFrame::SetChord(int key, bool value) {
diff --git a/init/main.cpp b/init/main.cpp
index 9ed451b..2ce46ef 100644
--- a/init/main.cpp
+++ b/init/main.cpp
@@ -14,8 +14,65 @@
* limitations under the License.
*/
+#include "builtins.h"
+#include "first_stage_init.h"
#include "init.h"
+#include "selinux.h"
+#include "subcontext.h"
+#include "ueventd.h"
+
+#include <android-base/logging.h>
+
+#if __has_feature(address_sanitizer)
+#include <sanitizer/asan_interface.h>
+#endif
+
+#if __has_feature(address_sanitizer)
+// Load asan.options if it exists since these are not yet in the environment.
+// Always ensure detect_container_overflow=0 as there are false positives with this check.
+// Always ensure abort_on_error=1 to ensure we reboot to bootloader for development builds.
+extern "C" const char* __asan_default_options() {
+ return "include_if_exists=/system/asan.options:detect_container_overflow=0:abort_on_error=1";
+}
+
+__attribute__((no_sanitize("address", "memory", "thread", "undefined"))) extern "C" void
+__sanitizer_report_error_summary(const char* summary) {
+ LOG(ERROR) << "Init (error summary): " << summary;
+}
+
+__attribute__((no_sanitize("address", "memory", "thread", "undefined"))) static void
+AsanReportCallback(const char* str) {
+ LOG(ERROR) << "Init: " << str;
+}
+#endif
+
+using namespace android::init;
int main(int argc, char** argv) {
- android::init::main(argc, argv);
+#if __has_feature(address_sanitizer)
+ __asan_set_error_report_callback(AsanReportCallback);
+#endif
+
+ if (!strcmp(basename(argv[0]), "ueventd")) {
+ return ueventd_main(argc, argv);
+ }
+
+ if (argc > 1) {
+ if (!strcmp(argv[1], "subcontext")) {
+ android::base::InitLogging(argv, &android::base::KernelLogger);
+ const BuiltinFunctionMap function_map;
+
+ return SubcontextMain(argc, argv, &function_map);
+ }
+
+ if (!strcmp(argv[1], "selinux_setup")) {
+ return SetupSelinux(argv);
+ }
+
+ if (!strcmp(argv[1], "second_stage")) {
+ return SecondStageMain(argc, argv);
+ }
+ }
+
+ return FirstStageMain(argc, argv);
}
diff --git a/init/modalias_handler.cpp b/init/modalias_handler.cpp
index 1e0db57..c61c210 100644
--- a/init/modalias_handler.cpp
+++ b/init/modalias_handler.cpp
@@ -50,7 +50,7 @@
}
// Key is striped module name to match names in alias file
- std::size_t start = args[0].find_last_of("/");
+ 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);
diff --git a/init/parser.cpp b/init/parser.cpp
index fa0fd11..bbfbdc6 100644
--- a/init/parser.cpp
+++ b/init/parser.cpp
@@ -53,7 +53,12 @@
int section_start_line = -1;
std::vector<std::string> args;
+ // If we encounter a bad section start, there is no valid parser object to parse the subsequent
+ // sections, so we must suppress errors until the next valid section is found.
+ bool bad_section_found = false;
+
auto end_section = [&] {
+ bad_section_found = false;
if (section_parser == nullptr) return;
if (auto result = section_parser->EndSection(); !result) {
@@ -101,6 +106,7 @@
parse_error_count_++;
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
section_parser = nullptr;
+ bad_section_found = true;
}
} else if (section_parser) {
if (auto result = section_parser->ParseLineSection(std::move(args), state.line);
@@ -108,7 +114,7 @@
parse_error_count_++;
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
}
- } else {
+ } else if (!bad_section_found) {
parse_error_count_++;
LOG(ERROR) << filename << ": " << state.line
<< ": Invalid section keyword found";
diff --git a/init/parser.h b/init/parser.h
index 2454b6a..f30bda7 100644
--- a/init/parser.h
+++ b/init/parser.h
@@ -72,6 +72,7 @@
Parser();
bool ParseConfig(const std::string& path);
+ bool ParseConfigFile(const std::string& path);
void AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser);
void AddSingleLineParser(const std::string& prefix, LineCallback callback);
@@ -82,7 +83,6 @@
private:
void ParseData(const std::string& filename, std::string* data);
- bool ParseConfigFile(const std::string& path);
bool ParseConfigDir(const std::string& path);
std::map<std::string, std::unique_ptr<SectionParser>> section_parsers_;
diff --git a/init/persistent_properties_test.cpp b/init/persistent_properties_test.cpp
index 872e9a1..13796a6 100644
--- a/init/persistent_properties_test.cpp
+++ b/init/persistent_properties_test.cpp
@@ -20,7 +20,7 @@
#include <vector>
-#include <android-base/test_utils.h>
+#include <android-base/file.h>
#include <gtest/gtest.h>
#include "util.h"
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 5c8b92a..3199d45 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -111,6 +111,22 @@
LOG(FATAL) << "Failed to load serialized property info file";
}
}
+
+bool CanReadProperty(const std::string& source_context, const std::string& name) {
+ const char* target_context = nullptr;
+ property_info_area->GetPropertyInfo(name.c_str(), &target_context, nullptr);
+
+ PropertyAuditData audit_data;
+
+ audit_data.name = name.c_str();
+
+ ucred cr = {.pid = 0, .uid = 0, .gid = 0};
+ audit_data.cr = &cr;
+
+ return selinux_check_access(source_context.c_str(), target_context, "file", "read",
+ &audit_data) == 0;
+}
+
static bool CheckMacPerms(const std::string& name, const char* target_context,
const char* source_context, const ucred& cr) {
if (!target_context || !source_context) {
@@ -683,22 +699,6 @@
}
}
-void property_load_boot_defaults() {
- if (!load_properties_from_file("/system/etc/prop.default", NULL)) {
- // Try recovery path
- if (!load_properties_from_file("/prop.default", NULL)) {
- // Try legacy path
- load_properties_from_file("/default.prop", NULL);
- }
- }
- load_properties_from_file("/product/build.prop", NULL);
- load_properties_from_file("/product_services/build.prop", NULL);
- load_properties_from_file("/odm/default.prop", NULL);
- load_properties_from_file("/vendor/default.prop", NULL);
-
- update_sys_usb_config();
-}
-
static void load_override_properties() {
if (ALLOW_LOCAL_PROP_OVERRIDE) {
load_properties_from_file("/data/local.prop", NULL);
@@ -746,7 +746,7 @@
return;
}
- int fd = open(rec->blk_device, O_RDONLY);
+ int fd = open(rec->blk_device, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
PLOG(ERROR) << "error opening block device " << rec->blk_device;
return;
@@ -763,12 +763,29 @@
close(fd);
}
-void load_system_props() {
+void property_load_boot_defaults() {
+ // TODO(b/117892318): merge prop.default and build.prop files into one
+ // TODO(b/122864654): read the prop files from all partitions and then
+ // resolve the duplication by their origin so that RO and non-RO properties
+ // have a consistent overriding order.
+ if (!load_properties_from_file("/system/etc/prop.default", NULL)) {
+ // Try recovery path
+ if (!load_properties_from_file("/prop.default", NULL)) {
+ // Try legacy path
+ load_properties_from_file("/default.prop", NULL);
+ }
+ }
+ load_properties_from_file("/product/build.prop", NULL);
+ load_properties_from_file("/product_services/build.prop", NULL);
+ load_properties_from_file("/odm/default.prop", NULL);
+ load_properties_from_file("/vendor/default.prop", NULL);
load_properties_from_file("/system/build.prop", NULL);
load_properties_from_file("/odm/build.prop", NULL);
load_properties_from_file("/vendor/build.prop", NULL);
load_properties_from_file("/factory/factory.prop", "ro.*");
load_recovery_id_prop();
+
+ update_sys_usb_config();
}
static int SelinuxAuditCallback(void* data, security_class_t /*cls*/, char* buf, size_t len) {
diff --git a/init/property_service.h b/init/property_service.h
index cacd987..9022f5a 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -26,6 +26,8 @@
namespace android {
namespace init {
+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,
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 2f88121..5b90969 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -20,9 +20,11 @@
#include <fcntl.h>
#include <linux/fs.h>
#include <mntent.h>
+#include <linux/loop.h>
#include <sys/cdefs.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
+#include <sys/swap.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
@@ -55,9 +57,11 @@
#include "service.h"
#include "sigchld_handler.h"
+using android::base::GetBoolProperty;
using android::base::Split;
using android::base::StringPrintf;
using android::base::Timer;
+using android::base::unique_fd;
namespace android {
namespace init {
@@ -103,13 +107,17 @@
int st;
if (IsF2Fs()) {
const char* f2fs_argv[] = {
- "/system/bin/fsck.f2fs", "-f", mnt_fsname_.c_str(),
+ "/system/bin/fsck.f2fs",
+ "-a",
+ mnt_fsname_.c_str(),
};
android_fork_execvp_ext(arraysize(f2fs_argv), (char**)f2fs_argv, &st, true, LOG_KLOG,
true, nullptr, nullptr, 0);
} else if (IsExt4()) {
const char* ext4_argv[] = {
- "/system/bin/e2fsck", "-f", "-y", mnt_fsname_.c_str(),
+ "/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);
@@ -142,7 +150,9 @@
LOG(WARNING) << "cannot find blank_screen in TurnOffBacklight";
return;
}
- service->Start();
+ if (auto result = service->Start(); !result) {
+ LOG(WARNING) << "Could not start blank_screen service: " << result.error();
+ }
}
static void ShutdownVold() {
@@ -162,7 +172,7 @@
*/
static bool FindPartitionsToUmount(std::vector<MountEntry>* blockDevPartitions,
std::vector<MountEntry>* emulatedPartitions, bool dump) {
- std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(setmntent("/proc/mounts", "r"), endmntent);
+ 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;
@@ -187,7 +197,7 @@
return true;
}
-static void DumpUmountDebuggingInfo(bool dump_all) {
+static void DumpUmountDebuggingInfo() {
int status;
if (!security_getenforce()) {
LOG(INFO) << "Run lsof";
@@ -196,10 +206,9 @@
true, nullptr, nullptr, 0);
}
FindPartitionsToUmount(nullptr, nullptr, true);
- if (dump_all) {
- // dump current tasks, this log can be lengthy, so only dump with dump_all
- android::base::WriteStringToFile("t", "/proc/sysrq-trigger");
- }
+ // dump current CPU stack traces and uninterruptible tasks
+ android::base::WriteStringToFile("l", "/proc/sysrq-trigger");
+ android::base::WriteStringToFile("w", "/proc/sysrq-trigger");
}
static UmountStat UmountPartitions(std::chrono::milliseconds timeout) {
@@ -262,11 +271,11 @@
UmountStat stat = UmountPartitions(timeout - t.duration());
if (stat != UMOUNT_STAT_SUCCESS) {
LOG(INFO) << "umount timeout, last resort, kill all and try";
- if (DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo(true);
+ if (DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo();
KillAllProcesses();
// even if it succeeds, still it is timeout and do not run fsck with all processes killed
UmountStat st = UmountPartitions(0ms);
- if ((st != UMOUNT_STAT_SUCCESS) && DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo(false);
+ if ((st != UMOUNT_STAT_SUCCESS) && DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo();
}
if (stat == UMOUNT_STAT_SUCCESS && runFsck) {
@@ -279,6 +288,48 @@
return stat;
}
+// zram is able to use backing device on top of a loopback device.
+// In order to unmount /data successfully, we have to kill the loopback device first
+#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() {
+ std::string backing_dev;
+ if (!android::base::ReadFileToString(ZRAM_BACK_DEV, &backing_dev)) return;
+
+ if (!android::base::StartsWith(backing_dev, "/dev/block/loop")) return;
+
+ // cut the last "\n"
+ backing_dev.erase(backing_dev.length() - 1);
+
+ // shutdown zram handle
+ Timer swap_timer;
+ LOG(INFO) << "swapoff() start...";
+ if (swapoff(ZRAM_DEVICE) == -1) {
+ LOG(ERROR) << "zram_backing_dev: swapoff (" << backing_dev << ")" << " failed";
+ return;
+ }
+ LOG(INFO) << "swapoff() took " << swap_timer;;
+
+ if (!android::base::WriteStringToFile("1", ZRAM_RESET)) {
+ LOG(ERROR) << "zram_backing_dev: reset (" << backing_dev << ")" << " failed";
+ return;
+ }
+
+ // 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;
+ }
+
+ if (ioctl(loop.get(), LOOP_CLR_FD, 0) < 0) {
+ LOG(ERROR) << "zram_backing_dev: loop_clear (" << backing_dev << ")" << " failed";
+ return;
+ }
+ LOG(INFO) << "zram_backing_dev: `" << backing_dev << "` is cleared successfully.";
+}
+
//* Reboot / shutdown the system.
// cmd ANDROID_RB_* as defined in android_reboot.h
// reason Reason string like "reboot", "shutdown,userrequested"
@@ -307,15 +358,14 @@
auto shutdown_timeout = 0ms;
if (!SHUTDOWN_ZERO_TIMEOUT) {
- if (is_thermal_shutdown) {
- constexpr unsigned int thermal_shutdown_timeout = 1;
- shutdown_timeout = std::chrono::seconds(thermal_shutdown_timeout);
- } else {
- constexpr unsigned int shutdown_timeout_default = 6;
- auto shutdown_timeout_property = android::base::GetUintProperty(
- "ro.build.shutdown_timeout", shutdown_timeout_default);
- shutdown_timeout = std::chrono::seconds(shutdown_timeout_property);
+ constexpr unsigned int shutdown_timeout_default = 6;
+ constexpr unsigned int max_thermal_shutdown_timeout = 3;
+ auto shutdown_timeout_final = android::base::GetUintProperty("ro.build.shutdown_timeout",
+ shutdown_timeout_default);
+ if (is_thermal_shutdown && shutdown_timeout_final > max_thermal_shutdown_timeout) {
+ shutdown_timeout_final = max_thermal_shutdown_timeout;
}
+ shutdown_timeout = std::chrono::seconds(shutdown_timeout_final);
}
LOG(INFO) << "Shutdown timeout: " << shutdown_timeout.count() << " ms";
@@ -349,9 +399,31 @@
Service* bootAnim = ServiceList::GetInstance().FindService("bootanim");
Service* surfaceFlinger = ServiceList::GetInstance().FindService("surfaceflinger");
if (bootAnim != nullptr && surfaceFlinger != nullptr && surfaceFlinger->IsRunning()) {
- // will not check animation class separately
+ bool do_shutdown_animation = GetBoolProperty("ro.init.shutdown_animation", false);
+
+ if (do_shutdown_animation) {
+ property_set("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();
+ }
+
for (const auto& service : ServiceList::GetInstance()) {
- if (service->classnames().count("animation")) service->SetShutdownCritical();
+ if (service->classnames().count("animation") == 0) {
+ continue;
+ }
+
+ // start all animation classes if stopped.
+ if (do_shutdown_animation) {
+ service->Start().IgnoreError();
+ }
+ service->SetShutdownCritical(); // will not check animation class separately
+ }
+
+ if (do_shutdown_animation) {
+ bootAnim->Start().IgnoreError();
+ surfaceFlinger->SetShutdownCritical();
+ bootAnim->SetShutdownCritical();
}
}
@@ -422,6 +494,9 @@
sync();
LOG(INFO) << "sync() before umount took" << sync_timer;
}
+ // 5. drop caches and disable zram backing device, if exist
+ KillZramBackingDevice();
+
UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration());
// Follow what linux shutdown is doing: one more sync with little bit delay
{
@@ -464,6 +539,12 @@
cmd = ANDROID_RB_RESTART2;
if (cmd_params.size() >= 2) {
reboot_target = cmd_params[1];
+ // adb reboot fastboot should boot into bootloader for devices not
+ // supporting logical partitions.
+ if (reboot_target == "fastboot" &&
+ !android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
+ reboot_target = "bootloader";
+ }
// When rebooting to the bootloader notify the bootloader writing
// also the BCB.
if (reboot_target == "bootloader") {
diff --git a/init/result.h b/init/result.h
index fc03962..0e3fd3d 100644
--- a/init/result.h
+++ b/init/result.h
@@ -151,7 +151,7 @@
}
template <typename T>
-class Result {
+class [[nodiscard]] Result {
public:
Result() {}
@@ -170,6 +170,8 @@
: 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_); }
diff --git a/init/selinux.cpp b/init/selinux.cpp
index fd7e86f..d93e9ec 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -18,8 +18,8 @@
// for SELinux operation for init.
// When the system boots, there is no SEPolicy present and init is running in the kernel domain.
-// Init loads the SEPolicy from the file system, restores the context of /init based on this
-// SEPolicy, and finally exec()'s itself to run in the proper domain.
+// Init loads the SEPolicy from the file system, restores the context of /system/bin/init based on
+// this SEPolicy, and finally exec()'s itself to run in the proper domain.
// The SEPolicy on Android comes in two variants: monolithic and split.
@@ -58,8 +58,10 @@
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/unique_fd.h>
+#include <cutils/android_reboot.h>
#include <selinux/android.h>
+#include "reboot_utils.h"
#include "util.h"
using android::base::ParseInt;
@@ -302,7 +304,17 @@
if (!GetVendorMappingVersion(&vend_plat_vers)) {
return false;
}
- std::string mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
+ std::string plat_mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
+
+ 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();
+ }
+
+ std::string product_mapping_file("/product/etc/selinux/mapping/" + vend_plat_vers + ".cil");
+ if (access(product_mapping_file.c_str(), F_OK) == -1) {
+ product_mapping_file.clear();
+ }
// vendor_sepolicy.cil and plat_pub_versioned.cil are the new design to replace
// nonplat_sepolicy.cil.
@@ -333,13 +345,19 @@
"-m", "-M", "true", "-G", "-N",
// Target the highest policy language version supported by the kernel
"-c", version_as_string.c_str(),
- mapping_file.c_str(),
+ plat_mapping_file.c_str(),
"-o", compiled_sepolicy,
// We don't care about file_contexts output by the compiler
"-f", "/sys/fs/selinux/null", // /dev/null is not yet available
};
// clang-format on
+ if (!product_policy_cil_file.empty()) {
+ compile_args.push_back(product_policy_cil_file.c_str());
+ }
+ if (!product_mapping_file.empty()) {
+ compile_args.push_back(product_mapping_file.c_str());
+ }
if (!plat_pub_versioned_cil_file.empty()) {
compile_args.push_back(plat_pub_versioned_cil_file.c_str());
}
@@ -379,8 +397,6 @@
return IsSplitPolicyDevice() ? LoadSplitPolicy() : LoadMonolithicPolicy();
}
-} // namespace
-
void SelinuxInitialize() {
Timer t;
@@ -405,6 +421,8 @@
setenv("INIT_SELINUX_TOOK", std::to_string(t.duration().count()).c_str(), 1);
}
+} // 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.
@@ -422,32 +440,8 @@
selinux_android_restorecon("/dev/urandom", 0);
selinux_android_restorecon("/dev/__properties__", 0);
- selinux_android_restorecon("/plat_file_contexts", 0);
- selinux_android_restorecon("/nonplat_file_contexts", 0);
- selinux_android_restorecon("/vendor_file_contexts", 0);
- selinux_android_restorecon("/plat_property_contexts", 0);
- selinux_android_restorecon("/nonplat_property_contexts", 0);
- selinux_android_restorecon("/vendor_property_contexts", 0);
- selinux_android_restorecon("/plat_seapp_contexts", 0);
- selinux_android_restorecon("/nonplat_seapp_contexts", 0);
- selinux_android_restorecon("/vendor_seapp_contexts", 0);
- selinux_android_restorecon("/plat_service_contexts", 0);
- selinux_android_restorecon("/nonplat_service_contexts", 0);
- selinux_android_restorecon("/vendor_service_contexts", 0);
- selinux_android_restorecon("/plat_hwservice_contexts", 0);
- selinux_android_restorecon("/nonplat_hwservice_contexts", 0);
- selinux_android_restorecon("/vendor_hwservice_contexts", 0);
- selinux_android_restorecon("/sepolicy", 0);
- selinux_android_restorecon("/vndservice_contexts", 0);
-
selinux_android_restorecon("/dev/block", SELINUX_ANDROID_RESTORECON_RECURSE);
selinux_android_restorecon("/dev/device-mapper", 0);
-
- selinux_android_restorecon("/sbin/mke2fs_static", 0);
- selinux_android_restorecon("/sbin/e2fsdroid_static", 0);
-
- selinux_android_restorecon("/sbin/mkfs.f2fs", 0);
- selinux_android_restorecon("/sbin/sload.f2fs", 0);
}
int SelinuxKlogCallback(int type, const char* fmt, ...) {
@@ -496,6 +490,39 @@
return major_version;
}
+// This function initializes SELinux then execs init to run in the init SELinux context.
+int SetupSelinux(char** argv) {
+ android::base::InitLogging(argv, &android::base::KernelLogger, [](const char*) {
+ RebootSystem(ANDROID_RB_RESTART2, "bootloader");
+ });
+
+ if (REBOOT_BOOTLOADER_ON_PANIC) {
+ InstallRebootSignalHandlers();
+ }
+
+ // Set up SELinux, loading the SELinux policy.
+ SelinuxSetupKernelLogging();
+ SelinuxInitialize();
+
+ // We're in the kernel domain and want to transition to the init domain. File systems that
+ // store SELabels in their xattrs, such as ext4 do not need an explicit restorecon here,
+ // but other file systems do. In particular, this is needed for ramdisks such as the
+ // recovery image for A/B devices.
+ if (selinux_android_restorecon("/system/bin/init", 0) == -1) {
+ PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
+ }
+
+ const char* path = "/system/bin/init";
+ const char* args[] = {path, "second_stage", nullptr};
+ execv(path, const_cast<char**>(args));
+
+ // execv() only returns if an error happened, in which case we
+ // panic and never return from this function.
+ PLOG(FATAL) << "execv(\"" << path << "\") failed";
+
+ 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
diff --git a/init/selinux.h b/init/selinux.h
index c41d7f0..3aa9406 100644
--- a/init/selinux.h
+++ b/init/selinux.h
@@ -23,7 +23,7 @@
namespace android {
namespace init {
-void SelinuxInitialize();
+int SetupSelinux(char** argv);
void SelinuxRestoreContext();
void SelinuxSetupKernelLogging();
diff --git a/init/service.cpp b/init/service.cpp
index d20e90a..272809f 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -60,6 +60,7 @@
using android::base::GetProperty;
using android::base::Join;
using android::base::ParseInt;
+using android::base::Split;
using android::base::StartsWith;
using android::base::StringPrintf;
using android::base::unique_fd;
@@ -234,9 +235,6 @@
ioprio_pri_(0),
priority_(0),
oom_score_adjust_(-1000),
- swappiness_(-1),
- soft_limit_in_bytes_(-1),
- limit_in_bytes_(-1),
start_order_(0),
args_(args) {}
@@ -369,12 +367,19 @@
return;
}
- // If we crash > 4 times in 4 minutes, reboot into recovery.
+ // If we crash > 4 times in 4 minutes, reboot into bootloader or set crashing property
boot_clock::time_point now = boot_clock::now();
- if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) {
+ if (((flags_ & SVC_CRITICAL) || classnames_.count("updatable")) && !(flags_ & SVC_RESTART)) {
if (now < time_crashed_ + 4min) {
if (++crash_count_ > 4) {
- LOG(FATAL) << "critical process '" << name_ << "' exited 4 times in 4 minutes";
+ if (flags_ & SVC_CRITICAL) {
+ // Aborts into bootloader
+ LOG(FATAL) << "critical process '" << name_ << "' exited 4 times in 4 minutes";
+ } else {
+ LOG(ERROR) << "updatable process '" << name_ << "' exited 4 times in 4 minutes";
+ // Notifies update_verifier and apexd
+ property_set("ro.init.updatable_crashing", "1");
+ }
}
} else {
time_crashed_ = now;
@@ -400,7 +405,7 @@
[] (const auto& info) { LOG(INFO) << *info; });
}
-Result<Success> Service::ParseCapabilities(const std::vector<std::string>& args) {
+Result<Success> Service::ParseCapabilities(std::vector<std::string>&& args) {
capabilities_ = 0;
if (!CapAmbientSupported()) {
@@ -429,29 +434,29 @@
return Success();
}
-Result<Success> Service::ParseClass(const std::vector<std::string>& args) {
+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(const std::vector<std::string>& args) {
+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(const std::vector<std::string>& args) {
+Result<Success> Service::ParseCritical(std::vector<std::string>&& args) {
flags_ |= SVC_CRITICAL;
return Success();
}
-Result<Success> Service::ParseDisabled(const std::vector<std::string>& args) {
+Result<Success> Service::ParseDisabled(std::vector<std::string>&& args) {
flags_ |= SVC_DISABLED;
flags_ |= SVC_RC_DISABLED;
return Success();
}
-Result<Success> Service::ParseEnterNamespace(const std::vector<std::string>& args) {
+Result<Success> Service::ParseEnterNamespace(std::vector<std::string>&& args) {
if (args[1] != "net") {
return Error() << "Init only supports entering network namespaces";
}
@@ -461,11 +466,11 @@
// 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, args[2]);
+ namespaces_to_enter_.emplace_back(CLONE_NEWNET, std::move(args[2]));
return Success();
}
-Result<Success> Service::ParseGroup(const std::vector<std::string>& args) {
+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();
@@ -482,7 +487,7 @@
return Success();
}
-Result<Success> Service::ParsePriority(const std::vector<std::string>& args) {
+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
@@ -493,7 +498,7 @@
return Success();
}
-Result<Success> Service::ParseInterface(const std::vector<std::string>& args) {
+Result<Success> Service::ParseInterface(std::vector<std::string>&& args) {
const std::string& interface_name = args[1];
const std::string& instance_name = args[2];
@@ -524,7 +529,7 @@
return Success();
}
-Result<Success> Service::ParseIoprio(const std::vector<std::string>& args) {
+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";
}
@@ -542,36 +547,53 @@
return Success();
}
-Result<Success> Service::ParseKeycodes(const std::vector<std::string>& args) {
- for (std::size_t i = 1; i < args.size(); i++) {
+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(args[i], &code, 0, KEY_MAX)) {
+ if (ParseInt(*it, &code, 0, KEY_MAX)) {
for (auto& key : keycodes_) {
- if (key == code) return Error() << "duplicate keycode: " << args[i];
+ if (key == code) return Error() << "duplicate keycode: " << *it;
}
keycodes_.insert(std::upper_bound(keycodes_.begin(), keycodes_.end(), code), code);
} else {
- return Error() << "invalid keycode: " << args[i];
+ return Error() << "invalid keycode: " << *it;
}
}
return Success();
}
-Result<Success> Service::ParseOneshot(const std::vector<std::string>& args) {
+Result<Success> Service::ParseOneshot(std::vector<std::string>&& args) {
flags_ |= SVC_ONESHOT;
return Success();
}
-Result<Success> Service::ParseOnrestart(const std::vector<std::string>& args) {
- std::vector<std::string> str_args(args.begin() + 1, args.end());
+Result<Success> Service::ParseOnrestart(std::vector<std::string>&& args) {
+ args.erase(args.begin());
int line = onrestart_.NumCommands() + 1;
- if (auto result = onrestart_.AddCommand(str_args, line); !result) {
+ if (auto result = onrestart_.AddCommand(std::move(args), line); !result) {
return Error() << "cannot add Onrestart command: " << result.error();
}
return Success();
}
-Result<Success> Service::ParseNamespace(const std::vector<std::string>& args) {
+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;
@@ -586,40 +608,52 @@
return Success();
}
-Result<Success> Service::ParseOomScoreAdjust(const std::vector<std::string>& args) {
+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(const std::vector<std::string>& args) {
+Result<Success> Service::ParseOverride(std::vector<std::string>&& args) {
override_ = true;
return Success();
}
-Result<Success> Service::ParseMemcgSwappiness(const std::vector<std::string>& args) {
+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(const std::vector<std::string>& args) {
+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::ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args) {
+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(const std::vector<std::string>& args) {
+Result<Success> Service::ParseProcessRlimit(std::vector<std::string>&& args) {
auto rlimit = ParseRlimit(args);
if (!rlimit) return rlimit.error();
@@ -627,22 +661,31 @@
return Success();
}
-Result<Success> Service::ParseSeclabel(const std::vector<std::string>& args) {
- seclabel_ = args[1];
+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::ParseSigstop(const std::vector<std::string>& args) {
+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(const std::vector<std::string>& args) {
- environment_vars_.emplace_back(args[1], args[2]);
+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(const std::vector<std::string>& args) {
+Result<Success> Service::ParseShutdown(std::vector<std::string>&& args) {
if (args[1] == "critical") {
flags_ |= SVC_SHUTDOWN_CRITICAL;
return Success();
@@ -650,8 +693,17 @@
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(const std::vector<std::string>& args) {
+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;
@@ -686,26 +738,26 @@
}
// name type perm [ uid gid context ]
-Result<Success> Service::ParseSocket(const std::vector<std::string>& args) {
+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>(args);
+ return AddDescriptor<SocketInfo>(std::move(args));
}
// name type perm [ uid gid context ]
-Result<Success> Service::ParseFile(const std::vector<std::string>& args) {
+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'";
}
if ((args[1][0] != '/') || (args[1].find("../") != std::string::npos)) {
return Error() << "file name must not be relative";
}
- return AddDescriptor<FileInfo>(args);
+ return AddDescriptor<FileInfo>(std::move(args));
}
-Result<Success> Service::ParseUser(const std::vector<std::string>& 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();
@@ -714,8 +766,14 @@
return Success();
}
-Result<Success> Service::ParseWritepid(const std::vector<std::string>& args) {
- writepid_files_.assign(args.begin() + 1, args.end());
+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();
}
@@ -746,6 +804,10 @@
{"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",
@@ -757,12 +819,17 @@
{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}},
};
@@ -770,16 +837,23 @@
return option_parsers;
}
-Result<Success> Service::ParseLine(const std::vector<std::string>& args) {
+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, args);
+ 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.
+ return Error() << "Cannot start an updatable service '" << name_
+ << "' before configs from APEXes are all loaded";
+ }
+
flags_ |= SVC_ONESHOT;
if (auto result = Start(); !result) {
@@ -797,6 +871,13 @@
}
Result<Success> Service::Start() {
+ if (is_updatable() && !ServiceList::GetInstance().IsServicesUpdated()) {
+ ServiceList::GetInstance().DelayService(*this);
+ return Error() << "Cannot start an updatable service '" << name_
+ << "' before configs from APEXes are all loaded. "
+ << "Queued for execution.";
+ }
+
bool disabled = (flags_ & (SVC_DISABLED | SVC_RESET));
// Starting a service removes it from the disabled or reset state and
// immediately takes it out of the restarting state if it was in there.
@@ -960,11 +1041,13 @@
start_order_ = next_start_order_++;
process_cgroup_empty_ = false;
- errno = -createProcessGroup(uid_, pid_);
+ 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);
if (errno != 0) {
PLOG(ERROR) << "createProcessGroup(" << uid_ << ", " << pid_ << ") failed for service '"
<< name_ << "'";
- } else {
+ } else if (use_memcg) {
if (swappiness_ != -1) {
if (!setProcessGroupSwappiness(uid_, pid_, swappiness_)) {
PLOG(ERROR) << "setProcessGroupSwappiness failed";
@@ -977,8 +1060,29 @@
}
}
- if (limit_in_bytes_ != -1) {
- if (!setProcessGroupLimit(uid_, pid_, limit_in_bytes_)) {
+ size_t computed_limit_in_bytes = limit_in_bytes_;
+ if (limit_percent_ != -1) {
+ long page_size = sysconf(_SC_PAGESIZE);
+ long num_pages = sysconf(_SC_PHYS_PAGES);
+ if (page_size > 0 && num_pages > 0) {
+ size_t max_mem = SIZE_MAX;
+ if (size_t(num_pages) < SIZE_MAX / size_t(page_size)) {
+ max_mem = size_t(num_pages) * size_t(page_size);
+ }
+ computed_limit_in_bytes =
+ std::min(computed_limit_in_bytes, max_mem / 100 * limit_percent_);
+ }
+ }
+
+ if (!limit_property_.empty()) {
+ // This ends up overwriting computed_limit_in_bytes but only if the
+ // property is defined.
+ computed_limit_in_bytes = android::base::GetUintProperty(
+ limit_property_, computed_limit_in_bytes, SIZE_MAX);
+ }
+
+ if (computed_limit_in_bytes != size_t(-1)) {
+ if (!setProcessGroupLimit(uid_, pid_, computed_limit_in_bytes)) {
PLOG(ERROR) << "setProcessGroupLimit failed";
}
}
@@ -1022,6 +1126,18 @@
}
}
+void Service::Timeout() {
+ // All process state flags will be taken care of in Reap(), we really just want to kill the
+ // process here when it times out. Oneshot processes will transition to be disabled, and
+ // all other processes will transition to be restarting.
+ LOG(INFO) << "Service '" << name_ << "' expired its timeout of " << timeout_period_->count()
+ << " seconds and will now be killed";
+ if (pid_) {
+ KillProcessGroup(SIGKILL);
+ NotifyStateChange("stopping");
+ }
+}
+
void Service::Restart() {
if (flags_ & SVC_RUNNING) {
/* Stop, wait, then start the service. */
@@ -1191,6 +1307,32 @@
}
}
+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) {
@@ -1202,6 +1344,8 @@
return Error() << "invalid service name '" << name << "'";
}
+ filename_ = filename;
+
Subcontext* restart_action_subcontext = nullptr;
if (subcontexts_) {
for (auto& subcontext : *subcontexts_) {
@@ -1237,6 +1381,11 @@
<< "'";
}
+ 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;
}
diff --git a/init/service.h b/init/service.h
index ea79a07..56e75b0 100644
--- a/init/service.h
+++ b/init/service.h
@@ -21,7 +21,9 @@
#include <sys/resource.h>
#include <sys/types.h>
+#include <chrono>
#include <memory>
+#include <optional>
#include <set>
#include <string>
#include <vector>
@@ -41,7 +43,7 @@
#define SVC_RUNNING 0x004 // currently active
#define SVC_RESTARTING 0x008 // waiting to restart
#define SVC_CONSOLE 0x010 // requires console
-#define SVC_CRITICAL 0x020 // will reboot into recovery if keeps crashing
+#define SVC_CRITICAL 0x020 // will reboot into bootloader if keeps crashing
#define SVC_RESET 0x040 // Use when stopping a process,
// but not disabling so it can be restarted with its class.
#define SVC_RC_DISABLED 0x080 // Remember if the disabled flag was set in the rc script.
@@ -73,7 +75,7 @@
static std::unique_ptr<Service> MakeTemporaryOneshotService(const std::vector<std::string>& args);
bool IsRunning() { return (flags_ & SVC_RUNNING) != 0; }
- Result<Success> ParseLine(const std::vector<std::string>& args);
+ Result<Success> ParseLine(std::vector<std::string>&& args);
Result<Success> ExecStart();
Result<Success> Start();
Result<Success> StartIfNotDisabled();
@@ -81,6 +83,7 @@
void Reset();
void Stop();
void Terminate();
+ void Timeout();
void Restart();
void Reap(const siginfo_t& siginfo);
void DumpState() const;
@@ -117,10 +120,13 @@
bool process_cgroup_empty() const { return process_cgroup_empty_; }
unsigned long start_order() const { return start_order_; }
void set_sigstop(bool value) { sigstop_ = value; }
+ std::chrono::seconds restart_period() const { return restart_period_; }
+ std::optional<std::chrono::seconds> timeout_period() const { return timeout_period_; }
const std::vector<std::string>& args() const { return args_; }
+ bool is_updatable() const { return updatable_; }
private:
- using OptionParser = Result<Success> (Service::*)(const std::vector<std::string>& args);
+ using OptionParser = Result<Success> (Service::*)(std::vector<std::string>&& args);
class OptionParserMap;
Result<Success> SetUpMountNamespace() const;
@@ -133,37 +139,42 @@
void KillProcessGroup(int signal);
void SetProcessAttributes();
- Result<Success> ParseCapabilities(const std::vector<std::string>& args);
- Result<Success> ParseClass(const std::vector<std::string>& args);
- Result<Success> ParseConsole(const std::vector<std::string>& args);
- Result<Success> ParseCritical(const std::vector<std::string>& args);
- Result<Success> ParseDisabled(const std::vector<std::string>& args);
- Result<Success> ParseEnterNamespace(const std::vector<std::string>& args);
- Result<Success> ParseGroup(const std::vector<std::string>& args);
- Result<Success> ParsePriority(const std::vector<std::string>& args);
- Result<Success> ParseInterface(const std::vector<std::string>& args);
- Result<Success> ParseIoprio(const std::vector<std::string>& args);
- Result<Success> ParseKeycodes(const std::vector<std::string>& args);
- Result<Success> ParseOneshot(const std::vector<std::string>& args);
- Result<Success> ParseOnrestart(const std::vector<std::string>& args);
- Result<Success> ParseOomScoreAdjust(const std::vector<std::string>& args);
- Result<Success> ParseOverride(const std::vector<std::string>& args);
- Result<Success> ParseMemcgLimitInBytes(const std::vector<std::string>& args);
- Result<Success> ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args);
- Result<Success> ParseMemcgSwappiness(const std::vector<std::string>& args);
- Result<Success> ParseNamespace(const std::vector<std::string>& args);
- Result<Success> ParseProcessRlimit(const std::vector<std::string>& args);
- Result<Success> ParseSeclabel(const std::vector<std::string>& args);
- Result<Success> ParseSetenv(const std::vector<std::string>& args);
- Result<Success> ParseShutdown(const std::vector<std::string>& args);
- Result<Success> ParseSigstop(const std::vector<std::string>& args);
- Result<Success> ParseSocket(const std::vector<std::string>& args);
- Result<Success> ParseFile(const std::vector<std::string>& args);
- Result<Success> ParseUser(const std::vector<std::string>& args);
- Result<Success> ParseWritepid(const std::vector<std::string>& args);
+ 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(const std::vector<std::string>& args);
+ Result<Success> AddDescriptor(std::vector<std::string>&& args);
static unsigned long next_start_order_;
static bool is_exec_service_running_;
@@ -206,9 +217,12 @@
int oom_score_adjust_;
- int swappiness_;
- int soft_limit_in_bytes_;
- int limit_in_bytes_;
+ int swappiness_ = -1;
+ int soft_limit_in_bytes_ = -1;
+
+ int limit_in_bytes_ = -1;
+ int limit_percent_ = -1;
+ std::string limit_property_;
bool process_cgroup_empty_ = false;
@@ -220,6 +234,11 @@
bool sigstop_ = false;
+ std::chrono::seconds restart_period_ = 5s;
+ std::optional<std::chrono::seconds> timeout_period_;
+
+ bool updatable_ = false;
+
std::vector<std::string> args_;
std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
@@ -264,8 +283,15 @@
const std::vector<std::unique_ptr<Service>>& services() const { return services_; }
const std::vector<Service*> services_in_shutdown_order() const;
+ void MarkServicesUpdate();
+ bool IsServicesUpdated() const { return services_update_finished_; }
+ void DelayService(const Service& service);
+
private:
std::vector<std::unique_ptr<Service>> services_;
+
+ bool services_update_finished_ = false;
+ std::vector<std::string> delayed_service_names_;
};
class ServiceParser : public SectionParser {
@@ -276,6 +302,7 @@
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;
@@ -283,6 +310,7 @@
ServiceList* service_list_;
std::vector<Subcontext>* subcontexts_;
std::unique_ptr<Service> service_;
+ std::string filename_;
};
} // namespace init
diff --git a/init/stable_properties.h b/init/stable_properties.h
deleted file mode 100644
index 4972d10..0000000
--- a/init/stable_properties.h
+++ /dev/null
@@ -1,66 +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 _INIT_STABLE_PROPERTIES_H
-#define _INIT_STABLE_PROPERTIES_H
-
-#include <set>
-#include <string>
-
-namespace android {
-namespace init {
-
-static constexpr const char* kPartnerPrefixes[] = {
- "init.svc.vendor.", "ro.vendor.", "persist.vendor.", "vendor.", "init.svc.odm.", "ro.odm.",
- "persist.odm.", "odm.", "ro.boot.",
-};
-
-static const std::set<std::string> kExportedActionableProperties = {
- "dev.bootcomplete",
- "init.svc.console",
- "init.svc.mediadrm",
- "init.svc.surfaceflinger",
- "init.svc.zygote",
- "persist.bluetooth.btsnoopenable",
- "persist.sys.crash_rcu",
- "persist.sys.usb.usbradio.config",
- "persist.sys.zram_enabled",
- "ro.board.platform",
- "ro.bootmode",
- "ro.build.type",
- "ro.crypto.state",
- "ro.crypto.type",
- "ro.debuggable",
- "sys.boot_completed",
- "sys.boot_from_charger_mode",
- "sys.retaildemo.enabled",
- "sys.shutdown.requested",
- "sys.usb.config",
- "sys.usb.configfs",
- "sys.usb.ffs.mtp.ready",
- "sys.usb.ffs.ready",
- "sys.user.0.ce_available",
- "sys.vdso",
- "vold.decrypt",
- "vold.post_fs_data_done",
- "vts.native_server.on",
- "wlan.driver.status",
-};
-
-} // namespace init
-} // namespace android
-
-#endif
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index c2a21d4..092c51c 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -62,7 +62,9 @@
Result<std::string> ReadMessage(int socket) {
char buffer[kBufferSize] = {};
auto result = TEMP_FAILURE_RETRY(recv(socket, buffer, sizeof(buffer), 0));
- if (result <= 0) {
+ if (result == 0) {
+ return Error();
+ } else if (result < 0) {
return ErrnoError();
}
return std::string(buffer, result);
@@ -175,6 +177,12 @@
auto init_message = ReadMessage(init_fd_);
if (!init_message) {
+ if (init_message.error_errno() == 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.
+ return;
+ }
LOG(FATAL) << "Could not read message from init: " << init_message.error();
}
diff --git a/init/subcontext_benchmark.cpp b/init/subcontext_benchmark.cpp
index 6307993..eae03e3 100644
--- a/init/subcontext_benchmark.cpp
+++ b/init/subcontext_benchmark.cpp
@@ -39,7 +39,7 @@
free(context);
while (state.KeepRunning()) {
- subcontext.Execute(std::vector<std::string>{"return_success"});
+ subcontext.Execute(std::vector<std::string>{"return_success"}).IgnoreError();
}
if (subcontext.pid() > 0) {
diff --git a/init/switch_root.cpp b/init/switch_root.cpp
index 0e59b57..575b67f 100644
--- a/init/switch_root.cpp
+++ b/init/switch_root.cpp
@@ -16,7 +16,6 @@
#include "switch_root.h"
-#include <dirent.h>
#include <fcntl.h>
#include <mntent.h>
#include <sys/mount.h>
@@ -35,45 +34,6 @@
namespace {
-void FreeRamdisk(DIR* dir, dev_t dev) {
- int dfd = dirfd(dir);
-
- dirent* de;
- while ((de = readdir(dir)) != nullptr) {
- if (de->d_name == "."s || de->d_name == ".."s) {
- continue;
- }
-
- bool is_dir = false;
-
- if (de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) {
- struct stat info;
- if (fstatat(dfd, de->d_name, &info, AT_SYMLINK_NOFOLLOW) != 0) {
- continue;
- }
-
- if (info.st_dev != dev) {
- continue;
- }
-
- if (S_ISDIR(info.st_mode)) {
- is_dir = true;
- auto fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
- if (fd >= 0) {
- auto subdir =
- std::unique_ptr<DIR, decltype(&closedir)>{fdopendir(fd), closedir};
- if (subdir) {
- FreeRamdisk(subdir.get(), dev);
- } else {
- close(fd);
- }
- }
- }
- }
- unlinkat(dfd, de->d_name, is_dir ? AT_REMOVEDIR : 0);
- }
-}
-
std::vector<std::string> GetMounts(const std::string& new_root) {
auto fp = std::unique_ptr<std::FILE, decltype(&endmntent)>{setmntent("/proc/mounts", "re"),
endmntent};
@@ -112,24 +72,16 @@
void SwitchRoot(const std::string& new_root) {
auto mounts = GetMounts(new_root);
+ LOG(INFO) << "Switching root to '" << new_root << "'";
+
for (const auto& mount_path : mounts) {
auto new_mount_path = new_root + mount_path;
+ mkdir(new_mount_path.c_str(), 0755);
if (mount(mount_path.c_str(), new_mount_path.c_str(), nullptr, MS_MOVE, nullptr) != 0) {
PLOG(FATAL) << "Unable to move mount at '" << mount_path << "'";
}
}
- auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir};
- if (!old_root_dir) {
- PLOG(ERROR) << "Could not opendir(\"/\"), not freeing ramdisk";
- }
-
- struct stat old_root_info;
- if (stat("/", &old_root_info) != 0) {
- PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
- old_root_dir.reset();
- }
-
if (chdir(new_root.c_str()) != 0) {
PLOG(FATAL) << "Could not chdir to new_root, '" << new_root << "'";
}
@@ -141,10 +93,6 @@
if (chroot(".") != 0) {
PLOG(FATAL) << "Unable to chroot to new root";
}
-
- if (old_root_dir) {
- FreeRamdisk(old_root_dir.get(), old_root_info.st_dev);
- }
}
} // namespace init
diff --git a/init/tokenizer.cpp b/init/tokenizer.cpp
index bb143f1..7e05a0a 100644
--- a/init/tokenizer.cpp
+++ b/init/tokenizer.cpp
@@ -1,5 +1,7 @@
#include "tokenizer.h"
+#include <android-base/macros.h>
+
namespace android {
namespace init {
@@ -106,6 +108,7 @@
continue;
}
x++;
+ FALLTHROUGH_INTENDED;
case '\n':
/* \ <lf> -> line continuation */
state->line++;
diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp
index 8cf2128..62cd2be 100644
--- a/init/uevent_listener.cpp
+++ b/init/uevent_listener.cpp
@@ -86,9 +86,8 @@
}
}
-UeventListener::UeventListener() {
- // is 2MB enough? udev uses 128MB!
- device_fd_.reset(uevent_open_socket(2 * 1024 * 1024, true));
+UeventListener::UeventListener(size_t uevent_socket_rcvbuf_size) {
+ device_fd_.reset(uevent_open_socket(uevent_socket_rcvbuf_size, true));
if (device_fd_ == -1) {
LOG(FATAL) << "Could not open uevent socket";
}
diff --git a/init/uevent_listener.h b/init/uevent_listener.h
index 5b453fe..aea094e 100644
--- a/init/uevent_listener.h
+++ b/init/uevent_listener.h
@@ -41,7 +41,7 @@
class UeventListener {
public:
- UeventListener();
+ UeventListener(size_t uevent_socket_rcvbuf_size);
void RegenerateUevents(const ListenerCallback& callback) const;
ListenerAction RegenerateUeventsForPath(const std::string& path,
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index 95be6af..7545d53 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -175,7 +175,7 @@
//
// When a subprocess crashes, we fatally abort from ueventd. init will restart ueventd when
// init reaps it, and the cold boot process will start again. If this continues to fail, then
- // since ueventd is marked as a critical service, init will reboot to recovery.
+ // since ueventd is marked as a critical service, init will reboot to bootloader.
//
// When a subprocess gets stuck, keep ueventd spinning waiting for it. init has a timeout for
// cold boot and will reboot to the bootloader if ueventd does not complete in time.
@@ -233,29 +233,26 @@
SelabelInitialize();
std::vector<std::unique_ptr<UeventHandler>> uevent_handlers;
- UeventListener uevent_listener;
- {
- // Keep the current product name base configuration so we remain backwards compatible and
- // allow it to override everything.
- // TODO: cleanup platform ueventd.rc to remove vendor specific device node entries (b/34968103)
- auto hardware = android::base::GetProperty("ro.hardware", "");
+ // Keep the current product name base configuration so we remain backwards compatible and
+ // allow it to override everything.
+ // 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", "/odm/ueventd.rc",
- "/ueventd." + hardware + ".rc"});
+ auto ueventd_configuration = ParseConfig({"/ueventd.rc", "/vendor/ueventd.rc",
+ "/odm/ueventd.rc", "/ueventd." + hardware + ".rc"});
- uevent_handlers.emplace_back(std::make_unique<DeviceHandler>(
- std::move(ueventd_configuration.dev_permissions),
- std::move(ueventd_configuration.sysfs_permissions),
- std::move(ueventd_configuration.subsystems), fs_mgr_get_boot_devices(), true));
- uevent_handlers.emplace_back(std::make_unique<FirmwareHandler>(
- std::move(ueventd_configuration.firmware_directories)));
+ uevent_handlers.emplace_back(std::make_unique<DeviceHandler>(
+ std::move(ueventd_configuration.dev_permissions),
+ std::move(ueventd_configuration.sysfs_permissions),
+ std::move(ueventd_configuration.subsystems), fs_mgr_get_boot_devices(), true));
+ uevent_handlers.emplace_back(std::make_unique<FirmwareHandler>(
+ std::move(ueventd_configuration.firmware_directories)));
- if (ueventd_configuration.enable_modalias_handling) {
- uevent_handlers.emplace_back(std::make_unique<ModaliasHandler>());
- }
+ if (ueventd_configuration.enable_modalias_handling) {
+ uevent_handlers.emplace_back(std::make_unique<ModaliasHandler>());
}
+ UeventListener uevent_listener(ueventd_configuration.uevent_socket_rcvbuf_size);
if (access(COLDBOOT_DONE, F_OK) != 0) {
ColdBoot cold_boot(uevent_listener, uevent_handlers);
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp
index 677938e..aac3fe5 100644
--- a/init/ueventd_parser.cpp
+++ b/init/ueventd_parser.cpp
@@ -19,9 +19,13 @@
#include <grp.h>
#include <pwd.h>
+#include <android-base/parseint.h>
+
#include "keyword_map.h"
#include "parser.h"
+using android::base::ParseByteCount;
+
namespace android {
namespace init {
@@ -101,6 +105,22 @@
return Success();
}
+Result<Success> 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";
+ }
+
+ size_t parsed_size;
+ if (!ParseByteCount(args[1], &parsed_size)) {
+ return Error() << "could not parse size '" << args[1] << "' for uevent_socket_rcvbuf_line";
+ }
+
+ *uevent_socket_rcvbuf_size = parsed_size;
+
+ return Success();
+}
+
class SubsystemParser : public SectionParser {
public:
SubsystemParser(std::vector<Subsystem>* subsystems) : subsystems_(subsystems) {}
@@ -202,6 +222,9 @@
parser.AddSingleLineParser("modalias_handling",
std::bind(ParseModaliasHandlingLine, _1,
&ueventd_configuration.enable_modalias_handling));
+ parser.AddSingleLineParser("uevent_socket_rcvbuf_size",
+ std::bind(ParseUeventSocketRcvbufSizeLine, _1,
+ &ueventd_configuration.uevent_socket_rcvbuf_size));
for (const auto& config : configs) {
parser.ParseConfig(config);
diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h
index 7d30edf..d476dec 100644
--- a/init/ueventd_parser.h
+++ b/init/ueventd_parser.h
@@ -31,6 +31,7 @@
std::vector<Permissions> dev_permissions;
std::vector<std::string> firmware_directories;
bool enable_modalias_handling = false;
+ size_t uevent_socket_rcvbuf_size = 0;
};
UeventdConfiguration ParseConfig(const std::vector<std::string>& configs);
diff --git a/init/ueventd_parser_test.cpp b/init/ueventd_parser_test.cpp
index 31208b9..9c1cedf 100644
--- a/init/ueventd_parser_test.cpp
+++ b/init/ueventd_parser_test.cpp
@@ -16,7 +16,7 @@
#include "ueventd_parser.h"
-#include <android-base/test_utils.h>
+#include <android-base/file.h>
#include <gtest/gtest.h>
#include <private/android_filesystem_config.h>
@@ -138,6 +138,15 @@
TestUeventdFile(ueventd_file, {{}, {}, {}, firmware_directories});
}
+TEST(ueventd_parser, UeventSocketRcvbufSize) {
+ auto ueventd_file = R"(
+uevent_socket_rcvbuf_size 8k
+uevent_socket_rcvbuf_size 8M
+)";
+
+ TestUeventdFile(ueventd_file, {{}, {}, {}, {}, false, 8 * 1024 * 1024});
+}
+
TEST(ueventd_parser, AllTogether) {
auto ueventd_file = R"(
@@ -169,6 +178,8 @@
/sys/devices/virtual/*/input poll_delay 0660 root input
firmware_directories /more
+uevent_socket_rcvbuf_size 6M
+
#ending comment
)";
@@ -197,8 +208,10 @@
"/more",
};
- TestUeventdFile(ueventd_file,
- {subsystems, sysfs_permissions, permissions, firmware_directories});
+ size_t uevent_socket_rcvbuf_size = 6 * 1024 * 1024;
+
+ TestUeventdFile(ueventd_file, {subsystems, sysfs_permissions, permissions, firmware_directories,
+ false, uevent_socket_rcvbuf_size});
}
// All of these lines are ill-formed, so test that there is 0 output.
@@ -213,6 +226,8 @@
/sys/devices/platform/trusty.* trusty_version 0440 baduidbad log
/sys/devices/platform/trusty.* trusty_version 0440 root baduidbad
+uevent_socket_rcvbuf_size blah
+
subsystem #no name
)";
diff --git a/init/ueventd_test.cpp b/init/ueventd_test.cpp
index 7290051..bfdc28e 100644
--- a/init/ueventd_test.cpp
+++ b/init/ueventd_test.cpp
@@ -27,7 +27,6 @@
#include <android-base/file.h>
#include <android-base/scopeguard.h>
-#include <android-base/test_utils.h>
#include <gtest/gtest.h>
#include <selinux/android.h>
#include <selinux/label.h>
diff --git a/init/util.cpp b/init/util.cpp
index 105ac87..3781141 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -436,5 +436,21 @@
return true;
}
+void InitKernelLogging(char** argv, std::function<void(const char*)> abort_function) {
+ // Make stdin/stdout/stderr all point to /dev/null.
+ int fd = open("/dev/null", O_RDWR);
+ if (fd == -1) {
+ int saved_errno = errno;
+ android::base::InitLogging(argv, &android::base::KernelLogger, std::move(abort_function));
+ errno = saved_errno;
+ PLOG(FATAL) << "Couldn't open /dev/null";
+ }
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+ if (fd > 2) close(fd);
+ android::base::InitLogging(argv, &android::base::KernelLogger, std::move(abort_function));
+}
+
} // namespace init
} // namespace android
diff --git a/init/util.h b/init/util.h
index 07e4864..53f4547 100644
--- a/init/util.h
+++ b/init/util.h
@@ -64,6 +64,8 @@
bool IsLegalPropertyName(const std::string& name);
+void InitKernelLogging(char** argv, std::function<void(const char*)> abort_function);
+
} // namespace init
} // namespace android
diff --git a/init/util_test.cpp b/init/util_test.cpp
index 3ae53a4..1b5afba 100644
--- a/init/util_test.cpp
+++ b/init/util_test.cpp
@@ -20,8 +20,8 @@
#include <fcntl.h>
#include <sys/stat.h>
+#include <android-base/file.h>
#include <android-base/stringprintf.h>
-#include <android-base/test_utils.h>
#include <gtest/gtest.h>
using namespace std::literals::string_literals;
diff --git a/janitors/OWNERS b/janitors/OWNERS
new file mode 100644
index 0000000..0610b41
--- /dev/null
+++ b/janitors/OWNERS
@@ -0,0 +1,4 @@
+# OWNERS file for projects that don't really have owners so much as volunteer janitors.
+enh@google.com
+hhb@google.com
+narayan@google.com
diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc
index 8b0c53e..ac94e69 100644
--- a/libappfuse/FuseBridgeLoop.cc
+++ b/libappfuse/FuseBridgeLoop.cc
@@ -311,7 +311,7 @@
};
FuseBridgeLoop::FuseBridgeLoop() : opened_(true) {
- base::unique_fd epoll_fd(epoll_create1(/* no flag */ 0));
+ base::unique_fd epoll_fd(epoll_create1(EPOLL_CLOEXEC));
if (epoll_fd.get() == -1) {
PLOG(ERROR) << "Failed to open FD for epoll";
opened_ = false;
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index a10e636..7f9a18a 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -27,15 +27,6 @@
enabled: false,
},
},
-
- multilib: {
- lib32: {
- suffix: "32",
- },
- lib64: {
- suffix: "64",
- },
- },
}
libbacktrace_sources = [
@@ -89,35 +80,26 @@
"libbase",
"liblog",
"libunwindstack",
- "libdexfile",
],
static_libs: [
"libprocinfo",
],
-
- // libdexfile will eventually properly export headers, for now
- // include these directly.
- include_dirs: [
- "art/runtime",
- ],
},
android: {
static_libs: ["libasync_safe"],
},
vendor: {
cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
- exclude_shared_libs: ["libdexfile"],
},
recovery: {
cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
- exclude_shared_libs: ["libdexfile"],
},
},
whole_static_libs: ["libdemangle"],
}
-cc_library_shared {
+cc_test_library {
name: "libbacktrace_test",
defaults: ["libbacktrace_common"],
host_supported: true,
@@ -130,6 +112,17 @@
shared_libs: [
"libunwindstack",
],
+ relative_install_path: "backtrace_test_libs",
+
+ target: {
+ linux_glibc: {
+ // This forces the creation of eh_frame with unwind information
+ // for host.
+ cflags: [
+ "-fcxx-exceptions"
+ ],
+ },
+ },
}
//-------------------------------------------------------------------------
@@ -137,12 +130,12 @@
//-------------------------------------------------------------------------
cc_test {
name: "backtrace_test",
+ isolated: true,
defaults: ["libbacktrace_common"],
host_supported: true,
srcs: [
"backtrace_offline_test.cpp",
"backtrace_test.cpp",
- "GetPss.cpp",
],
cflags: [
@@ -152,9 +145,7 @@
],
shared_libs: [
- "libbacktrace_test",
"libbacktrace",
- "libdexfile",
"libbase",
"liblog",
"libunwindstack",
@@ -162,22 +153,9 @@
group_static_libs: true,
- target: {
- android: {
- cflags: ["-DENABLE_PSS_TESTS"],
- shared_libs: [
- "libutils",
- ],
- },
- linux_glibc: {
- static_libs: ["libutils"],
- },
- },
-
- // libdexfile will eventually properly export headers, for now
- // include these directly.
- include_dirs: [
- "art/runtime",
+ // So that the dlopen can find the libbacktrace_test.so.
+ ldflags: [
+ "-Wl,--rpath,${ORIGIN}/../backtrace_test_libs",
],
test_suites: ["device-tests"],
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
index 39cb995..038b59e 100644
--- a/libbacktrace/BacktraceCurrent.cpp
+++ b/libbacktrace/BacktraceCurrent.cpp
@@ -76,7 +76,7 @@
return UnwindFromContext(num_ignore_frames, ucontext);
}
- if (Tid() != android::base::GetThreadId()) {
+ if (Tid() != static_cast<pid_t>(android::base::GetThreadId())) {
return UnwindThread(num_ignore_frames);
}
diff --git a/libbacktrace/BacktraceTest.h b/libbacktrace/BacktraceTest.h
new file mode 100644
index 0000000..c38af04
--- /dev/null
+++ b/libbacktrace/BacktraceTest.h
@@ -0,0 +1,78 @@
+/*
+ * 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 _LIBBACKTRACE_BACKTRACE_TEST_H
+#define _LIBBACKTRACE_BACKTRACE_TEST_H
+
+#include <dlfcn.h>
+
+#include <gtest/gtest.h>
+
+class BacktraceTest : public ::testing::Test {
+ protected:
+ static void SetUpTestCase() {
+ dl_handle_ = dlopen("libbacktrace_test.so", RTLD_NOW | RTLD_LOCAL);
+
+ test_level_one_ = reinterpret_cast<int (*)(int, int, int, int, void (*)(void*), void*)>(
+ dlsym(dl_handle_, "test_level_one"));
+
+ test_level_two_ = reinterpret_cast<int (*)(int, int, int, int, void (*)(void*), void*)>(
+ dlsym(dl_handle_, "test_level_two"));
+
+ test_level_three_ = reinterpret_cast<int (*)(int, int, int, int, void (*)(void*), void*)>(
+ dlsym(dl_handle_, "test_level_three"));
+
+ test_level_four_ = reinterpret_cast<int (*)(int, int, int, int, void (*)(void*), void*)>(
+ dlsym(dl_handle_, "test_level_four"));
+
+ test_recursive_call_ = reinterpret_cast<int (*)(int, void (*)(void*), void*)>(
+ dlsym(dl_handle_, "test_recursive_call"));
+
+ test_get_context_and_wait_ = reinterpret_cast<void (*)(void*, volatile int*)>(
+ dlsym(dl_handle_, "test_get_context_and_wait"));
+
+ test_signal_action_ =
+ reinterpret_cast<void (*)(int, siginfo_t*, void*)>(dlsym(dl_handle_, "test_signal_action"));
+
+ test_signal_handler_ =
+ reinterpret_cast<void (*)(int)>(dlsym(dl_handle_, "test_signal_handler"));
+ }
+
+ void SetUp() override {
+ ASSERT_TRUE(dl_handle_ != nullptr);
+ ASSERT_TRUE(test_level_one_ != nullptr);
+ ASSERT_TRUE(test_level_two_ != nullptr);
+ ASSERT_TRUE(test_level_three_ != nullptr);
+ ASSERT_TRUE(test_level_four_ != nullptr);
+ ASSERT_TRUE(test_recursive_call_ != nullptr);
+ ASSERT_TRUE(test_get_context_and_wait_ != nullptr);
+ ASSERT_TRUE(test_signal_action_ != nullptr);
+ ASSERT_TRUE(test_signal_handler_ != nullptr);
+ }
+
+ public:
+ static void* dl_handle_;
+ static int (*test_level_one_)(int, int, int, int, void (*)(void*), void*);
+ static int (*test_level_two_)(int, int, int, int, void (*)(void*), void*);
+ static int (*test_level_three_)(int, int, int, int, void (*)(void*), void*);
+ static int (*test_level_four_)(int, int, int, int, void (*)(void*), void*);
+ static int (*test_recursive_call_)(int, void (*)(void*), void*);
+ static void (*test_get_context_and_wait_)(void*, volatile int*);
+ static void (*test_signal_action_)(int, siginfo_t*, void*);
+ static void (*test_signal_handler_)(int);
+};
+
+#endif // _LIBBACKTRACE_BACKTRACE_TEST_H
diff --git a/libbacktrace/GetPss.cpp b/libbacktrace/GetPss.cpp
deleted file mode 100644
index 6d750ea..0000000
--- a/libbacktrace/GetPss.cpp
+++ /dev/null
@@ -1,94 +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 <inttypes.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-// This is an extremely simplified version of libpagemap.
-
-#define _BITS(x, offset, bits) (((x) >> (offset)) & ((1LL << (bits)) - 1))
-
-#define PAGEMAP_PRESENT(x) (_BITS(x, 63, 1))
-#define PAGEMAP_SWAPPED(x) (_BITS(x, 62, 1))
-#define PAGEMAP_SHIFT(x) (_BITS(x, 55, 6))
-#define PAGEMAP_PFN(x) (_BITS(x, 0, 55))
-#define PAGEMAP_SWAP_OFFSET(x) (_BITS(x, 5, 50))
-#define PAGEMAP_SWAP_TYPE(x) (_BITS(x, 0, 5))
-
-static bool ReadData(int fd, off_t place, uint64_t *data) {
- if (lseek(fd, place * sizeof(uint64_t), SEEK_SET) < 0) {
- return false;
- }
- if (read(fd, (void*)data, sizeof(uint64_t)) != (ssize_t)sizeof(uint64_t)) {
- return false;
- }
- return true;
-}
-
-size_t GetPssBytes() {
- FILE* maps = fopen("/proc/self/maps", "r");
- if (maps == nullptr) {
- return 0;
- }
-
- int pagecount_fd = open("/proc/kpagecount", O_RDONLY);
- if (pagecount_fd == -1) {
- fclose(maps);
- return 0;
- }
-
- int pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
- if (pagemap_fd == -1) {
- fclose(maps);
- close(pagecount_fd);
- return 0;
- }
-
- char line[4096];
- size_t total_pss = 0;
- int pagesize = getpagesize();
- while (fgets(line, sizeof(line), maps)) {
- uintptr_t start, end;
- if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR " ", &start, &end) != 2) {
- total_pss = 0;
- break;
- }
- for (off_t page = static_cast<off_t>(start/pagesize);
- page < static_cast<off_t>(end/pagesize); page++) {
- uint64_t data;
- if (ReadData(pagemap_fd, page, &data)) {
- if (PAGEMAP_PRESENT(data) && !PAGEMAP_SWAPPED(data)) {
- uint64_t count;
- if (ReadData(pagecount_fd, static_cast<off_t>(PAGEMAP_PFN(data)), &count)) {
- total_pss += (count >= 1) ? pagesize / count : 0;
- }
- }
- }
- }
- }
-
- fclose(maps);
-
- close(pagecount_fd);
- close(pagemap_fd);
-
- return total_pss;
-}
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index 4e7f761..f5f9b2a 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -49,6 +49,7 @@
unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(),
regs, stack_map->process_memory());
unwinder.SetResolveNames(stack_map->ResolveNames());
+ stack_map->SetArch(regs->Arch());
if (stack_map->GetJitDebug() != nullptr) {
unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch());
}
@@ -116,7 +117,7 @@
back_frame->map.name = frame->map_name;
back_frame->map.start = frame->map_start;
back_frame->map.end = frame->map_end;
- back_frame->map.offset = frame->map_offset;
+ back_frame->map.offset = frame->map_elf_start_offset;
back_frame->map.load_bias = frame->map_load_bias;
back_frame->map.flags = frame->map_flags;
}
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
index d2d6ab8..9d15af2 100644
--- a/libbacktrace/UnwindStackMap.cpp
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -25,6 +25,7 @@
#include <unwindstack/Elf.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Maps.h>
+#include <unwindstack/Regs.h>
#include "UnwindStackMap.h"
@@ -106,7 +107,17 @@
return "";
}
- unwindstack::Elf* elf = map_info->GetElf(process_memory(), true);
+ if (arch_ == unwindstack::ARCH_UNKNOWN) {
+ if (pid_ == getpid()) {
+ arch_ = unwindstack::Regs::CurrentArch();
+ } else {
+ // Create a remote regs, to figure out the architecture.
+ std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::RemoteGet(pid_));
+ arch_ = regs->Arch();
+ }
+ }
+
+ unwindstack::Elf* elf = map_info->GetElf(process_memory(), arch_);
std::string name;
uint64_t func_offset;
diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h
index 039f4a2..e19b605 100644
--- a/libbacktrace/UnwindStackMap.h
+++ b/libbacktrace/UnwindStackMap.h
@@ -30,6 +30,7 @@
#if !defined(NO_LIBDEXFILE_SUPPORT)
#include <unwindstack/DexFiles.h>
#endif
+#include <unwindstack/Elf.h>
#include <unwindstack/JitDebug.h>
#include <unwindstack/Maps.h>
@@ -58,6 +59,8 @@
unwindstack::DexFiles* GetDexFiles() { return dex_files_.get(); }
#endif
+ void SetArch(unwindstack::ArchEnum arch) { arch_ = arch; }
+
protected:
uint64_t GetLoadBias(size_t index) override;
@@ -67,6 +70,8 @@
#if !defined(NO_LIBDEXFILE_SUPPORT)
std::unique_ptr<unwindstack::DexFiles> dex_files_;
#endif
+
+ unwindstack::ArchEnum arch_ = unwindstack::ARCH_UNKNOWN;
};
class UnwindStackOfflineMap : public UnwindStackMap {
diff --git a/libbacktrace/backtrace_offline_test.cpp b/libbacktrace/backtrace_offline_test.cpp
index 7d1027e..662fb99 100644
--- a/libbacktrace/backtrace_offline_test.cpp
+++ b/libbacktrace/backtrace_offline_test.cpp
@@ -37,15 +37,7 @@
#include <gtest/gtest.h>
-extern "C" {
-// Prototypes for functions in the test library.
-int test_level_one(int, int, int, int, void (*)(void*), void*);
-int test_level_two(int, int, int, int, void (*)(void*), void*);
-int test_level_three(int, int, int, int, void (*)(void*), void*);
-int test_level_four(int, int, int, int, void (*)(void*), void*);
-int test_recursive_call(int, void (*)(void*), void*);
-void test_get_context_and_wait(void* context, volatile int* exit_flag);
-}
+#include "BacktraceTest.h"
struct FunctionSymbol {
std::string name;
@@ -56,12 +48,13 @@
static std::vector<FunctionSymbol> GetFunctionSymbols() {
std::vector<FunctionSymbol> symbols = {
{"unknown_start", 0, 0},
- {"test_level_one", reinterpret_cast<uint64_t>(&test_level_one), 0},
- {"test_level_two", reinterpret_cast<uint64_t>(&test_level_two), 0},
- {"test_level_three", reinterpret_cast<uint64_t>(&test_level_three), 0},
- {"test_level_four", reinterpret_cast<uint64_t>(&test_level_four), 0},
- {"test_recursive_call", reinterpret_cast<uint64_t>(&test_recursive_call), 0},
- {"test_get_context_and_wait", reinterpret_cast<uint64_t>(&test_get_context_and_wait), 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(
@@ -100,7 +93,7 @@
static void* OfflineThreadFunc(void* arg) {
OfflineThreadArg* fn_arg = reinterpret_cast<OfflineThreadArg*>(arg);
fn_arg->tid = android::base::GetThreadId();
- test_get_context_and_wait(&fn_arg->ucontext, &fn_arg->exit_flag);
+ BacktraceTest::test_get_context_and_wait_(&fn_arg->ucontext, &fn_arg->exit_flag);
return nullptr;
}
@@ -109,7 +102,7 @@
}
// This test is disable because it is for generating test data.
-TEST(libbacktrace, DISABLED_generate_offline_testdata) {
+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);
@@ -304,22 +297,22 @@
}
// For now, these tests can only run on the given architectures.
-TEST(libbacktrace, offline_eh_frame) {
+TEST_F(BacktraceTest, offline_eh_frame) {
BacktraceOfflineTest("arm64", "libbacktrace_test_eh_frame.so");
BacktraceOfflineTest("x86_64", "libbacktrace_test_eh_frame.so");
}
-TEST(libbacktrace, offline_debug_frame) {
+TEST_F(BacktraceTest, offline_debug_frame) {
BacktraceOfflineTest("arm", "libbacktrace_test_debug_frame.so");
BacktraceOfflineTest("x86", "libbacktrace_test_debug_frame.so");
}
-TEST(libbacktrace, offline_gnu_debugdata) {
+TEST_F(BacktraceTest, offline_gnu_debugdata) {
BacktraceOfflineTest("arm", "libbacktrace_test_gnu_debugdata.so");
BacktraceOfflineTest("x86", "libbacktrace_test_gnu_debugdata.so");
}
-TEST(libbacktrace, offline_arm_exidx) {
+TEST_F(BacktraceTest, offline_arm_exidx) {
BacktraceOfflineTest("arm", "libbacktrace_test_arm_exidx.so");
}
@@ -373,32 +366,32 @@
// 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(libbacktrace, offline_unwind_mix_eh_frame_and_arm_exidx) {
+TEST_F(BacktraceTest, offline_unwind_mix_eh_frame_and_arm_exidx) {
LibUnwindingTest("arm", "offline_testdata_for_libart", "libart.so");
}
-TEST(libbacktrace, offline_debug_frame_with_load_bias) {
+TEST_F(BacktraceTest, offline_debug_frame_with_load_bias) {
LibUnwindingTest("arm", "offline_testdata_for_libandroid_runtime", "libandroid_runtime.so");
}
-TEST(libbacktrace, offline_try_armexidx_after_debug_frame) {
+TEST_F(BacktraceTest, offline_try_armexidx_after_debug_frame) {
LibUnwindingTest("arm", "offline_testdata_for_libGLESv2_adreno", "libGLESv2_adreno.so");
}
-TEST(libbacktrace, offline_cie_with_P_augmentation) {
+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(libbacktrace, offline_empty_eh_frame_hdr) {
+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(libbacktrace, offline_max_frames_limit) {
+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/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 06a32c7..f4191b9 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -20,6 +20,7 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
+#include <malloc.h>
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
@@ -55,6 +56,7 @@
// For the THREAD_SIGNAL definition.
#include "BacktraceCurrent.h"
+#include "BacktraceTest.h"
#include "backtrace_testlib.h"
// Number of microseconds per milliseconds.
@@ -95,6 +97,23 @@
static void VerifyMaxDump(Backtrace* backtrace, create_func_t create_func = nullptr,
map_create_func_t map_func = nullptr);
+void* BacktraceTest::dl_handle_;
+int (*BacktraceTest::test_level_one_)(int, int, int, int, void (*)(void*), void*);
+int (*BacktraceTest::test_level_two_)(int, int, int, int, void (*)(void*), void*);
+int (*BacktraceTest::test_level_three_)(int, int, int, int, void (*)(void*), void*);
+int (*BacktraceTest::test_level_four_)(int, int, int, int, void (*)(void*), void*);
+int (*BacktraceTest::test_recursive_call_)(int, void (*)(void*), void*);
+void (*BacktraceTest::test_get_context_and_wait_)(void*, volatile int*);
+void (*BacktraceTest::test_signal_action_)(int, siginfo_t*, void*);
+void (*BacktraceTest::test_signal_handler_)(int);
+
+extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
+ static const char* initial_args[] = {"--slow_threshold_ms=8000", "--deadline_threshold_ms=15000"};
+ *args = initial_args;
+ *num_args = 2;
+ return true;
+}
+
static uint64_t NanoTime() {
struct timespec t = { 0, 0 };
clock_gettime(CLOCK_MONOTONIC, &t);
@@ -250,7 +269,7 @@
return false;
}
-TEST(libbacktrace, local_no_unwind_frames) {
+TEST_F(BacktraceTest, local_no_unwind_frames) {
// Verify that a local unwind does not include any frames within
// libunwind or libbacktrace.
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), getpid()));
@@ -270,7 +289,7 @@
}
}
-TEST(libbacktrace, local_unwind_frames) {
+TEST_F(BacktraceTest, local_unwind_frames) {
// Verify that a local unwind with the skip frames disabled does include
// frames within the backtrace libraries.
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), getpid()));
@@ -302,8 +321,8 @@
<< DumpFrames(backtrace.get());
}
-TEST(libbacktrace, local_trace) {
- ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0);
+TEST_F(BacktraceTest, local_trace) {
+ ASSERT_NE(test_level_one_(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0);
}
static void VerifyIgnoreFrames(Backtrace* bt_all, Backtrace* bt_ign1, Backtrace* bt_ign2,
@@ -357,12 +376,12 @@
VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), "VerifyLevelIgnoreFrames");
}
-TEST(libbacktrace, local_trace_ignore_frames) {
- ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelIgnoreFrames, nullptr), 0);
+TEST_F(BacktraceTest, local_trace_ignore_frames) {
+ ASSERT_NE(test_level_one_(1, 2, 3, 4, VerifyLevelIgnoreFrames, nullptr), 0);
}
-TEST(libbacktrace, local_max_trace) {
- ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxBacktrace, nullptr), 0);
+TEST_F(BacktraceTest, local_max_trace) {
+ ASSERT_NE(test_recursive_call_(MAX_BACKTRACE_FRAMES + 10, VerifyMaxBacktrace, nullptr), 0);
}
static void VerifyProcTest(pid_t pid, pid_t tid, bool (*ReadyFunc)(Backtrace*),
@@ -402,10 +421,10 @@
ASSERT_TRUE(verified) << "Last backtrace:\n" << last_dump;
}
-TEST(libbacktrace, ptrace_trace) {
+TEST_F(BacktraceTest, ptrace_trace) {
pid_t pid;
if ((pid = fork()) == 0) {
- ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
+ ASSERT_NE(test_level_one_(1, 2, 3, 4, nullptr, nullptr), 0);
_exit(1);
}
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyLevelDump,
@@ -416,10 +435,10 @@
ASSERT_EQ(waitpid(pid, &status, 0), pid);
}
-TEST(libbacktrace, ptrace_max_trace) {
+TEST_F(BacktraceTest, ptrace_max_trace) {
pid_t pid;
if ((pid = fork()) == 0) {
- ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, nullptr, nullptr), 0);
+ ASSERT_NE(test_recursive_call_(MAX_BACKTRACE_FRAMES + 10, nullptr, nullptr), 0);
_exit(1);
}
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyMaxBacktrace, VerifyMaxDump, Backtrace::Create,
@@ -446,10 +465,10 @@
VerifyIgnoreFrames(bt_all, ign1.get(), ign2.get(), nullptr);
}
-TEST(libbacktrace, ptrace_ignore_frames) {
+TEST_F(BacktraceTest, ptrace_ignore_frames) {
pid_t pid;
if ((pid = fork()) == 0) {
- ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
+ ASSERT_NE(test_level_one_(1, 2, 3, 4, nullptr, nullptr), 0);
_exit(1);
}
VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyProcessIgnoreFrames,
@@ -462,7 +481,7 @@
// Create a process with multiple threads and dump all of the threads.
static void* PtraceThreadLevelRun(void*) {
- EXPECT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
+ EXPECT_NE(BacktraceTest::test_level_one_(1, 2, 3, 4, nullptr, nullptr), 0);
return nullptr;
}
@@ -483,7 +502,7 @@
}
}
-TEST(libbacktrace, ptrace_threads) {
+TEST_F(BacktraceTest, ptrace_threads) {
pid_t pid;
if ((pid = fork()) == 0) {
for (size_t i = 0; i < NUM_PTRACE_THREADS; i++) {
@@ -494,7 +513,7 @@
pthread_t thread;
ASSERT_TRUE(pthread_create(&thread, &attr, PtraceThreadLevelRun, nullptr) == 0);
}
- ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0);
+ ASSERT_NE(test_level_one_(1, 2, 3, 4, nullptr, nullptr), 0);
_exit(1);
}
@@ -532,8 +551,8 @@
VerifyLevelDump(backtrace.get());
}
-TEST(libbacktrace, thread_current_level) {
- ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelThread, nullptr), 0);
+TEST_F(BacktraceTest, thread_current_level) {
+ ASSERT_NE(test_level_one_(1, 2, 3, 4, VerifyLevelThread, nullptr), 0);
}
static void VerifyMaxThread(void*) {
@@ -545,19 +564,19 @@
VerifyMaxDump(backtrace.get());
}
-TEST(libbacktrace, thread_current_max) {
- ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxThread, nullptr), 0);
+TEST_F(BacktraceTest, thread_current_max) {
+ ASSERT_NE(test_recursive_call_(MAX_BACKTRACE_FRAMES + 10, VerifyMaxThread, nullptr), 0);
}
static void* ThreadLevelRun(void* data) {
thread_t* thread = reinterpret_cast<thread_t*>(data);
thread->tid = android::base::GetThreadId();
- EXPECT_NE(test_level_one(1, 2, 3, 4, ThreadSetState, data), 0);
+ EXPECT_NE(BacktraceTest::test_level_one_(1, 2, 3, 4, ThreadSetState, data), 0);
return nullptr;
}
-TEST(libbacktrace, thread_level_trace) {
+TEST_F(BacktraceTest, thread_level_trace) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
@@ -607,7 +626,7 @@
EXPECT_EQ(cur_action.sa_flags, new_action.sa_flags);
}
-TEST(libbacktrace, thread_ignore_frames) {
+TEST_F(BacktraceTest, thread_ignore_frames) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
@@ -644,11 +663,12 @@
thread_t* thread = reinterpret_cast<thread_t*>(data);
thread->tid = android::base::GetThreadId();
- EXPECT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, ThreadSetState, data), 0);
+ EXPECT_NE(BacktraceTest::test_recursive_call_(MAX_BACKTRACE_FRAMES + 10, ThreadSetState, data),
+ 0);
return nullptr;
}
-TEST(libbacktrace, thread_max_trace) {
+TEST_F(BacktraceTest, thread_max_trace) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
@@ -742,17 +762,17 @@
}
}
-TEST(libbacktrace, thread_multiple_dump) {
+TEST_F(BacktraceTest, thread_multiple_dump) {
MultipleThreadDumpTest(false);
}
-TEST(libbacktrace, thread_multiple_dump_same_map) {
+TEST_F(BacktraceTest, thread_multiple_dump_same_map) {
MultipleThreadDumpTest(true);
}
// This test is for UnwindMaps that should share the same map cursor when
// multiple maps are created for the current process at the same time.
-TEST(libbacktrace, simultaneous_maps) {
+TEST_F(BacktraceTest, simultaneous_maps) {
BacktraceMap* map1 = BacktraceMap::Create(getpid());
BacktraceMap* map2 = BacktraceMap::Create(getpid());
BacktraceMap* map3 = BacktraceMap::Create(getpid());
@@ -779,7 +799,7 @@
delete map3;
}
-TEST(libbacktrace, fillin_erases) {
+TEST_F(BacktraceTest, fillin_erases) {
BacktraceMap* back_map = BacktraceMap::Create(getpid());
backtrace_map_t map;
@@ -798,7 +818,7 @@
ASSERT_EQ("", map.name);
}
-TEST(libbacktrace, format_test) {
+TEST_F(BacktraceTest, format_test) {
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD));
ASSERT_TRUE(backtrace.get() != nullptr);
@@ -969,7 +989,7 @@
ASSERT_TRUE(test_it == test_maps.end());
}
-TEST(libbacktrace, verify_map_remote) {
+TEST_F(BacktraceTest, verify_map_remote) {
pid_t pid;
CreateRemoteProcess(&pid);
@@ -1069,7 +1089,7 @@
delete[] expected;
}
-TEST(libbacktrace, thread_read) {
+TEST_F(BacktraceTest, thread_read) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
@@ -1120,7 +1140,7 @@
}
}
-TEST(libbacktrace, process_read) {
+TEST_F(BacktraceTest, process_read) {
g_ready = 0;
pid_t pid;
if ((pid = fork()) == 0) {
@@ -1187,29 +1207,23 @@
}
static void CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) {
- std::string system_dir;
-
-#if defined(__BIONIC__)
- system_dir = "/system/lib";
-#else
- const char* host_out_env = getenv("ANDROID_HOST_OUT");
- ASSERT_TRUE(host_out_env != nullptr);
- system_dir = std::string(host_out_env) + "/lib";
-#endif
-
-#if defined(__LP64__)
- system_dir += "64";
-#endif
+ std::string test_lib(testing::internal::GetArgvs()[0]);
+ auto const value = test_lib.find_last_of('/');
+ if (value == std::string::npos) {
+ test_lib = "../backtrace_test_libs/";
+ } else {
+ test_lib = test_lib.substr(0, value + 1) + "../backtrace_test_libs/";
+ }
+ test_lib += "libbacktrace_test.so";
*tmp_so_name = std::string(tmp_dir) + "/libbacktrace_test.so";
- std::string cp_cmd =
- android::base::StringPrintf("cp %s/libbacktrace_test.so %s", system_dir.c_str(), tmp_dir);
+ std::string cp_cmd = android::base::StringPrintf("cp %s %s", test_lib.c_str(), tmp_dir);
// Copy the shared so to a tempory directory.
ASSERT_EQ(0, system(cp_cmd.c_str()));
}
-TEST(libbacktrace, check_unreadable_elf_local) {
+TEST_F(BacktraceTest, check_unreadable_elf_local) {
TemporaryDir td;
std::string tmp_so_name;
ASSERT_NO_FATAL_FAILURE(CopySharedLibrary(td.path, &tmp_so_name));
@@ -1251,7 +1265,7 @@
VerifyFunctionsFound(found_functions);
}
-TEST(libbacktrace, check_unreadable_elf_remote) {
+TEST_F(BacktraceTest, check_unreadable_elf_remote) {
TemporaryDir td;
std::string tmp_so_name;
ASSERT_NO_FATAL_FAILURE(CopySharedLibrary(td.path, &tmp_so_name));
@@ -1390,7 +1404,7 @@
typedef int (*test_func_t)(int, int, int, int, void (*)(void*), void*);
-TEST(libbacktrace, unwind_through_unreadable_elf_local) {
+TEST_F(BacktraceTest, unwind_through_unreadable_elf_local) {
TemporaryDir td;
std::string tmp_so_name;
ASSERT_NO_FATAL_FAILURE(CopySharedLibrary(td.path, &tmp_so_name));
@@ -1405,11 +1419,9 @@
ASSERT_NE(test_func(1, 2, 3, 4, VerifyUnreadableElfBacktrace, reinterpret_cast<void*>(test_func)),
0);
-
- ASSERT_TRUE(dlclose(lib_handle) == 0);
}
-TEST(libbacktrace, unwind_through_unreadable_elf_remote) {
+TEST_F(BacktraceTest, unwind_through_unreadable_elf_remote) {
TemporaryDir td;
std::string tmp_so_name;
ASSERT_NO_FATAL_FAILURE(CopySharedLibrary(td.path, &tmp_so_name));
@@ -1428,7 +1440,6 @@
exit(0);
}
ASSERT_TRUE(pid > 0);
- ASSERT_TRUE(dlclose(lib_handle) == 0);
uint64_t start = NanoTime();
bool done = false;
@@ -1465,7 +1476,7 @@
ASSERT_TRUE(done) << "Test function never found in unwind.";
}
-TEST(libbacktrace, unwind_thread_doesnt_exist) {
+TEST_F(BacktraceTest, unwind_thread_doesnt_exist) {
std::unique_ptr<Backtrace> backtrace(
Backtrace::Create(BACKTRACE_CURRENT_PROCESS, 99999999));
ASSERT_TRUE(backtrace.get() != nullptr);
@@ -1473,18 +1484,18 @@
ASSERT_EQ(BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST, backtrace->GetError().error_code);
}
-TEST(libbacktrace, local_get_function_name_before_unwind) {
+TEST_F(BacktraceTest, local_get_function_name_before_unwind) {
std::unique_ptr<Backtrace> backtrace(
Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
ASSERT_TRUE(backtrace.get() != nullptr);
// Verify that trying to get a function name before doing an unwind works.
- uint64_t cur_func_offset = reinterpret_cast<uint64_t>(&test_level_one) + 1;
+ uint64_t cur_func_offset = reinterpret_cast<uint64_t>(test_level_one_) + 1;
uint64_t offset;
ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset));
}
-TEST(libbacktrace, remote_get_function_name_before_unwind) {
+TEST_F(BacktraceTest, remote_get_function_name_before_unwind) {
pid_t pid;
CreateRemoteProcess(&pid);
@@ -1492,7 +1503,7 @@
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
// Verify that trying to get a function name before doing an unwind works.
- uint64_t cur_func_offset = reinterpret_cast<uint64_t>(&test_level_one) + 1;
+ uint64_t cur_func_offset = reinterpret_cast<uint64_t>(test_level_one_) + 1;
uint64_t offset;
ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset));
@@ -1579,7 +1590,7 @@
ASSERT_EQ(std::string(""), backtrace->GetFunctionName(device_map_uint, &offset, &map));
ASSERT_EQ(std::string(""), backtrace->GetFunctionName(0, &offset));
- uint64_t cur_func_offset = reinterpret_cast<uint64_t>(&test_level_one) + 1;
+ uint64_t cur_func_offset = reinterpret_cast<uint64_t>(BacktraceTest::test_level_one_) + 1;
// Now verify the device map flag actually causes the function name to be empty.
backtrace->FillInMap(cur_func_offset, &map);
ASSERT_TRUE((map.flags & PROT_DEVICE_MAP) == 0);
@@ -1628,7 +1639,7 @@
ASSERT_EQ(0U, backtrace->NumFrames());
}
-TEST(libbacktrace, unwind_disallow_device_map_local) {
+TEST_F(BacktraceTest, unwind_disallow_device_map_local) {
void* device_map;
SetupDeviceMap(&device_map);
@@ -1642,7 +1653,7 @@
munmap(device_map, DEVICE_MAP_SIZE);
}
-TEST(libbacktrace, unwind_disallow_device_map_remote) {
+TEST_F(BacktraceTest, unwind_disallow_device_map_remote) {
void* device_map;
SetupDeviceMap(&device_map);
@@ -1698,13 +1709,13 @@
pid_t pid;
if ((pid = fork()) == 0) {
if (use_action) {
- ScopedSignalHandler ssh(SIGUSR1, test_signal_action);
+ ScopedSignalHandler ssh(SIGUSR1, BacktraceTest::test_signal_action_);
- test_level_one(1, 2, 3, 4, SetValueAndLoop, const_cast<int*>(&value));
+ BacktraceTest::test_level_one_(1, 2, 3, 4, SetValueAndLoop, const_cast<int*>(&value));
} else {
- ScopedSignalHandler ssh(SIGUSR1, test_signal_handler);
+ ScopedSignalHandler ssh(SIGUSR1, BacktraceTest::test_signal_handler_);
- test_level_one(1, 2, 3, 4, SetValueAndLoop, const_cast<int*>(&value));
+ BacktraceTest::test_level_one_(1, 2, 3, 4, SetValueAndLoop, const_cast<int*>(&value));
}
}
ASSERT_NE(-1, pid);
@@ -1805,11 +1816,11 @@
FinishRemoteProcess(pid);
}
-TEST(libbacktrace, unwind_remote_through_signal_using_handler) {
+TEST_F(BacktraceTest, unwind_remote_through_signal_using_handler) {
UnwindThroughSignal(false, Backtrace::Create, BacktraceMap::Create);
}
-TEST(libbacktrace, unwind_remote_through_signal_using_action) {
+TEST_F(BacktraceTest, unwind_remote_through_signal_using_action) {
UnwindThroughSignal(true, Backtrace::Create, BacktraceMap::Create);
}
@@ -1822,49 +1833,41 @@
ASSERT_EQ(0U, backtrace->GetFrame(0)->num);
}
-TEST(libbacktrace, unwind_frame_skip_numbering) {
+TEST_F(BacktraceTest, unwind_frame_skip_numbering) {
TestFrameSkipNumbering(Backtrace::Create, BacktraceMap::Create);
}
-#if defined(ENABLE_PSS_TESTS)
-#include "GetPss.h"
-
#define MAX_LEAK_BYTES (32*1024UL)
static void CheckForLeak(pid_t pid, pid_t tid) {
std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(pid));
- // Do a few runs to get the PSS stable.
- for (size_t i = 0; i < 100; i++) {
- Backtrace* backtrace = Backtrace::Create(pid, tid, map.get());
- ASSERT_TRUE(backtrace != nullptr);
- ASSERT_TRUE(backtrace->Unwind(0));
- VERIFY_NO_ERROR(backtrace->GetError().error_code);
- delete backtrace;
- }
- size_t stable_pss = GetPssBytes();
- ASSERT_TRUE(stable_pss != 0);
-
// Loop enough that even a small leak should be detectable.
+ size_t first_allocated_bytes = 0;
+ size_t last_allocated_bytes = 0;
for (size_t i = 0; i < 4096; i++) {
Backtrace* backtrace = Backtrace::Create(pid, tid, map.get());
ASSERT_TRUE(backtrace != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
VERIFY_NO_ERROR(backtrace->GetError().error_code);
delete backtrace;
- }
- size_t new_pss = GetPssBytes();
- ASSERT_TRUE(new_pss != 0);
- if (new_pss > stable_pss) {
- ASSERT_LE(new_pss - stable_pss, MAX_LEAK_BYTES);
+
+ size_t allocated_bytes = mallinfo().uordblks;
+ if (first_allocated_bytes == 0) {
+ first_allocated_bytes = allocated_bytes;
+ } else if (last_allocated_bytes > first_allocated_bytes) {
+ // Check that the memory did not increase too much over the first loop.
+ ASSERT_LE(last_allocated_bytes - first_allocated_bytes, MAX_LEAK_BYTES);
+ }
+ last_allocated_bytes = allocated_bytes;
}
}
-TEST(libbacktrace, check_for_leak_local) {
+TEST_F(BacktraceTest, check_for_leak_local) {
CheckForLeak(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD);
}
-TEST(libbacktrace, check_for_leak_local_thread) {
+TEST_F(BacktraceTest, check_for_leak_local_thread) {
thread_t thread_data = { 0, 0, 0, nullptr };
pthread_t thread;
ASSERT_TRUE(pthread_create(&thread, nullptr, ThreadLevelRun, &thread_data) == 0);
@@ -1880,7 +1883,7 @@
ASSERT_TRUE(pthread_join(thread, nullptr) == 0);
}
-TEST(libbacktrace, check_for_leak_remote) {
+TEST_F(BacktraceTest, check_for_leak_remote) {
pid_t pid;
CreateRemoteProcess(&pid);
@@ -1888,4 +1891,3 @@
FinishRemoteProcess(pid);
}
-#endif
diff --git a/libcrypto_utils/tests/Android.bp b/libcrypto_utils/tests/Android.bp
new file mode 100644
index 0000000..5aadfe2
--- /dev/null
+++ b/libcrypto_utils/tests/Android.bp
@@ -0,0 +1,29 @@
+//
+// 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.
+//
+
+cc_test_host {
+ name: "libcrypto_utils_test",
+ srcs: ["android_pubkey_test.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ shared_libs: [
+ "libcrypto_utils",
+ "libcrypto",
+ ],
+}
diff --git a/libcrypto_utils/tests/Android.mk b/libcrypto_utils/tests/Android.mk
deleted file mode 100644
index ef3d0cf..0000000
--- a/libcrypto_utils/tests/Android.mk
+++ /dev/null
@@ -1,24 +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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils_test
-LOCAL_SRC_FILES := android_pubkey_test.cpp
-LOCAL_CFLAGS := -Wall -Werror -Wextra
-LOCAL_SHARED_LIBRARIES := libcrypto_utils libcrypto
-include $(BUILD_HOST_NATIVE_TEST)
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 37afb98..0dbbc3f 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -66,7 +66,6 @@
"load_file.cpp",
"native_handle.cpp",
"record_stream.cpp",
- "sched_policy.cpp",
"sockets.cpp",
"strdup16to8.cpp",
"strdup8to16.cpp",
@@ -89,6 +88,7 @@
"socket_inaddr_any_server_windows.cpp",
"socket_network_client_windows.cpp",
"sockets_windows.cpp",
+ "trace-host.cpp",
],
enabled: true,
@@ -177,8 +177,12 @@
"libbase_headers",
"libcutils_headers",
"libutils_headers",
+ "libprocessgroup_headers",
],
- export_header_lib_headers: ["libcutils_headers"],
+ export_header_lib_headers: [
+ "libcutils_headers",
+ "libprocessgroup_headers",
+ ],
local_include_dirs: ["include"],
cflags: [
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index bd5f26f..1490fbc 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -60,7 +60,7 @@
// way up to the root.
static const struct fs_path_config android_dirs[] = {
- // clang-format off
+ // clang-format off
{ 00770, AID_SYSTEM, AID_CACHE, 0, "cache" },
{ 00555, AID_ROOT, AID_ROOT, 0, "config" },
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },
@@ -80,17 +80,18 @@
{ 00775, AID_ROOT, AID_ROOT, 0, "data/preloads" },
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
{ 00755, AID_ROOT, AID_SYSTEM, 0, "mnt" },
- { 00755, AID_ROOT, AID_SHELL, 0, "product/bin" },
+ { 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" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin" },
{ 00755, AID_ROOT, AID_ROOT, 0, "system/etc/ppp" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/vendor" },
- { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin" },
+ { 00751, AID_ROOT, AID_SHELL, 0, "system/xbin" },
+ { 00751, AID_ROOT, AID_SHELL, 0, "vendor/bin" },
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor" },
{ 00755, AID_ROOT, AID_ROOT, 0, 0 },
- // clang-format on
+ // clang-format on
};
#ifndef __ANDROID_VNDK__
auto __for_testing_only__android_dirs = android_dirs;
@@ -107,7 +108,9 @@
// although the developer is advised to restrict the scope to the /vendor or
// 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 or /system/odm.
+// customization can also land on /system/vendor, /system/oem, /system/odm,
+// /system/product or /system/product_services.
+//
// We expect build-time checking or filtering when constructing the associated
// fs_config_* files (see build/tools/fs_config/fs_config_generate.c)
static const char ven_conf_dir[] = "/vendor/etc/fs_config_dirs";
@@ -116,11 +119,17 @@
static const char oem_conf_file[] = "/oem/etc/fs_config_files";
static const char odm_conf_dir[] = "/odm/etc/fs_config_dirs";
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* 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},
+ {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},
};
// Do not use android_files to grant Linux capabilities. Use ambient capabilities in their
@@ -149,7 +158,11 @@
{ 00444, AID_ROOT, AID_ROOT, 0, oem_conf_dir + 1 },
{ 00444, AID_ROOT, AID_ROOT, 0, oem_conf_file + 1 },
{ 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" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump32" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump64" },
@@ -235,10 +248,10 @@
return fd;
}
-// if path is "odm/<stuff>", "oem/<stuff>", "product/<stuff>" or
-// "vendor/<stuff>"
+// if path is "odm/<stuff>", "oem/<stuff>", "product/<stuff>",
+// "product_services/<stuff>" or "vendor/<stuff>"
static bool is_partition(const char* path, size_t len) {
- static const char* partitions[] = {"odm/", "oem/", "product/", "vendor/"};
+ static const char* partitions[] = {"odm/", "oem/", "product/", "product_services/", "vendor/"};
for (size_t i = 0; i < (sizeof(partitions) / sizeof(partitions[0])); ++i) {
size_t plen = strlen(partitions[i]);
if (len <= plen) continue;
diff --git a/libcutils/include/cutils/partition_utils.h b/libcutils/include/cutils/partition_utils.h
index 7518559..8bc9b48 100644
--- a/libcutils/include/cutils/partition_utils.h
+++ b/libcutils/include/cutils/partition_utils.h
@@ -21,7 +21,7 @@
__BEGIN_DECLS
-int partition_wiped(char *source);
+int partition_wiped(const char* source);
__END_DECLS
diff --git a/libcutils/include/cutils/sched_policy.h b/libcutils/include/cutils/sched_policy.h
index cf91b76..538ff6b 100644
--- a/libcutils/include/cutils/sched_policy.h
+++ b/libcutils/include/cutils/sched_policy.h
@@ -17,67 +17,10 @@
#ifndef __CUTILS_SCHED_POLICY_H
#define __CUTILS_SCHED_POLICY_H
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/*
- * Check if Linux kernel enables CPUSETS feature.
- *
- * Return value: 1 if Linux kernel CONFIG_CPUSETS=y; 0 otherwise.
+ * For backwards compatibility only
+ * New users should include processgroup/sched_policy.h directly
*/
-extern bool cpusets_enabled();
-
-/*
- * Check if Linux kernel enables SCHEDTUNE feature (only available in Android
- * common kernel or Linaro LSK, not in mainline Linux as of v4.9)
- *
- * Return value: 1 if Linux kernel CONFIG_CGROUP_SCHEDTUNE=y; 0 otherwise.
- */
-extern bool schedboost_enabled();
-
-/* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
-typedef enum {
- SP_DEFAULT = -1,
- SP_BACKGROUND = 0,
- SP_FOREGROUND = 1,
- SP_SYSTEM = 2, // can't be used with set_sched_policy()
- SP_AUDIO_APP = 3,
- SP_AUDIO_SYS = 4,
- SP_TOP_APP = 5,
- SP_RT_APP = 6,
- SP_RESTRICTED = 7,
- SP_CNT,
- SP_MAX = SP_CNT - 1,
- SP_SYSTEM_DEFAULT = SP_FOREGROUND,
-} SchedPolicy;
-
-extern int set_cpuset_policy(int tid, SchedPolicy policy);
-
-/* Assign thread tid to the cgroup associated with the specified policy.
- * If the thread is a thread group leader, that is it's gettid() == getpid(),
- * then the other threads in the same thread group are _not_ affected.
- * On platforms which support gettid(), zero tid means current thread.
- * Return value: 0 for success, or -errno for error.
- */
-extern int set_sched_policy(int tid, SchedPolicy policy);
-
-/* Return the policy associated with the cgroup of thread tid via policy pointer.
- * On platforms which support gettid(), zero tid means current thread.
- * Return value: 0 for success, or -1 for error and set errno.
- */
-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;
- * the caller is responsible for displaying the useful part of the string.
- */
-extern const char *get_sched_policy_name(SchedPolicy policy);
-
-#ifdef __cplusplus
-}
-#endif
+#include <processgroup/sched_policy.h>
#endif /* __CUTILS_SCHED_POLICY_H */
diff --git a/libcutils/include/cutils/sockets.h b/libcutils/include/cutils/sockets.h
index b24468b..285f150 100644
--- a/libcutils/include/cutils/sockets.h
+++ b/libcutils/include/cutils/sockets.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef __CUTILS_SOCKETS_H
-#define __CUTILS_SOCKETS_H
+#pragma once
#include <errno.h>
#include <limits.h>
@@ -141,19 +140,6 @@
const cutils_socket_buffer_t* buffers,
size_t num_buffers);
-/*
- * socket_peer_is_trusted - Takes a socket which is presumed to be a
- * connected local socket (e.g. AF_LOCAL) and returns whether the peer
- * (the userid that owns the process on the other end of that socket)
- * is one of the two trusted userids, root or shell.
- *
- * Note: This only works as advertised on the Android OS and always
- * just returns true when called on other operating systems.
- */
-extern bool socket_peer_is_trusted(int fd);
-
#ifdef __cplusplus
}
#endif
-
-#endif /* __CUTILS_SOCKETS_H */
diff --git a/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h
index 58b9f09..79b4b35 100644
--- a/libcutils/include/cutils/trace.h
+++ b/libcutils/include/cutils/trace.h
@@ -75,7 +75,8 @@
#define ATRACE_TAG_VIBRATOR (1<<23)
#define ATRACE_TAG_AIDL (1<<24)
#define ATRACE_TAG_NNAPI (1<<25)
-#define ATRACE_TAG_LAST ATRACE_TAG_NNAPI
+#define ATRACE_TAG_RRO (1<<26)
+#define ATRACE_TAG_LAST ATRACE_TAG_RRO
// Reserved for initialization.
#define ATRACE_TAG_NOT_READY (1ULL<<63)
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 3be8ad0..03edfb5 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -131,6 +131,9 @@
#define AID_SECURE_ELEMENT 1068 /* secure element subsystem */
#define AID_LMKD 1069 /* low memory killer daemon */
#define AID_LLKD 1070 /* live lock daemon */
+#define AID_IORAPD 1071 /* input/output readahead and pin daemon */
+#define AID_GPU_SERVICE 1072 /* GPU service daemon */
+#define AID_NETWORK_STACK 1073 /* network stack service */
/* Changes to this file must be made in AOSP, *not* in internal branches. */
#define AID_SHELL 2000 /* adb and debug shell user */
@@ -187,7 +190,8 @@
*/
#define AID_OVERFLOWUID 65534 /* unmapped user in the user namespace */
-#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */
+/* use the ranges below to determine whether a process is isolated */
+#define AID_ISOLATED_START 90000 /* start of uids for fully isolated sandboxed processes */
#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */
#define AID_USER 100000 /* TODO: switch users over to AID_USER_OFFSET */
diff --git a/libcutils/partition_utils.cpp b/libcutils/partition_utils.cpp
index 6735d6c..b840559 100644
--- a/libcutils/partition_utils.cpp
+++ b/libcutils/partition_utils.cpp
@@ -25,7 +25,7 @@
#include <cutils/properties.h>
-static int only_one_char(char *buf, int len, char c)
+static int only_one_char(uint8_t *buf, int len, uint8_t c)
{
int i, ret;
@@ -39,9 +39,8 @@
return ret;
}
-int partition_wiped(char *source)
-{
- char buf[4096];
+int partition_wiped(const char* source) {
+ uint8_t buf[4096];
int fd, ret;
if ((fd = open(source, O_RDONLY)) < 0) {
@@ -67,4 +66,3 @@
return 0;
}
-
diff --git a/libcutils/sockets_unix.cpp b/libcutils/sockets_unix.cpp
index 0cb8a4d..2248817 100644
--- a/libcutils/sockets_unix.cpp
+++ b/libcutils/sockets_unix.cpp
@@ -32,34 +32,6 @@
#include "android_get_control_env.h"
-#if defined(__ANDROID__)
-/* For the socket trust (credentials) check */
-#include <private/android_filesystem_config.h>
-#define __android_unused
-#else
-#define __android_unused __attribute__((__unused__))
-#endif
-
-bool socket_peer_is_trusted(int fd __android_unused) {
-#if defined(__ANDROID__)
- ucred cr;
- socklen_t len = sizeof(cr);
- int n = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
-
- if (n != 0) {
- ALOGE("could not get socket credentials: %s\n", strerror(errno));
- return false;
- }
-
- if ((cr.uid != AID_ROOT) && (cr.uid != AID_SHELL)) {
- ALOGE("untrusted userid on other end of socket: userid %d\n", cr.uid);
- return false;
- }
-#endif
-
- return true;
-}
-
int socket_close(int sock) {
return close(sock);
}
diff --git a/libcutils/tests/Android.bp b/libcutils/tests/Android.bp
index 7884190..72ae559 100644
--- a/libcutils/tests/Android.bp
+++ b/libcutils/tests/Android.bp
@@ -59,6 +59,7 @@
"libcutils",
"liblog",
"libbase",
+ "libprocessgroup",
]
cc_test {
diff --git a/libcutils/tests/android_get_control_file_test.cpp b/libcutils/tests/android_get_control_file_test.cpp
index 6c6fd2a..8de8530 100644
--- a/libcutils/tests/android_get_control_file_test.cpp
+++ b/libcutils/tests/android_get_control_file_test.cpp
@@ -23,8 +23,8 @@
#include <string>
+#include <android-base/file.h>
#include <android-base/stringprintf.h>
-#include <android-base/test_utils.h>
#include <cutils/android_get_control_file.h>
#include <gtest/gtest.h>
diff --git a/libcutils/tests/trace-dev_test.cpp b/libcutils/tests/trace-dev_test.cpp
index f8d4f00..832b36a 100644
--- a/libcutils/tests/trace-dev_test.cpp
+++ b/libcutils/tests/trace-dev_test.cpp
@@ -22,7 +22,6 @@
#include <android-base/file.h>
#include <android-base/stringprintf.h>
-#include <android-base/test_utils.h>
#include <gtest/gtest.h>
#include "../trace-dev.cpp"
diff --git a/libcutils/uevent.cpp b/libcutils/uevent.cpp
index 2dfceed..721de7c 100644
--- a/libcutils/uevent.cpp
+++ b/libcutils/uevent.cpp
@@ -95,6 +95,8 @@
int uevent_open_socket(int buf_sz, bool passcred) {
struct sockaddr_nl addr;
int on = passcred;
+ int buf_sz_readback = 0;
+ socklen_t optlen = sizeof(buf_sz_readback);
int s;
memset(&addr, 0, sizeof(addr));
@@ -105,11 +107,21 @@
s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
if (s < 0) return -1;
- /* buf_sz should be less than net.core.rmem_max for this to succeed */
- if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(buf_sz)) < 0) {
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz, sizeof(buf_sz)) < 0 ||
+ getsockopt(s, SOL_SOCKET, SO_RCVBUF, &buf_sz_readback, &optlen) < 0) {
close(s);
return -1;
}
+ /* Only if SO_RCVBUF was not effective, try SO_RCVBUFFORCE. Generally, we
+ * want to avoid SO_RCVBUFFORCE, because it generates SELinux denials in
+ * case we don't have CAP_NET_ADMIN. This is the case, for example, for
+ * healthd. */
+ if (buf_sz_readback < 2 * buf_sz) {
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &buf_sz, sizeof(buf_sz)) < 0) {
+ close(s);
+ return -1;
+ }
+ }
setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
diff --git a/libgrallocusage/Android.bp b/libgrallocusage/Android.bp
index bcc0616..d27feb9 100644
--- a/libgrallocusage/Android.bp
+++ b/libgrallocusage/Android.bp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library_static {
+cc_library {
name: "libgrallocusage",
vendor_available: true,
cflags: [
diff --git a/libgrallocusage/OWNERS b/libgrallocusage/OWNERS
new file mode 100644
index 0000000..154dc6d
--- /dev/null
+++ b/libgrallocusage/OWNERS
@@ -0,0 +1,3 @@
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/liblog/.clang-format b/liblog/.clang-format
deleted file mode 100644
index 9db87a8..0000000
--- a/liblog/.clang-format
+++ /dev/null
@@ -1,9 +0,0 @@
-BasedOnStyle: Google
-AllowShortFunctionsOnASingleLine: false
-
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-PointerAlignment: Left
-PenaltyExcessCharacter: 32
-
-Cpp11BracedListStyle: false
diff --git a/liblog/.clang-format b/liblog/.clang-format
new file mode 120000
index 0000000..fd0645f
--- /dev/null
+++ b/liblog/.clang-format
@@ -0,0 +1 @@
+../.clang-format-2
\ No newline at end of file
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 4a165a0..bd7a551 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -15,31 +15,29 @@
//
liblog_sources = [
- "config_read.c",
- "config_write.c",
- "local_logger.c",
- "log_event_list.c",
- "log_event_write.c",
- "log_ratelimit.cpp",
- "logger_lock.c",
- "logger_name.c",
- "logger_read.c",
- "logger_write.c",
- "logprint.c",
- "stderr_write.c",
+ "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.c",
- "fake_writer.c",
+ "fake_log_device.cpp",
+ "fake_writer.cpp",
]
liblog_target_sources = [
"event_tag_map.cpp",
"log_time.cpp",
- "properties.c",
- "pmsg_reader.c",
- "pmsg_writer.c",
- "logd_reader.c",
- "logd_writer.c",
+ "properties.cpp",
+ "pmsg_reader.cpp",
+ "pmsg_writer.cpp",
+ "logd_reader.cpp",
+ "logd_writer.cpp",
]
cc_library_headers {
@@ -75,6 +73,7 @@
cflags: ["-DFAKE_LOG_DEVICE=1"],
},
android: {
+ version_script: "liblog.map.txt",
srcs: liblog_target_sources,
// AddressSanitizer runtime library depends on liblog.
sanitize: {
@@ -87,7 +86,6 @@
ldflags: ["-Wl,--hash-style=both"],
},
windows: {
- srcs: ["uio.c"],
enabled: true,
},
not_windows: {
diff --git a/liblog/Android.mk b/liblog/Android.mk
deleted file mode 100644
index 6c4dff5..0000000
--- a/liblog/Android.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-LOCAL_PATH := $(my-dir)
-
-include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/liblog/README b/liblog/README
deleted file mode 100644
index 5a845be..0000000
--- a/liblog/README
+++ /dev/null
@@ -1,209 +0,0 @@
-LIBLOG(3) Android Internal NDK Programming Manual LIBLOG(3)
-
-
-
-NAME
- liblog - Android Internal NDK logger interfaces
-
-SYNOPSIS
- /*
- * Please limit to 24 characters for runtime is loggable,
- * 16 characters for persist is loggable, and logcat pretty
- * alignment with limit of 7 characters.
- */
- #define LOG_TAG "yourtag"
- #include <log/log.h>
-
- ALOG(android_priority, tag, format, ...)
- IF_ALOG(android_priority, tag)
- LOG_PRI(priority, tag, format, ...)
- LOG_PRI_VA(priority, tag, format, args)
- #define LOG_TAG NULL
- ALOGV(format, ...)
- SLOGV(format, ...)
- RLOGV(format, ...)
- ALOGV_IF(cond, format, ...)
- SLOGV_IF(cond, format, ...)
- RLOGV_IF(cond, format, ...)
- IF_ALOGC()
- ALOGD(format, ...)
- SLOGD(format, ...)
- RLOGD(format, ...)
- ALOGD_IF(cond, format, ...)
- SLOGD_IF(cond, format, ...)
- RLOGD_IF(cond, format, ...)
- IF_ALOGD()
- ALOGI(format, ...)
- SLOGI(format, ...)
- RLOGI(format, ...)
- ALOGI_IF(cond, format, ...)
- SLOGI_IF(cond, format, ...)
- RLOGI_IF(cond, format, ...)
- IF_ALOGI()
- ALOGW(format, ...)
- SLOGW(format, ...)
- RLOGW(format, ...)
- ALOGW_IF(cond, format, ...)
- SLOGW_IF(cond, format, ...)
- RLOGW_IF(cond, format, ...)
- IF_ALOGW()
- ALOGE(format, ...)
- SLOGE(format, ...)
- RLOGE(format, ...)
- ALOGE_IF(cond, format, ...)
- SLOGE_IF(cond, format, ...)
- RLOGE_IF(cond, format, ...)
- IF_ALOGE()
- LOG_FATAL(format, ...)
- LOG_ALWAYS_FATAL(format, ...)
- LOG_FATAL_IF(cond, format, ...)
- LOG_ALWAYS_FATAL_IF(cond, format, ...)
- ALOG_ASSERT(cond, format, ...)
- LOG_EVENT_INT(tag, value)
- LOG_EVENT_LONG(tag, value)
-
- clockid_t android_log_clockid()
-
- log_id_t android_logger_get_id(struct logger *logger)
- int android_logger_clear(struct logger *logger)
- int android_logger_get_log_size(struct logger *logger)
- int android_logger_get_log_readable_size(struct logger *logger)
- int android_logger_get_log_version(struct logger *logger)
-
- struct logger_list *android_logger_list_alloc(int mode,
- unsigned int tail,
- pid_t pid)
- struct logger *android_logger_open(struct logger_list *logger_list,
- log_id_t id)
- struct logger_list *android_logger_list_open(log_id_t id, int mode,
- unsigned int tail,
- pid_t pid)
- int android_logger_list_read(struct logger_list *logger_list,
- struct log_msg *log_msg)
- void android_logger_list_free(struct logger_list *logger_list)
-
- log_id_t android_name_to_log_id(const char *logName)
- const char *android_log_id_to_name(log_id_t log_id)
-
- android_log_context create_android_logger(uint32_t tag)
-
- int android_log_write_list_begin(android_log_context ctx)
- int android_log_write_list_end(android_log_context ctx)
-
- int android_log_write_int32(android_log_context ctx, int32_t value)
- int android_log_write_int64(android_log_context ctx, int64_t value)
- int android_log_write_string8(android_log_context ctx,
- const char *value)
- int android_log_write_string8_len(android_log_context ctx,
- const char *value, size_t maxlen)
- int android_log_write_float32(android_log_context ctx, float value)
-
- int android_log_write_list(android_log_context ctx,
- log_id_t id = LOG_ID_EVENTS)
-
- android_log_context create_android_log_parser(const char *msg,
- size_t len)
- android_log_list_element android_log_read_next(android_log_context ctx)
- android_log_list_element android_log_peek_next(android_log_context ctx)
-
- 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()
-
- Link with -llog
-
-DESCRIPTION
- liblog represents an interface to the volatile Android Logging system
- for NDK (Native) applications and libraries. Interfaces for either
- writing or reading logs. The log buffers are divided up in Main, Sys‐
- tem, Radio and Events sub-logs.
-
- The logging interfaces are a series of macros, all of which can be
- overridden individually in order to control the verbosity of the appli‐
- cation or library. [ASR]LOG[VDIWE] calls are used to log to BAsic,
- System or Radio sub-logs in either the Verbose, Debug, Info, Warning or
- Error priorities. [ASR]LOG[VDIWE]_IF calls are used to perform thus
- based on a condition being true. IF_ALOG[VDIWE] calls are true if the
- current LOG_TAG is enabled at the specified priority. LOG_ALWAYS_FATAL
- is used to ALOG a message, then kill the process. LOG_FATAL call is a
- variant of LOG_ALWAYS_FATAL, only enabled in engineering, and not
- release builds. ALOG_ASSERT is used to ALOG a message if the condition
- is false; the condition is part of the logged message.
- LOG_EVENT_(INT|LONG) is used to drop binary content into the Events
- sub-log.
-
- The log reading interfaces permit opening the logs either singly or
- multiply, retrieving a log entry at a time in time sorted order,
- optionally limited to a specific pid and tail of the log(s) and finally
- a call closing the logs. A single log can be opened with android_log‐
- ger_list_open; or multiple logs can be opened with android_log‐
- ger_list_alloc, calling in turn the android_logger_open for each log
- id. Each entry can be retrieved with android_logger_list_read. The
- log(s) can be closed with android_logger_list_free. The logs should be
- opened with an ANDROID_LOG_RDONLY mode. ANDROID_LOG_NONBLOCK mode
- will report when the log reading is done with an EAGAIN error return
- code, otherwise the android_logger_list_read call will block for new
- entries.
-
- The ANDROID_LOG_WRAP mode flag to the android_logger_list_alloc_time
- signals logd to quiesce the reader until the buffer is about to prune
- at the start time then proceed to dumping content.
-
- The ANDROID_LOG_PSTORE mode flag to the android_logger_open is used to
- switch from the active logs to the persistent logs from before the last
- reboot.
-
- The value returned by android_logger_open can be used as a parameter to
- the android_logger_clear function to empty the sub-log. It is recom‐
- mended to only open log ANDROID_LOG_WRONLY in that case.
-
- The value returned by android_logger_open can be used as a parameter to
- the android_logger_get_log_(size|readable_size|version) to retrieve the
- sub-log maximum size, readable size and log buffer format protocol ver‐
- sion respectively. android_logger_get_id returns the id 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, LOGGER_NULL or LOGGER_LOCAL. Log to
- logger daemon for default or logd, drop contents on floor, or log into
- local memory respectively. Both android_set_log_transport()
- and android_get_log_transport() return the current transport mask, or
- a negative errno for any problems.
-
-ERRORS
- If messages fail, a negative error code will be returned to the caller.
-
- The -ENOTCONN return code indicates that the logger daemon is stopped.
-
- The -EBADF return code indicates that the log access point can not be
- opened, or the log buffer id is out of range.
-
- For the -EAGAIN return code, this means that the logging message was
- temporarily backed-up either because of Denial Of Service (DOS) logging
- pressure from some chatty application or service in the Android system,
- or if too small of a value is set in /proc/sys/net/unix/max_dgram_qlen.
- To aid in diagnosing the occurence of this, a binary event from liblog
- will be sent to the log daemon once a new message can get through
- indicating how many messages were dropped as a result. Please take
- action to resolve the structural problems at the source.
-
- It is generally not advised for the caller to retry the -EAGAIN return
- code as this will only make the problem(s) worse and cause your
- application to temporarily drop to the logger daemon priority, BATCH
- scheduling policy and background task cgroup. If you require a group of
- messages to be passed atomically, merge them into one message with
- embedded newlines to the maximum length LOGGER_ENTRY_MAX_PAYLOAD.
-
- Other return codes from writing operation can be returned. Since the
- library retries on EINTR, -EINTR should never be returned.
-
-SEE ALSO
- syslogd(8), klogd, auditd(8)
-
-
-
- 08 Feb 2017 LIBLOG(3)
diff --git a/liblog/README.md b/liblog/README.md
new file mode 100644
index 0000000..98bee9f
--- /dev/null
+++ b/liblog/README.md
@@ -0,0 +1,176 @@
+Android liblog
+--------------
+
+Public Functions and Macros
+---------------------------
+
+ /*
+ * Please limit to 24 characters for runtime is loggable,
+ * 16 characters for persist is loggable, and logcat pretty
+ * alignment with limit of 7 characters.
+ */
+ #define LOG_TAG "yourtag"
+ #include <log/log.h>
+
+ ALOG(android_priority, tag, format, ...)
+ IF_ALOG(android_priority, tag)
+ LOG_PRI(priority, tag, format, ...)
+ LOG_PRI_VA(priority, tag, format, args)
+ #define LOG_TAG NULL
+ ALOGV(format, ...)
+ SLOGV(format, ...)
+ RLOGV(format, ...)
+ ALOGV_IF(cond, format, ...)
+ SLOGV_IF(cond, format, ...)
+ RLOGV_IF(cond, format, ...)
+ IF_ALOGC()
+ ALOGD(format, ...)
+ SLOGD(format, ...)
+ RLOGD(format, ...)
+ ALOGD_IF(cond, format, ...)
+ SLOGD_IF(cond, format, ...)
+ RLOGD_IF(cond, format, ...)
+ IF_ALOGD()
+ ALOGI(format, ...)
+ SLOGI(format, ...)
+ RLOGI(format, ...)
+ ALOGI_IF(cond, format, ...)
+ SLOGI_IF(cond, format, ...)
+ RLOGI_IF(cond, format, ...)
+ IF_ALOGI()
+ ALOGW(format, ...)
+ SLOGW(format, ...)
+ RLOGW(format, ...)
+ ALOGW_IF(cond, format, ...)
+ SLOGW_IF(cond, format, ...)
+ RLOGW_IF(cond, format, ...)
+ IF_ALOGW()
+ ALOGE(format, ...)
+ SLOGE(format, ...)
+ RLOGE(format, ...)
+ ALOGE_IF(cond, format, ...)
+ SLOGE_IF(cond, format, ...)
+ RLOGE_IF(cond, format, ...)
+ IF_ALOGE()
+ LOG_FATAL(format, ...)
+ LOG_ALWAYS_FATAL(format, ...)
+ LOG_FATAL_IF(cond, format, ...)
+ LOG_ALWAYS_FATAL_IF(cond, format, ...)
+ ALOG_ASSERT(cond, format, ...)
+ LOG_EVENT_INT(tag, value)
+ LOG_EVENT_LONG(tag, value)
+
+ clockid_t android_log_clockid()
+
+ log_id_t android_logger_get_id(struct logger *logger)
+ int android_logger_clear(struct logger *logger)
+ int android_logger_get_log_size(struct logger *logger)
+ int android_logger_get_log_readable_size(struct logger *logger)
+ int android_logger_get_log_version(struct logger *logger)
+
+ struct logger_list *android_logger_list_alloc(int mode, unsigned int tail, pid_t pid)
+ struct logger *android_logger_open(struct logger_list *logger_list, log_id_t id)
+ struct logger_list *android_logger_list_open(log_id_t id, int mode, unsigned int tail, pid_t pid)
+ int android_logger_list_read(struct logger_list *logger_list, struct log_msg *log_msg)
+ void android_logger_list_free(struct logger_list *logger_list)
+
+ log_id_t android_name_to_log_id(const char *logName)
+ const char *android_log_id_to_name(log_id_t log_id)
+
+ android_log_context create_android_logger(uint32_t tag)
+
+ int android_log_write_list_begin(android_log_context ctx)
+ int android_log_write_list_end(android_log_context ctx)
+
+ int android_log_write_int32(android_log_context ctx, int32_t value)
+ int android_log_write_int64(android_log_context ctx, int64_t value)
+ int android_log_write_string8(android_log_context ctx, const char *value)
+ int android_log_write_string8_len(android_log_context ctx, const char *value, size_t maxlen)
+ int android_log_write_float32(android_log_context ctx, float value)
+
+ int android_log_write_list(android_log_context ctx, log_id_t id = LOG_ID_EVENTS)
+
+ android_log_context create_android_log_parser(const char *msg, size_t len)
+ android_log_list_element android_log_read_next(android_log_context ctx)
+ android_log_list_element android_log_peek_next(android_log_context ctx)
+
+ 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
+-----------
+
+liblog represents an interface to the volatile Android Logging system for NDK (Native) applications
+and libraries. Interfaces for either writing or reading logs. The log buffers are divided up in
+Main, System, Radio and Events sub-logs.
+
+The logging interfaces are a series of macros, all of which can be overridden individually in order
+to control the verbosity of the application or library. `[ASR]LOG[VDIWE]` calls are used to log to
+BAsic, System or Radio sub-logs in either the Verbose, Debug, Info, Warning or Error priorities.
+`[ASR]LOG[VDIWE]_IF` calls are used to perform thus based on a condition being true.
+`IF_ALOG[VDIWE]` calls are true if the current `LOG_TAG` is enabled at the specified priority.
+`LOG_ALWAYS_FATAL` is used to `ALOG` a message, then kill the process. `LOG_FATAL` call is a
+variant of `LOG_ALWAYS_FATAL`, only enabled in engineering, and not release builds. `ALOG_ASSERT`
+is used to `ALOG` a message if the condition is false; the condition is part of the logged message.
+`LOG_EVENT_(INT|LONG)` is used to drop binary content into the Events sub-log.
+
+The log reading interfaces permit opening the logs either singly or multiply, retrieving a log entry
+at a time in time sorted order, optionally limited to a specific pid and tail of the log(s) and
+finally a call closing the logs. A single log can be opened with `android_logger_list_open()`; or
+multiple logs can be opened with `android_logger_list_alloc()`, calling in turn the
+`android_logger_open()` for each log id. Each entry can be retrieved with
+`android_logger_list_read()`. The log(s) can be closed with `android_logger_list_free()`. The logs
+should be opened with an `ANDROID_LOG_RDONLY` mode. `ANDROID_LOG_NONBLOCK` mode will report when
+the log reading is done with an `EAGAIN` error return code, otherwise the
+`android_logger_list_read()` call will block for new entries.
+
+The `ANDROID_LOG_WRAP` mode flag to the `android_logger_list_alloc_time()` signals logd to quiesce
+the reader until the buffer is about to prune at the start time then proceed to dumping content.
+
+The `ANDROID_LOG_PSTORE` mode flag to the `android_logger_open()` is used to switch from the active
+logs to the persistent logs from before the last reboot.
+
+The value returned by `android_logger_open()` can be used as a parameter to the
+`android_logger_clear()` function to empty the sub-log. It is recommended to only open log
+`ANDROID_LOG_WRONLY` in that case.
+
+The value returned by `android_logger_open()` can be used as a parameter to the
+`android_logger_get_log_(size|readable_size|version)` to retrieve the sub-log maximum size, readable
+size and log buffer format protocol version respectively. `android_logger_get_id()` returns the id
+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
+------
+
+If messages fail, a negative error code will be returned to the caller.
+
+The `-ENOTCONN` return code indicates that the logger daemon is stopped.
+
+The `-EBADF` return code indicates that the log access point can not be opened, or the log buffer id
+is out of range.
+
+For the `-EAGAIN` return code, this means that the logging message was temporarily backed-up either
+because of Denial Of Service (DOS) logging pressure from some chatty application or service in the
+Android system, or if too small of a value is set in /proc/sys/net/unix/max_dgram_qlen. To aid in
+diagnosing the occurence of this, a binary event from liblog will be sent to the log daemon once a
+new message can get through indicating how many messages were dropped as a result. Please take
+action to resolve the structural problems at the source.
+
+It is generally not advised for the caller to retry the `-EAGAIN` return code as this will only make
+the problem(s) worse and cause your application to temporarily drop to the logger daemon priority,
+BATCH scheduling policy and background task cgroup. If you require a group of messages to be passed
+atomically, merge them into one message with embedded newlines to the maximum length
+`LOGGER_ENTRY_MAX_PAYLOAD`.
+
+Other return codes from writing operation can be returned. Since the library retries on `EINTR`,
+`-EINTR` should never be returned.
diff --git a/liblog/config_read.c b/liblog/config_read.cpp
similarity index 68%
rename from liblog/config_read.c
rename to liblog/config_read.cpp
index ca80c80..80177a4 100644
--- a/liblog/config_read.c
+++ b/liblog/config_read.cpp
@@ -19,23 +19,21 @@
#include "config_read.h"
#include "logger.h"
-LIBLOG_HIDDEN struct listnode __android_log_transport_read = {
- &__android_log_transport_read, &__android_log_transport_read
-};
-LIBLOG_HIDDEN struct listnode __android_log_persist_read = {
- &__android_log_persist_read, &__android_log_persist_read
-};
+LIBLOG_HIDDEN struct listnode __android_log_transport_read = {&__android_log_transport_read,
+ &__android_log_transport_read};
+LIBLOG_HIDDEN 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) {
- size_t i;
+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)(i) >= 0)) {
+ if (!transport->available || ((*transport->available)(static_cast<log_id_t>(i)) >= 0)) {
list_add_tail(list, &transport->node);
return;
}
@@ -44,8 +42,8 @@
if (!transp->available) {
return;
}
- if (((*transp->available)(i) < 0) &&
- (!transport->available || ((*transport->available)(i) >= 0))) {
+ 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;
}
@@ -55,15 +53,8 @@
}
LIBLOG_HIDDEN void __android_log_config_read() {
- if (__android_log_transport & LOGGER_LOCAL) {
- extern struct android_log_transport_read localLoggerRead;
-
- __android_log_add_transport(&__android_log_transport_read, &localLoggerRead);
- }
-
#if (FAKE_LOG_DEVICE == 0)
- if ((__android_log_transport == LOGGER_DEFAULT) ||
- (__android_log_transport & LOGGER_LOGD)) {
+ 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;
diff --git a/liblog/config_read.h b/liblog/config_read.h
index 7b29fa4..00ea453 100644
--- a/liblog/config_read.h
+++ b/liblog/config_read.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBLOG_CONFIG_READ_H__
-#define _LIBLOG_CONFIG_READ_H__
+#pragma once
#include <cutils/list.h>
@@ -51,5 +50,3 @@
LIBLOG_HIDDEN void __android_log_config_read_close();
__END_DECLS
-
-#endif /* _LIBLOG_CONFIG_READ_H__ */
diff --git a/liblog/config_write.c b/liblog/config_write.cpp
similarity index 66%
rename from liblog/config_write.c
rename to liblog/config_write.cpp
index 0a8b52f..e65c238 100644
--- a/liblog/config_write.c
+++ b/liblog/config_write.cpp
@@ -19,23 +19,21 @@
#include "config_write.h"
#include "logger.h"
-LIBLOG_HIDDEN struct listnode __android_log_transport_write = {
- &__android_log_transport_write, &__android_log_transport_write
-};
-LIBLOG_HIDDEN struct listnode __android_log_persist_write = {
- &__android_log_persist_write, &__android_log_persist_write
-};
+LIBLOG_HIDDEN struct listnode __android_log_transport_write = {&__android_log_transport_write,
+ &__android_log_transport_write};
+LIBLOG_HIDDEN 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) {
- size_t i;
+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)(i) >= 0)) {
+ if (!transport->available || ((*transport->available)(static_cast<log_id_t>(i)) >= 0)) {
list_add_tail(list, &transport->node);
return;
}
@@ -44,8 +42,8 @@
if (!transp->available) {
return;
}
- if (((*transp->available)(i) < 0) &&
- (!transport->available || ((*transport->available)(i) >= 0))) {
+ 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;
}
@@ -55,27 +53,17 @@
}
LIBLOG_HIDDEN void __android_log_config_write() {
- if (__android_log_transport & LOGGER_LOCAL) {
- extern struct android_log_transport_write localLoggerWrite;
-
- __android_log_add_transport(&__android_log_transport_write,
- &localLoggerWrite);
- }
-
- if ((__android_log_transport == LOGGER_DEFAULT) ||
- (__android_log_transport & LOGGER_LOGD)) {
+ 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_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);
+ __android_log_add_transport(&__android_log_transport_write, &fakeLoggerWrite);
#endif
}
@@ -88,8 +76,7 @@
* 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);
+ __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) {
@@ -97,8 +84,7 @@
return;
}
}
- __android_log_add_transport(&__android_log_persist_write,
- &stderrLoggerWrite);
+ __android_log_add_transport(&__android_log_persist_write, &stderrLoggerWrite);
}
}
}
diff --git a/liblog/config_write.h b/liblog/config_write.h
index db1a083..e3be445 100644
--- a/liblog/config_write.h
+++ b/liblog/config_write.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBLOG_CONFIG_WRITE_H__
-#define _LIBLOG_CONFIG_WRITE_H__
+#pragma once
#include <cutils/list.h>
@@ -51,5 +50,3 @@
LIBLOG_HIDDEN void __android_log_config_write_close();
__END_DECLS
-
-#endif /* _LIBLOG_CONFIG_WRITE_H__ */
diff --git a/liblog/event_tag_map.cpp b/liblog/event_tag_map.cpp
index 2e2bf87..574a386 100644
--- a/liblog/event_tag_map.cpp
+++ b/liblog/event_tag_map.cpp
@@ -72,7 +72,7 @@
explicit MapString(const std::string& str)
: alloc(new std::string(str)), str(alloc->data(), alloc->length()) {
}
- MapString(MapString&& rval)
+ MapString(MapString&& rval) noexcept
: alloc(rval.alloc), str(rval.data(), rval.length()) {
rval.alloc = NULL;
}
diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.cpp
similarity index 88%
rename from liblog/fake_log_device.c
rename to liblog/fake_log_device.cpp
index 1483c24..5daae41 100644
--- a/liblog/fake_log_device.c
+++ b/liblog/fake_log_device.cpp
@@ -17,6 +17,9 @@
* Intercepts log messages intended for the Android log device.
* Messages are printed to stderr.
*/
+
+#include "fake_log_device.h"
+
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -30,9 +33,7 @@
#include <time.h>
#include <android/log.h>
-#include <log/uio.h>
-#include "fake_log_device.h"
#include "log_portability.h"
#define kMaxTagLen 16 /* from the long-dead utils/Log.cpp */
@@ -181,8 +182,7 @@
logState->debugName[sizeof(logState->debugName) - 1] = '\0';
/* identify binary logs */
- if (!strcmp(pathName + kDevLogLen, "events") ||
- !strcmp(pathName + kDevLogLen, "security")) {
+ if (!strcmp(pathName + kDevLogLen, "events") || !strcmp(pathName + kDevLogLen, "security")) {
logState->isBinary = 1;
}
@@ -204,8 +204,7 @@
while (isspace(*tags)) tags++;
i = 0;
- while (*tags != '\0' && !isspace(*tags) && *tags != ':' &&
- i < kMaxTagLen) {
+ while (*tags != '\0' && !isspace(*tags) && *tags != ':' && i < kMaxTagLen) {
tagName[i++] = *tags++;
}
if (i == kMaxTagLen) {
@@ -313,13 +312,11 @@
*/
static const char* getPriorityString(int priority) {
/* the first character of each string should be unique */
- static const char* priorityStrings[] = { "Verbose", "Debug", "Info",
- "Warn", "Error", "Assert" };
+ static const char* priorityStrings[] = {"Verbose", "Debug", "Info", "Warn", "Error", "Assert"};
int idx;
idx = (int)priority - (int)ANDROID_LOG_VERBOSE;
- if (idx < 0 ||
- idx >= (int)(sizeof(priorityStrings) / sizeof(priorityStrings[0])))
+ if (idx < 0 || idx >= (int)(sizeof(priorityStrings) / sizeof(priorityStrings[0])))
return "?unknown?";
return priorityStrings[idx];
}
@@ -351,8 +348,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(LogState* state, int logPrio, const char* tag, const char* msg) {
#if !defined(_WIN32)
struct tm tmBuf;
#endif
@@ -397,19 +393,16 @@
switch (state->outputFormat) {
case FORMAT_TAG:
- prefixLen =
- snprintf(prefixBuf, sizeof(prefixBuf), "%c/%-8s: ", priChar, tag);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c/%-8s: ", priChar, tag);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
case FORMAT_PROCESS:
- prefixLen =
- snprintf(prefixBuf, sizeof(prefixBuf), "%c(%5d) ", priChar, pid);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c(%5d) ", priChar, pid);
suffixLen = snprintf(suffixBuf, sizeof(suffixBuf), " (%s)\n", tag);
break;
case FORMAT_THREAD:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c(%5d:%5d) ",
- priChar, pid, tid);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c(%5d:%5d) ", priChar, pid, tid);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
@@ -420,28 +413,24 @@
suffixLen = 1;
break;
case FORMAT_TIME:
- prefixLen =
- snprintf(prefixBuf, sizeof(prefixBuf), "%s %-8s\n\t", timeBuf, tag);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%s %-8s\n\t", timeBuf, tag);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
case FORMAT_THREADTIME:
- prefixLen =
- snprintf(prefixBuf, sizeof(prefixBuf), "%s %5d %5d %c %-8s \n\t",
- timeBuf, pid, tid, priChar, tag);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%s %5d %5d %c %-8s \n\t", timeBuf, pid,
+ tid, priChar, tag);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
case FORMAT_LONG:
- prefixLen =
- snprintf(prefixBuf, sizeof(prefixBuf), "[ %s %5d:%5d %c/%-8s ]\n",
- timeBuf, pid, tid, priChar, tag);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "[ %s %5d:%5d %c/%-8s ]\n", timeBuf, pid,
+ tid, priChar, tag);
strcpy(suffixBuf, "\n\n");
suffixLen = 2;
break;
default:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%c/%-8s(%5d): ", priChar, tag, pid);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c/%-8s(%5d): ", priChar, tag, pid);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
@@ -559,8 +548,7 @@
* tag (N bytes -- null-terminated ASCII string)
* message (N bytes -- null-terminated ASCII string)
*/
-LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, const struct iovec* vector,
- int count) {
+LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count) {
LogState* state;
/* Make sure that no-one frees the LogState while we're using it.
@@ -572,17 +560,24 @@
state = fdToLogState(fd);
if (state == NULL) {
errno = EBADF;
- goto error;
+ unlock();
+ return -1;
}
if (state->isBinary) {
TRACE("%s: ignoring binary log\n", state->debugName);
- goto bail;
+ unlock();
+ int len = 0;
+ for (int 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);
- goto error;
+ unlock();
+ return -1;
}
/* pull out the three fields */
@@ -598,7 +593,6 @@
break; /* reached end of configured values */
if (strcmp(state->tagSet[i].tag, tag) == 0) {
- // TRACE("MATCH tag '%s'\n", tag);
minPrio = state->tagSet[i].minPriority;
break;
}
@@ -606,21 +600,14 @@
if (logPrio >= minPrio) {
showLog(state, logPrio, tag, msg);
- } else {
- // TRACE("+++ NOLOG(%d): %s %s", logPrio, tag, msg);
}
-bail:
unlock();
int len = 0;
for (i = 0; i < count; ++i) {
len += vector[i].iov_len;
}
return len;
-
-error:
- unlock();
- return -1;
}
/*
@@ -663,22 +650,16 @@
return fd;
}
-LIBLOG_HIDDEN ssize_t __send_log_msg(char* buf __unused,
- size_t buf_size __unused) {
+LIBLOG_HIDDEN ssize_t __send_log_msg(char*, size_t) {
return -ENODEV;
}
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio,
- const char* tag __unused,
- int def) {
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char*, int def) {
int logLevel = def;
return logLevel >= 0 && prio >= logLevel;
}
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio,
- const char* tag __unused,
- size_t len __unused,
- int def) {
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char*, size_t, int def) {
int logLevel = def;
return logLevel >= 0 && prio >= logLevel;
}
diff --git a/liblog/fake_log_device.h b/liblog/fake_log_device.h
index 7b0e745..ef0beb6 100644
--- a/liblog/fake_log_device.h
+++ b/liblog/fake_log_device.h
@@ -14,18 +14,25 @@
* limitations under the License.
*/
-#ifndef _LIBLOG_FAKE_LOG_DEVICE_H
-#define _LIBLOG_FAKE_LOG_DEVICE_H
+#pragma once
#include <sys/types.h>
#include "log_portability.h"
+#include "uio.h"
struct iovec;
+__BEGIN_DECLS
+
LIBLOG_HIDDEN int fakeLogOpen(const char* pathName);
LIBLOG_HIDDEN int fakeLogClose(int fd);
LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, const struct iovec* vector,
int count);
-#endif // _LIBLOG_FAKE_LOG_DEVICE_H
+LIBLOG_HIDDEN ssize_t __send_log_msg(char*, size_t);
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char*, int def);
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char*, size_t, int def);
+LIBLOG_ABI_PRIVATE int __android_log_is_debuggable();
+
+__END_DECLS
diff --git a/liblog/fake_writer.c b/liblog/fake_writer.cpp
similarity index 82%
rename from liblog/fake_writer.c
rename to liblog/fake_writer.cpp
index 403dc72..46d171b 100644
--- a/liblog/fake_writer.c
+++ b/liblog/fake_writer.cpp
@@ -27,19 +27,18 @@
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 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 };
+static int logFds[(int)LOG_ID_MAX] = {-1, -1, -1, -1, -1, -1};
LIBLOG_HIDDEN struct android_log_transport_write fakeLoggerWrite = {
- .node = { &fakeLoggerWrite.node, &fakeLoggerWrite.node },
- .context.priv = &logFds,
- .name = "fake",
- .available = NULL,
- .open = fakeOpen,
- .close = fakeClose,
- .write = fakeWrite,
+ .node = {&fakeLoggerWrite.node, &fakeLoggerWrite.node},
+ .context.priv = &logFds,
+ .name = "fake",
+ .available = NULL,
+ .open = fakeOpen,
+ .close = fakeClose,
+ .write = fakeWrite,
};
static int fakeOpen() {
@@ -54,7 +53,7 @@
if (logFds[i] >= 0) {
continue;
}
- snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
+ 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);
@@ -72,8 +71,7 @@
}
}
-static int fakeWrite(log_id_t log_id, struct timespec* ts __unused,
- struct iovec* vec, size_t nr) {
+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;
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index ee9220d..b2f0ed9 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -14,25 +14,7 @@
* limitations under the License.
*/
-#ifndef _ANDROID_LOG_H
-#define _ANDROID_LOG_H
-
-/******************************************************************
- *
- * IMPORTANT NOTICE:
- *
- * This file is part of Android's set of stable system headers
- * exposed by the Android NDK (Native Development Kit) since
- * platform release 1.5
- *
- * Third-party source AND binary code relies on the definitions
- * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
- *
- * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
- * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
- * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
- * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
- */
+#pragma once
/**
* @addtogroup Logging
@@ -154,27 +136,51 @@
#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().
+ */
typedef enum log_id {
LOG_ID_MIN = 0,
+ /** The main log buffer. This is the only log buffer available to apps. */
LOG_ID_MAIN = 0,
+ /** The radio log buffer. */
LOG_ID_RADIO = 1,
+ /** The event log buffer. */
LOG_ID_EVENTS = 2,
+ /** The system log buffer. */
LOG_ID_SYSTEM = 3,
+ /** The crash log buffer. */
LOG_ID_CRASH = 4,
+ /** The statistics log buffer. */
LOG_ID_STATS = 5,
+ /** The security log buffer. */
LOG_ID_SECURITY = 6,
- LOG_ID_KERNEL = 7, /* place last, third-parties can not use it */
+ /** The kernel log buffer. */
+ LOG_ID_KERNEL = 7,
LOG_ID_MAX
} log_id_t;
#endif
-/*
- * Send a simple string to the log.
+/**
+ * Writes the constant string `text` to the log buffer `id`,
+ * with priority `prio` and tag `tag`.
+ *
+ * Apps should use __android_log_write() instead.
*/
int __android_log_buf_write(int bufID, int prio, const char* tag,
const char* text);
+
+/**
+ * Writes a formatted string to log buffer `id`,
+ * with priority `prio` and tag `tag`.
+ * The details of formatting are the same as for
+ * [printf(3)](http://man7.org/linux/man-pages/man3/printf.3.html).
+ *
+ * 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__)
@@ -187,5 +193,3 @@
#endif
/** @} */
-
-#endif /* _ANDROID_LOG_H */
diff --git a/liblog/include/log/event_tag_map.h b/liblog/include/log/event_tag_map.h
index 8dd9157..2687b3a 100644
--- a/liblog/include/log/event_tag_map.h
+++ b/liblog/include/log/event_tag_map.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBS_CUTILS_EVENTTAGMAP_H
-#define _LIBS_CUTILS_EVENTTAGMAP_H
+#pragma once
#ifdef __cplusplus
extern "C" {
@@ -69,5 +68,3 @@
#ifdef __cplusplus
}
#endif
-
-#endif /*_LIBS_CUTILS_EVENTTAGMAP_H*/
diff --git a/liblog/include/log/log.h b/liblog/include/log/log.h
index 3813e6e..5928649 100644
--- a/liblog/include/log/log.h
+++ b/liblog/include/log/log.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_H
-#define _LIBS_LOG_LOG_H
+#pragma once
/* Too many in the ecosystem assume these are included */
#if !defined(_WIN32)
@@ -35,7 +34,6 @@
#include <log/log_safetynet.h>
#include <log/log_system.h>
#include <log/log_time.h>
-#include <log/uio.h> /* helper to define iovec for portability */
#ifdef __cplusplus
extern "C" {
@@ -152,35 +150,12 @@
#ifdef __linux__
-#ifndef __ANDROID_USE_LIBLOG_CLOCK_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_CLOCK_INTERFACE 1
-#elif __ANDROID_API__ > 22 /* > Lollipop */
-#define __ANDROID_USE_LIBLOG_CLOCK_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_CLOCK_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_CLOCK_INTERFACE
clockid_t android_log_clockid(void);
-#endif
#endif /* __linux__ */
/* --------------------------------------------------------------------- */
-#ifndef __ANDROID_USE_LIBLOG_CLOSE_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_CLOSE_INTERFACE 1
-#elif __ANDROID_API__ > 18 /* > JellyBean */
-#define __ANDROID_USE_LIBLOG_CLOSE_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_CLOSE_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_CLOSE_INTERFACE
/*
* Release any logger resources (a new log write will immediately re-acquire)
*
@@ -188,54 +163,6 @@
* all O_CLOEXEC so wil self clean on exec().
*/
void __android_log_close(void);
-#endif
-
-#ifndef __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE 1
-#elif __ANDROID_API__ > 25 /* > OC */
-#define __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE
-
-/*
- * if last is NULL, caller _must_ provide a consistent value for seconds.
- *
- * Return -1 if we can not acquire a lock, which below will permit the logging,
- * error on allowing a log message through.
- */
-int __android_log_ratelimit(time_t seconds, time_t* last);
-
-/*
- * Usage:
- *
- * // Global default and state
- * IF_ALOG_RATELIMIT() {
- * ALOG*(...);
- * }
- *
- * // local state, 10 seconds ratelimit
- * static time_t local_state;
- * IF_ALOG_RATELIMIT_LOCAL(10, &local_state) {
- * ALOG*(...);
- * }
- */
-
-#define IF_ALOG_RATELIMIT() if (__android_log_ratelimit(0, NULL) > 0)
-#define IF_ALOG_RATELIMIT_LOCAL(seconds, state) \
- if (__android_log_ratelimit(seconds, state) > 0)
-
-#else
-
-/* No ratelimiting as API unsupported */
-#define IF_ALOG_RATELIMIT() if (1)
-#define IF_ALOG_RATELIMIT_LOCAL(...) if (1)
-
-#endif
#if defined(__clang__)
#pragma clang diagnostic pop
@@ -244,5 +171,3 @@
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_LOG_H */
diff --git a/liblog/include/log/log_event_list.h b/liblog/include/log/log_event_list.h
index 1b7c377..636d417 100644
--- a/liblog/include/log/log_event_list.h
+++ b/liblog/include/log/log_event_list.h
@@ -14,16 +14,13 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_EVENT_LIST_H
-#define _LIBS_LOG_EVENT_LIST_H
+#pragma once
#include <errno.h>
#include <stdint.h>
-#if (defined(__cplusplus) && defined(_USING_LIBCXX))
-extern "C++" {
+#ifdef __cplusplus
#include <string>
-}
#endif
#include <log/log.h>
@@ -32,18 +29,6 @@
extern "C" {
#endif
-#ifndef __ANDROID_USE_LIBLOG_EVENT_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_EVENT_INTERFACE 1
-#elif __ANDROID_API__ > 23 /* > Marshmallow */
-#define __ANDROID_USE_LIBLOG_EVENT_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_EVENT_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_EVENT_INTERFACE
-
/* For manipulating lists of events. */
#define ANDROID_MAX_LIST_NEST_DEPTH 8
@@ -124,8 +109,6 @@
/* android_log_list C++ helpers */
extern "C++" {
class android_log_event_list {
- friend class __android_log_event_list;
-
private:
android_log_context ctx;
int ret;
@@ -137,10 +120,6 @@
explicit android_log_event_list(int tag) : ret(0) {
ctx = create_android_logger(static_cast<uint32_t>(tag));
}
- explicit android_log_event_list(log_msg& log_msg) : ret(0) {
- ctx = create_android_log_parser(log_msg.msg() + sizeof(uint32_t),
- log_msg.entry.len - sizeof(uint32_t));
- }
~android_log_event_list() {
android_log_destroy(&ctx);
}
@@ -208,14 +187,12 @@
return *this;
}
-#if defined(_USING_LIBCXX)
android_log_event_list& operator<<(const std::string& value) {
int retval =
android_log_write_string8_len(ctx, value.data(), value.length());
if (retval < 0) ret = retval;
return *this;
}
-#endif
android_log_event_list& operator<<(float value) {
int retval = android_log_write_float32(ctx, value);
@@ -269,7 +246,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());
@@ -283,7 +259,6 @@
if (retval < 0) ret = retval;
return ret;
}
-#endif
bool AppendFloat(float value) {
int retval = android_log_write_float32(ctx, value);
@@ -302,22 +277,11 @@
if (retval < 0) ret = retval;
return ret >= 0;
}
-
- android_log_list_element read() {
- return android_log_read_next(ctx);
- }
- android_log_list_element peek() {
- return android_log_peek_next(ctx);
- }
};
}
#endif
#endif
-#endif /* __ANDROID_USE_LIBLOG_EVENT_INTERFACE */
-
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_EVENT_LIST_H */
diff --git a/liblog/include/log/log_id.h b/liblog/include/log/log_id.h
index c44f5a2..c052a50 100644
--- a/liblog/include/log/log_id.h
+++ b/liblog/include/log/log_id.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_ID_H
-#define _LIBS_LOG_LOG_ID_H
+#pragma once
#ifdef __cplusplus
extern "C" {
@@ -62,5 +61,3 @@
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_LOG_ID_H */
diff --git a/liblog/include/log/log_main.h b/liblog/include/log/log_main.h
index e7b1728..64791c2 100644
--- a/liblog/include/log/log_main.h
+++ b/liblog/include/log/log_main.h
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_MAIN_H
-#define _LIBS_LOG_LOG_MAIN_H
+#pragma once
#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
#include <android/log.h>
-#include <sys/cdefs.h>
__BEGIN_DECLS
@@ -56,15 +56,24 @@
/*
* Use __VA_ARGS__ if running a static analyzer,
* to avoid warnings of unused variables in __VA_ARGS__.
- * __FAKE_USE_VA_ARGS is undefined at link time,
- * so don't link with __clang_analyzer__ defined.
+ * Use contexpr function in C++ mode, so these macros can be used
+ * in other constexpr functions without warning.
*/
#ifdef __clang_analyzer__
-extern void __fake_use_va_args(int, ...);
-#define __FAKE_USE_VA_ARGS(...) __fake_use_va_args(0, ##__VA_ARGS__)
+#ifdef __cplusplus
+extern "C++" {
+template <typename... Ts>
+constexpr int __fake_use_va_args(Ts...) {
+ return 0;
+}
+}
+#else
+extern int __fake_use_va_args(int, ...);
+#endif /* __cplusplus */
+#define __FAKE_USE_VA_ARGS(...) ((void)__fake_use_va_args(0, ##__VA_ARGS__))
#else
#define __FAKE_USE_VA_ARGS(...) ((void)(0))
-#endif
+#endif /* __clang_analyzer__ */
#ifndef __predict_false
#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
@@ -340,20 +349,6 @@
* over Android.
*/
-#ifndef __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE 2
-#elif __ANDROID_API__ > 24 /* > Nougat */
-#define __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE 2
-#elif __ANDROID_API__ > 22 /* > Lollipop */
-#define __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE
-
/*
* Use the per-tag properties "log.tag.<tagname>" to generate a runtime
* result of non-zero to expose a log. prio is ANDROID_LOG_VERBOSE to
@@ -361,12 +356,7 @@
* any other value.
*/
int __android_log_is_loggable(int prio, const char* tag, int default_prio);
-
-#if __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE > 1
-#include <sys/types.h>
-
-int __android_log_is_loggable_len(int prio, const char* tag, size_t len,
- int default_prio);
+int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio);
#if LOG_NDEBUG /* Production */
#define android_testLog(prio, tag) \
@@ -378,28 +368,8 @@
ANDROID_LOG_VERBOSE) != 0)
#endif
-#else
-
-#if LOG_NDEBUG /* Production */
-#define android_testLog(prio, tag) \
- (__android_log_is_loggable(prio, tag, ANDROID_LOG_DEBUG) != 0)
-#else
-#define android_testLog(prio, tag) \
- (__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE) != 0)
-#endif
-
-#endif
-
-#else /* __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE */
-
-#define android_testLog(prio, tag) (1)
-
-#endif /* !__ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE */
-
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
__END_DECLS
-
-#endif /* _LIBS_LOG_LOG_MAIN_H */
diff --git a/liblog/include/log/log_properties.h b/liblog/include/log/log_properties.h
index 7d398a6..3a8af6d 100644
--- a/liblog/include/log/log_properties.h
+++ b/liblog/include/log/log_properties.h
@@ -7,29 +7,14 @@
** General Public License.
*/
-#ifndef _LIBS_LOG_PROPERTIES_H
-#define _LIBS_LOG_PROPERTIES_H
+#pragma once
#ifdef __cplusplus
extern "C" {
#endif
-#ifndef __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE 1
-#elif __ANDROID_API__ > 24 /* > Nougat */
-#define __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE
int __android_log_is_debuggable();
-#endif
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_PROPERTIES_H */
diff --git a/liblog/include/log/log_radio.h b/liblog/include/log/log_radio.h
index bd629fe..8b8a362 100644
--- a/liblog/include/log/log_radio.h
+++ b/liblog/include/log/log_radio.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_RADIO_H
-#define _LIBS_LOG_LOG_RADIO_H
+#pragma once
#include <android/log.h>
#include <log/log_id.h>
@@ -140,5 +139,3 @@
LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif
-
-#endif /* _LIBS_LOG_LOG_RADIO_H */
diff --git a/liblog/include/log/log_read.h b/liblog/include/log/log_read.h
index 93b9d4e..fdef306 100644
--- a/liblog/include/log/log_read.h
+++ b/liblog/include/log/log_read.h
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_READ_H
-#define _LIBS_LOG_LOG_READ_H
+#pragma once
+
+#include <sys/types.h>
/* deal with possible sys/cdefs.h conflict with fcntl.h */
#ifdef __unused
@@ -47,6 +48,8 @@
* access to raw information, or parsing is an issue.
*/
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wzero-length-array"
/*
* The userspace structure for version 1 of the logger_entry ABI.
*/
@@ -59,9 +62,7 @@
int32_t tid; /* generating process's tid */
int32_t sec; /* seconds since Epoch */
int32_t nsec; /* nanoseconds */
-#ifndef __cplusplus
char msg[0]; /* the entry's payload */
-#endif
};
#endif
@@ -78,9 +79,7 @@
int32_t sec; /* seconds since Epoch */
int32_t nsec; /* nanoseconds */
uint32_t euid; /* effective UID of logger */
-#ifndef __cplusplus
char msg[0]; /* the entry's payload */
-#endif
} __attribute__((__packed__));
#endif
@@ -97,9 +96,7 @@
int32_t sec; /* seconds since Epoch */
int32_t nsec; /* nanoseconds */
uint32_t lid; /* log id of the payload */
-#ifndef __cplusplus
char msg[0]; /* the entry's payload */
-#endif
} __attribute__((__packed__));
#endif
@@ -117,11 +114,10 @@
uint32_t nsec; /* nanoseconds */
uint32_t lid; /* log id of the payload, bottom 4 bits currently */
uint32_t uid; /* generating process's uid */
-#ifndef __cplusplus
char msg[0]; /* the entry's payload */
-#endif
};
#endif
+#pragma clang diagnostic pop
/*
* The maximum size of the log entry payload that can be
@@ -197,22 +193,6 @@
};
#endif
-#ifndef __ANDROID_USE_LIBLOG_READER_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_READER_INTERFACE 3
-#elif __ANDROID_API__ > 23 /* > Marshmallow */
-#define __ANDROID_USE_LIBLOG_READER_INTERFACE 3
-#elif __ANDROID_API__ > 22 /* > Lollipop */
-#define __ANDROID_USE_LIBLOG_READER_INTERFACE 2
-#elif __ANDROID_API__ > 19 /* > KitKat */
-#define __ANDROID_USE_LIBLOG_READER_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_READER_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_READER_INTERFACE
-
struct logger;
log_id_t android_logger_get_id(struct logger* logger);
@@ -225,14 +205,12 @@
struct logger_list;
-#if __ANDROID_USE_LIBLOG_READER_INTERFACE > 1
ssize_t android_logger_get_statistics(struct logger_list* logger_list,
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);
-#endif
#define ANDROID_LOG_RDONLY O_RDONLY
#define ANDROID_LOG_WRONLY O_WRONLY
@@ -243,13 +221,9 @@
#else
#define ANDROID_LOG_NONBLOCK O_NONBLOCK
#endif
-#if __ANDROID_USE_LIBLOG_READER_INTERFACE > 2
#define ANDROID_LOG_WRAP 0x40000000 /* Block until buffer about to wrap */
#define ANDROID_LOG_WRAP_DEFAULT_TIMEOUT 7200 /* 2 hour default */
-#endif
-#if __ANDROID_USE_LIBLOG_READER_INTERFACE > 1
#define ANDROID_LOG_PSTORE 0x80000000
-#endif
struct logger_list* android_logger_list_alloc(int mode, unsigned int tail,
pid_t pid);
@@ -268,10 +242,6 @@
unsigned int tail, pid_t pid);
#define android_logger_list_close android_logger_list_free
-#endif /* __ANDROID_USE_LIBLOG_READER_INTERFACE */
-
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_LOG_H */
diff --git a/liblog/include/log/log_safetynet.h b/liblog/include/log/log_safetynet.h
index 07e8c8a..d3e9b19 100644
--- a/liblog/include/log/log_safetynet.h
+++ b/liblog/include/log/log_safetynet.h
@@ -7,8 +7,7 @@
** General Public License.
*/
-#ifndef _LIBS_LOG_SAFETYNET_H
-#define _LIBS_LOG_SAFETYNET_H
+#pragma once
#include <stdint.h>
@@ -16,18 +15,6 @@
extern "C" {
#endif
-#ifndef _ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE 1
-#elif __ANDROID_API__ > 22 /* > Lollipop */
-#define __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE
-
#define android_errorWriteLog(tag, subTag) \
__android_log_error_write(tag, subTag, -1, NULL, 0)
@@ -37,10 +24,6 @@
int __android_log_error_write(int tag, const char* subTag, int32_t uid,
const char* data, uint32_t dataLen);
-#endif /* __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE */
-
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_SAFETYNET_H */
diff --git a/liblog/include/log/log_system.h b/liblog/include/log/log_system.h
index 3b5ae22..eaec741 100644
--- a/liblog/include/log/log_system.h
+++ b/liblog/include/log/log_system.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_SYSTEM_H
-#define _LIBS_LOG_LOG_SYSTEM_H
+#pragma once
#include <android/log.h>
#include <log/log_id.h>
@@ -138,5 +137,3 @@
LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif
-
-#endif /* _LIBS_LOG_LOG_SYSTEM_H */
diff --git a/liblog/include/log/log_time.h b/liblog/include/log/log_time.h
index 309f5d1..09c9910 100644
--- a/liblog/include/log/log_time.h
+++ b/liblog/include/log/log_time.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_TIME_H
-#define _LIBS_LOG_LOG_TIME_H
+#pragma once
#include <stdint.h>
#include <time.h>
@@ -34,6 +33,8 @@
#ifdef __cplusplus
+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
@@ -41,25 +42,19 @@
*/
struct log_time {
public:
- uint32_t tv_sec; /* good to Feb 5 2106 */
- uint32_t tv_nsec;
+ uint32_t tv_sec = 0; /* good to Feb 5 2106 */
+ uint32_t tv_nsec = 0;
static const uint32_t tv_sec_max = 0xFFFFFFFFUL;
static const uint32_t tv_nsec_max = 999999999UL;
+ static const timespec EPOCH;
- log_time(const timespec& T)
- : tv_sec(static_cast<uint32_t>(T.tv_sec)),
- tv_nsec(static_cast<uint32_t>(T.tv_nsec)) {
- }
+ log_time() {}
+ explicit log_time(const timespec& T)
+ : tv_sec(static_cast<uint32_t>(T.tv_sec)), tv_nsec(static_cast<uint32_t>(T.tv_nsec)) {}
explicit log_time(uint32_t sec, uint32_t nsec = 0)
: tv_sec(sec), tv_nsec(nsec) {
}
-#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
-#define __struct_log_time_private_defined
- static const timespec EPOCH;
-#endif
- log_time() {
- }
#ifdef __linux__
explicit log_time(clockid_t id) {
timespec T;
@@ -103,7 +98,6 @@
return !(*this > T);
}
-#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
log_time operator-=(const timespec& T);
log_time operator-(const timespec& T) const {
log_time local(*this);
@@ -114,7 +108,6 @@
log_time local(*this);
return local += T;
}
-#endif
/* log_time */
bool operator==(const log_time& T) const {
@@ -138,7 +131,6 @@
return !(*this > T);
}
-#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
log_time operator-=(const log_time& T);
log_time operator-(const log_time& T) const {
log_time local(*this);
@@ -149,7 +141,6 @@
log_time local(*this);
return local += T;
}
-#endif
uint64_t nsec() const {
return static_cast<uint64_t>(tv_sec) * NS_PER_SEC + tv_nsec;
@@ -163,13 +154,12 @@
tv_nsec / (NS_PER_SEC / MS_PER_SEC);
}
-#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
static const char default_format[];
/* Add %#q for the fraction of a second to the standard library functions */
char* strptime(const char* s, const char* format = default_format);
-#endif
} __attribute__((__packed__));
+}
#else /* __cplusplus */
@@ -181,5 +171,3 @@
#endif /* __cplusplus */
#endif /* __struct_log_time_defined */
-
-#endif /* _LIBS_LOG_LOG_TIME_H */
diff --git a/liblog/include/log/log_transport.h b/liblog/include/log/log_transport.h
index 80b30db..b48761a 100644
--- a/liblog/include/log/log_transport.h
+++ b/liblog/include/log/log_transport.h
@@ -7,8 +7,7 @@
** General Public License.
*/
-#ifndef _LIBS_LOG_TRANSPORT_H
-#define _LIBS_LOG_TRANSPORT_H
+#pragma once
#ifdef __cplusplus
extern "C" {
@@ -22,7 +21,7 @@
#define LOGGER_LOGD 0x01
#define LOGGER_KERNEL 0x02 /* Reserved/Deprecated */
#define LOGGER_NULL 0x04 /* Does not release resources of other selections */
-#define LOGGER_LOCAL 0x08 /* logs sent to local memory */
+#define LOGGER_RESERVED 0x08 /* Reserved, previously for logging to local memory */
#define LOGGER_STDERR 0x10 /* logs sent to stderr */
/* clang-format on */
@@ -33,5 +32,3 @@
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_TRANSPORT_H */
diff --git a/liblog/include/log/logd.h b/liblog/include/log/logd.h
deleted file mode 100644
index 77400ca..0000000
--- a/liblog/include/log/logd.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef _LIBS_LOG_LOGD_H
-#define _LIBS_LOG_LOGD_H
-#include <log/log.h>
-#warning "Deprecated: do not include log/logd.h, use log/log.h instead"
-#endif /*_LIBS_LOG_LOGD_H*/
diff --git a/liblog/include/log/logger.h b/liblog/include/log/logger.h
deleted file mode 100644
index 1bf2d17..0000000
--- a/liblog/include/log/logger.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef _LIBS_LOG_LOGGER_H
-#define _LIBS_LOG_LOGGER_H
-#include <log/log.h>
-#warning "Deprecated: do not include log/logger.h, use log/log.h instead"
-#endif /*_LIBS_LOG_LOGGER_H*/
diff --git a/liblog/include/log/logprint.h b/liblog/include/log/logprint.h
index ca58bc7..8f4b187 100644
--- a/liblog/include/log/logprint.h
+++ b/liblog/include/log/logprint.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LOGPRINT_H
-#define _LOGPRINT_H
+#pragma once
#include <pthread.h>
@@ -158,5 +157,3 @@
#ifdef __cplusplus
}
#endif
-
-#endif /*_LOGPRINT_H*/
diff --git a/liblog/include/log/uio.h b/liblog/include/log/uio.h
deleted file mode 100644
index a492bae..0000000
--- a/liblog/include/log/uio.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2007-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 _LIBS_CUTILS_UIO_H
-#define _LIBS_CUTILS_UIO_H
-
-#if !defined(_WIN32)
-
-#include <sys/uio.h>
-
-#else
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//
-// Implementation of sys/uio.h for Win32.
-//
-
-#include <stddef.h>
-
-struct iovec {
- void* iov_base;
- size_t iov_len;
-};
-
-extern int readv(int fd, struct iovec* vecs, int count);
-extern int writev(int fd, const struct iovec* vecs, int count);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-#endif /* _LIBS_UTILS_UIO_H */
diff --git a/liblog/include/private/android_logger.h b/liblog/include/private/android_logger.h
index b927b46..5e04148 100644
--- a/liblog/include/private/android_logger.h
+++ b/liblog/include/private/android_logger.h
@@ -16,8 +16,7 @@
/* This file is used to define the internal protocol for the Android Logger */
-#ifndef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
-#define _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
+#pragma once
/* Android private interfaces */
@@ -25,10 +24,8 @@
#include <stdint.h>
#include <sys/types.h>
-#if (defined(__cplusplus) && defined(_USING_LIBCXX))
-extern "C++" {
+#ifdef __cplusplus
#include <string>
-}
#endif
#include <log/log.h>
@@ -153,41 +150,6 @@
/* Retrieve the composed event buffer */
int android_log_write_list_buffer(android_log_context ctx, const char** msg);
-#ifdef __cplusplus
-#ifdef __class_android_log_event_list_defined
-#ifndef __class_android_log_event_list_private_defined
-#define __class_android_log_event_list_private_defined
-/* android_log_context C++ helpers */
-extern "C++" {
-class __android_log_event_list : public android_log_event_list {
- __android_log_event_list(const android_log_event_list&) = delete;
- void operator=(const __android_log_event_list&) = delete;
-
- public:
- explicit __android_log_event_list(int tag) : android_log_event_list(tag) {
- }
- explicit __android_log_event_list(log_msg& log_msg)
- : android_log_event_list(log_msg) {
- }
-
-#if defined(_USING_LIBCXX)
- operator std::string() {
- if (ret) return std::string("");
- const char* cp = nullptr;
- ssize_t len = android_log_write_list_buffer(ctx, &cp);
- if (len < 0) ret = len;
- if (!cp || (len <= 0)) return std::string("");
- return std::string(cp, len);
- }
-#endif
-};
-}
-#endif
-#endif
-#endif
-
#if defined(__cplusplus)
}
#endif
-
-#endif /* _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_ */
diff --git a/liblog/include_vndk/log/log_event_list.h b/liblog/include_vndk/log/log_event_list.h
index 9f74534..1f3dd37 100644
--- a/liblog/include_vndk/log/log_event_list.h
+++ b/liblog/include_vndk/log/log_event_list.h
@@ -27,8 +27,6 @@
extern "C" {
#endif
-#define __ANDROID_USE_LIBLOG_EVENT_INTERFACE 1
-
/*
* The opaque context used to manipulate lists of events.
*/
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index 015c9cb..191ef1b 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -59,3 +59,24 @@
android_log_reset; #vndk
android_log_parser_reset; #vndk
};
+
+LIBLOG_PRIVATE {
+ global:
+ __android_log_bswrite;
+ __android_log_btwrite;
+ __android_log_bwrite;
+ __android_log_close;
+ __android_log_pmsg_file_read;
+ __android_log_pmsg_file_write;
+ __android_log_security;
+ __android_log_security_bswrite;
+ __android_logger_get_buffer_size;
+ __android_logger_property_get_bool;
+ android_openEventTagMap;
+ android_log_processBinaryLogBuffer;
+ android_log_processLogBuffer;
+ android_log_read_next;
+ android_log_write_list_buffer;
+ android_lookupEventTagNum;
+ create_android_log_parser;
+};
diff --git a/liblog/local_logger.c b/liblog/local_logger.c
deleted file mode 100644
index 563cb3f..0000000
--- a/liblog/local_logger.c
+++ /dev/null
@@ -1,550 +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 <fcntl.h>
-#include <pthread.h>
-#if !defined(__MINGW32__)
-#include <pwd.h>
-#endif
-#include <log/uio.h>
-#include <sched.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include <cutils/list.h> /* template, no library dependency */
-#include <log/log_transport.h>
-#include <private/android_filesystem_config.h>
-#include <private/android_logger.h>
-#include <system/thread_defs.h>
-
-#include "config_read.h"
-#include "config_write.h"
-#include "log_portability.h"
-#include "logger.h"
-
-static const char baseServiceName[] = "android.logd";
-
-static int writeToLocalInit();
-static int writeToLocalAvailable(log_id_t logId);
-static void writeToLocalReset();
-static int writeToLocalWrite(log_id_t logId, struct timespec* ts,
- struct iovec* vec, size_t nr);
-
-LIBLOG_HIDDEN struct android_log_transport_write localLoggerWrite = {
- .node = { &localLoggerWrite.node, &localLoggerWrite.node },
- .context.priv = NULL,
- .name = "local",
- .available = writeToLocalAvailable,
- .open = writeToLocalInit,
- .close = writeToLocalReset,
- .write = writeToLocalWrite,
-};
-
-static int writeToLocalVersion(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-static int writeToLocalRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp,
- struct log_msg* log_msg);
-static int writeToLocalPoll(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp);
-static void writeToLocalClose(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp);
-static int writeToLocalClear(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-static ssize_t writeToLocalGetSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-static ssize_t writeToLocalSetSize(
- struct android_log_logger* logger,
- struct android_log_transport_context* transp __unused, size_t size);
-static ssize_t writeToLocalGetReadbleSize(
- struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-
-struct android_log_transport_read localLoggerRead = {
- .node = { &localLoggerRead.node, &localLoggerRead.node },
- .name = "local",
- .available = writeToLocalAvailable,
- .version = writeToLocalVersion,
- .read = writeToLocalRead,
- .poll = writeToLocalPoll,
- .close = writeToLocalClose,
- .clear = writeToLocalClear,
- .getSize = writeToLocalGetSize,
- .setSize = writeToLocalSetSize,
- .getReadableSize = writeToLocalGetReadbleSize,
- .getPrune = NULL,
- .setPrune = NULL,
- .getStats = NULL,
-};
-
-struct LogBufferElement {
- struct listnode node;
- log_id_t logId;
- pid_t tid;
- log_time timestamp;
- unsigned short len;
- char msg[];
-};
-
-static const size_t MAX_SIZE_DEFAULT = 32768;
-
-/*
- * Number of log buffers we support with the following assumption:
- * . . .
- * LOG_ID_SECURITY = 5, // security logs go to the system logs only
- * LOG_ID_KERNEL = 6, // place last, third-parties can not use it
- * LOG_ID_MAX
- * } log_id_t;
- *
- * Confirm the following should <log/log_id.h> be adjusted in the future.
- */
-#define NUMBER_OF_LOG_BUFFERS \
- ((LOG_ID_SECURITY == (LOG_ID_MAX - 2)) ? LOG_ID_SECURITY : LOG_ID_KERNEL)
-#define BLOCK_LOG_BUFFERS(id) \
- (((id) == LOG_ID_SECURITY) || ((id) == LOG_ID_KERNEL))
-
-static struct LogBuffer {
- struct listnode head;
- pthread_rwlock_t listLock;
- char* serviceName; /* Also indicates ready by having a value */
- /* Order and proximity important for memset */
- size_t number[NUMBER_OF_LOG_BUFFERS]; /* clear memset */
- size_t size[NUMBER_OF_LOG_BUFFERS]; /* clear memset */
- size_t totalSize[NUMBER_OF_LOG_BUFFERS]; /* init memset */
- size_t maxSize[NUMBER_OF_LOG_BUFFERS]; /* init MAX_SIZE_DEFAULT */
- struct listnode* last[NUMBER_OF_LOG_BUFFERS]; /* init &head */
-} logbuf = {
- .head = { &logbuf.head, &logbuf.head }, .listLock = PTHREAD_RWLOCK_INITIALIZER,
-};
-
-static void LogBufferInit(struct LogBuffer* log) {
- size_t i;
-
- pthread_rwlock_wrlock(&log->listLock);
- list_init(&log->head);
- memset(log->number, 0,
- sizeof(log->number) + sizeof(log->size) + sizeof(log->totalSize));
- for (i = 0; i < NUMBER_OF_LOG_BUFFERS; ++i) {
- log->maxSize[i] = MAX_SIZE_DEFAULT;
- log->last[i] = &log->head;
- }
-#ifdef __BIONIC__
- asprintf(&log->serviceName, "%s@%d:%d", baseServiceName, __android_log_uid(),
- getpid());
-#else
- char buffer[sizeof(baseServiceName) + 1 + 5 + 1 + 5 + 8];
- snprintf(buffer, sizeof(buffer), "%s@%d:%d", baseServiceName,
- __android_log_uid(), getpid());
- log->serviceName = strdup(buffer);
-#endif
- pthread_rwlock_unlock(&log->listLock);
-}
-
-static void LogBufferClear(struct LogBuffer* log) {
- size_t i;
- struct listnode* node;
-
- pthread_rwlock_wrlock(&log->listLock);
- memset(log->number, 0, sizeof(log->number) + sizeof(log->size));
- for (i = 0; i < NUMBER_OF_LOG_BUFFERS; ++i) {
- log->last[i] = &log->head;
- }
- while ((node = list_head(&log->head)) != &log->head) {
- struct LogBufferElement* element;
-
- element = node_to_item(node, struct LogBufferElement, node);
- list_remove(node);
- free(element);
- }
- pthread_rwlock_unlock(&log->listLock);
-}
-
-static inline void LogBufferFree(struct LogBuffer* log) {
- pthread_rwlock_wrlock(&log->listLock);
- free(log->serviceName);
- log->serviceName = NULL;
- pthread_rwlock_unlock(&log->listLock);
- LogBufferClear(log);
-}
-
-static int LogBufferLog(struct LogBuffer* log,
- struct LogBufferElement* element) {
- log_id_t logId = element->logId;
-
- pthread_rwlock_wrlock(&log->listLock);
- log->number[logId]++;
- log->size[logId] += element->len;
- log->totalSize[logId] += element->len;
- /* prune entry(s) until enough space is available */
- if (log->last[logId] == &log->head) {
- log->last[logId] = list_tail(&log->head);
- }
- while (log->size[logId] > log->maxSize[logId]) {
- struct listnode* node = log->last[logId];
- struct LogBufferElement* e;
- struct android_log_logger_list* logger_list;
-
- e = node_to_item(node, struct LogBufferElement, node);
- log->number[logId]--;
- log->size[logId] -= e->len;
- logger_list_rdlock();
- logger_list_for_each(logger_list) {
- struct android_log_transport_context* transp;
-
- transport_context_for_each(transp, logger_list) {
- if ((transp->transport == &localLoggerRead) &&
- (transp->context.node == node)) {
- if (node == &log->head) {
- transp->context.node = &log->head;
- } else {
- transp->context.node = node->next;
- }
- }
- }
- }
- logger_list_unlock();
- if (node != &log->head) {
- log->last[logId] = node->prev;
- }
- list_remove(node);
- LOG_ALWAYS_FATAL_IF(node == log->last[logId], "corrupted list");
- free(e);
- }
- /* add entry to list */
- list_add_head(&log->head, &element->node);
- /* ToDo: wake up all readers */
- pthread_rwlock_unlock(&log->listLock);
-
- return element->len;
-}
-
-/*
- * return zero if permitted to log directly to logd,
- * return 1 if binder server started and
- * return negative error number if failed to start binder server.
- */
-static int writeToLocalInit() {
- pthread_attr_t attr;
- struct LogBuffer* log;
-
- if (writeToLocalAvailable(LOG_ID_MAIN) < 0) {
- return -EPERM;
- }
-
- log = &logbuf;
- if (!log->serviceName) {
- LogBufferInit(log);
- }
-
- if (!log->serviceName) {
- LogBufferFree(log);
- return -ENOMEM;
- }
-
- return EPERM; /* successful local-only logging */
-}
-
-static void writeToLocalReset() {
- LogBufferFree(&logbuf);
-}
-
-static int writeToLocalAvailable(log_id_t logId) {
-#if !defined(__MINGW32__)
- uid_t uid;
-#endif
-
- if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
- return -EINVAL;
- }
-
-/* Android hard coded permitted, system goes to logd */
-#if !defined(__MINGW32__)
- if (__android_log_transport == LOGGER_DEFAULT) {
- uid = __android_log_uid();
- if ((uid < AID_APP) && (getpwuid(uid) != NULL)) {
- return -EPERM;
- }
- }
-#endif
-
- /* ToDo: Ask package manager for LOGD permissions */
- /* Assume we do _not_ have permissions to go to LOGD, so must go local */
- return 0;
-}
-
-static int writeToLocalWrite(log_id_t logId, struct timespec* ts,
- struct iovec* vec, size_t nr) {
- size_t len, i;
- struct LogBufferElement* element;
-
- if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
- 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;
- }
- element = (struct LogBufferElement*)calloc(
- 1, sizeof(struct LogBufferElement) + len + 1);
- if (!element) {
- return errno ? -errno : -ENOMEM;
- }
- element->timestamp.tv_sec = ts->tv_sec;
- element->timestamp.tv_nsec = ts->tv_nsec;
-#ifdef __BIONIC__
- element->tid = gettid();
-#else
- element->tid = getpid();
-#endif
- element->logId = logId;
- element->len = len;
-
- char* cp = element->msg;
- for (i = 0; i < nr; ++i) {
- size_t iov_len = vec[i].iov_len;
- if (iov_len > len) {
- iov_len = len;
- }
- memcpy(cp, vec[i].iov_base, iov_len);
- len -= iov_len;
- if (len == 0) {
- break;
- }
- cp += iov_len;
- }
-
- return LogBufferLog(&logbuf, element);
-}
-
-static int writeToLocalVersion(struct android_log_logger* logger __unused,
- struct android_log_transport_context* transp
- __unused) {
- return 3;
-}
-
-/* within reader lock, serviceName already validated */
-static struct listnode* writeToLocalNode(
- struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp) {
- struct listnode* node;
- unsigned logMask;
- unsigned int tail;
-
- node = transp->context.node;
- if (node) {
- return node;
- }
-
- if (!logger_list->tail) {
- return transp->context.node = &logbuf.head;
- }
-
- logMask = transp->logMask;
- tail = logger_list->tail;
-
- for (node = list_head(&logbuf.head); node != &logbuf.head; node = node->next) {
- struct LogBufferElement* element;
- log_id_t logId;
-
- element = node_to_item(node, struct LogBufferElement, node);
- logId = element->logId;
-
- if ((logMask & (1 << logId)) && !--tail) {
- node = node->next;
- break;
- }
- }
- return transp->context.node = node;
-}
-
-static int writeToLocalRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp,
- struct log_msg* log_msg) {
- int ret;
- struct listnode* node;
- unsigned logMask;
-
- pthread_rwlock_rdlock(&logbuf.listLock);
- if (!logbuf.serviceName) {
- pthread_rwlock_unlock(&logbuf.listLock);
- return (logger_list->mode & ANDROID_LOG_NONBLOCK) ? -ENODEV : 0;
- }
-
- logMask = transp->logMask;
-
- node = writeToLocalNode(logger_list, transp);
-
- ret = 0;
-
- while (node != list_head(&logbuf.head)) {
- struct LogBufferElement* element;
- log_id_t logId;
-
- node = node->prev;
- element = node_to_item(node, struct LogBufferElement, node);
- logId = element->logId;
-
- if (logMask & (1 << logId)) {
- ret = log_msg->entry_v3.len = element->len;
- log_msg->entry_v3.hdr_size = sizeof(log_msg->entry_v3);
- log_msg->entry_v3.pid = getpid();
- log_msg->entry_v3.tid = element->tid;
- log_msg->entry_v3.sec = element->timestamp.tv_sec;
- log_msg->entry_v3.nsec = element->timestamp.tv_nsec;
- log_msg->entry_v3.lid = logId;
- memcpy(log_msg->entry_v3.msg, element->msg, ret);
- ret += log_msg->entry_v3.hdr_size;
- break;
- }
- }
-
- transp->context.node = node;
-
- /* ToDo: if blocking, and no entry, put reader to sleep */
- pthread_rwlock_unlock(&logbuf.listLock);
- return ret;
-}
-
-static int writeToLocalPoll(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp) {
- int ret = (logger_list->mode & ANDROID_LOG_NONBLOCK) ? -ENODEV : 0;
-
- pthread_rwlock_rdlock(&logbuf.listLock);
-
- if (logbuf.serviceName) {
- unsigned logMask = transp->logMask;
- struct listnode* node = writeToLocalNode(logger_list, transp);
-
- ret = (node != list_head(&logbuf.head));
- if (ret) {
- do {
- ret = !!(logMask &
- (1 << (node_to_item(node->prev, struct LogBufferElement, node))
- ->logId));
- } while (!ret && ((node = node->prev) != list_head(&logbuf.head)));
- }
-
- transp->context.node = node;
- }
-
- pthread_rwlock_unlock(&logbuf.listLock);
-
- return ret;
-}
-
-static void writeToLocalClose(struct android_log_logger_list* logger_list
- __unused,
- struct android_log_transport_context* transp) {
- pthread_rwlock_wrlock(&logbuf.listLock);
- transp->context.node = list_head(&logbuf.head);
- pthread_rwlock_unlock(&logbuf.listLock);
-}
-
-static int writeToLocalClear(struct android_log_logger* logger,
- struct android_log_transport_context* unused
- __unused) {
- log_id_t logId = logger->logId;
- struct listnode *node, *n;
-
- if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
- return -EINVAL;
- }
-
- pthread_rwlock_wrlock(&logbuf.listLock);
- logbuf.number[logId] = 0;
- logbuf.last[logId] = &logbuf.head;
- list_for_each_safe(node, n, &logbuf.head) {
- struct LogBufferElement* element;
- element = node_to_item(node, struct LogBufferElement, node);
-
- if (logId == element->logId) {
- struct android_log_logger_list* logger_list;
-
- logger_list_rdlock();
- logger_list_for_each(logger_list) {
- struct android_log_transport_context* transp;
-
- transport_context_for_each(transp, logger_list) {
- if ((transp->transport == &localLoggerRead) &&
- (transp->context.node == node)) {
- transp->context.node = node->next;
- }
- }
- }
- logger_list_unlock();
- list_remove(node);
- free(element);
- }
- }
-
- pthread_rwlock_unlock(&logbuf.listLock);
-
- return 0;
-}
-
-static ssize_t writeToLocalGetSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp
- __unused) {
- ssize_t ret = -EINVAL;
- log_id_t logId = logger->logId;
-
- if ((logId < NUMBER_OF_LOG_BUFFERS) && !BLOCK_LOG_BUFFERS(logId)) {
- pthread_rwlock_rdlock(&logbuf.listLock);
- ret = logbuf.maxSize[logId];
- pthread_rwlock_unlock(&logbuf.listLock);
- }
-
- return ret;
-}
-
-static ssize_t writeToLocalSetSize(
- struct android_log_logger* logger,
- struct android_log_transport_context* transp __unused, size_t size) {
- ssize_t ret = -EINVAL;
-
- if ((size > LOGGER_ENTRY_MAX_LEN) || (size < (4 * 1024 * 1024))) {
- log_id_t logId = logger->logId;
- if ((logId < NUMBER_OF_LOG_BUFFERS) || !BLOCK_LOG_BUFFERS(logId)) {
- pthread_rwlock_wrlock(&logbuf.listLock);
- ret = logbuf.maxSize[logId] = size;
- pthread_rwlock_unlock(&logbuf.listLock);
- }
- }
-
- return ret;
-}
-
-static ssize_t writeToLocalGetReadbleSize(
- struct android_log_logger* logger,
- struct android_log_transport_context* transp __unused) {
- ssize_t ret = -EINVAL;
- log_id_t logId = logger->logId;
-
- if ((logId < NUMBER_OF_LOG_BUFFERS) && !BLOCK_LOG_BUFFERS(logId)) {
- pthread_rwlock_rdlock(&logbuf.listLock);
- ret = logbuf.serviceName ? (ssize_t)logbuf.size[logId] : -EBADF;
- pthread_rwlock_unlock(&logbuf.listLock);
- }
-
- return ret;
-}
diff --git a/liblog/log_event_list.c b/liblog/log_event_list.cpp
similarity index 88%
rename from liblog/log_event_list.c
rename to liblog/log_event_list.cpp
index 14002ce..088ea94 100644
--- a/liblog/log_event_list.c
+++ b/liblog/log_event_list.cpp
@@ -29,21 +29,26 @@
#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
-typedef struct {
+enum ReadWriteFlag {
+ kAndroidLoggerRead = 1,
+ kAndroidLoggerWrite = 2,
+};
+
+struct android_log_context_internal {
uint32_t tag;
- unsigned pos; /* Read/write position into buffer */
+ 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;
+ ReadWriteFlag read_write_flag;
uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
-} android_log_context_internal;
+};
+
+// 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;
@@ -60,8 +65,8 @@
context->pos += needed;
}
-static void init_parser_context(android_log_context_internal* context,
- const char* msg, size_t len) {
+static void init_parser_context(android_log_context_internal* context, const char* msg,
+ size_t len) {
len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD;
context->len = len;
memcpy(context->storage, msg, len);
@@ -71,7 +76,8 @@
LIBLOG_ABI_PUBLIC android_log_context create_android_logger(uint32_t tag) {
android_log_context_internal* context;
- context = calloc(1, sizeof(android_log_context_internal));
+ context =
+ static_cast<android_log_context_internal*>(calloc(1, sizeof(android_log_context_internal)));
if (!context) {
return NULL;
}
@@ -80,12 +86,12 @@
return (android_log_context)context;
}
-LIBLOG_ABI_PUBLIC android_log_context create_android_log_parser(const char* msg,
- size_t len) {
+LIBLOG_ABI_PUBLIC android_log_context create_android_log_parser(const char* msg, size_t len) {
android_log_context_internal* context;
size_t i;
- context = calloc(1, sizeof(android_log_context_internal));
+ context =
+ static_cast<android_log_context_internal*>(calloc(1, sizeof(android_log_context_internal)));
if (!context) {
return NULL;
}
@@ -123,8 +129,8 @@
return 0;
}
-LIBLOG_ABI_PUBLIC int android_log_parser_reset(android_log_context ctx,
- const char* msg, size_t len) {
+LIBLOG_ABI_PUBLIC 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;
@@ -138,7 +144,6 @@
return 0;
}
-
LIBLOG_ABI_PUBLIC int android_log_write_list_begin(android_log_context ctx) {
size_t needed;
android_log_context_internal* context;
@@ -180,8 +185,7 @@
buf[3] = (val >> 24) & 0xFF;
}
-LIBLOG_ABI_PUBLIC int android_log_write_int32(android_log_context ctx,
- int32_t value) {
+LIBLOG_ABI_PUBLIC int android_log_write_int32(android_log_context ctx, int32_t value) {
size_t needed;
android_log_context_internal* context;
@@ -215,8 +219,7 @@
buf[7] = (val >> 56) & 0xFF;
}
-LIBLOG_ABI_PUBLIC int android_log_write_int64(android_log_context ctx,
- int64_t value) {
+LIBLOG_ABI_PUBLIC int android_log_write_int64(android_log_context ctx, int64_t value) {
size_t needed;
android_log_context_internal* context;
@@ -239,8 +242,7 @@
return 0;
}
-LIBLOG_ABI_PUBLIC int android_log_write_string8_len(android_log_context ctx,
- const char* value,
+LIBLOG_ABI_PUBLIC int android_log_write_string8_len(android_log_context ctx, const char* value,
size_t maxlen) {
size_t needed;
ssize_t len;
@@ -276,13 +278,11 @@
return len;
}
-LIBLOG_ABI_PUBLIC int android_log_write_string8(android_log_context ctx,
- const char* value) {
+LIBLOG_ABI_PUBLIC int android_log_write_string8(android_log_context ctx, const char* value) {
return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD);
}
-LIBLOG_ABI_PUBLIC int android_log_write_float32(android_log_context ctx,
- float value) {
+LIBLOG_ABI_PUBLIC int android_log_write_float32(android_log_context ctx, float value) {
size_t needed;
uint32_t ivalue;
android_log_context_internal* context;
@@ -337,8 +337,7 @@
/*
* Logs the list of elements to the event log.
*/
-LIBLOG_ABI_PUBLIC int android_log_write_list(android_log_context ctx,
- log_id_t id) {
+LIBLOG_ABI_PUBLIC int android_log_write_list(android_log_context ctx, log_id_t id) {
android_log_context_internal* context;
const char* msg;
ssize_t len;
@@ -368,13 +367,11 @@
}
return (id == LOG_ID_EVENTS)
? __android_log_bwrite(context->tag, msg, len)
- : ((id == LOG_ID_STATS)
- ? __android_log_stats_bwrite(context->tag, msg, len)
- : __android_log_security_bwrite(context->tag, msg, len));
+ : ((id == LOG_ID_STATS) ? __android_log_stats_bwrite(context->tag, msg, len)
+ : __android_log_security_bwrite(context->tag, msg, len));
}
-LIBLOG_ABI_PRIVATE int android_log_write_list_buffer(android_log_context ctx,
- const char** buffer) {
+LIBLOG_ABI_PRIVATE int android_log_write_list_buffer(android_log_context ctx, const char** buffer) {
android_log_context_internal* context;
const char* msg;
ssize_t len;
@@ -428,8 +425,7 @@
* 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 ctx, int peek) {
android_log_list_element elem;
unsigned pos;
android_log_context_internal* context;
@@ -444,9 +440,9 @@
(context->count[context->list_nest_depth] >=
(MAX_EVENT_PAYLOAD / (sizeof(uint8_t) + sizeof(uint8_t))))) {
elem.type = EVENT_TYPE_UNKNOWN;
- if (context && (context->list_stop ||
- ((context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) &&
- !context->count[context->list_nest_depth]))) {
+ if (context &&
+ (context->list_stop || ((context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) &&
+ !context->count[context->list_nest_depth]))) {
elem.type = EVENT_TYPE_LIST_STOP;
}
elem.complete = true;
@@ -460,9 +456,8 @@
pos = context->pos;
if (context->list_stop) {
elem.type = EVENT_TYPE_LIST_STOP;
- elem.complete = !context->count[0] &&
- (!context->list_nest_depth ||
- ((context->list_nest_depth == 1) && !context->count[1]));
+ elem.complete = !context->count[0] && (!context->list_nest_depth ||
+ ((context->list_nest_depth == 1) && !context->count[1]));
if (!peek) {
/* Suck in superfluous stop */
if (context->storage[pos] == EVENT_TYPE_LIST_STOP) {
@@ -485,7 +480,7 @@
return elem;
}
- elem.type = 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 */
@@ -598,12 +593,10 @@
}
}
-LIBLOG_ABI_PUBLIC android_log_list_element
-android_log_read_next(android_log_context ctx) {
+LIBLOG_ABI_PUBLIC android_log_list_element android_log_read_next(android_log_context ctx) {
return android_log_read_next_internal(ctx, 0);
}
-LIBLOG_ABI_PUBLIC android_log_list_element
-android_log_peek_next(android_log_context ctx) {
+LIBLOG_ABI_PUBLIC android_log_list_element android_log_peek_next(android_log_context ctx) {
return android_log_read_next_internal(ctx, 1);
}
diff --git a/liblog/log_event_write.c b/liblog/log_event_write.cpp
similarity index 89%
rename from liblog/log_event_write.c
rename to liblog/log_event_write.cpp
index 45a6f37..e644a3b 100644
--- a/liblog/log_event_write.c
+++ b/liblog/log_event_write.cpp
@@ -24,9 +24,8 @@
#define MAX_SUBTAG_LEN 32
-LIBLOG_ABI_PUBLIC int __android_log_error_write(int tag, const char* subTag,
- int32_t uid, const char* data,
- uint32_t dataLen) {
+LIBLOG_ABI_PUBLIC int __android_log_error_write(int tag, const char* subTag, int32_t uid,
+ const char* data, uint32_t dataLen) {
int ret = -EINVAL;
if (subTag && (data || !dataLen)) {
diff --git a/liblog/log_portability.h b/liblog/log_portability.h
index 88805c7..b9fb1d2 100644
--- a/liblog/log_portability.h
+++ b/liblog/log_portability.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBLOG_PORTABILITY_H__
-#define _LIBLOG_PORTABILITY_H__
+#pragma once
#include <sys/cdefs.h>
#include <unistd.h>
@@ -46,7 +45,7 @@
#if defined(_WIN32)
#define LIBLOG_WEAK static /* Accept that it is totally private */
#else
-#define LIBLOG_WEAK __attribute__((weak, visibility("default")))
+#define LIBLOG_WEAK extern "C" __attribute__((weak, visibility("default")))
#endif
/* possible missing definitions in sys/cdefs.h */
@@ -62,11 +61,6 @@
#endif
#endif
-/* Unused argument. For C code only, remove symbol name for C++ */
-#ifndef __unused
-#define __unused __attribute__((__unused__))
-#endif
-
/* possible missing definitions in unistd.h */
#ifndef TEMP_FAILURE_RETRY
@@ -80,5 +74,3 @@
_rc; \
})
#endif
-
-#endif /* _LIBLOG_PORTABILITY_H__ */
diff --git a/liblog/log_ratelimit.cpp b/liblog/log_ratelimit.cpp
deleted file mode 100644
index 33770dd..0000000
--- a/liblog/log_ratelimit.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-** Copyright 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 <pthread.h>
-#include <time.h>
-
-#include <log/log.h>
-
-#include "log_portability.h"
-
-// Global default if 'last' argument in __android_log_ratelimit is NULL
-static time_t g_last_clock;
-// Global above can not deal well with callers playing games with the
-// seconds argument, so we will also hold on to the maximum value
-// ever provided and use that to gain consistency. If the caller
-// provides their own 'last' argument, then they can play such games
-// of varying the 'seconds' argument to their pleasure.
-static time_t g_last_seconds;
-static const time_t last_seconds_default = 10;
-static const time_t last_seconds_max = 24 * 60 * 60; // maximum of a day
-static const time_t last_seconds_min = 2; // granularity
-// Lock to protect last_clock and last_seconds, but also 'last'
-// argument (not NULL) as supplied to __android_log_ratelimit.
-static pthread_mutex_t lock_ratelimit = PTHREAD_MUTEX_INITIALIZER;
-
-// if last is NULL, caller _must_ provide a consistent value for
-// seconds, otherwise we will take the maximum ever issued and hold
-// on to that. Preserves value of non-zero errno. Return -1 if we
-// can not acquire a lock, 0 if we are not to log a message, and 1
-// if we are ok to log a message. Caller should check > 0 for true.
-LIBLOG_ABI_PUBLIC int __android_log_ratelimit(time_t seconds, time_t* last) {
- int save_errno = errno;
-
- // Two reasons for trylock failure:
- // 1. In a signal handler. Must prevent deadlock
- // 2. Too many threads calling __android_log_ratelimit.
- // Bonus to not print if they race here because that
- // dovetails the goal of ratelimiting. One may print
- // and the others will wait their turn ...
- if (pthread_mutex_trylock(&lock_ratelimit)) {
- if (save_errno) errno = save_errno;
- return -1;
- }
-
- if (seconds == 0) {
- seconds = last_seconds_default;
- } else if (seconds < last_seconds_min) {
- seconds = last_seconds_min;
- } else if (seconds > last_seconds_max) {
- seconds = last_seconds_max;
- }
-
- if (!last) {
- if (g_last_seconds > seconds) {
- seconds = g_last_seconds;
- } else if (g_last_seconds < seconds) {
- g_last_seconds = seconds;
- }
- last = &g_last_clock;
- }
-
- time_t now = time(NULL);
- if ((now == (time_t)-1) || ((*last + seconds) > now)) {
- pthread_mutex_unlock(&lock_ratelimit);
- if (save_errno) errno = save_errno;
- return 0;
- }
- *last = now;
- pthread_mutex_unlock(&lock_ratelimit);
- if (save_errno) errno = save_errno;
- return 1;
-}
diff --git a/liblog/log_time.cpp b/liblog/log_time.cpp
index ae376be..77bb94f 100644
--- a/liblog/log_time.cpp
+++ b/liblog/log_time.cpp
@@ -137,7 +137,7 @@
LIBLOG_ABI_PRIVATE log_time log_time::operator-=(const timespec& T) {
// No concept of negative time, clamp to EPOCH
if (*this <= T) {
- return *this = EPOCH;
+ return *this = log_time(EPOCH);
}
if (this->tv_nsec < (unsigned long int)T.tv_nsec) {
@@ -165,7 +165,7 @@
LIBLOG_ABI_PRIVATE log_time log_time::operator-=(const log_time& T) {
// No concept of negative time, clamp to EPOCH
if (*this <= T) {
- return *this = EPOCH;
+ return *this = log_time(EPOCH);
}
if (this->tv_nsec < T.tv_nsec) {
diff --git a/liblog/logd_reader.c b/liblog/logd_reader.cpp
similarity index 86%
rename from liblog/logd_reader.c
rename to liblog/logd_reader.cpp
index 603ba24..05bbcbc 100644
--- a/liblog/logd_reader.c
+++ b/liblog/logd_reader.cpp
@@ -47,8 +47,7 @@
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);
+ 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,
@@ -56,37 +55,33 @@
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);
+ 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);
+ 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);
+ 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_context* transp, char* buf, size_t len);
LIBLOG_HIDDEN 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,
+ .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) {
@@ -109,8 +104,7 @@
#if defined(_WIN32)
-LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId,
- int type) {
+LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId, int type) {
errno = ENOSYS;
return -ENOSYS;
}
@@ -131,8 +125,7 @@
/* Documented in header file. */
LIBLOG_WEAK int socket_make_sockaddr_un(const char* name, int namespaceId,
- struct sockaddr_un* p_addr,
- socklen_t* alen) {
+ struct sockaddr_un* p_addr, socklen_t* alen) {
memset(p_addr, 0, sizeof(*p_addr));
size_t namelen;
@@ -158,8 +151,7 @@
namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
/* unix_path_max appears to be missing on linux */
- if (namelen >
- sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
+ if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
goto error;
}
@@ -171,8 +163,7 @@
case ANDROID_SOCKET_NAMESPACE_RESERVED:
namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
/* unix_path_max appears to be missing on linux */
- if (namelen >
- sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
+ if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
goto error;
}
@@ -183,8 +174,7 @@
case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
namelen = strlen(name);
/* unix_path_max appears to be missing on linux */
- if (namelen >
- sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
+ if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
goto error;
}
@@ -210,8 +200,8 @@
*
* Used by AndroidSocketImpl
*/
-LIBLOG_WEAK int socket_local_client_connect(int fd, const char* name,
- int namespaceId, int type __unused) {
+LIBLOG_WEAK int socket_local_client_connect(int fd, const char* name, int namespaceId,
+ int type __unused) {
struct sockaddr_un addr;
socklen_t alen;
int err;
@@ -236,8 +226,7 @@
* connect to peer named "name"
* returns fd or -1 on error
*/
-LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId,
- int type) {
+LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId, int type) {
int s;
s = socket(AF_LOCAL, type, 0);
@@ -255,14 +244,13 @@
/* End of ../libcutils/socket_local_client.c */
/* 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) {
+static ssize_t send_log_msg(struct android_log_logger* logger, const char* msg, char* buf,
+ size_t buf_size) {
ssize_t ret;
size_t len;
char* cp;
int errno_save = 0;
- int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM);
+ int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
if (sock < 0) {
return sock;
}
@@ -342,8 +330,7 @@
struct android_log_transport_context* transp __unused) {
char buf[512];
- return check_log_success(buf,
- send_log_msg(logger, "clear %d", buf, sizeof(buf)));
+ return check_log_success(buf, send_log_msg(logger, "clear %d", buf, sizeof(buf)));
}
/* returns the total size of the log's ring buffer */
@@ -364,8 +351,7 @@
}
static ssize_t logdSetSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp __unused,
- size_t size) {
+ struct android_log_transport_context* transp __unused, size_t size) {
char buf[512];
snprintf(buf, sizeof(buf), "setLogSize %d %zu", logger->logId, size);
@@ -378,8 +364,7 @@
* log consumed)
*/
static ssize_t logdGetReadableSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp
- __unused) {
+ struct android_log_transport_context* transp __unused) {
char buf[512];
ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
@@ -407,8 +392,8 @@
* 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_transport_context* transp __unused, char* buf,
+ size_t len) {
struct android_log_logger* logger;
char* cp = buf;
size_t remaining = len;
@@ -434,14 +419,14 @@
}
static ssize_t logdGetPrune(struct android_log_logger_list* logger_list __unused,
- struct android_log_transport_context* transp __unused,
- char* buf, size_t len) {
+ 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) {
+ struct android_log_transport_context* transp __unused, char* buf,
+ size_t len) {
const char cmd[] = "setPruneList ";
const size_t cmdlen = sizeof(cmd) - 1;
@@ -455,8 +440,7 @@
return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
}
-static void caught_signal(int signum __unused) {
-}
+static void caught_signal(int signum __unused) {}
static int logdOpen(struct android_log_logger_list* logger_list,
struct android_log_transport_context* transp) {
@@ -476,12 +460,10 @@
return sock;
}
- sock = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_SEQPACKET);
+ sock = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
if (sock == 0) {
/* Guarantee not file descriptor zero */
- int newsock = socket_local_client(
- "logdr", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
+ int newsock = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
close(sock);
sock = newsock;
}
@@ -492,8 +474,7 @@
return sock;
}
- strcpy(buffer, (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose"
- : "stream");
+ strcpy(buffer, (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream");
cp = buffer + strlen(buffer);
strcpy(cp, " lids");
@@ -518,14 +499,13 @@
if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
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 = snprintf(cp, remaining, " timeout=%u", ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
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 = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32, logger_list->start.tv_sec,
+ logger_list->start.tv_nsec);
ret = min(ret, remaining);
remaining -= ret;
cp += ret;
@@ -576,8 +556,7 @@
/* 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) {
+ struct android_log_transport_context* transp, struct log_msg* log_msg) {
int ret, e;
struct sigaction ignore;
struct sigaction old_sigaction;
diff --git a/liblog/logd_reader.h b/liblog/logd_reader.h
index 8ebb1ae..0bba7cf 100644
--- a/liblog/logd_reader.h
+++ b/liblog/logd_reader.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBLOG_LOGD_READER_H__
-#define _LIBLOG_LOGD_READER_H__
+#pragma once
#include <unistd.h>
@@ -26,5 +25,3 @@
LIBLOG_HIDDEN ssize_t __send_log_msg(char* buf, size_t buf_size);
__END_DECLS
-
-#endif /* _LIBLOG_LOGD_READER_H__ */
diff --git a/liblog/logd_writer.c b/liblog/logd_writer.cpp
similarity index 85%
rename from liblog/logd_writer.c
rename to liblog/logd_writer.cpp
index e0e3eca..ed906b3 100644
--- a/liblog/logd_writer.c
+++ b/liblog/logd_writer.cpp
@@ -38,6 +38,7 @@
#include "config_write.h"
#include "log_portability.h"
#include "logger.h"
+#include "uio.h"
/* branchless on many architectures. */
#define min(x, y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
@@ -45,17 +46,16 @@
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);
LIBLOG_HIDDEN struct android_log_transport_write logdLoggerWrite = {
- .node = { &logdLoggerWrite.node, &logdLoggerWrite.node },
- .context.sock = -EBADF,
- .name = "logd",
- .available = logdAvailable,
- .open = logdOpen,
- .close = logdClose,
- .write = logdWrite,
+ .node = {&logdLoggerWrite.node, &logdLoggerWrite.node},
+ .context.sock = -EBADF,
+ .name = "logd",
+ .available = logdAvailable,
+ .open = logdOpen,
+ .close = logdClose,
+ .write = logdWrite,
};
/* log_init_lock assumed */
@@ -64,8 +64,7 @@
i = atomic_load(&logdLoggerWrite.context.sock);
if (i < 0) {
- int sock = TEMP_FAILURE_RETRY(
- socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
+ int sock = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
if (sock < 0) {
ret = -errno;
} else {
@@ -74,15 +73,15 @@
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) {
+ 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);
- /* FALLTHRU */
+ [[fallthrough]];
default:
break;
}
@@ -124,16 +123,15 @@
return 1;
}
-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) {
ssize_t ret;
int sock;
static const unsigned headerLength = 1;
struct iovec newVec[nr + headerLength];
android_log_header_t header;
size_t i, payloadSize;
- static atomic_int_fast32_t dropped;
- static atomic_int_fast32_t droppedSecurity;
+ static atomic_int dropped;
+ static atomic_int droppedSecurity;
sock = atomic_load(&logdLoggerWrite.context.sock);
if (sock < 0) switch (sock) {
@@ -181,8 +179,7 @@
newVec[0].iov_len = sizeof(header);
if (sock >= 0) {
- int32_t snapshot =
- atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed);
+ int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed);
if (snapshot) {
android_log_event_int_t buffer;
@@ -196,14 +193,12 @@
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);
+ 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)) {
+ 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;
@@ -267,12 +262,11 @@
return ret;
}
- ret = TEMP_FAILURE_RETRY(
- writev(atomic_load(&logdLoggerWrite.context.sock), newVec, i));
+ ret = TEMP_FAILURE_RETRY(writev(atomic_load(&logdLoggerWrite.context.sock), newVec, i));
if (ret < 0) {
ret = -errno;
}
- /* FALLTHRU */
+ [[fallthrough]];
default:
break;
}
diff --git a/liblog/logger.h b/liblog/logger.h
index 246b33c..b2479d2 100644
--- a/liblog/logger.h
+++ b/liblog/logger.h
@@ -14,22 +14,21 @@
* limitations under the License.
*/
-#ifndef _LIBLOG_LOGGER_H__
-#define _LIBLOG_LOGGER_H__
+#pragma once
#include <stdatomic.h>
#include <stdbool.h>
#include <cutils/list.h>
#include <log/log.h>
-#include <log/uio.h>
#include "log_portability.h"
+#include "uio.h"
__BEGIN_DECLS
/* Union, sock or fd of zero is not allowed unless static initialized */
-union android_log_context {
+union android_log_context_union {
void* priv;
atomic_int sock;
atomic_int fd;
@@ -41,7 +40,7 @@
struct listnode node;
const char* name; /* human name to describe the transport */
unsigned logMask; /* mask cache of available() success */
- union android_log_context context; /* Initialized by static allocation */
+ 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 */
@@ -98,7 +97,6 @@
};
struct android_log_logger_list {
- struct listnode node;
struct listnode logger;
struct listnode transport;
int mode;
@@ -116,7 +114,7 @@
struct android_log_transport_context {
struct listnode node;
- union android_log_context context; /* zero init per-transport context */
+ union android_log_context_union context; /* zero init per-transport context */
struct android_log_logger_list* parent;
struct android_log_transport_read* transport;
@@ -144,37 +142,6 @@
(logp) = \
node_to_item((logp)->node.next, struct android_log_logger, node))
-/*
- * Global list of log readers.
- *
- * Usage case: search out transport contexts for all readers
- */
-
-LIBLOG_HIDDEN struct listnode __android_log_readers;
-
-#if defined(_WIN32)
-#define logger_list_rdlock()
-#define logger_list_wrlock()
-#define logger_list_unlock()
-#else
-LIBLOG_HIDDEN pthread_rwlock_t __android_log_readers_lock;
-
-#define logger_list_rdlock() pthread_rwlock_rdlock(&__android_log_readers_lock)
-#define logger_list_wrlock() pthread_rwlock_wrlock(&__android_log_readers_lock)
-#define logger_list_unlock() pthread_rwlock_unlock(&__android_log_readers_lock)
-#endif
-
-/* Must be called with logger_list_rdlock() or logger_list_wrlock() held */
-#define logger_list_for_each(logger_list) \
- for ((logger_list) = node_to_item(&__android_log_readers, \
- struct android_log_logger_list, node); \
- (logger_list) != node_to_item(&__android_log_readers, \
- struct android_log_logger_list, node) && \
- (logger_list) != node_to_item((logger_list)->node.next, \
- struct android_log_logger_list, node); \
- (logger_list) = node_to_item((logger_list)->node.next, \
- struct android_log_logger_list, node))
-
/* OS specific dribs and drabs */
#if defined(_WIN32)
@@ -193,8 +160,6 @@
LIBLOG_HIDDEN int __android_log_trylock();
LIBLOG_HIDDEN void __android_log_unlock();
-LIBLOG_HIDDEN int __android_log_transport;
+extern LIBLOG_HIDDEN int __android_log_transport;
__END_DECLS
-
-#endif /* _LIBLOG_LOGGER_H__ */
diff --git a/liblog/logger_lock.c b/liblog/logger_lock.cpp
similarity index 100%
rename from liblog/logger_lock.c
rename to liblog/logger_lock.cpp
diff --git a/liblog/logger_name.c b/liblog/logger_name.cpp
similarity index 79%
rename from liblog/logger_name.c
rename to liblog/logger_name.cpp
index 479bbfe..c6f3cb7 100644
--- a/liblog/logger_name.c
+++ b/liblog/logger_name.cpp
@@ -15,6 +15,7 @@
*/
#include <string.h>
+#include <type_traits>
#include <log/log.h>
@@ -22,7 +23,7 @@
/* In the future, we would like to make this list extensible */
static const char* LOG_NAME[LOG_ID_MAX] = {
- /* clang-format off */
+ /* clang-format off */
[LOG_ID_MAIN] = "main",
[LOG_ID_RADIO] = "radio",
[LOG_ID_EVENTS] = "events",
@@ -31,7 +32,7 @@
[LOG_ID_STATS] = "stats",
[LOG_ID_SECURITY] = "security",
[LOG_ID_KERNEL] = "kernel",
- /* clang-format on */
+ /* clang-format on */
};
LIBLOG_ABI_PUBLIC const char* android_log_id_to_name(log_id_t log_id) {
@@ -41,12 +42,15 @@
return LOG_NAME[log_id];
}
+static_assert(std::is_same<std::underlying_type<log_id_t>::type, uint32_t>::value,
+ "log_id_t must be an unsigned int");
+
LIBLOG_ABI_PUBLIC log_id_t android_name_to_log_id(const char* logName) {
const char* b;
- int ret;
+ unsigned int ret;
if (!logName) {
- return -1; /* NB: log_id_t is unsigned */
+ return static_cast<log_id_t>(0xFFFFFFFF);
}
b = strrchr(logName, '/');
if (!b) {
@@ -58,8 +62,8 @@
for (ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
const char* l = LOG_NAME[ret];
if (l && !strcmp(b, l)) {
- return ret;
+ return static_cast<log_id_t>(ret);
}
}
- return -1; /* should never happen */
+ return static_cast<log_id_t>(0xFFFFFFFF); /* should never happen */
}
diff --git a/liblog/logger_read.c b/liblog/logger_read.cpp
similarity index 76%
rename from liblog/logger_read.c
rename to liblog/logger_read.cpp
index 0fd6efa..e429c36 100644
--- a/liblog/logger_read.c
+++ b/liblog/logger_read.cpp
@@ -14,6 +14,8 @@
** limitations under the License.
*/
+#include "log/log_read.h"
+
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
@@ -34,8 +36,7 @@
/* 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;
+ struct android_log_logger* logger_internal = (struct android_log_logger*)logger;
if (!logger_internal) {
return;
@@ -71,15 +72,13 @@
__android_log_lock();
/* mini __write_to_log_initialize() to populate transports */
- if (list_empty(&__android_log_transport_read) &&
- list_empty(&__android_log_persist_read)) {
+ 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;
+ 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;
@@ -92,15 +91,14 @@
if ((logId == LOG_ID_SECURITY) && (__android_log_uid() != AID_SYSTEM)) {
continue;
}
- if (transport->read &&
- (!transport->available || (transport->available(logId) >= 0))) {
+ if (transport->read && (!transport->available || (transport->available(logId) >= 0))) {
logMask |= 1 << logId;
}
}
if (!logMask) {
continue;
}
- transp = calloc(1, sizeof(*transp));
+ transp = static_cast<android_log_transport_context*>(calloc(1, sizeof(*transp)));
if (!transp) {
return -ENOMEM;
}
@@ -116,31 +114,29 @@
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; \
- } \
- } \
- } \
+#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
LIBLOG_ABI_PUBLIC int android_logger_clear(struct logger* logger) {
@@ -152,8 +148,7 @@
LOGGER_FUNCTION(logger, -ENODEV, getSize);
}
-LIBLOG_ABI_PUBLIC int android_logger_set_log_size(struct logger* logger,
- unsigned long size) {
+LIBLOG_ABI_PUBLIC int android_logger_set_log_size(struct logger* logger, unsigned long size) {
LOGGER_FUNCTION(logger, -ENODEV, setSize, size);
}
@@ -161,8 +156,7 @@
* returns the readable size of the log's ring buffer (that is, amount of the
* log consumed)
*/
-LIBLOG_ABI_PUBLIC long android_logger_get_log_readable_size(
- struct logger* logger) {
+LIBLOG_ABI_PUBLIC long android_logger_get_log_readable_size(struct logger* logger) {
LOGGER_FUNCTION(logger, -ENODEV, getReadableSize);
}
@@ -173,58 +167,50 @@
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; \
- } \
- } \
- } \
+#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
*/
-LIBLOG_ABI_PUBLIC ssize_t android_logger_get_statistics(
- struct logger_list* logger_list, char* buf, size_t len) {
+LIBLOG_ABI_PUBLIC 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);
}
-LIBLOG_ABI_PUBLIC ssize_t android_logger_get_prune_list(
- struct logger_list* logger_list, char* buf, size_t len) {
+LIBLOG_ABI_PUBLIC 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);
}
-LIBLOG_ABI_PUBLIC int android_logger_set_prune_list(
- struct logger_list* logger_list, char* buf, size_t len) {
+LIBLOG_ABI_PUBLIC 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);
}
-LIBLOG_HIDDEN struct listnode __android_log_readers = { &__android_log_readers,
- &__android_log_readers };
-#if !defined(_WIN32)
-LIBLOG_HIDDEN pthread_rwlock_t __android_log_readers_lock =
- PTHREAD_RWLOCK_INITIALIZER;
-#endif
-
-LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc(
- int mode, unsigned int tail, pid_t pid) {
+LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc(int mode, unsigned int tail,
+ pid_t pid) {
struct android_log_logger_list* logger_list;
- logger_list = calloc(1, sizeof(*logger_list));
+ logger_list = static_cast<android_log_logger_list*>(calloc(1, sizeof(*logger_list)));
if (!logger_list) {
return NULL;
}
@@ -235,18 +221,14 @@
logger_list->tail = tail;
logger_list->pid = pid;
- logger_list_wrlock();
- list_add_tail(&__android_log_readers, &logger_list->node);
- logger_list_unlock();
-
return (struct logger_list*)logger_list;
}
-LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc_time(
- int mode, log_time start, pid_t pid) {
+LIBLOG_ABI_PUBLIC 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 = calloc(1, sizeof(*logger_list));
+ logger_list = static_cast<android_log_logger_list*>(calloc(1, sizeof(*logger_list)));
if (!logger_list) {
return NULL;
}
@@ -257,10 +239,6 @@
logger_list->start = start;
logger_list->pid = pid;
- logger_list_wrlock();
- list_add_tail(&__android_log_readers, &logger_list->node);
- logger_list_unlock();
-
return (struct logger_list*)logger_list;
}
@@ -268,8 +246,8 @@
/* android_logger_list_unregister unimplemented, no use case */
/* Open the named log and add it to the logger list */
-LIBLOG_ABI_PUBLIC struct logger* android_logger_open(
- struct logger_list* logger_list, log_id_t logId) {
+LIBLOG_ABI_PUBLIC 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;
@@ -284,7 +262,7 @@
}
}
- logger = calloc(1, sizeof(*logger));
+ logger = static_cast<android_log_logger*>(calloc(1, sizeof(*logger)));
if (!logger) {
goto err;
}
@@ -311,8 +289,8 @@
}
/* Open the single named log and make it part of a new logger list */
-LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_open(
- log_id_t logId, int mode, unsigned int tail, pid_t pid) {
+LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_open(log_id_t logId, int mode,
+ unsigned int tail, pid_t pid) {
struct logger_list* logger_list = android_logger_list_alloc(mode, tail, pid);
if (!logger_list) {
@@ -379,8 +357,8 @@
}
/* at least one transport */
- transp = node_to_item(logger_list_internal->transport.next,
- struct android_log_transport_context, node);
+ 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) {
@@ -401,11 +379,9 @@
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);
+ retval = android_transport_read(logger_list_internal, transp, &transp->logMsg);
} else {
- int pollval =
- (*transp->transport->poll)(logger_list_internal, transp);
+ int pollval = (*transp->transport->poll)(logger_list_internal, transp);
if (pollval <= 0) {
sched_yield();
pollval = (*transp->transport->poll)(logger_list_internal, transp);
@@ -417,8 +393,7 @@
}
retval = transp->ret = pollval;
} else if (pollval > 0) {
- retval = android_transport_read(logger_list_internal, transp,
- &transp->logMsg);
+ retval = android_transport_read(logger_list_internal, transp, &transp->logMsg);
}
}
}
@@ -431,11 +406,9 @@
(oldest->logMsg.entry.nsec > transp->logMsg.entry.nsec)))) {
oldest = transp;
}
- transp = node_to_item(transp->node.next,
- struct android_log_transport_context, node);
+ 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));
+ struct android_log_transport_context, node));
if (!oldest && (logger_list_internal->mode & ANDROID_LOG_NONBLOCK)) {
return (ret < 0) ? ret : -EAGAIN;
}
@@ -449,10 +422,10 @@
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));
+ 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 */
@@ -472,10 +445,6 @@
return;
}
- logger_list_wrlock();
- list_remove(&logger_list_internal->node);
- logger_list_unlock();
-
while (!list_empty(&logger_list_internal->transport)) {
struct listnode* node = list_head(&logger_list_internal->transport);
struct android_log_transport_context* transp =
@@ -490,8 +459,7 @@
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);
+ struct android_log_logger* logger = node_to_item(node, struct android_log_logger, node);
android_logger_free((struct logger*)logger);
}
diff --git a/liblog/logger_write.c b/liblog/logger_write.cpp
similarity index 87%
rename from liblog/logger_write.c
rename to liblog/logger_write.cpp
index 2754e6e..af8cb2d 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.cpp
@@ -33,23 +33,19 @@
#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;
+static int (*write_to_log)(log_id_t, struct iovec* vec, size_t nr) = __write_to_log_init;
/*
* 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;
+static enum { kLogUninitialized, kLogNotAvailable, kLogAvailable } g_log_status = kLogUninitialized;
static int check_log_uid_permissions() {
#if defined(__ANDROID__)
@@ -70,7 +66,7 @@
if (num_groups <= 0) {
return -EPERM;
}
- groups = calloc(num_groups, sizeof(gid_t));
+ groups = static_cast<gid_t*>(calloc(num_groups, sizeof(gid_t)));
if (!groups) {
return -ENOMEM;
}
@@ -93,9 +89,8 @@
return 0;
}
-static void __android_log_cache_available(
- struct android_log_transport_write* node) {
- size_t i;
+static void __android_log_cache_available(struct android_log_transport_write* node) {
+ uint32_t i;
if (node->logMask) {
return;
@@ -104,13 +99,13 @@
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)(i) >= 0))) {
+ (!node->available || ((*node->available)(static_cast<log_id_t>(i)) >= 0))) {
node->logMask |= 1 << i;
}
}
}
-LIBLOG_ABI_PUBLIC int __android_log_dev_available() {
+LIBLOG_ABI_PUBLIC extern "C" int __android_log_dev_available() {
struct android_log_transport_write* node;
if (list_empty(&__android_log_transport_write)) {
@@ -308,10 +303,9 @@
}
}
if (m && (m != (EventTagMap*)(uintptr_t)-1LL)) {
- tag = android_lookupEventTag_len(m, &len, get4LE(vec[0].iov_base));
+ 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);
+ ret = __android_log_is_loggable_len(ANDROID_LOG_INFO, tag, len, ANDROID_LOG_VERBOSE);
if (f) { /* local copy marked for close */
android_closeEventTagMap(f);
}
@@ -322,7 +316,7 @@
} else {
/* Validate the incoming tag, tag content can not split across iovec */
char prio = ANDROID_LOG_VERBOSE;
- const char* tag = vec[0].iov_base;
+ const char* tag = static_cast<const char*>(vec[0].iov_base);
size_t len = vec[0].iov_len;
if (!tag) {
len = 0;
@@ -408,13 +402,12 @@
return ret;
}
-LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char* tag,
- const char* msg) {
+LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char* tag, const char* msg) {
return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
}
-LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio,
- const char* tag, const char* msg) {
+LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio, const char* tag,
+ const char* msg) {
struct iovec vec[3];
char tmp_tag[32];
@@ -457,7 +450,7 @@
bufID = LOG_ID_RADIO;
snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
tag = tmp_tag;
- /* FALLTHRU */
+ [[fallthrough]];
default:
break;
}
@@ -476,11 +469,10 @@
vec[2].iov_base = (void*)msg;
vec[2].iov_len = strlen(msg) + 1;
- return write_to_log(bufID, vec, 3);
+ return write_to_log(static_cast<log_id_t>(bufID), vec, 3);
}
-LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char* tag,
- const char* fmt, va_list ap) {
+LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap) {
char buf[LOG_BUF_SIZE];
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
@@ -488,8 +480,7 @@
return __android_log_write(prio, tag, buf);
}
-LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char* tag,
- const char* fmt, ...) {
+LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char* tag, const char* fmt, ...) {
va_list ap;
char buf[LOG_BUF_SIZE];
@@ -500,8 +491,7 @@
return __android_log_write(prio, tag, buf);
}
-LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio,
- const char* tag, const char* fmt,
+LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt,
...) {
va_list ap;
char buf[LOG_BUF_SIZE];
@@ -513,8 +503,8 @@
return __android_log_buf_write(bufID, prio, tag, buf);
}
-LIBLOG_ABI_PUBLIC void __android_log_assert(const char* cond, const char* tag,
- const char* fmt, ...) {
+LIBLOG_ABI_PUBLIC void __android_log_assert(const char* cond, const char* tag, const char* fmt,
+ ...) {
char buf[LOG_BUF_SIZE];
if (fmt) {
@@ -535,18 +525,15 @@
// Log assertion failures to stderr for the benefit of "adb shell" users
// and gtests (http://b/23675822).
- struct iovec iov[2] = {
- { buf, strlen(buf) }, { (char*)"\n", 1 },
- };
- TEMP_FAILURE_RETRY(writev(2, iov, 2));
+ TEMP_FAILURE_RETRY(write(2, buf, strlen(buf)));
+ TEMP_FAILURE_RETRY(write(2, "\n", 1));
__android_log_write(ANDROID_LOG_FATAL, tag, buf);
abort(); /* abort so we have a chance to debug the situation */
/* NOTREACHED */
}
-LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag, const void* payload,
- size_t len) {
+LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag, const void* payload, size_t len) {
struct iovec vec[2];
vec[0].iov_base = &tag;
@@ -557,9 +544,7 @@
return write_to_log(LOG_ID_EVENTS, vec, 2);
}
-LIBLOG_ABI_PUBLIC int __android_log_stats_bwrite(int32_t tag,
- const void* payload,
- size_t len) {
+LIBLOG_ABI_PUBLIC int __android_log_stats_bwrite(int32_t tag, const void* payload, size_t len) {
struct iovec vec[2];
vec[0].iov_base = &tag;
@@ -570,9 +555,7 @@
return write_to_log(LOG_ID_STATS, vec, 2);
}
-LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag,
- const void* payload,
- size_t len) {
+LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag, const void* payload, size_t len) {
struct iovec vec[2];
vec[0].iov_base = &tag;
@@ -588,8 +571,8 @@
* for the general case where we're generating lists of stuff, but very
* handy if we just want to dump an integer into the log.
*/
-LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type,
- const void* payload, size_t len) {
+LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type, const void* payload,
+ size_t len) {
struct iovec vec[3];
vec[0].iov_base = &tag;
@@ -627,8 +610,7 @@
* Like __android_log_security_bwrite, but used for writing strings to the
* security log.
*/
-LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag,
- const char* payload) {
+LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag, const char* payload) {
struct iovec vec[4];
char type = EVENT_TYPE_STRING;
uint32_t len = strlen(payload);
@@ -684,9 +666,9 @@
return retval;
}
- __android_log_transport &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
+ __android_log_transport &= LOGGER_LOGD | LOGGER_STDERR;
- transport_flag &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
+ transport_flag &= LOGGER_LOGD | LOGGER_STDERR;
if (__android_log_transport != transport_flag) {
__android_log_transport = transport_flag;
@@ -695,8 +677,7 @@
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)) {
+ } else if ((write_to_log != __write_to_log_init) && (write_to_log != __write_to_log_daemon)) {
write_to_log = __write_to_log_init;
}
@@ -714,10 +695,9 @@
if (write_to_log == __write_to_log_null) {
ret = LOGGER_NULL;
} else {
- __android_log_transport &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
+ __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)) {
+ if ((write_to_log != __write_to_log_init) && (write_to_log != __write_to_log_daemon)) {
ret = -EINVAL;
}
}
diff --git a/liblog/logprint.c b/liblog/logprint.cpp
similarity index 90%
rename from liblog/logprint.c
rename to liblog/logprint.cpp
index 7937cb1..798b089 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.cpp
@@ -15,7 +15,6 @@
** limitations under the License.
*/
-#define _GNU_SOURCE /* for asprintf */
#ifndef __MINGW32__
#define HAVE_STRSEP
#endif
@@ -154,7 +153,7 @@
case ANDROID_LOG_DEFAULT:
case ANDROID_LOG_UNKNOWN:
default: return '?';
- /* clang-format on */
+ /* clang-format on */
}
}
@@ -172,16 +171,14 @@
case ANDROID_LOG_DEFAULT:
case ANDROID_LOG_UNKNOWN:
default: return ANDROID_COLOR_DEFAULT;
- /* clang-format on */
+ /* clang-format on */
}
}
-static android_LogPriority filterPriForTag(AndroidLogFormat* p_format,
- const char* tag) {
+static android_LogPriority filterPriForTag(AndroidLogFormat* p_format, const char* tag) {
FilterInfo* p_curFilter;
- for (p_curFilter = p_format->filters; p_curFilter != NULL;
- p_curFilter = p_curFilter->p_next) {
+ for (p_curFilter = p_format->filters; p_curFilter != NULL; p_curFilter = p_curFilter->p_next) {
if (0 == strcmp(tag, p_curFilter->mTag)) {
if (p_curFilter->mPri == ANDROID_LOG_DEFAULT) {
return p_format->global_pri;
@@ -198,8 +195,7 @@
* returns 1 if this log line should be printed based on its priority
* and tag, and 0 if it should not
*/
-LIBLOG_ABI_PUBLIC int android_log_shouldPrintLine(AndroidLogFormat* p_format,
- const char* tag,
+LIBLOG_ABI_PUBLIC int android_log_shouldPrintLine(AndroidLogFormat* p_format, const char* tag,
android_LogPriority pri) {
return pri >= filterPriForTag(p_format, tag);
}
@@ -207,7 +203,7 @@
LIBLOG_ABI_PUBLIC AndroidLogFormat* android_log_format_new() {
AndroidLogFormat* p_ret;
- p_ret = calloc(1, sizeof(AndroidLogFormat));
+ p_ret = static_cast<AndroidLogFormat*>(calloc(1, sizeof(AndroidLogFormat)));
p_ret->global_pri = ANDROID_LOG_VERBOSE;
p_ret->format = FORMAT_BRIEF;
@@ -302,8 +298,7 @@
/**
* Returns FORMAT_OFF on invalid string
*/
-LIBLOG_ABI_PUBLIC AndroidLogPrintFormat
-android_log_formatFromString(const char* formatString) {
+LIBLOG_ABI_PUBLIC AndroidLogPrintFormat android_log_formatFromString(const char* formatString) {
static AndroidLogPrintFormat format;
/* clang-format off */
@@ -326,7 +321,7 @@
else if (!strcmp(formatString, "monotonic")) format = FORMAT_MODIFIER_MONOTONIC;
else if (!strcmp(formatString, "uid")) format = FORMAT_MODIFIER_UID;
else if (!strcmp(formatString, "descriptive")) format = FORMAT_MODIFIER_DESCRIPT;
- /* clang-format on */
+ /* clang-format on */
#ifndef __MINGW32__
else {
@@ -344,9 +339,8 @@
*/
tzset();
if (!tzname[0] ||
- ((!strcmp(tzname[0], utc) || !strcmp(tzname[0], gmt)) /* error? */
- && strcasecmp(formatString, utc) &&
- strcasecmp(formatString, gmt))) { /* ok */
+ ((!strcmp(tzname[0], utc) || !strcmp(tzname[0], gmt)) /* error? */
+ && strcasecmp(formatString, utc) && strcasecmp(formatString, gmt))) { /* ok */
if (cp) {
setenv(tz, cp, 1);
} else {
@@ -581,7 +575,7 @@
msg[msgEnd] = '\0';
}
- entry->priority = msg[0];
+ entry->priority = static_cast<android_LogPriority>(msg[0]);
entry->tag = msg + 1;
entry->tagLen = msgStart - 1;
entry->message = msg + msgStart;
@@ -643,9 +637,8 @@
TYPE_MONOTONIC = 's'
};
-static int android_log_printBinaryEvent(const unsigned char** pEventData,
- size_t* pEventDataLen, char** pOutBuf,
- size_t* pOutBufLen, const char** fmtStr,
+static int android_log_printBinaryEvent(const unsigned char** pEventData, size_t* pEventDataLen,
+ char** pOutBuf, size_t* pOutBufLen, const char** fmtStr,
size_t* fmtLen) {
const unsigned char* eventData = *pEventData;
size_t eventDataLen = *pEventDataLen;
@@ -729,13 +722,10 @@
}
if (findChar(&cp, &len, '|') && findChar(&cp, &len, INT_MAX)) {
- static const unsigned char typeTable[] = {
- EVENT_TYPE_INT, EVENT_TYPE_LONG, EVENT_TYPE_STRING, EVENT_TYPE_LIST,
- EVENT_TYPE_FLOAT
- };
+ static const unsigned char typeTable[] = {EVENT_TYPE_INT, EVENT_TYPE_LONG, EVENT_TYPE_STRING,
+ EVENT_TYPE_LIST, EVENT_TYPE_FLOAT};
- if ((*cp >= '1') &&
- (*cp < (char)('1' + (sizeof(typeTable) / sizeof(typeTable[0])))) &&
+ if ((*cp >= '1') && (*cp < (char)('1' + (sizeof(typeTable) / sizeof(typeTable[0])))) &&
(type != typeTable[(size_t)(*cp - '1')]))
len = 0;
@@ -858,8 +848,8 @@
outBufLen--;
for (i = 0; i < count; i++) {
- result = android_log_printBinaryEvent(
- &eventData, &eventDataLen, &outBuf, &outBufLen, fmtStr, fmtLen);
+ result = android_log_printBinaryEvent(&eventData, &eventDataLen, &outBuf, &outBufLen,
+ fmtStr, fmtLen);
if (result != 0) goto bail;
if (i < (count - 1)) {
@@ -889,24 +879,21 @@
case TYPE_BYTES:
if ((lval != 0) && ((lval % 1024) == 0)) {
/* repaint with multiplier */
- static const char suffixTable[] = { 'K', 'M', 'G', 'T' };
+ static const char suffixTable[] = {'K', 'M', 'G', 'T'};
size_t idx = 0;
outBuf -= outCount;
outBufLen += outCount;
do {
lval /= 1024;
if ((lval % 1024) != 0) break;
- } while (++idx <
- ((sizeof(suffixTable) / sizeof(suffixTable[0])) - 1));
- outCount = snprintf(outBuf, outBufLen, "%" PRId64 "%cB", lval,
- suffixTable[idx]);
+ } while (++idx < ((sizeof(suffixTable) / sizeof(suffixTable[0])) - 1));
+ outCount = snprintf(outBuf, outBufLen, "%" PRId64 "%cB", lval, suffixTable[idx]);
} else {
outCount = snprintf(outBuf, outBufLen, "B");
}
break;
case TYPE_MILLISECONDS:
- if (((lval <= -1000) || (1000 <= lval)) &&
- (outBufLen || (outBuf[-1] == '0'))) {
+ if (((lval <= -1000) || (1000 <= lval)) && (outBufLen || (outBuf[-1] == '0'))) {
/* repaint as (fractional) seconds, possibly saving space */
if (outBufLen) outBuf[0] = outBuf[-1];
outBuf[-1] = outBuf[-2];
@@ -943,22 +930,19 @@
}
if (val >= minute) {
if (val >= hour) {
- outCount = snprintf(outBuf, outBufLen, "%" PRIu64 ":",
- (val / hour) % (day / hour));
+ outCount = snprintf(outBuf, outBufLen, "%" PRIu64 ":", (val / hour) % (day / hour));
if (outCount >= outBufLen) break;
outBuf += outCount;
outBufLen -= outCount;
}
outCount =
- snprintf(outBuf, outBufLen,
- (val >= hour) ? "%02" PRIu64 ":" : "%" PRIu64 ":",
+ snprintf(outBuf, outBufLen, (val >= hour) ? "%02" PRIu64 ":" : "%" PRIu64 ":",
(val / minute) % (hour / minute));
if (outCount >= outBufLen) break;
outBuf += outCount;
outBufLen -= outCount;
}
- outCount = snprintf(outBuf, outBufLen,
- (val >= minute) ? "%02" PRIu64 : "%" PRIu64 "s",
+ outCount = snprintf(outBuf, outBufLen, (val >= minute) ? "%02" PRIu64 : "%" PRIu64 "s",
val % minute);
} break;
case TYPE_ALLOCATIONS:
@@ -1015,7 +999,7 @@
*/
LIBLOG_ABI_PUBLIC int android_log_processBinaryLogBuffer(
struct logger_entry* buf, AndroidLogEntry* entry,
- const EventTagMap* map __unused, /* only on !__ANDROID__ */
+ [[maybe_unused]] const EventTagMap* map, /* only on !__ANDROID__ */
char* messageBuf, int messageBufLen) {
size_t inCount;
uint32_t tagIndex;
@@ -1100,8 +1084,8 @@
int result = 0;
if ((inCount > 0) || fmtLen) {
- result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf,
- &outRemaining, &fmtStr, &fmtLen);
+ result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf, &outRemaining, &fmtStr,
+ &fmtLen);
}
if ((result == 1) && fmtStr) {
/* We overflowed :-(, let's repaint the line w/o format dressings */
@@ -1112,8 +1096,7 @@
eventData += 4;
outBuf = messageBuf;
outRemaining = messageBufLen - 1;
- result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf,
- &outRemaining, NULL, NULL);
+ result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf, &outRemaining, NULL, NULL);
}
if (result < 0) {
fprintf(stderr, "Binary log entry conversion failed\n");
@@ -1187,8 +1170,7 @@
}
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) {
+ num_to_read < 5 && (first_char & mask); num_to_read++, to_ignore_mask |= mask, mask >>= 1) {
if (num_to_read > len) {
return -1;
}
@@ -1226,8 +1208,7 @@
len = utf8_character_length(message, len);
if (len < 0) {
- snprintf(buf, sizeof(buf),
- ((messageLen > 1) && isdigit(message[1])) ? "\\%03o" : "\\%o",
+ snprintf(buf, sizeof(buf), ((messageLen > 1) && isdigit(message[1])) ? "\\%03o" : "\\%o",
*message & 0377);
len = 1;
} else {
@@ -1281,8 +1262,7 @@
return p;
}
-static struct timespec* sumTimespec(struct timespec* left,
- struct timespec* right) {
+static struct timespec* sumTimespec(struct timespec* left, struct timespec* right) {
left->tv_nsec += right->tv_nsec;
left->tv_sec += right->tv_sec;
if (left->tv_nsec >= (long)NS_PER_SEC) {
@@ -1292,8 +1272,7 @@
return left;
}
-static struct timespec* subTimespec(struct timespec* result,
- struct timespec* left,
+static struct timespec* subTimespec(struct timespec* result, struct timespec* left,
struct timespec* right) {
result->tv_nsec = left->tv_nsec - right->tv_nsec;
result->tv_sec = left->tv_sec - right->tv_sec;
@@ -1309,8 +1288,7 @@
}
#ifdef __ANDROID__
-static void convertMonotonic(struct timespec* result,
- const AndroidLogEntry* entry) {
+static void convertMonotonic(struct timespec* result, const AndroidLogEntry* entry) {
struct listnode* node;
struct conversionList {
struct listnode node; /* first */
@@ -1322,8 +1300,8 @@
/* If we do not have a conversion list, build one up */
if (list_empty(&convertHead)) {
bool suspended_pending = false;
- struct timespec suspended_monotonic = { 0, 0 };
- struct timespec suspended_diff = { 0, 0 };
+ struct timespec suspended_monotonic = {0, 0};
+ struct timespec suspended_diff = {0, 0};
/*
* Read dmesg for _some_ synchronization markers and insert
@@ -1413,15 +1391,14 @@
} else {
unsetenv(tz);
}
- list = calloc(1, sizeof(struct conversionList));
+ list = static_cast<conversionList*>(calloc(1, sizeof(conversionList)));
list_init(&list->node);
list->time = time;
subTimespec(&list->convert, &time, &monotonic);
list_add_tail(&convertHead, &list->node);
}
if (suspended_pending && !list_empty(&convertHead)) {
- list = node_to_item(list_tail(&convertHead), struct conversionList,
- node);
+ list = node_to_item(list_tail(&convertHead), struct conversionList, node);
if (subTimespec(&time, subTimespec(&time, &list->time, &list->convert),
&suspended_monotonic)
->tv_sec > 0) {
@@ -1434,13 +1411,13 @@
time = suspended_monotonic;
sumTimespec(&time, &convert);
/* breakpoint just before sleep */
- list = calloc(1, sizeof(struct conversionList));
+ list = static_cast<conversionList*>(calloc(1, sizeof(conversionList)));
list_init(&list->node);
list->time = time;
list->convert = convert;
list_add_tail(&convertHead, &list->node);
/* breakpoint just after sleep */
- list = calloc(1, sizeof(struct conversionList));
+ list = static_cast<conversionList*>(calloc(1, sizeof(conversionList)));
list_init(&list->node);
list->time = time;
sumTimespec(&list->time, &suspended_diff);
@@ -1453,7 +1430,7 @@
pclose(p);
}
/* last entry is our current time conversion */
- list = calloc(1, sizeof(struct conversionList));
+ list = static_cast<conversionList*>(calloc(1, sizeof(conversionList)));
list_init(&list->node);
clock_gettime(CLOCK_REALTIME, &list->time);
clock_gettime(CLOCK_MONOTONIC, &convert);
@@ -1469,7 +1446,7 @@
time = suspended_monotonic;
sumTimespec(&time, &convert);
/* breakpoint just after sleep */
- list = calloc(1, sizeof(struct conversionList));
+ list = static_cast<conversionList*>(calloc(1, sizeof(conversionList)));
list_init(&list->node);
list->time = time;
sumTimespec(&list->time, &suspended_diff);
@@ -1477,7 +1454,7 @@
sumTimespec(&list->convert, &suspended_diff);
list_add_head(&convertHead, &list->node);
/* breakpoint just before sleep */
- list = calloc(1, sizeof(struct conversionList));
+ list = static_cast<conversionList*>(calloc(1, sizeof(conversionList)));
list_init(&list->node);
list->time = time;
list->convert = convert;
@@ -1548,8 +1525,7 @@
* Returns NULL on malloc error
*/
-LIBLOG_ABI_PUBLIC char* android_log_formatLogLine(AndroidLogFormat* p_format,
- char* defaultBuffer,
+LIBLOG_ABI_PUBLIC char* android_log_formatLogLine(AndroidLogFormat* p_format, char* defaultBuffer,
size_t defaultBufferSize,
const AndroidLogEntry* entry,
size_t* p_outLength) {
@@ -1600,26 +1576,23 @@
}
if (p_format->epoch_output || p_format->monotonic_output) {
ptm = NULL;
- snprintf(timeBuf, sizeof(timeBuf),
- p_format->monotonic_output ? "%6lld" : "%19lld", (long long)now);
+ snprintf(timeBuf, sizeof(timeBuf), p_format->monotonic_output ? "%6lld" : "%19lld",
+ (long long)now);
} else {
#if !defined(_WIN32)
ptm = localtime_r(&now, &tmBuf);
#else
ptm = localtime(&now);
#endif
- strftime(timeBuf, sizeof(timeBuf),
- &"%Y-%m-%d %H:%M:%S"[p_format->year_output ? 0 : 3], ptm);
+ strftime(timeBuf, sizeof(timeBuf), &"%Y-%m-%d %H:%M:%S"[p_format->year_output ? 0 : 3], ptm);
}
len = strlen(timeBuf);
if (p_format->nsec_time_output) {
len += snprintf(timeBuf + len, sizeof(timeBuf) - len, ".%09ld", nsec);
} else if (p_format->usec_time_output) {
- len += snprintf(timeBuf + len, sizeof(timeBuf) - len, ".%06ld",
- nsec / US_PER_NSEC);
+ len += snprintf(timeBuf + len, sizeof(timeBuf) - len, ".%06ld", nsec / US_PER_NSEC);
} else {
- len += snprintf(timeBuf + len, sizeof(timeBuf) - len, ".%03ld",
- nsec / MS_PER_NSEC);
+ len += snprintf(timeBuf + len, sizeof(timeBuf) - len, ".%03ld", nsec / MS_PER_NSEC);
}
if (p_format->zone_output && ptm) {
strftime(timeBuf + len, sizeof(timeBuf) - len, " %z", ptm);
@@ -1629,8 +1602,8 @@
* Construct a buffer containing the log header and log message.
*/
if (p_format->colored_output) {
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "\x1B[38;5;%dm",
- colorFromPri(entry->priority));
+ prefixLen =
+ snprintf(prefixBuf, sizeof(prefixBuf), "\x1B[38;5;%dm", colorFromPri(entry->priority));
prefixLen = MIN(prefixLen, sizeof(prefixBuf));
const char suffixContents[] = "\x1B[0m";
@@ -1649,8 +1622,7 @@
#if !defined(__MINGW32__)
#if (FAKE_LOG_DEVICE == 0)
#ifndef __BIONIC__
-#warning \
- "This code assumes that getpwuid is thread safe, only true with Bionic!"
+#warning "This code assumes that getpwuid is thread safe, only true with Bionic!"
#endif
#endif
struct passwd* pwd = getpwuid(entry->uid);
@@ -1669,21 +1641,21 @@
switch (p_format->format) {
case FORMAT_TAG:
- len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%c/%-8.*s: ", priChar, (int)entry->tagLen, entry->tag);
+ len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, "%c/%-8.*s: ", priChar,
+ (int)entry->tagLen, entry->tag);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
case FORMAT_PROCESS:
- len = snprintf(suffixBuf + suffixLen, sizeof(suffixBuf) - suffixLen,
- " (%.*s)\n", (int)entry->tagLen, entry->tag);
+ len = snprintf(suffixBuf + suffixLen, sizeof(suffixBuf) - suffixLen, " (%.*s)\n",
+ (int)entry->tagLen, entry->tag);
suffixLen += MIN(len, sizeof(suffixBuf) - suffixLen);
- len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%c(%s%5d) ", priChar, uid, entry->pid);
+ len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, "%c(%s%5d) ", priChar,
+ uid, entry->pid);
break;
case FORMAT_THREAD:
- len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%c(%s%5d:%5d) ", priChar, uid, entry->pid, entry->tid);
+ len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, "%c(%s%5d:%5d) ",
+ priChar, uid, entry->pid, entry->tid);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
@@ -1695,8 +1667,8 @@
break;
case FORMAT_TIME:
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%s %c/%-8.*s(%s%5d): ", timeBuf, priChar,
- (int)entry->tagLen, entry->tag, uid, entry->pid);
+ "%s %c/%-8.*s(%s%5d): ", timeBuf, priChar, (int)entry->tagLen, entry->tag, uid,
+ entry->pid);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
@@ -1706,24 +1678,24 @@
*ret = ' ';
}
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%s %s%5d %5d %c %-8.*s: ", timeBuf, uid, entry->pid,
- entry->tid, priChar, (int)entry->tagLen, entry->tag);
+ "%s %s%5d %5d %c %-8.*s: ", timeBuf, uid, entry->pid, entry->tid, priChar,
+ (int)entry->tagLen, entry->tag);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
case FORMAT_LONG:
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "[ %s %s%5d:%5d %c/%-8.*s ]\n", timeBuf, uid, entry->pid,
- entry->tid, priChar, (int)entry->tagLen, entry->tag);
+ "[ %s %s%5d:%5d %c/%-8.*s ]\n", timeBuf, uid, entry->pid, entry->tid, priChar,
+ (int)entry->tagLen, entry->tag);
strcpy(suffixBuf + suffixLen, "\n\n");
suffixLen += 2;
prefixSuffixIsHeaderFooter = 1;
break;
case FORMAT_BRIEF:
default:
- len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%c/%-8.*s(%s%5d): ", priChar, (int)entry->tagLen,
- entry->tag, uid, entry->pid);
+ len =
+ snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
+ "%c/%-8.*s(%s%5d): ", priChar, (int)entry->tagLen, entry->tag, uid, entry->pid);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
@@ -1847,16 +1819,15 @@
* Returns count bytes written
*/
-LIBLOG_ABI_PUBLIC int android_log_printLogLine(AndroidLogFormat* p_format,
- int fd,
+LIBLOG_ABI_PUBLIC int android_log_printLogLine(AndroidLogFormat* p_format, int fd,
const AndroidLogEntry* entry) {
int ret;
char defaultBuffer[512];
char* outBuffer = NULL;
size_t totalLen;
- outBuffer = android_log_formatLogLine(
- p_format, defaultBuffer, sizeof(defaultBuffer), entry, &totalLen);
+ outBuffer =
+ android_log_formatLogLine(p_format, defaultBuffer, sizeof(defaultBuffer), entry, &totalLen);
if (!outBuffer) return -1;
diff --git a/liblog/pmsg_reader.c b/liblog/pmsg_reader.cpp
similarity index 83%
rename from liblog/pmsg_reader.c
rename to liblog/pmsg_reader.cpp
index c3ed8a2..7bc6e4a 100644
--- a/liblog/pmsg_reader.c
+++ b/liblog/pmsg_reader.cpp
@@ -32,28 +32,27 @@
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);
+ 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);
LIBLOG_HIDDEN 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,
+ .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) {
@@ -68,8 +67,7 @@
/* 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);
+ return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT) || (uid == AID_LOGD);
}
static uid_t get_best_effective_uid() {
@@ -130,8 +128,7 @@
}
static int pmsgRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp,
- struct log_msg* log_msg) {
+ struct android_log_transport_context* transp, struct log_msg* log_msg) {
ssize_t ret;
off_t current, next;
uid_t uid;
@@ -174,8 +171,7 @@
if (fd <= 0) {
return -EBADF;
}
- ret = TEMP_FAILURE_RETRY(
- read(fd, &buf.p.magic + preread_count, sizeof(buf) - preread_count));
+ ret = TEMP_FAILURE_RETRY(read(fd, &buf.p.magic + preread_count, sizeof(buf) - preread_count));
if (ret < 0) {
return -errno;
}
@@ -185,11 +181,10 @@
return preread_count ? -EIO : -EAGAIN;
}
if ((buf.p.magic != LOGGER_MAGIC) || (buf.p.len <= sizeof(buf)) ||
- (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD)) ||
- (buf.l.id >= LOG_ID_MAX) || (buf.l.realtime.tv_nsec >= NS_PER_SEC) ||
+ (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD)) || (buf.l.id >= LOG_ID_MAX) ||
+ (buf.l.realtime.tv_nsec >= NS_PER_SEC) ||
((buf.l.id != LOG_ID_EVENTS) && (buf.l.id != LOG_ID_SECURITY) &&
- ((buf.prio == ANDROID_LOG_UNKNOWN) ||
- (buf.prio == ANDROID_LOG_DEFAULT) ||
+ ((buf.prio == ANDROID_LOG_UNKNOWN) || (buf.prio == ANDROID_LOG_DEFAULT) ||
(buf.prio >= ANDROID_LOG_SILENT)))) {
do {
memmove(&buf.p.magic, &buf.p.magic + 1, --preread_count);
@@ -213,8 +208,7 @@
if (fd <= 0) {
return -EBADF;
}
- ret = TEMP_FAILURE_RETRY(
- read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
+ ret = TEMP_FAILURE_RETRY(read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
if (ret < 0) {
return -errno;
}
@@ -250,8 +244,7 @@
if (fd <= 0) {
return -EBADF;
}
- next = TEMP_FAILURE_RETRY(
- lseek(fd, (off_t)(buf.p.len - sizeof(buf)), SEEK_CUR));
+ next = TEMP_FAILURE_RETRY(lseek(fd, (off_t)(buf.p.len - sizeof(buf)), SEEK_CUR));
if (next < 0) {
return -errno;
}
@@ -269,9 +262,18 @@
}
}
-LIBLOG_ABI_PRIVATE 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) {
+static void* realloc_or_free(void* ptr, size_t new_size) {
+ void* result = realloc(ptr, new_size);
+ if (!result) {
+ free(ptr);
+ }
+ return result;
+}
+
+LIBLOG_ABI_PRIVATE 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;
@@ -304,14 +306,12 @@
memset(&logger_list, 0, sizeof(logger_list));
memset(&transp, 0, sizeof(transp));
- logger_list.mode =
- ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK | ANDROID_LOG_RDONLY;
+ logger_list.mode = ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK | ANDROID_LOG_RDONLY;
transp.logMask = (unsigned)-1;
if (logId != LOG_ID_ANY) {
transp.logMask = (1 << logId);
}
- transp.logMask &=
- ~((1 << LOG_ID_KERNEL) | (1 << LOG_ID_EVENTS) | (1 << LOG_ID_SECURITY));
+ transp.logMask &= ~((1 << LOG_ID_KERNEL) | (1 << LOG_ID_EVENTS) | (1 << LOG_ID_SECURITY));
if (!transp.logMask) {
return -EINVAL;
}
@@ -338,15 +338,13 @@
/* Read the file content */
while (pmsgRead(&logger_list, &transp, &transp.logMsg) > 0) {
- char* cp;
- size_t hdr_size = transp.logMsg.entry.hdr_size
- ? transp.logMsg.entry.hdr_size
- : sizeof(transp.logMsg.entry_v1);
+ 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;
- char* split = NULL;
+ const char* split = NULL;
- if ((hdr_size < sizeof(transp.logMsg.entry_v1)) ||
- (hdr_size > sizeof(transp.logMsg.entry))) {
+ if ((hdr_size < sizeof(transp.logMsg.entry_v1)) || (hdr_size > sizeof(transp.logMsg.entry))) {
continue;
}
/* Check for invalid sequence number */
@@ -358,8 +356,7 @@
/* Determine if it has <dirbase>:<filebase> format for tag */
len = transp.logMsg.entry.len - sizeof(prio);
- for (cp = msg + sizeof(prio); *cp && isprint(*cp) && !isspace(*cp) && --len;
- ++cp) {
+ for (cp = msg + sizeof(prio); *cp && isprint(*cp) && !isspace(*cp) && --len; ++cp) {
if (*cp == ':') {
if (split) {
break;
@@ -387,13 +384,12 @@
continue;
}
offset = split - prefix;
- if ((msg[offset + sizeof(prio)] != ':') ||
- strncmp(msg + sizeof(prio), prefix, offset)) {
+ if ((msg[offset + sizeof(prio)] != ':') || strncmp(msg + sizeof(prio), prefix, offset)) {
continue;
}
++offset;
- if ((prefix_len > offset) && strncmp(&msg[offset + sizeof(prio)],
- split + 1, prefix_len - offset)) {
+ if ((prefix_len > offset) &&
+ strncmp(&msg[offset + sizeof(prio)], split + 1, prefix_len - offset)) {
continue;
}
}
@@ -405,8 +401,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 == transp.logMsg.entry.lid) &&
+ (names->prio == *msg)) {
break;
}
}
@@ -417,13 +413,13 @@
unsigned long long nl;
len = strlen(msg + sizeof(prio)) + 1;
- names = calloc(1, sizeof(*names) + len);
+ names = static_cast<struct names*>(calloc(1, sizeof(*names) + len));
if (!names) {
ret = -ENOMEM;
break;
}
strcpy(names->name, msg + sizeof(prio));
- names->id = transp.logMsg.entry.lid;
+ names->id = static_cast<log_id_t>(transp.logMsg.entry.lid);
names->prio = *msg;
list_init(&names->content);
/*
@@ -483,19 +479,17 @@
}
/* Add content */
- content =
- calloc(1, sizeof(content->node) + hdr_size + transp.logMsg.entry.len);
+ content = static_cast<struct content*>(
+ calloc(1, sizeof(content->node) + hdr_size + transp.logMsg.entry.len));
if (!content) {
ret = -ENOMEM;
break;
}
- memcpy(&content->entry, &transp.logMsg.entry,
- hdr_size + transp.logMsg.entry.len);
+ memcpy(&content->entry, &transp.logMsg.entry, hdr_size + transp.logMsg.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 < transp.logMsg.entry.nsec) {
break;
}
}
@@ -528,7 +522,7 @@
}
if (!buf) {
- buf = malloc(sizeof(char));
+ buf = static_cast<char*>(malloc(sizeof(char)));
if (!buf) {
ret = -ENOMEM;
list_remove(content_node);
@@ -541,7 +535,7 @@
/* Missing sequence numbers */
while (sequence < content->entry.nsec) {
/* plus space for enforced nul */
- buf = realloc(buf, len + sizeof(char) + sizeof(char));
+ buf = static_cast<char*>(realloc_or_free(buf, len + sizeof(char) + sizeof(char)));
if (!buf) {
break;
}
@@ -556,16 +550,14 @@
continue;
}
/* plus space for enforced nul */
- buf = realloc(buf, len + add_len + sizeof(char));
+ buf = static_cast<char*>(realloc_or_free(buf, len + add_len + sizeof(char)));
if (!buf) {
ret = -ENOMEM;
list_remove(content_node);
free(content);
continue;
}
- memcpy(buf + len,
- (char*)&content->entry + content->entry.hdr_size + tag_len +
- sizeof(prio),
+ memcpy(buf + len, (char*)&content->entry + content->entry.hdr_size + tag_len + sizeof(prio),
add_len);
len += add_len;
buf[len] = '\0'; /* enforce trailing hidden nul */
diff --git a/liblog/pmsg_writer.c b/liblog/pmsg_writer.cpp
similarity index 88%
rename from liblog/pmsg_writer.c
rename to liblog/pmsg_writer.cpp
index dc42856..b2fc6d0 100644
--- a/liblog/pmsg_writer.c
+++ b/liblog/pmsg_writer.cpp
@@ -33,21 +33,21 @@
#include "config_write.h"
#include "log_portability.h"
#include "logger.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 int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
LIBLOG_HIDDEN struct android_log_transport_write pmsgLoggerWrite = {
- .node = { &pmsgLoggerWrite.node, &pmsgLoggerWrite.node },
- .context.fd = -1,
- .name = "pmsg",
- .available = pmsgAvailable,
- .open = pmsgOpen,
- .close = pmsgClose,
- .write = pmsgWrite,
+ .node = {&pmsgLoggerWrite.node, &pmsgLoggerWrite.node},
+ .context.fd = -1,
+ .name = "pmsg",
+ .available = pmsgAvailable,
+ .open = pmsgOpen,
+ .close = pmsgClose,
+ .write = pmsgWrite,
};
static int pmsgOpen() {
@@ -76,8 +76,7 @@
if (logId > LOG_ID_SECURITY) {
return -EINVAL;
}
- if ((logId != LOG_ID_SECURITY) && (logId != LOG_ID_EVENTS) &&
- !__android_log_is_debuggable()) {
+ if ((logId != LOG_ID_SECURITY) && (logId != LOG_ID_EVENTS) && !__android_log_is_debuggable()) {
return -EINVAL;
}
if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
@@ -96,8 +95,7 @@
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;
@@ -110,7 +108,7 @@
return -EINVAL;
}
- if (SNET_EVENT_LOG_TAG != get4LE(vec[0].iov_base)) {
+ if (SNET_EVENT_LOG_TAG != get4LE(static_cast<uint8_t*>(vec[0].iov_base))) {
return -EPERM;
}
}
@@ -169,8 +167,7 @@
}
pmsgHeader.len += payloadSize;
- ret = TEMP_FAILURE_RETRY(
- writev(atomic_load(&pmsgLoggerWrite.context.fd), newVec, i));
+ ret = TEMP_FAILURE_RETRY(writev(atomic_load(&pmsgLoggerWrite.context.fd), newVec, i));
if (ret < 0) {
ret = errno ? -errno : -ENOTCONN;
}
@@ -203,10 +200,8 @@
}
/* Write a buffer as filename references (tag = <basedir>:<basename>) */
-LIBLOG_ABI_PRIVATE ssize_t __android_log_pmsg_file_write(log_id_t logId,
- char prio,
- const char* filename,
- const char* buf,
+LIBLOG_ABI_PRIVATE 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;
@@ -249,13 +244,11 @@
vec[1].iov_len = length;
weOpened = false;
- for (ts.tv_nsec = 0, length = len; length;
- ts.tv_nsec += ANDROID_LOG_PMSG_FILE_SEQUENCE) {
+ for (ts.tv_nsec = 0, length = len; length; ts.tv_nsec += ANDROID_LOG_PMSG_FILE_SEQUENCE) {
ssize_t ret;
size_t transfer;
- if ((ts.tv_nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >=
- ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE) {
+ if ((ts.tv_nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >= ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE) {
len -= length;
break;
}
diff --git a/liblog/properties.c b/liblog/properties.cpp
similarity index 86%
rename from liblog/properties.c
rename to liblog/properties.cpp
index 11be827..764877e 100644
--- a/liblog/properties.c
+++ b/liblog/properties.cpp
@@ -14,9 +14,10 @@
** limitations under the License.
*/
+#include <log/log_properties.h>
+
#include <ctype.h>
#include <pthread.h>
-#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
@@ -160,11 +161,11 @@
}
if (!last_tag || !last_tag[0]) {
if (!last_tag) {
- last_tag = calloc(1, len + 1);
+ last_tag = static_cast<char*>(calloc(1, len + 1));
last_tag_len = 0;
if (last_tag) last_tag_len = len + 1;
} else if (len >= last_tag_len) {
- last_tag = realloc(last_tag, len + 1);
+ last_tag = static_cast<char*>(realloc(last_tag, len + 1));
last_tag_len = 0;
if (last_tag) last_tag_len = len + 1;
}
@@ -258,22 +259,19 @@
case 'A': return ANDROID_LOG_FATAL;
case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
- /* clang-format on */
+ /* clang-format on */
}
return default_prio;
}
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char* tag,
- size_t len,
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char* tag, size_t len,
int default_prio) {
int logLevel = __android_log_level(tag, len, default_prio);
return logLevel >= 0 && prio >= logLevel;
}
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char* tag,
- int default_prio) {
- int logLevel =
- __android_log_level(tag, (tag && *tag) ? strlen(tag) : 0, default_prio);
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char* tag, int default_prio) {
+ int logLevel = __android_log_level(tag, (tag && *tag) ? strlen(tag) : 0, default_prio);
return logLevel >= 0 && prio >= logLevel;
}
@@ -286,7 +284,7 @@
if (tag_cache.c) { /* ro property does not change after set */
ret = tag_cache.c == '1';
} else if (lock()) {
- struct cache_char temp_cache = { { NULL, -1 }, '\0' };
+ struct cache_char temp_cache = {{NULL, 0xFFFFFFFF}, '\0'};
refresh_cache(&temp_cache, key);
ret = temp_cache.c == '1';
} else {
@@ -332,8 +330,7 @@
return self->evaluate(self);
}
- change_detected = check_cache(&self->cache_persist.cache) ||
- check_cache(&self->cache_ro.cache);
+ change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
current_serial = __system_property_area_serial();
if (current_serial != self->serial) {
change_detected = 1;
@@ -365,15 +362,12 @@
* to handle developer requirements.
*/
LIBLOG_ABI_PUBLIC clockid_t android_log_clockid() {
- static struct cache2_char clockid = {
- PTHREAD_MUTEX_INITIALIZER, 0,
- "persist.logd.timestamp", { { NULL, -1 }, '\0' },
- "ro.logd.timestamp", { { NULL, -1 }, '\0' },
- evaluate_persist_ro
- };
+ static struct cache2_char clockid = {PTHREAD_MUTEX_INITIALIZER, 0,
+ "persist.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
+ "ro.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
+ evaluate_persist_ro};
- return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC
- : CLOCK_REALTIME;
+ return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
}
/*
@@ -388,11 +382,10 @@
LIBLOG_ABI_PUBLIC int __android_log_security() {
static struct cache2_char security = {
- PTHREAD_MUTEX_INITIALIZER, 0,
- "persist.logd.security", { { NULL, -1 }, BOOLEAN_FALSE },
- "ro.device_owner", { { NULL, -1 }, BOOLEAN_FALSE },
- evaluate_security
- };
+ PTHREAD_MUTEX_INITIALIZER, 0,
+ "persist.logd.security", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
+ "ro.device_owner", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
+ evaluate_security};
return do_cache2_char(&security);
}
@@ -423,8 +416,7 @@
char property[PROP_VALUE_MAX];
};
-static void refresh_cache_property(struct cache_property* cache,
- const char* key) {
+static void refresh_cache_property(struct cache_property* cache, const char* key) {
if (!cache->cache.pinfo) {
cache->cache.pinfo = __system_property_find(key);
if (!cache->cache.pinfo) {
@@ -436,19 +428,18 @@
}
/* get boolean with the logger twist that supports eng adjustments */
-LIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key,
- int flag) {
- struct cache_property property = { { NULL, -1 }, { 0 } };
+LIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key, int flag) {
+ struct cache_property property = {{NULL, 0xFFFFFFFF}, {0}};
if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
char newkey[strlen("persist.") + strlen(key) + 1];
snprintf(newkey, sizeof(newkey), "ro.%s", key);
refresh_cache_property(&property, newkey);
property.cache.pinfo = NULL;
- property.cache.serial = -1;
+ property.cache.serial = 0xFFFFFFFF;
snprintf(newkey, sizeof(newkey), "persist.%s", key);
refresh_cache_property(&property, newkey);
property.cache.pinfo = NULL;
- property.cache.serial = -1;
+ property.cache.serial = 0xFFFFFFFF;
}
refresh_cache_property(&property, key);
@@ -477,8 +468,7 @@
}
if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
- __android_logger_property_get_bool("ro.config.low_ram",
- BOOL_DEFAULT_FALSE)) {
+ __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)) {
return false;
}
if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
@@ -531,8 +521,7 @@
unsigned long (*const evaluate)(const struct cache2_property_size* self);
};
-static inline unsigned long do_cache2_property_size(
- struct cache2_property_size* self) {
+static inline unsigned long do_cache2_property_size(struct cache2_property_size* self) {
uint32_t current_serial;
int change_detected;
unsigned long v;
@@ -542,8 +531,7 @@
return self->evaluate(self);
}
- change_detected = check_cache(&self->cache_persist.cache) ||
- check_cache(&self->cache_ro.cache);
+ change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
current_serial = __system_property_area_serial();
if (current_serial != self->serial) {
change_detected = 1;
@@ -560,8 +548,7 @@
return v;
}
-static unsigned long property_get_size_from_cache(
- const struct cache_property* cache) {
+static unsigned long property_get_size_from_cache(const struct cache_property* cache) {
char* cp;
unsigned long value = strtoul(cache->property, &cp, 10);
@@ -569,11 +556,11 @@
case 'm':
case 'M':
value *= 1024;
- /* FALLTHRU */
+ [[fallthrough]];
case 'k':
case 'K':
value *= 1024;
- /* FALLTHRU */
+ [[fallthrough]];
case '\0':
break;
@@ -588,8 +575,7 @@
return value;
}
-static unsigned long evaluate_property_get_size(
- const struct cache2_property_size* self) {
+static unsigned long evaluate_property_get_size(const struct cache2_property_size* self) {
unsigned long size = property_get_size_from_cache(&self->cache_persist);
if (size) {
return size;
@@ -601,37 +587,35 @@
static const char global_tunable[] = "persist.logd.size"; /* Settings App */
static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
static struct cache2_property_size global = {
- /* clang-format off */
+ /* clang-format off */
PTHREAD_MUTEX_INITIALIZER, 0,
- global_tunable, { { NULL, -1 }, {} },
- global_default, { { NULL, -1 }, {} },
+ global_tunable, { { NULL, 0xFFFFFFFF }, {} },
+ global_default, { { NULL, 0xFFFFFFFF }, {} },
evaluate_property_get_size
- /* clang-format on */
+ /* clang-format on */
};
char key_persist[strlen(global_tunable) + strlen(".security") + 1];
char key_ro[strlen(global_default) + strlen(".security") + 1];
struct cache2_property_size local = {
- /* clang-format off */
+ /* clang-format off */
PTHREAD_MUTEX_INITIALIZER, 0,
- key_persist, { { NULL, -1 }, {} },
- key_ro, { { NULL, -1 }, {} },
+ key_persist, { { NULL, 0xFFFFFFFF }, {} },
+ key_ro, { { NULL, 0xFFFFFFFF }, {} },
evaluate_property_get_size
- /* clang-format on */
+ /* clang-format on */
};
unsigned long property_size, default_size;
default_size = do_cache2_property_size(&global);
if (!default_size) {
- default_size = __android_logger_property_get_bool("ro.config.low_ram",
- BOOL_DEFAULT_FALSE)
+ default_size = __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)
? LOG_BUFFER_MIN_SIZE /* 64K */
: LOG_BUFFER_SIZE; /* 256K */
}
snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
android_log_id_to_name(logId));
- snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default,
- android_log_id_to_name(logId));
+ snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default, android_log_id_to_name(logId));
property_size = do_cache2_property_size(&local);
if (!property_size) {
diff --git a/liblog/stderr_write.c b/liblog/stderr_write.cpp
similarity index 90%
rename from liblog/stderr_write.c
rename to liblog/stderr_write.cpp
index dbe5309..28195aa 100644
--- a/liblog/stderr_write.c
+++ b/liblog/stderr_write.cpp
@@ -37,16 +37,15 @@
#include <log/event_tag_map.h>
#include <log/log.h>
#include <log/logprint.h>
-#include <log/uio.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);
+static int stderrWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
struct stderrContext {
AndroidLogFormat* logformat;
@@ -56,13 +55,13 @@
};
LIBLOG_HIDDEN struct android_log_transport_write stderrLoggerWrite = {
- .node = { &stderrLoggerWrite.node, &stderrLoggerWrite.node },
- .context.priv = NULL,
- .name = "stderr",
- .available = stderrAvailable,
- .open = stderrOpen,
- .close = stderrClose,
- .write = stderrWrite,
+ .node = {&stderrLoggerWrite.node, &stderrLoggerWrite.node},
+ .context.priv = NULL,
+ .name = "stderr",
+ .available = stderrAvailable,
+ .open = stderrOpen,
+ .close = stderrClose,
+ .write = stderrWrite,
};
static int stderrOpen() {
@@ -78,7 +77,7 @@
return fileno(stderr);
}
- ctx = calloc(1, sizeof(struct stderrContext));
+ ctx = static_cast<stderrContext*>(calloc(1, sizeof(stderrContext)));
if (!ctx) {
return -ENOMEM;
}
@@ -123,7 +122,7 @@
}
static void stderrClose() {
- struct stderrContext* ctx = stderrLoggerWrite.context.priv;
+ stderrContext* ctx = static_cast<stderrContext*>(stderrLoggerWrite.context.priv);
if (ctx) {
stderrLoggerWrite.context.priv = NULL;
@@ -147,14 +146,13 @@
return 1;
}
-static int stderrWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
- size_t nr) {
+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;
- struct stderrContext* ctx = stderrLoggerWrite.context.priv;
+ stderrContext* ctx = static_cast<stderrContext*>(stderrLoggerWrite.context.priv);
if (!ctx) return -EBADF;
if (!vec || !nr) return -EINVAL;
diff --git a/liblog/tests/Android.bp b/liblog/tests/Android.bp
new file mode 100644
index 0000000..4ab2acb
--- /dev/null
+++ b/liblog/tests/Android.bp
@@ -0,0 +1,96 @@
+//
+// Copyright (C) 2013-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.
+//
+
+// -----------------------------------------------------------------------------
+// Benchmarks.
+// -----------------------------------------------------------------------------
+
+// Build benchmarks for the device. Run with:
+// adb shell liblog-benchmarks
+cc_benchmark {
+ name: "liblog-benchmarks",
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-fno-builtin",
+ ],
+ shared_libs: [
+ "libm",
+ "libbase",
+ ],
+ static_libs: ["liblog"],
+ srcs: ["liblog_benchmark.cpp"],
+}
+
+// -----------------------------------------------------------------------------
+// Unit tests.
+// -----------------------------------------------------------------------------
+
+cc_defaults {
+ name: "liblog-tests-defaults",
+
+ cflags: [
+ "-fstack-protector-all",
+ "-g",
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-fno-builtin",
+ ],
+ srcs: [
+ "libc_test.cpp",
+ "liblog_test_default.cpp",
+ "liblog_test_stderr.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",
+ ],
+ shared_libs: [
+ "libcutils",
+ "libbase",
+ ],
+ static_libs: ["liblog"],
+}
+
+// Build tests for the device (with .so). Run with:
+// adb shell /data/nativetest/liblog-unit-tests/liblog-unit-tests
+cc_test {
+ name: "liblog-unit-tests",
+ defaults: ["liblog-tests-defaults"],
+}
+
+cc_test {
+ name: "CtsLiblogTestCases",
+ defaults: ["liblog-tests-defaults"],
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
+
+ cflags: ["-DNO_PSTORE"],
+ test_suites: [
+ "cts",
+ "vts",
+ ],
+}
diff --git a/liblog/tests/Android.mk b/liblog/tests/Android.mk
deleted file mode 100644
index cfa849b..0000000
--- a/liblog/tests/Android.mk
+++ /dev/null
@@ -1,116 +0,0 @@
-#
-# Copyright (C) 2013-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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-# -----------------------------------------------------------------------------
-# Benchmarks.
-# -----------------------------------------------------------------------------
-
-test_module_prefix := liblog-
-test_tags := tests
-
-benchmark_c_flags := \
- -Wall \
- -Wextra \
- -Werror \
- -fno-builtin \
-
-benchmark_src_files := \
- liblog_benchmark.cpp
-
-# Build benchmarks for the device. Run with:
-# adb shell liblog-benchmarks
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(test_module_prefix)benchmarks
-LOCAL_MODULE_TAGS := $(test_tags)
-LOCAL_CFLAGS += $(benchmark_c_flags)
-LOCAL_SHARED_LIBRARIES += liblog libm libbase
-LOCAL_SRC_FILES := $(benchmark_src_files)
-include $(BUILD_NATIVE_BENCHMARK)
-
-# -----------------------------------------------------------------------------
-# Unit tests.
-# -----------------------------------------------------------------------------
-
-test_c_flags := \
- -fstack-protector-all \
- -g \
- -Wall -Wextra \
- -Werror \
- -fno-builtin \
-
-cts_src_files := \
- libc_test.cpp \
- liblog_test_default.cpp \
- liblog_test_local.cpp \
- liblog_test_stderr.cpp \
- liblog_test_stderr_local.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
-
-test_src_files := \
- $(cts_src_files) \
-
-# Build tests for the device (with .so). Run with:
-# adb shell /data/nativetest/liblog-unit-tests/liblog-unit-tests
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(test_module_prefix)unit-tests
-LOCAL_MODULE_TAGS := $(test_tags)
-LOCAL_CFLAGS += $(test_c_flags)
-LOCAL_SHARED_LIBRARIES := liblog libcutils libbase
-LOCAL_SRC_FILES := $(test_src_files)
-include $(BUILD_NATIVE_TEST)
-
-cts_executable := CtsLiblogTestCases
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(cts_executable)
-LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS += $(test_c_flags) -DNO_PSTORE
-LOCAL_SRC_FILES := $(cts_src_files)
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-LOCAL_SHARED_LIBRARIES := liblog libcutils libbase
-LOCAL_STATIC_LIBRARIES := libgtest libgtest_main
-LOCAL_COMPATIBILITY_SUITE := cts vts
-LOCAL_CTS_TEST_PACKAGE := android.core.liblog
-include $(BUILD_CTS_EXECUTABLE)
-
-ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(cts_executable)_list
-LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS := $(test_c_flags) -DHOST
-LOCAL_C_INCLUDES := external/gtest/include
-LOCAL_SRC_FILES := $(test_src_files)
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-LOCAL_CXX_STL := libc++
-LOCAL_SHARED_LIBRARIES := liblog libcutils libbase
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_LDLIBS_linux := -lrt
-include $(BUILD_HOST_NATIVE_TEST)
-
-endif # ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index c2f3f83..c8ac321 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -21,6 +21,7 @@
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
+#include <sys/uio.h>
#include <unistd.h>
#include <unordered_set>
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index a8a9a12..83f0fa9 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -30,6 +30,7 @@
#include <string>
#include <android-base/file.h>
+#include <android-base/macros.h>
#include <android-base/stringprintf.h>
#ifdef __ANDROID__ // includes sys/properties.h which does not exist outside
#include <cutils/properties.h>
@@ -51,22 +52,6 @@
#endif
#endif
-#if (!defined(USING_LOGGER_DEFAULT) || !defined(USING_LOGGER_LOCAL) || \
- !defined(USING_LOGGER_STDERR))
-#ifdef liblog // a binary clue that we are overriding the test names
-// Does not support log reading blocking feature yet
-// Does not support LOG_ID_SECURITY (unless we set LOGGER_LOCAL | LOGGER_LOGD)
-// Assume some common aspects are tested by USING_LOGGER_DEFAULT:
-// Does not need to _retest_ pmsg functionality
-// Does not need to _retest_ property handling as it is a higher function
-// Does not need to _retest_ event mapping functionality
-// Does not need to _retest_ ratelimit
-// Does not need to _retest_ logprint
-#define USING_LOGGER_LOCAL
-#else
-#define USING_LOGGER_DEFAULT
-#endif
-#endif
#ifdef USING_LOGGER_STDERR
#define SUPPORTS_END_TO_END 0
#else
@@ -130,7 +115,7 @@
static bool isLogdwActive() {
std::string logdwSignature =
- popenToString("grep /dev/socket/logdw /proc/net/unix");
+ popenToString("grep -a /dev/socket/logdw /proc/net/unix");
size_t beginning = logdwSignature.find(' ');
if (beginning == std::string::npos) return true;
beginning = logdwSignature.find(' ', beginning + 1);
@@ -144,7 +129,7 @@
end = logdwSignature.find(' ', end + 1);
if (end == std::string::npos) return true;
std::string allLogdwEndpoints = popenToString(
- "grep ' 00000002" + logdwSignature.substr(beginning, end - beginning) +
+ "grep -a ' 00000002" + logdwSignature.substr(beginning, end - beginning) +
" ' /proc/net/unix | " +
"sed -n 's/.* \\([0-9][0-9]*\\)$/ -> socket:[\\1]/p'");
if (allLogdwEndpoints.length() == 0) return true;
@@ -174,7 +159,7 @@
#endif
TEST(liblog, __android_log_btwrite__android_logger_list_read) {
-#if (defined(__ANDROID__) || defined(USING_LOGGER_LOCAL))
+#ifdef __ANDROID__
#ifdef TEST_PREFIX
TEST_PREFIX
#endif
@@ -268,7 +253,7 @@
#endif
}
-#if (defined(__ANDROID__) || defined(USING_LOGGER_LOCAL))
+#ifdef __ANDROID__
static void print_transport(const char* prefix, int logger) {
static const char orstr[] = " | ";
@@ -296,16 +281,11 @@
fprintf(stderr, "%sLOGGER_NULL", prefix);
prefix = orstr;
}
- if (logger & LOGGER_LOCAL) {
- fprintf(stderr, "%sLOGGER_LOCAL", prefix);
- prefix = orstr;
- }
if (logger & LOGGER_STDERR) {
fprintf(stderr, "%sLOGGER_STDERR", prefix);
prefix = orstr;
}
- logger &= ~(LOGGER_LOGD | LOGGER_KERNEL | LOGGER_NULL | LOGGER_LOCAL |
- LOGGER_STDERR);
+ logger &= ~(LOGGER_LOGD | LOGGER_KERNEL | LOGGER_NULL | LOGGER_STDERR);
if (logger) {
fprintf(stderr, "%s0x%x", prefix, logger);
prefix = orstr;
@@ -320,7 +300,7 @@
// 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) {
-#if (defined(__ANDROID__) || defined(USING_LOGGER_LOCAL))
+#ifdef __ANDROID__
#ifdef TEST_PREFIX
TEST_PREFIX
#endif
@@ -631,7 +611,7 @@
buf_write_test("\n Hello World \n");
}
-#ifndef USING_LOGGER_LOCAL // requires blocking reader functionality
+#ifdef USING_LOGGER_DEFAULT // requires blocking reader functionality
#ifdef TEST_PREFIX
static unsigned signaled;
static log_time signal_time;
@@ -943,7 +923,7 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
#ifdef TEST_PREFIX
static const char max_payload_tag[] = "TEST_max_payload_and_longish_tag_XXXX";
@@ -2416,7 +2396,7 @@
}
// Do not retest logger list handling
-#if (defined(TEST_PREFIX) || !defined(USING_LOGGER_LOCAL))
+#ifdef TEST_PREFIX
static int is_real_element(int type) {
return ((type == EVENT_TYPE_INT) || (type == EVENT_TYPE_LONG) ||
(type == EVENT_TYPE_STRING) || (type == EVENT_TYPE_FLOAT));
@@ -2516,7 +2496,7 @@
#endif
elem.data.string = const_cast<char*>("<unknown>");
elem.len = strlen(elem.data.string);
- /* FALLTHRU */
+ FALLTHROUGH_INTENDED;
case EVENT_TYPE_STRING:
if (elem.len <= strOutLen) {
memcpy(strOut, elem.data.string, elem.len);
@@ -2571,7 +2551,7 @@
return 0;
}
-#endif // TEST_PREFIX || !USING_LOGGER_LOCAL
+#endif // TEST_PREFIX
#ifdef TEST_PREFIX
static const char* event_test_int32(uint32_t tag, size_t& expected_len) {
@@ -3180,41 +3160,6 @@
}
#endif // USING_LOGGER_DEFAULT
-#ifdef USING_LOGGER_DEFAULT // Do not retest ratelimit
-TEST(liblog, __android_log_ratelimit) {
- time_t state = 0;
-
- errno = 42;
- // Prime
- __android_log_ratelimit(3, &state);
- EXPECT_EQ(errno, 42);
- // Check
- EXPECT_FALSE(__android_log_ratelimit(3, &state));
- sleep(1);
- EXPECT_FALSE(__android_log_ratelimit(3, &state));
- sleep(4);
- EXPECT_TRUE(__android_log_ratelimit(3, &state));
- sleep(5);
- EXPECT_TRUE(__android_log_ratelimit(3, &state));
-
- // API checks
- IF_ALOG_RATELIMIT_LOCAL(3, &state) {
- EXPECT_FALSE(0 != "IF_ALOG_RATELIMIT_LOCAL(3, &state)");
- }
-
- IF_ALOG_RATELIMIT() {
- ;
- }
- else {
- EXPECT_TRUE(0 == "IF_ALOG_RATELIMIT()");
- }
- IF_ALOG_RATELIMIT() {
- EXPECT_FALSE(0 != "IF_ALOG_RATELIMIT()");
- }
- // Do not test default seconds, to allow liblog to tune freely
-}
-#endif // USING_LOGGER_DEFAULT
-
#ifdef USING_LOGGER_DEFAULT // Do not retest event mapping functionality
TEST(liblog, android_lookupEventTagNum) {
#ifdef __ANDROID__
diff --git a/liblog/tests/liblog_test_local.cpp b/liblog/tests/liblog_test_local.cpp
deleted file mode 100644
index 451beca..0000000
--- a/liblog/tests/liblog_test_local.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-#include <log/log_transport.h>
-#define liblog liblog_local
-#define TEST_LOGGER LOGGER_LOCAL
-#include "liblog_test.cpp"
diff --git a/liblog/tests/liblog_test_stderr_local.cpp b/liblog/tests/liblog_test_stderr_local.cpp
deleted file mode 100644
index bb5c7ae..0000000
--- a/liblog/tests/liblog_test_stderr_local.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-#include <log/log_transport.h>
-#define liblog liblog_stderr_local
-#define TEST_LOGGER (LOGGER_LOCAL | LOGGER_STDERR)
-#include "liblog_test.cpp"
diff --git a/liblog/tests/log_time_test.cpp b/liblog/tests/log_time_test.cpp
index 0ae1d18..47fe594 100644
--- a/liblog/tests/log_time_test.cpp
+++ b/liblog/tests/log_time_test.cpp
@@ -21,12 +21,6 @@
#include <log/log_time.h>
TEST(liblog, log_time) {
-#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
- log_time(CLOCK_MONOTONIC);
-
- EXPECT_EQ(log_time, log_time::EPOCH);
-#endif
-
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
log_time tl(ts);
diff --git a/liblog/uio.c b/liblog/uio.c
deleted file mode 100644
index e127202..0000000
--- a/liblog/uio.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2007-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.
- */
-
-#if defined(_WIN32)
-
-#include <unistd.h>
-
-#include <log/uio.h>
-
-#include "log_portability.h"
-
-LIBLOG_ABI_PUBLIC int readv(int fd, struct iovec* vecs, int count) {
- int total = 0;
-
- for (; count > 0; count--, vecs++) {
- char* buf = vecs->iov_base;
- int len = vecs->iov_len;
-
- while (len > 0) {
- int ret = read(fd, buf, len);
- if (ret < 0) {
- if (total == 0) total = -1;
- goto Exit;
- }
- if (ret == 0) goto Exit;
-
- total += ret;
- buf += ret;
- len -= ret;
- }
- }
-Exit:
- return total;
-}
-
-LIBLOG_ABI_PUBLIC int writev(int fd, const struct iovec* vecs, int count) {
- int total = 0;
-
- for (; count > 0; count--, vecs++) {
- const char* buf = vecs->iov_base;
- int len = vecs->iov_len;
-
- while (len > 0) {
- int ret = write(fd, buf, len);
- if (ret < 0) {
- if (total == 0) total = -1;
- goto Exit;
- }
- if (ret == 0) goto Exit;
-
- total += ret;
- buf += ret;
- len -= ret;
- }
- }
-Exit:
- return total;
-}
-
-#endif
diff --git a/libbacktrace/GetPss.h b/liblog/uio.h
similarity index 73%
copy from libbacktrace/GetPss.h
copy to liblog/uio.h
index 787c33d..c85893c 100644
--- a/libbacktrace/GetPss.h
+++ b/liblog/uio.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 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,9 +14,14 @@
* limitations under the License.
*/
-#ifndef _LIBBACKTRACE_GET_PSS_H
-#define _LIBBACKTRACE_GET_PSS_H
+#pragma once
-size_t GetPssBytes();
-
-#endif // _LIBBACKTRACE_GET_PSS_H
+#if defined(_WIN32)
+#include <stddef.h>
+struct iovec {
+ void* iov_base;
+ size_t iov_len;
+};
+#else
+#include <sys/uio.h>
+#endif
diff --git a/libmeminfo/.clang-format b/libmeminfo/.clang-format
new file mode 120000
index 0000000..1af4f51
--- /dev/null
+++ b/libmeminfo/.clang-format
@@ -0,0 +1 @@
+../.clang-format-4
\ No newline at end of file
diff --git a/libmeminfo/Android.bp b/libmeminfo/Android.bp
new file mode 100644
index 0000000..3e191ad
--- /dev/null
+++ b/libmeminfo/Android.bp
@@ -0,0 +1,79 @@
+//
+// 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",
+ "libpagemap",
+ "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
new file mode 100644
index 0000000..26e71fe
--- /dev/null
+++ b/libmeminfo/OWNERS
@@ -0,0 +1 @@
+sspatil@google.com
diff --git a/libmeminfo/include/meminfo/meminfo.h b/libmeminfo/include/meminfo/meminfo.h
new file mode 100644
index 0000000..2fc7867
--- /dev/null
+++ b/libmeminfo/include/meminfo/meminfo.h
@@ -0,0 +1,82 @@
+/*
+ * 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
new file mode 100644
index 0000000..8483d84
--- /dev/null
+++ b/libmeminfo/include/meminfo/pageacct.h
@@ -0,0 +1,81 @@
+/*
+ * 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
new file mode 100644
index 0000000..95e5053
--- /dev/null
+++ b/libmeminfo/include/meminfo/procmeminfo.h
@@ -0,0 +1,121 @@
+/*
+ * 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();
+
+ // 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 ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss);
+
+ 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
new file mode 100644
index 0000000..450a469
--- /dev/null
+++ b/libmeminfo/include/meminfo/sysmeminfo.h
@@ -0,0 +1,88 @@
+/*
+ * 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(const std::string& path = "/proc/vmallocinfo");
+
+ // 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);
+};
+
+} // namespace meminfo
+} // namespace android
diff --git a/libmeminfo/libmeminfo_benchmark.cpp b/libmeminfo/libmeminfo_benchmark.cpp
new file mode 100644
index 0000000..81fc3b3
--- /dev/null
+++ b/libmeminfo/libmeminfo_benchmark.cpp
@@ -0,0 +1,545 @@
+/*
+ * 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) {
+ SysMemInfo smi;
+ CHECK_EQ(smi.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
new file mode 100644
index 0000000..0e0212f
--- /dev/null
+++ b/libmeminfo/libmeminfo_test.cpp
@@ -0,0 +1,921 @@
+/*
+ * 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 <pagemap/pagemap.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;
+
+class ValidateProcMemInfo : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ ASSERT_EQ(0, pm_kernel_create(&ker));
+ ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
+ proc_mem = new ProcMemInfo(pid);
+ ASSERT_NE(proc_mem, nullptr);
+ }
+
+ void TearDown() override {
+ delete proc_mem;
+ pm_process_destroy(proc);
+ pm_kernel_destroy(ker);
+ }
+
+ pm_kernel_t* ker;
+ pm_process_t* proc;
+ ProcMemInfo* proc_mem;
+};
+
+TEST_F(ValidateProcMemInfo, TestMapsSize) {
+ const std::vector<Vma>& maps = proc_mem->Maps();
+ ASSERT_FALSE(maps.empty()) << "Process " << getpid() << " maps are empty";
+}
+
+TEST_F(ValidateProcMemInfo, TestMapsEquality) {
+ const std::vector<Vma>& maps = proc_mem->Maps();
+ ASSERT_EQ(proc->num_maps, maps.size());
+
+ for (size_t i = 0; i < maps.size(); ++i) {
+ EXPECT_EQ(proc->maps[i]->start, maps[i].start);
+ EXPECT_EQ(proc->maps[i]->end, maps[i].end);
+ EXPECT_EQ(proc->maps[i]->offset, maps[i].offset);
+ EXPECT_EQ(std::string(proc->maps[i]->name), maps[i].name);
+ }
+}
+
+TEST_F(ValidateProcMemInfo, TestMaps) {
+ const std::vector<Vma>& maps = proc_mem->Maps();
+ ASSERT_FALSE(maps.empty());
+ ASSERT_EQ(proc->num_maps, maps.size());
+
+ pm_memusage_t map_usage, proc_usage;
+ pm_memusage_zero(&map_usage);
+ pm_memusage_zero(&proc_usage);
+ for (size_t i = 0; i < maps.size(); i++) {
+ ASSERT_EQ(0, pm_map_usage(proc->maps[i], &map_usage));
+ EXPECT_EQ(map_usage.vss, maps[i].usage.vss) << "VSS mismatch for map: " << maps[i].name;
+ EXPECT_EQ(map_usage.rss, maps[i].usage.rss) << "RSS mismatch for map: " << maps[i].name;
+ EXPECT_EQ(map_usage.pss, maps[i].usage.pss) << "PSS mismatch for map: " << maps[i].name;
+ EXPECT_EQ(map_usage.uss, maps[i].usage.uss) << "USS mismatch for map: " << maps[i].name;
+ pm_memusage_add(&proc_usage, &map_usage);
+ }
+
+ EXPECT_EQ(proc_usage.vss, proc_mem->Usage().vss);
+ EXPECT_EQ(proc_usage.rss, proc_mem->Usage().rss);
+ EXPECT_EQ(proc_usage.pss, proc_mem->Usage().pss);
+ EXPECT_EQ(proc_usage.uss, proc_mem->Usage().uss);
+}
+
+TEST_F(ValidateProcMemInfo, TestSwapUsage) {
+ const std::vector<Vma>& maps = proc_mem->Maps();
+ ASSERT_FALSE(maps.empty());
+ ASSERT_EQ(proc->num_maps, maps.size());
+
+ pm_memusage_t map_usage, proc_usage;
+ pm_memusage_zero(&map_usage);
+ pm_memusage_zero(&proc_usage);
+ for (size_t i = 0; i < maps.size(); i++) {
+ ASSERT_EQ(0, pm_map_usage(proc->maps[i], &map_usage));
+ EXPECT_EQ(map_usage.swap, maps[i].usage.swap) << "SWAP mismatch for map: " << maps[i].name;
+ pm_memusage_add(&proc_usage, &map_usage);
+ }
+
+ EXPECT_EQ(proc_usage.swap, proc_mem->Usage().swap);
+}
+
+TEST_F(ValidateProcMemInfo, TestSwapOffsets) {
+ const MemUsage& proc_usage = proc_mem->Usage();
+ const std::vector<uint16_t>& swap_offsets = proc_mem->SwapOffsets();
+
+ EXPECT_EQ(proc_usage.swap / getpagesize(), swap_offsets.size());
+}
+
+TEST_F(ValidateProcMemInfo, TestPageMap) {
+ std::vector<uint64_t> pagemap;
+
+ auto vma_callback = [&](const Vma& vma) {
+ uint64_t* pmap_out;
+ size_t len;
+ ASSERT_EQ(0, pm_process_pagemap_range(proc, vma.start, vma.end, &pmap_out, &len));
+ ASSERT_TRUE(proc_mem->PageMap(vma, &pagemap));
+
+ EXPECT_EQ(len, ((vma.end - vma.start) / getpagesize()));
+ for (size_t i = 0; i < len; i++) {
+ EXPECT_EQ(pmap_out[i], pagemap[i]);
+ }
+ };
+ ASSERT_TRUE(proc_mem->ForEachVma(vma_callback));
+}
+
+class ValidateProcMemInfoWss : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ ASSERT_EQ(0, pm_kernel_create(&ker));
+ ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
+ proc_mem = new ProcMemInfo(pid, true);
+ ASSERT_NE(proc_mem, nullptr);
+ }
+
+ void TearDown() override {
+ delete proc_mem;
+ pm_process_destroy(proc);
+ pm_kernel_destroy(ker);
+ }
+
+ pm_kernel_t* ker;
+ pm_process_t* proc;
+ ProcMemInfo* proc_mem;
+};
+
+TEST_F(ValidateProcMemInfoWss, TestWorkingTestReset) {
+ // Expect reset to succeed
+ EXPECT_TRUE(ProcMemInfo::ResetWorkingSet(pid));
+}
+
+TEST_F(ValidateProcMemInfoWss, TestWssEquality) {
+ // Read wss using libpagemap
+ pm_memusage_t wss_pagemap;
+ EXPECT_EQ(0, pm_process_workingset(proc, &wss_pagemap, 0));
+
+ // Read wss using libmeminfo
+ MemUsage wss = proc_mem->Wss();
+
+ // compare
+ EXPECT_EQ(wss_pagemap.rss, wss.rss);
+ EXPECT_EQ(wss_pagemap.pss, wss.pss);
+ EXPECT_EQ(wss_pagemap.uss, wss.uss);
+}
+
+class ValidatePageAcct : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ ASSERT_EQ(0, pm_kernel_create(&ker));
+ ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
+ }
+
+ void TearDown() override {
+ pm_process_destroy(proc);
+ pm_kernel_destroy(ker);
+ }
+
+ pm_kernel_t* ker;
+ pm_process_t* proc;
+};
+
+TEST_F(ValidatePageAcct, TestPageFlags) {
+ PageAcct& pi = PageAcct::Instance();
+ pi.InitPageAcct(false);
+
+ uint64_t* pagemap;
+ size_t num_pages;
+ for (size_t i = 0; i < proc->num_maps; i++) {
+ ASSERT_EQ(0, pm_map_pagemap(proc->maps[i], &pagemap, &num_pages));
+ for (size_t j = 0; j < num_pages; j++) {
+ if (!PM_PAGEMAP_PRESENT(pagemap[j])) continue;
+
+ uint64_t pfn = PM_PAGEMAP_PFN(pagemap[j]);
+ uint64_t page_flags_pagemap, page_flags_meminfo;
+
+ ASSERT_EQ(0, pm_kernel_flags(ker, pfn, &page_flags_pagemap));
+ ASSERT_TRUE(pi.PageFlags(pfn, &page_flags_meminfo));
+ // check if page flags equal
+ EXPECT_EQ(page_flags_pagemap, page_flags_meminfo);
+ }
+ free(pagemap);
+ }
+}
+
+TEST_F(ValidatePageAcct, TestPageCounts) {
+ PageAcct& pi = PageAcct::Instance();
+ pi.InitPageAcct(false);
+
+ uint64_t* pagemap;
+ size_t num_pages;
+ for (size_t i = 0; i < proc->num_maps; i++) {
+ ASSERT_EQ(0, pm_map_pagemap(proc->maps[i], &pagemap, &num_pages));
+ for (size_t j = 0; j < num_pages; j++) {
+ uint64_t pfn = PM_PAGEMAP_PFN(pagemap[j]);
+ uint64_t map_count_pagemap, map_count_meminfo;
+
+ ASSERT_EQ(0, pm_kernel_count(ker, pfn, &map_count_pagemap));
+ ASSERT_TRUE(pi.PageMapCount(pfn, &map_count_meminfo));
+ // check if map counts are equal
+ EXPECT_EQ(map_count_pagemap, map_count_meminfo);
+ }
+ free(pagemap);
+ }
+}
+
+TEST_F(ValidatePageAcct, TestPageIdle) {
+ // skip the test if idle page tracking isn't enabled
+ if (pm_kernel_init_page_idle(ker) != 0) {
+ return;
+ }
+
+ PageAcct& pi = PageAcct::Instance();
+ ASSERT_TRUE(pi.InitPageAcct(true));
+
+ uint64_t* pagemap;
+ size_t num_pages;
+ for (size_t i = 0; i < proc->num_maps; i++) {
+ ASSERT_EQ(0, pm_map_pagemap(proc->maps[i], &pagemap, &num_pages));
+ for (size_t j = 0; j < num_pages; j++) {
+ if (!PM_PAGEMAP_PRESENT(pagemap[j])) continue;
+ uint64_t pfn = PM_PAGEMAP_PFN(pagemap[j]);
+
+ ASSERT_EQ(0, pm_kernel_mark_page_idle(ker, &pfn, 1));
+ int idle_status_pagemap = pm_kernel_get_page_idle(ker, pfn);
+ int idle_status_meminfo = pi.IsPageIdle(pfn);
+ EXPECT_EQ(idle_status_pagemap, idle_status_meminfo);
+ }
+ free(pagemap);
+ }
+}
+
+TEST(TestProcMemInfo, MapsEmpty) {
+ ProcMemInfo proc_mem(pid);
+ const std::vector<Vma>& maps = proc_mem.Maps();
+ EXPECT_GT(maps.size(), 0);
+}
+
+TEST(TestProcMemInfo, UsageEmpty) {
+ // 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(TestProcMemInfo, 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(TestProcMemInfo, 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(TestProcMemInfo, IsSmapsSupportedTest) {
+ 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(TestProcMemInfo, SmapsOrRollupTest) {
+ 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(TestProcMemInfo, SmapsOrRollupSmapsTest) {
+ // This is a made up smaps for the test
+ 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(TestProcMemInfo, SmapsOrRollupPssRollupTest) {
+ // This is a made up smaps for the test
+ 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(TestProcMemInfo, SmapsOrRollupPssSmapsTest) {
+ 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(TestProcMemInfo, ForEachVmaFromFileTest) {
+ 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(TestProcMemInfo, SmapsReturnTest) {
+ ProcMemInfo proc_mem(pid);
+ auto vmas = proc_mem.Smaps();
+ EXPECT_FALSE(vmas.empty());
+}
+
+TEST(TestProcMemInfo, 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(ValidateProcMemInfoFlags, TestPageFlags1) {
+ // Create proc object using libpagemap
+ pm_kernel_t* ker;
+ ASSERT_EQ(0, pm_kernel_create(&ker));
+ pm_process_t* proc;
+ ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
+
+ // count swapbacked pages using libpagemap
+ pm_memusage_t proc_usage;
+ pm_memusage_zero(&proc_usage);
+ ASSERT_EQ(0, pm_process_usage_flags(proc, &proc_usage, (1 << KPF_SWAPBACKED),
+ (1 << KPF_SWAPBACKED)));
+
+ // Create ProcMemInfo that counts swapbacked pages
+ ProcMemInfo proc_mem(pid, false, (1 << KPF_SWAPBACKED), (1 << KPF_SWAPBACKED));
+
+ EXPECT_EQ(proc_usage.vss, proc_mem.Usage().vss);
+ EXPECT_EQ(proc_usage.rss, proc_mem.Usage().rss);
+ EXPECT_EQ(proc_usage.pss, proc_mem.Usage().pss);
+ EXPECT_EQ(proc_usage.uss, proc_mem.Usage().uss);
+
+ pm_process_destroy(proc);
+ pm_kernel_destroy(ker);
+}
+
+TEST(ValidateProcMemInfoFlags, TestPageFlags2) {
+ // Create proc object using libpagemap
+ pm_kernel_t* ker;
+ ASSERT_EQ(0, pm_kernel_create(&ker));
+ pm_process_t* proc;
+ ASSERT_EQ(0, pm_process_create(ker, pid, &proc));
+
+ // count non-swapbacked pages using libpagemap
+ pm_memusage_t proc_usage;
+ pm_memusage_zero(&proc_usage);
+ ASSERT_EQ(0, pm_process_usage_flags(proc, &proc_usage, (1 << KPF_SWAPBACKED), 0));
+
+ // Create ProcMemInfo that counts non-swapbacked pages
+ ProcMemInfo proc_mem(pid, false, 0, (1 << KPF_SWAPBACKED));
+
+ EXPECT_EQ(proc_usage.vss, proc_mem.Usage().vss);
+ EXPECT_EQ(proc_usage.rss, proc_mem.Usage().rss);
+ EXPECT_EQ(proc_usage.pss, proc_mem.Usage().pss);
+ EXPECT_EQ(proc_usage.uss, proc_mem.Usage().uss);
+
+ pm_process_destroy(proc);
+ pm_kernel_destroy(ker);
+}
+
+TEST(SysMemInfoParser, TestSysMemInfoFile) {
+ 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(SysMemInfoParser, 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(SysMemInfoParser, 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(SysMemInfoParser, 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(SysMemInfoParser, 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);
+
+ SysMemInfo smi;
+ EXPECT_EQ(smi.ReadVmallocInfo(file), 0);
+}
+
+TEST(SysMemInfoParser, 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);
+
+ SysMemInfo smi;
+ EXPECT_EQ(smi.ReadVmallocInfo(file), getpagesize());
+}
+
+TEST(SysMemInfoParser, 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);
+
+ SysMemInfo smi;
+ EXPECT_EQ(smi.ReadVmallocInfo(file), 6 * getpagesize());
+}
+
+TEST(SysMemInfoParser, 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);
+
+ SysMemInfo smi;
+ EXPECT_EQ(smi.ReadVmallocInfo(file), 7 * getpagesize());
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ if (argc <= 1) {
+ cerr << "Pid of a permanently sleeping process must be provided." << endl;
+ exit(EXIT_FAILURE);
+ }
+ ::android::base::InitLogging(argv, android::base::StderrLogger);
+ pid = std::stoi(std::string(argv[1]));
+ return RUN_ALL_TESTS();
+}
diff --git a/libmeminfo/meminfo_private.h b/libmeminfo/meminfo_private.h
new file mode 100644
index 0000000..df5699c
--- /dev/null
+++ b/libmeminfo/meminfo_private.h
@@ -0,0 +1,34 @@
+/*
+ * 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
new file mode 100644
index 0000000..0a26c08
--- /dev/null
+++ b/libmeminfo/pageacct.cpp
@@ -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 <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)) < 0) {
+ 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)) < 0) {
+ 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) < 0) {
+ 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
new file mode 100644
index 0000000..1df03b2
--- /dev/null
+++ b/libmeminfo/procmeminfo.cpp
@@ -0,0 +1,498 @@
+/*
+ * 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 <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::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) {
+ // 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,
+ 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)) {
+ 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) {
+ PageAcct& pinfo = PageAcct::Instance();
+ uint64_t pagesz = getpagesize();
+ uint64_t num_pages = (vma.end - vma.start) / pagesz;
+
+ std::unique_ptr<uint64_t[]> pg_frames(new uint64_t[num_pages]);
+ uint64_t first = vma.start / pagesz;
+ if (pread64(pagemap_fd, pg_frames.get(), num_pages * sizeof(uint64_t),
+ first * sizeof(uint64_t)) < 0) {
+ PLOG(ERROR) << "Failed to read page frames from page map for pid: " << pid_;
+ return false;
+ }
+
+ std::unique_ptr<uint64_t[]> pg_flags(new uint64_t[num_pages]);
+ std::unique_ptr<uint64_t[]> pg_counts(new uint64_t[num_pages]);
+ for (uint64_t i = 0; i < num_pages; ++i) {
+ if (!get_wss) {
+ vma.usage.vss += pagesz;
+ }
+ uint64_t p = pg_frames[i];
+ if (!PAGE_PRESENT(p) && !PAGE_SWAPPED(p)) continue;
+
+ if (PAGE_SWAPPED(p)) {
+ vma.usage.swap += pagesz;
+ swap_offsets_.emplace_back(PAGE_SWAP_OFFSET(p));
+ continue;
+ }
+
+ uint64_t page_frame = PAGE_PFN(p);
+ if (!pinfo.PageFlags(page_frame, &pg_flags[i])) {
+ 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 ((pg_flags[i] & pgflags_mask_) != pgflags_) continue;
+
+ if (!pinfo.PageMapCount(page_frame, &pg_counts[i])) {
+ 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 (pg_counts[i] == 0) {
+ pg_frames[i] = 0;
+ pg_flags[i] = 0;
+ continue;
+ }
+
+ bool is_dirty = !!(pg_flags[i] & (1 << KPF_DIRTY));
+ bool is_private = (pg_counts[i] == 1);
+ // Working set
+ if (get_wss) {
+ bool is_referenced = !!(pg_flags[i] & (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 / pg_counts[i];
+ 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,
+ 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
new file mode 100644
index 0000000..8fd18d0
--- /dev/null
+++ b/libmeminfo/sysmeminfo.cpp
@@ -0,0 +1,267 @@
+/*
+ * 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(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[1024];
+ while (fgets(line, 1024, fp.get()) != nullptr) {
+ // 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;
+ }
+
+ p_start = strtok(p_start, " ");
+ long nr_pages;
+ if (sscanf(p_start, "pages=%ld", &nr_pages) == 1) {
+ vmalloc_total += (nr_pages * getpagesize());
+ }
+ }
+
+ return vmalloc_total;
+}
+
+// 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;
+}
+
+} // namespace meminfo
+} // namespace android
diff --git a/libmeminfo/testdata1/mm_stat b/libmeminfo/testdata1/mm_stat
new file mode 100644
index 0000000..32b325f
--- /dev/null
+++ b/libmeminfo/testdata1/mm_stat
@@ -0,0 +1 @@
+ 145674240 26801454 31236096 0 45772800 3042 1887 517
diff --git a/libmeminfo/testdata1/showmap_test.sh b/libmeminfo/testdata1/showmap_test.sh
new file mode 100755
index 0000000..8ee713e
--- /dev/null
+++ b/libmeminfo/testdata1/showmap_test.sh
@@ -0,0 +1,86 @@
+#! /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
new file mode 100644
index 0000000..23aa2af
--- /dev/null
+++ b/libmeminfo/testdata1/smaps
@@ -0,0 +1,56297 @@
+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
new file mode 100644
index 0000000..cee67b3
--- /dev/null
+++ b/libmeminfo/testdata1/smaps_short
@@ -0,0 +1,122 @@
+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
new file mode 100644
index 0000000..d48d8bf
--- /dev/null
+++ b/libmeminfo/testdata1/vmallocinfo
@@ -0,0 +1,1774 @@
+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
new file mode 100644
index 0000000..97fcf41
--- /dev/null
+++ b/libmeminfo/testdata2/mem_used_total
@@ -0,0 +1 @@
+31236096
diff --git a/libmeminfo/tools/Android.bp b/libmeminfo/tools/Android.bp
new file mode 100644
index 0000000..24054c6
--- /dev/null
+++ b/libmeminfo/tools/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.
+
+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",
+ ],
+}
diff --git a/libmeminfo/tools/librank.cpp b/libmeminfo/tools/librank.cpp
new file mode 100644
index 0000000..2c2583d
--- /dev/null
+++ b/libmeminfo/tools/librank.cpp
@@ -0,0 +1,350 @@
+/*
+ * 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 <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::vector<ProcessRecord>& processes() const { return procs_; }
+ uint64_t pss() const { return usage_.pss; }
+ void AddUsage(const ProcessRecord& proc, const MemUsage& mem_usage) {
+ auto process = std::find_if(procs_.begin(), procs_.end(),
+ [&](auto p) -> bool { return p.pid() == proc.pid(); });
+ if (process == procs_.end()) {
+ process = procs_.emplace(procs_.end(), proc.pid());
+ }
+ process->AddUsage(mem_usage);
+ add_mem_usage(&usage_, mem_usage);
+ }
+
+ void Sort(std::function<bool(const ProcessRecord&, const ProcessRecord&)>& sorter) {
+ std::sort(procs_.begin(), procs_.end(), sorter);
+ }
+
+ private:
+ std::string name_;
+ MemUsage usage_;
+ std::vector<ProcessRecord> procs_;
+};
+
+// List of every library / map
+static std::vector<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 lib = std::find_if(g_libs.begin(), g_libs.end(),
+ [&](auto l) -> bool { return map.name == l.name(); });
+ if (lib == g_libs.end()) {
+ lib = g_libs.emplace(g_libs.end(), map.name);
+ }
+
+ lib->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");
+
+ // sort the libraries by their pss
+ std::sort(g_libs.begin(), g_libs.end(),
+ [](const LibRecord& l1, const LibRecord& l2) { return l1.pss() > l2.pss(); });
+
+ for (auto& lib : g_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
+ lib.Sort(sort_func);
+
+ for (auto& p : lib.processes()) {
+ 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
new file mode 100644
index 0000000..47881ed
--- /dev/null
+++ b/libmeminfo/tools/procmem.cpp
@@ -0,0 +1,192 @@
+/*
+ * 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
new file mode 100644
index 0000000..21a684c
--- /dev/null
+++ b/libmeminfo/tools/procrank.cpp
@@ -0,0 +1,530 @@
+/*
+ * 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 <inttypes.h>
+#include <linux/kernel-page-flags.h>
+#include <linux/oom.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <memory>
+#include <sstream>
+#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>
+#include <meminfo/sysmeminfo.h>
+
+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),
+ procmem_(nullptr),
+ 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()));
+ procmem_ = std::move(procmem);
+ pid_ = pid;
+ }
+
+ bool valid() const { return pid_ != -1; }
+
+ void CalculateSwap(const uint16_t* swap_offset_array, float zram_compression_ratio) {
+ const std::vector<uint16_t>& swp_offs = procmem_->SwapOffsets();
+ for (auto& off : swp_offs) {
+ 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 procmem_->SwapOffsets(); }
+ const MemUsage& Usage() const { return procmem_->Usage(); }
+ const MemUsage& Wss() const { return procmem_->Wss(); }
+
+ private:
+ pid_t pid_;
+ std::unique_ptr<ProcMemInfo> procmem_;
+ int32_t oomadj_;
+ std::string cmdline_;
+ uint64_t proportional_swap_;
+ uint64_t unique_swap_;
+ uint64_t zswap_;
+};
+
+// 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->push_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.pss : stats_a.pss > stats_b.pss;
+ };
+
+ 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()) {
+ std::cerr << "Failed to create process record for: " << pid << std::endl;
+ return false;
+ }
+
+ // Skip processes with no memory mappings
+ uint64_t 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.push_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
new file mode 100644
index 0000000..a80fa76
--- /dev/null
+++ b/libmeminfo/tools/showmap.cpp
@@ -0,0 +1,265 @@
+/*
+ * 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/libmemtrack/.clang-format b/libmemtrack/.clang-format
new file mode 120000
index 0000000..1af4f51
--- /dev/null
+++ b/libmemtrack/.clang-format
@@ -0,0 +1 @@
+../.clang-format-4
\ No newline at end of file
diff --git a/libmemtrack/Android.bp b/libmemtrack/Android.bp
index 0955633..4e4554a 100644
--- a/libmemtrack/Android.bp
+++ b/libmemtrack/Android.bp
@@ -28,10 +28,11 @@
cc_binary {
name: "memtrack_test",
- srcs: ["memtrack_test.c"],
+ srcs: ["memtrack_test.cpp"],
+ static_libs: ["libc++fs"],
shared_libs: [
+ "libbase",
"libmemtrack",
- "libpagemap",
],
cflags: [
"-Wall",
diff --git a/libmemtrack/memtrack_test.c b/libmemtrack/memtrack_test.c
deleted file mode 100644
index 77c935e..0000000
--- a/libmemtrack/memtrack_test.c
+++ /dev/null
@@ -1,139 +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 <memtrack/memtrack.h>
-
-#include <pagemap/pagemap.h>
-
-#define DIV_ROUND_UP(x,y) (((x) + (y) - 1) / (y))
-
-static int getprocname(pid_t pid, char *buf, int len) {
- char *filename;
- FILE *f;
- int rc = 0;
- static const char* unknown_cmdline = "<unknown>";
-
- if (len <= 0) {
- return -1;
- }
-
- if (asprintf(&filename, "/proc/%d/cmdline", pid) < 0) {
- rc = 1;
- goto exit;
- }
-
- f = fopen(filename, "r");
- if (f == NULL) {
- rc = 2;
- goto releasefilename;
- }
-
- if (fgets(buf, len, f) == NULL) {
- rc = 3;
- goto closefile;
- }
-
-closefile:
- (void) fclose(f);
-releasefilename:
- free(filename);
-exit:
- if (rc != 0) {
- /*
- * The process went away before we could read its process name. Try
- * to give the user "<unknown>" here, but otherwise they get to look
- * at a blank.
- */
- if (strlcpy(buf, unknown_cmdline, (size_t)len) >= (size_t)len) {
- rc = 4;
- }
- }
-
- return rc;
-}
-
-int main(int argc, char *argv[])
-{
- int ret;
- pm_kernel_t *ker;
- size_t num_procs;
- pid_t *pids;
- struct memtrack_proc *p;
- size_t i;
-
- (void)argc;
- (void)argv;
-
- ret = pm_kernel_create(&ker);
- if (ret) {
- fprintf(stderr, "Error creating kernel interface -- "
- "does this kernel have pagemap?\n");
- exit(EXIT_FAILURE);
- }
-
- ret = pm_kernel_pids(ker, &pids, &num_procs);
- if (ret) {
- fprintf(stderr, "Error listing processes.\n");
- exit(EXIT_FAILURE);
- }
-
- p = memtrack_proc_new();
- if (ret) {
- fprintf(stderr, "failed to create memtrack process handle\n");
- exit(EXIT_FAILURE);
- }
-
- for (i = 0; i < num_procs; i++) {
- pid_t pid = pids[i];
- char cmdline[256];
- size_t v1;
- size_t v2;
- size_t v3;
- size_t v4;
- size_t v5;
- size_t v6;
-
- getprocname(pid, cmdline, (int)sizeof(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) {
- printf("%5d %6zu %6zu %6zu %6zu %6zu %6zu %s\n", pid,
- v1, v2, v3, v4, v5, v6, cmdline);
- }
- }
-
- memtrack_proc_destroy(p);
-
- return 0;
-}
diff --git a/libmemtrack/memtrack_test.cpp b/libmemtrack/memtrack_test.cpp
new file mode 100644
index 0000000..aeeaf24
--- /dev/null
+++ b/libmemtrack/memtrack_test.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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/Android.bp b/libmemunreachable/Android.bp
index 248a9d2..b78a4c4 100644
--- a/libmemunreachable/Android.bp
+++ b/libmemunreachable/Android.bp
@@ -46,12 +46,6 @@
static_libs: ["libunwind_llvm"],
},
},
-
- // TODO(b/78118944), clang lld link flags do not work with special link
- // rules for libunwind_llvm yet. Linked aosp_arm-eng image failed to
- // boot up in the emulator.
- use_clang_lld: false,
-
export_include_dirs: ["include"],
local_include_dirs: ["include"],
}
diff --git a/libmemunreachable/HeapWalker.cpp b/libmemunreachable/HeapWalker.cpp
index 2403ad0..89837f7 100644
--- a/libmemunreachable/HeapWalker.cpp
+++ b/libmemunreachable/HeapWalker.cpp
@@ -35,6 +35,13 @@
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);
@@ -76,15 +83,22 @@
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});
}
@@ -113,6 +127,10 @@
RecurseRoot(vals);
+ if (segv_page_count_ > 0) {
+ MEM_ALOGE("%zu pages skipped due to segfaults", segv_page_count_);
+ }
+
return true;
}
@@ -168,7 +186,15 @@
handler.reset();
return;
}
- MEM_ALOGW("failed to read page at %p, signal %d", si->si_addr, signal);
+ 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();
}
diff --git a/libmemunreachable/HeapWalker.h b/libmemunreachable/HeapWalker.h
index 5c7ec13..9e3db08 100644
--- a/libmemunreachable/HeapWalker.h
+++ b/libmemunreachable/HeapWalker.h
@@ -52,10 +52,15 @@
allocation_bytes_(0),
roots_(allocator),
root_vals_(allocator),
- segv_handler_(allocator),
- walking_ptr_(0) {
+ segv_handler_(),
+ 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;
segv_handler_.install(
SIGSEGV, [=](ScopedSignalHandler& handler, int signal, siginfo_t* siginfo, void* uctx) {
@@ -65,6 +70,7 @@
~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);
@@ -95,12 +101,16 @@
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 segv_handler_;
- uintptr_t walking_ptr_;
+ volatile uintptr_t walking_ptr_;
+ Range walking_range_;
+ bool segv_logged_;
+ size_t segv_page_count_;
};
template <class F>
diff --git a/libmemunreachable/LeakFolding.cpp b/libmemunreachable/LeakFolding.cpp
index 69f320c..074dc48 100644
--- a/libmemunreachable/LeakFolding.cpp
+++ b/libmemunreachable/LeakFolding.cpp
@@ -57,7 +57,7 @@
}
void LeakFolding::AccumulateLeaks(SCCInfo* dominator) {
- std::function<void(SCCInfo*)> walk(std::allocator_arg, allocator_, [&](SCCInfo* scc) {
+ std::function<void(SCCInfo*)> walk([&](SCCInfo* scc) {
if (scc->accumulator != dominator) {
scc->accumulator = dominator;
dominator->cuumulative_size += scc->size;
diff --git a/libmemunreachable/MemUnreachable.cpp b/libmemunreachable/MemUnreachable.cpp
index b160de9..3d7b8a8 100644
--- a/libmemunreachable/MemUnreachable.cpp
+++ b/libmemunreachable/MemUnreachable.cpp
@@ -87,6 +87,11 @@
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};
diff --git a/libmemunreachable/ScopedPipe.h b/libmemunreachable/ScopedPipe.h
index adabfd8..b9dead5 100644
--- a/libmemunreachable/ScopedPipe.h
+++ b/libmemunreachable/ScopedPipe.h
@@ -33,12 +33,12 @@
}
~ScopedPipe() { Close(); }
- ScopedPipe(ScopedPipe&& other) {
+ ScopedPipe(ScopedPipe&& other) noexcept {
SetReceiver(other.ReleaseReceiver());
SetSender(other.ReleaseSender());
}
- ScopedPipe& operator=(ScopedPipe&& other) {
+ ScopedPipe& operator=(ScopedPipe&& other) noexcept {
SetReceiver(other.ReleaseReceiver());
SetSender(other.ReleaseSender());
return *this;
diff --git a/libmemunreachable/ScopedSignalHandler.h b/libmemunreachable/ScopedSignalHandler.h
index ff53fad..9e08a8e 100644
--- a/libmemunreachable/ScopedSignalHandler.h
+++ b/libmemunreachable/ScopedSignalHandler.h
@@ -32,15 +32,14 @@
public:
using Fn = std::function<void(ScopedSignalHandler&, int, siginfo_t*, void*)>;
- explicit ScopedSignalHandler(Allocator<Fn> allocator) : allocator_(allocator), signal_(-1) {}
+ explicit ScopedSignalHandler() : signal_(-1) {}
~ScopedSignalHandler() { reset(); }
template <class F>
void install(int signal, F&& f) {
if (signal_ != -1) MEM_LOG_ALWAYS_FATAL("ScopedSignalHandler already installed");
- handler_ = SignalFn(std::allocator_arg, allocator_,
- [=](int signal, siginfo_t* si, void* uctx) { f(*this, signal, si, uctx); });
+ handler_ = 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_(signal, si, uctx); };
@@ -68,7 +67,6 @@
private:
using SignalFn = std::function<void(int, siginfo_t*, void*)>;
DISALLOW_COPY_AND_ASSIGN(ScopedSignalHandler);
- Allocator<Fn> allocator_;
int signal_;
struct sigaction old_act_;
// TODO(ccross): to support multiple ScopedSignalHandlers handler_ would need
diff --git a/libmemunreachable/Tarjan.h b/libmemunreachable/Tarjan.h
index 355679f..f3ab652 100644
--- a/libmemunreachable/Tarjan.h
+++ b/libmemunreachable/Tarjan.h
@@ -38,7 +38,7 @@
Node(T* ptr, Allocator<Node> allocator)
: references_in(allocator), references_out(allocator), ptr(ptr){};
- Node(Node&& rhs) = default;
+ Node(Node&& rhs) noexcept = default;
void Edge(Node<T>* ref) {
references_out.emplace(ref);
ref->references_in.emplace(this);
diff --git a/libmemunreachable/tests/HeapWalker_test.cpp b/libmemunreachable/tests/HeapWalker_test.cpp
index 84a0ec6..9610cd6 100644
--- a/libmemunreachable/tests/HeapWalker_test.cpp
+++ b/libmemunreachable/tests/HeapWalker_test.cpp
@@ -73,6 +73,24 @@
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))
diff --git a/libmetricslogger/Android.bp b/libmetricslogger/Android.bp
index e6e17ce..7d7554b 100644
--- a/libmetricslogger/Android.bp
+++ b/libmetricslogger/Android.bp
@@ -11,7 +11,11 @@
export_include_dirs: ["include"],
local_include_dirs: ["include"],
- shared_libs: ["liblog"],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libstatssocket",
+ ],
whole_static_libs: ["libgtest_prod"],
cflags: [
@@ -23,17 +27,11 @@
// metricslogger shared library
// -----------------------------------------------------------------------------
-cc_library_shared {
+cc_library {
name: "libmetricslogger",
srcs: metricslogger_lib_src_files,
defaults: ["metricslogger_defaults"],
-}
-
-// static version of libmetricslogger, needed by a few art static binaries
-cc_library_static {
- name: "libmetricslogger_static",
- srcs: metricslogger_lib_src_files,
- defaults: ["metricslogger_defaults"],
+ export_shared_lib_headers: ["libstatssocket"],
}
// metricslogger shared library, debug
@@ -54,12 +52,12 @@
// -----------------------------------------------------------------------------
cc_test {
name: "metricslogger_tests",
+ isolated: true,
defaults: ["metricslogger_defaults"],
shared_libs: [
"libbase",
"libmetricslogger_debug",
],
- static_libs: ["libBionicGtestMain"],
srcs: [
"metrics_logger_test.cpp",
],
diff --git a/libmetricslogger/include/metricslogger/metrics_logger.h b/libmetricslogger/include/metricslogger/metrics_logger.h
index c305db2..71c04a6 100644
--- a/libmetricslogger/include/metricslogger/metrics_logger.h
+++ b/libmetricslogger/include/metricslogger/metrics_logger.h
@@ -15,6 +15,7 @@
*/
#include <log/log_event_list.h>
+#include <stats_event_list.h>
#include <cstdint>
#include <string>
@@ -43,6 +44,7 @@
class ComplexEventLogger {
private:
android_log_event_list logger;
+ stats_event_list stats_logger;
public:
// Create a complex event with category|category|.
@@ -114,7 +116,7 @@
FIELD_BATTERY_RESISTANCE_UOHMS = 1448,
FIELD_BATTERY_CURRENT_UA = 1449,
FIELD_HARDWARE_LOCATION = 1450,
- ACTION_BATTERY_CAUSED_SHUTDOWN = 1441,
+ ACTION_BATTERY_CAUSED_SHUTDOWN = 1451,
};
enum {
diff --git a/libmetricslogger/metrics_logger.cpp b/libmetricslogger/metrics_logger.cpp
index 6a32153..2a1b137 100644
--- a/libmetricslogger/metrics_logger.cpp
+++ b/libmetricslogger/metrics_logger.cpp
@@ -18,11 +18,15 @@
#include <cstdlib>
+#include <android-base/chrono_utils.h>
#include <log/event_tag_map.h>
-#include <log/log_event_list.h>
+
+using namespace android;
namespace {
+const static int kStatsEventTag = 1937006964;
+const static int kKeyValuePairAtomId = 83;
#ifdef __ANDROID__
EventTagMap* kEventTagMap = android_openEventTagMap(nullptr);
const int kSysuiMultiActionTag = android_lookupEventTagNum(
@@ -32,6 +36,12 @@
const int kSysuiMultiActionTag = 0;
#endif
+int64_t getElapsedTimeNanoSinceBoot() {
+ return std::chrono::duration_cast<std::chrono::nanoseconds>(
+ android::base::boot_clock::now().time_since_epoch())
+ .count();
+}
+
} // namespace
namespace android {
@@ -42,6 +52,12 @@
android_log_event_list log(kSysuiMultiActionTag);
log << LOGBUILDER_CATEGORY << LOGBUILDER_HISTOGRAM << LOGBUILDER_NAME << event
<< LOGBUILDER_BUCKET << data << LOGBUILDER_VALUE << 1 << LOG_ID_EVENTS;
+
+ stats_event_list stats_log(kStatsEventTag);
+ stats_log << getElapsedTimeNanoSinceBoot() << kKeyValuePairAtomId << LOGBUILDER_CATEGORY
+ << LOGBUILDER_HISTOGRAM << LOGBUILDER_NAME << event << LOGBUILDER_BUCKET << data
+ << LOGBUILDER_VALUE << 1;
+ stats_log.write(LOG_ID_STATS);
}
// Mirror com.android.internal.logging.MetricsLogger#count().
@@ -49,6 +65,11 @@
android_log_event_list log(kSysuiMultiActionTag);
log << LOGBUILDER_CATEGORY << LOGBUILDER_COUNTER << LOGBUILDER_NAME << name << LOGBUILDER_VALUE
<< val << LOG_ID_EVENTS;
+
+ stats_event_list stats_log(kStatsEventTag);
+ stats_log << getElapsedTimeNanoSinceBoot() << kKeyValuePairAtomId << LOGBUILDER_CATEGORY
+ << LOGBUILDER_COUNTER << LOGBUILDER_NAME << name << LOGBUILDER_VALUE << val;
+ stats_log.write(LOG_ID_STATS);
}
// Mirror com.android.internal.logging.MetricsLogger#action().
@@ -56,34 +77,48 @@
android_log_event_list log(kSysuiMultiActionTag);
log << LOGBUILDER_CATEGORY << category << LOGBUILDER_TYPE << TYPE_ACTION
<< field << value << LOG_ID_EVENTS;
+
+ stats_event_list stats_log(kStatsEventTag);
+ stats_log << getElapsedTimeNanoSinceBoot() << kKeyValuePairAtomId << LOGBUILDER_CATEGORY
+ << category << LOGBUILDER_TYPE << TYPE_ACTION << field << value;
+ stats_log.write(LOG_ID_STATS);
}
-ComplexEventLogger::ComplexEventLogger(int category) : logger(kSysuiMultiActionTag) {
+ComplexEventLogger::ComplexEventLogger(int category)
+ : logger(kSysuiMultiActionTag), stats_logger(kStatsEventTag) {
logger << LOGBUILDER_CATEGORY << category;
+ stats_logger << getElapsedTimeNanoSinceBoot() << kKeyValuePairAtomId << LOGBUILDER_CATEGORY
+ << category;
}
void ComplexEventLogger::SetPackageName(const std::string& package_name) {
logger << LOGBUILDER_PACKAGENAME << package_name;
+ stats_logger << LOGBUILDER_PACKAGENAME << package_name;
}
void ComplexEventLogger::AddTaggedData(int tag, int32_t value) {
logger << tag << value;
+ stats_logger << tag << value;
}
void ComplexEventLogger::AddTaggedData(int tag, const std::string& value) {
logger << tag << value;
+ stats_logger << tag << value;
}
void ComplexEventLogger::AddTaggedData(int tag, int64_t value) {
logger << tag << value;
+ stats_logger << tag << value;
}
void ComplexEventLogger::AddTaggedData(int tag, float value) {
logger << tag << value;
+ stats_logger << tag << value;
}
void ComplexEventLogger::Record() {
logger << LOG_ID_EVENTS;
+ stats_logger.write(LOG_ID_STATS);
}
} // namespace metricslogger
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index 6e63b74..c54570e 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -10,11 +10,27 @@
host_supported: true,
srcs: ["native_bridge.cc"],
+ header_libs: [
+ "libbase_headers",
+ ],
shared_libs: [
"liblog",
- "libbase",
],
+ target: {
+ android: {
+ version_script: "libnativebridge.map.txt",
+ },
+ linux: {
+ version_script: "libnativebridge.map.txt",
+ },
+ },
+
+ stubs: {
+ symbol_file: "libnativebridge.map.txt",
+ versions: ["1"],
+ },
+
export_include_dirs: ["include"],
cflags: [
diff --git a/libnativebridge/Android.mk b/libnativebridge/Android.mk
deleted file mode 100644
index 3887b1b..0000000
--- a/libnativebridge/Android.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(LOCAL_PATH)/tests/Android.mk
diff --git a/libnativebridge/OWNERS b/libnativebridge/OWNERS
index f2cc942..6f0824b 100644
--- a/libnativebridge/OWNERS
+++ b/libnativebridge/OWNERS
@@ -1 +1,2 @@
dimitry@google.com
+eaeltsin@google.com
diff --git a/libnativebridge/include/nativebridge/native_bridge.h b/libnativebridge/include/nativebridge/native_bridge.h
index 9bfc935..5aea967 100644
--- a/libnativebridge/include/nativebridge/native_bridge.h
+++ b/libnativebridge/include/nativebridge/native_bridge.h
@@ -17,12 +17,17 @@
#ifndef NATIVE_BRIDGE_H_
#define NATIVE_BRIDGE_H_
-#include "jni.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;
@@ -32,11 +37,10 @@
// 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 NativeBridgeRuntimeCallbacks* runtime_callbacks);
+ 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.
@@ -99,7 +103,7 @@
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.
+// 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.
@@ -138,19 +142,17 @@
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
-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);
+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(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
+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.
@@ -159,10 +161,11 @@
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Use NativeBridgeLoadLibrary() instead in non-namespace scenario.
-void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns);
+void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
+ struct native_bridge_namespace_t* ns);
// Returns vendor namespace if it is enabled for the device and null otherwise
-native_bridge_namespace_t* NativeBridgeGetVendorNamespace();
+struct native_bridge_namespace_t* NativeBridgeGetVendorNamespace();
// Native bridge interfaces to runtime.
struct NativeBridgeCallbacks {
@@ -177,8 +180,8 @@
// runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks.
// Returns:
// true if initialization was successful.
- bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir,
- const char* instruction_set);
+ 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.
//
@@ -314,12 +317,12 @@
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
- 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,
- native_bridge_namespace_t* parent_ns);
+ 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.
@@ -334,8 +337,8 @@
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Should not use in non-namespace scenario.
- bool (*linkNamespaces)(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
- const char* shared_libs_sonames);
+ 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
@@ -350,7 +353,7 @@
//
// Starting with v3, NativeBridge has two scenarios: with/without namespace.
// Use loadLibrary instead in non-namespace scenario.
- void* (*loadLibraryExt)(const char* libpath, int flag, native_bridge_namespace_t* ns);
+ 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.
@@ -359,7 +362,7 @@
//
// Returns:
// vendor namespace or null if it was not set up for the device
- native_bridge_namespace_t* (*getVendorNamespace)();
+ struct native_bridge_namespace_t* (*getVendorNamespace)();
};
// Runtime interfaces to native bridge.
@@ -396,6 +399,9 @@
uint32_t method_count);
};
-}; // namespace android
+#ifdef __cplusplus
+} // extern "C"
+} // namespace android
+#endif // __cplusplus
#endif // NATIVE_BRIDGE_H_
diff --git a/libnativebridge/libnativebridge.map.txt b/libnativebridge/libnativebridge.map.txt
new file mode 100644
index 0000000..a616b85
--- /dev/null
+++ b/libnativebridge/libnativebridge.map.txt
@@ -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.
+#
+
+# 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;
+ NativeBridgeGetVendorNamespace;
+ 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
index e24307a..a2d8d81 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -33,6 +33,13 @@
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;
@@ -252,10 +259,6 @@
return strncmp(instruction_set, ABI_STRING, strlen(ABI_STRING) + 1) != 0;
}
-#ifdef __APPLE__
-template<typename T> void UNUSED(const T&) {}
-#endif
-
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.");
@@ -626,4 +629,6 @@
return nullptr;
}
-}; // namespace android
+} // extern "C"
+
+} // namespace android
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp
index 9e2e641..744a4a8 100644
--- a/libnativebridge/tests/Android.bp
+++ b/libnativebridge/tests/Android.bp
@@ -44,3 +44,56 @@
srcs: ["DummyNativeBridge3.cpp"],
defaults: ["libnativebridge-dummy-defaults"],
}
+
+// Build the unit tests.
+cc_test {
+ name: "libnativebridge-tests",
+ host_supported: true,
+ 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",
+ "libnativebridge-dummy",
+ ],
+ header_libs: ["libbase_headers"],
+}
+
+// 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-dummy-headers"],
+}
diff --git a/libnativebridge/tests/Android.mk b/libnativebridge/tests/Android.mk
deleted file mode 100644
index 5b9ba1c..0000000
--- a/libnativebridge/tests/Android.mk
+++ /dev/null
@@ -1,56 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Build the unit tests.
-test_src_files := \
- 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_libraries := \
- liblog \
- libbase \
- libnativebridge \
- libnativebridge-dummy
-
-libnativebridge_tests_common_cflags := \
- -Wall \
- -Werror \
-
-$(foreach file,$(test_src_files), \
- $(eval include $(CLEAR_VARS)) \
- $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
- $(eval LOCAL_SRC_FILES := $(file)) \
- $(eval LOCAL_CFLAGS := $(libnativebridge_tests_common_cflags)) \
- $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
- $(eval include $(BUILD_NATIVE_TEST)) \
-)
-
-$(foreach file,$(test_src_files), \
- $(eval include $(CLEAR_VARS)) \
- $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
- $(eval LOCAL_SRC_FILES := $(file)) \
- $(eval LOCAL_CFLAGS := $(libnativebridge_tests_common_cflags)) \
- $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
- $(eval include $(BUILD_HOST_NATIVE_TEST)) \
-)
diff --git a/libbacktrace/GetPss.h b/libnativebridge/tests/NativeBridgeApi.c
similarity index 64%
copy from libbacktrace/GetPss.h
copy to libnativebridge/tests/NativeBridgeApi.c
index 787c33d..7ab71fe 100644
--- a/libbacktrace/GetPss.h
+++ b/libnativebridge/tests/NativeBridgeApi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 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,9 +14,12 @@
* limitations under the License.
*/
-#ifndef _LIBBACKTRACE_GET_PSS_H
-#define _LIBBACKTRACE_GET_PSS_H
+/* 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"
-size_t GetPssBytes();
-
-#endif // _LIBBACKTRACE_GET_PSS_H
+int main(int argc, char** argv) {
+ (void)argc;
+ (void)argv;
+ return 0;
+}
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
index 17983bc..2802d36 100644
--- a/libnativeloader/Android.bp
+++ b/libnativeloader/Android.bp
@@ -24,3 +24,10 @@
"vndksp.libraries.txt",
],
}
+
+cc_library_headers {
+ name: "libnativeloader-dummy-headers",
+
+ host_supported: true,
+ export_include_dirs: ["include"],
+}
diff --git a/libnativeloader/OWNERS b/libnativeloader/OWNERS
index 5c28a9f..f735653 100644
--- a/libnativeloader/OWNERS
+++ b/libnativeloader/OWNERS
@@ -1,2 +1,6 @@
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
index 43c9329..2d6ce85 100644
--- a/libnativeloader/include/nativeloader/dlext_namespaces.h
+++ b/libnativeloader/include/nativeloader/dlext_namespaces.h
@@ -18,6 +18,7 @@
#define __ANDROID_DLEXT_NAMESPACES_H__
#include <android/dlext.h>
+#include <stdbool.h>
__BEGIN_DECLS
@@ -84,12 +85,9 @@
* 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,
- android_namespace_t* parent);
+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
@@ -107,24 +105,11 @@
* step will not go deeper into linked namespaces for this library but
* will do so for DT_NEEDED libraries.
*/
-extern bool android_link_namespaces(android_namespace_t* from,
- android_namespace_t* to,
+extern bool android_link_namespaces(struct android_namespace_t* from,
+ struct android_namespace_t* to,
const char* shared_libs_sonames);
-/*
- * Get the default library search path.
- * The path will be copied into buffer, which must have space for at least
- * buffer_size chars. Elements are separated with ':', and the path will always
- * be null-terminated.
- *
- * If buffer_size is too small to hold the entire default search path and the
- * null terminator, this function will abort. There is currently no way to find
- * out what the required buffer size is. At the time of this writing, PATH_MAX
- * is sufficient and used by all callers of this function.
- */
-extern void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size);
-
-extern android_namespace_t* android_get_exported_namespace(const char* name);
+extern struct android_namespace_t* android_get_exported_namespace(const char* name);
__END_DECLS
diff --git a/libnativeloader/include/nativeloader/native_loader.h b/libnativeloader/include/nativeloader/native_loader.h
index 19a1783..260f655 100644
--- a/libnativeloader/include/nativeloader/native_loader.h
+++ b/libnativeloader/include/nativeloader/native_loader.h
@@ -17,14 +17,21 @@
#ifndef NATIVE_LOADER_H_
#define NATIVE_LOADER_H_
-#include "jni.h"
+#include <stdbool.h>
#include <stdint.h>
-#include <string>
+#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();
@@ -38,41 +45,39 @@
jstring library_path,
jstring permitted_path);
-__attribute__((visibility("default")))
-void* OpenNativeLibrary(JNIEnv* env,
- int32_t target_sdk_version,
- const char* path,
- jobject class_loader,
- jstring library_path,
- bool* needs_native_bridge,
- std::string* error_msg);
+__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);
+__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")))
-android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
-// That version works with native bridge namespaces, but requires use of OpenNativeLibrary.
-class NativeLoaderNamespace;
-__attribute__((visibility("default")))
-NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(
+__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* OpenNativeLibrary(NativeLoaderNamespace* ns,
- const char* path,
- bool* needs_native_bridge,
- std::string* error_msg);
+__attribute__((visibility("default"))) void* OpenNativeLibraryInNamespace(
+ struct NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge,
+ char** error_msg);
#endif
__attribute__((visibility("default")))
void ResetNativeLoader();
-}; // namespace android
+#ifdef __cplusplus
+} // extern "C"
+} // namespace android
+#endif // __cplusplus
#endif // NATIVE_BRIDGE_H_
diff --git a/libnativeloader/libnativeloader.map.txt b/libnativeloader/libnativeloader.map.txt
new file mode 100644
index 0000000..40c30bd
--- /dev/null
+++ b/libnativeloader/libnativeloader.map.txt
@@ -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.
+#
+
+# 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
index 67c1c10..ab17b29 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -43,6 +43,10 @@
#include <android-base/properties.h>
#endif
+extern "C" {
+struct android_namespace_t* android_get_exported_namespace(const char*);
+}
+
#define CHECK(predicate) LOG_ALWAYS_FATAL_IF(!(predicate),\
"%s:%d: %s CHECK '" #predicate "' failed.",\
__FILE__, __LINE__, __FUNCTION__)
@@ -52,7 +56,7 @@
namespace android {
#if defined(__ANDROID__)
-class NativeLoaderNamespace {
+struct NativeLoaderNamespace {
public:
NativeLoaderNamespace()
: android_ns_(nullptr), native_bridge_ns_(nullptr) { }
@@ -119,6 +123,8 @@
// 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/";
+
static bool is_debuggable() {
char debuggable[PROP_VALUE_MAX];
property_get("ro.debuggable", debuggable, "0");
@@ -151,14 +157,9 @@
public:
LibraryNamespaces() : initialized_(false) { }
- NativeLoaderNamespace* Create(JNIEnv* env,
- uint32_t target_sdk_version,
- jobject class_loader,
- bool is_shared,
- bool is_for_vendor,
- jstring java_library_path,
- jstring java_permitted_path,
- std::string* error_msg) {
+ NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader,
+ bool is_shared, bool is_for_vendor, 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) {
@@ -628,18 +629,56 @@
return nullptr;
}
-void* OpenNativeLibrary(JNIEnv* env,
- int32_t target_sdk_version,
- const char* path,
- jobject class_loader,
- jstring library_path,
- bool* needs_native_bridge,
- std::string* error_msg) {
+#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;
- return dlopen(path, RTLD_NOW);
+ 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);
@@ -648,21 +687,18 @@
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.
- if ((ns = g_namespaces->Create(env,
- target_sdk_version,
- class_loader,
- false /* is_shared */,
- false /* is_for_vendor */,
- library_path,
- nullptr,
- error_msg)) == nullptr) {
+ std::string create_error_msg;
+ if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */,
+ false /* is_for_vendor */, library_path, nullptr,
+ &create_error_msg)) == nullptr) {
+ *error_msg = strdup(create_error_msg.c_str());
return nullptr;
}
}
- return OpenNativeLibrary(ns, path, needs_native_bridge, error_msg);
+ return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
#else
- UNUSED(env, target_sdk_version, class_loader);
+ UNUSED(env, target_sdk_version, class_loader, caller_location);
// Do some best effort to emulate library-path support. It will not
// work for dependencies.
@@ -701,23 +737,40 @@
if (handle != nullptr) {
return handle;
}
- *error_msg = NativeBridgeGetError();
+ *error_msg = strdup(NativeBridgeGetError());
} else {
- *error_msg = dlerror();
+ *error_msg = strdup(dlerror());
}
}
return nullptr;
#endif
}
-bool CloseNativeLibrary(void* handle, const bool needs_native_bridge) {
- return needs_native_bridge ? NativeBridgeUnloadLibrary(handle) :
- dlclose(handle);
+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* OpenNativeLibrary(NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge,
- std::string* error_msg) {
+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;
@@ -725,14 +778,14 @@
void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo);
if (handle == nullptr) {
- *error_msg = dlerror();
+ *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 = NativeBridgeGetError();
+ *error_msg = strdup(NativeBridgeGetError());
}
*needs_native_bridge = true;
return handle;
diff --git a/libnativeloader/test/Android.bp b/libnativeloader/test/Android.bp
index d528f30..1464e39 100644
--- a/libnativeloader/test/Android.bp
+++ b/libnativeloader/test/Android.bp
@@ -69,3 +69,14 @@
"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-dummy-headers"],
+}
diff --git a/libbacktrace/GetPss.h b/libnativeloader/test/api_test.c
similarity index 64%
copy from libbacktrace/GetPss.h
copy to libnativeloader/test/api_test.c
index 787c33d..e7025fd 100644
--- a/libbacktrace/GetPss.h
+++ b/libnativeloader/test/api_test.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 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,9 +14,12 @@
* limitations under the License.
*/
-#ifndef _LIBBACKTRACE_GET_PSS_H
-#define _LIBBACKTRACE_GET_PSS_H
+/* 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"
-size_t GetPssBytes();
-
-#endif // _LIBBACKTRACE_GET_PSS_H
+int main(int argc, char** argv) {
+ (void)argc;
+ (void)argv;
+ return 0;
+}
diff --git a/libpackagelistparser/include/packagelistparser/packagelistparser.h b/libpackagelistparser/include/packagelistparser/packagelistparser.h
index d602c26..8bcc1e2 100644
--- a/libpackagelistparser/include/packagelistparser/packagelistparser.h
+++ b/libpackagelistparser/include/packagelistparser/packagelistparser.h
@@ -53,6 +53,7 @@
char *seinfo;
gid_list gids;
void *private_data;
+ bool profileable_from_shell;
};
/**
diff --git a/libpackagelistparser/packagelistparser.c b/libpackagelistparser/packagelistparser.c
index 3e1a3d1..4ce2363 100644
--- a/libpackagelistparser/packagelistparser.c
+++ b/libpackagelistparser/packagelistparser.c
@@ -223,6 +223,23 @@
}
}
+ 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;
+ }
+
rc = callback(pkg_info, userdata);
if (rc == false) {
/*
diff --git a/libpixelflinger/Android.bp b/libpixelflinger/Android.bp
new file mode 100644
index 0000000..76d9444
--- /dev/null
+++ b/libpixelflinger/Android.bp
@@ -0,0 +1,115 @@
+cc_defaults {
+ name: "pixelflinger_defaults",
+
+ cflags: [
+ "-fstrict-aliasing",
+ "-fomit-frame-pointer",
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-function",
+ ],
+ export_include_dirs: ["include"],
+ header_libs: ["libbase_headers"],
+ shared_libs: [
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
+
+ arch: {
+ arm: {
+ neon: {
+ cflags: ["-D__ARM_HAVE_NEON"],
+ },
+ },
+ },
+}
+
+cc_library_static {
+ name: "libpixelflinger-arm",
+ defaults: ["pixelflinger_defaults"],
+
+ srcs: [
+ "fixed.cpp",
+ "picker.cpp",
+ "pixelflinger.cpp",
+ "trap.cpp",
+ "scanline.cpp",
+ ],
+
+ arch: {
+ arm: {
+ instruction_set: "arm",
+ },
+ },
+}
+
+// For the tests to use
+cc_library_headers {
+ name: "libpixelflinger_internal",
+ export_include_dirs: [
+ "include",
+ ".",
+ ],
+}
+
+cc_library {
+ name: "libpixelflinger",
+ defaults: ["pixelflinger_defaults"],
+
+ srcs: [
+ "codeflinger/ARMAssemblerInterface.cpp",
+ "codeflinger/ARMAssemblerProxy.cpp",
+ "codeflinger/CodeCache.cpp",
+ "codeflinger/GGLAssembler.cpp",
+ "codeflinger/load_store.cpp",
+ "codeflinger/blending.cpp",
+ "codeflinger/texturing.cpp",
+ "format.cpp",
+ "clear.cpp",
+ "raster.cpp",
+ "buffer.cpp",
+ ],
+ whole_static_libs: ["libpixelflinger-arm"],
+
+ arch: {
+ arm: {
+ srcs: [
+ "codeflinger/ARMAssembler.cpp",
+ "codeflinger/disassem.c",
+ "col32cb16blend.S",
+ "t32cb16blend.S",
+ ],
+
+ neon: {
+ srcs: ["col32cb16blend_neon.S"],
+ },
+ },
+ arm64: {
+ srcs: [
+ "codeflinger/Arm64Assembler.cpp",
+ "codeflinger/Arm64Disassembler.cpp",
+ "arch-arm64/col32cb16blend.S",
+ "arch-arm64/t32cb16blend.S",
+ ],
+ },
+ mips: {
+ mips32r6: {
+ srcs: [
+ "codeflinger/MIPSAssembler.cpp",
+ "codeflinger/mips_disassem.c",
+ "arch-mips/t32cb16blend.S",
+ ],
+ },
+ },
+ mips64: {
+ srcs: [
+ "codeflinger/MIPSAssembler.cpp",
+ "codeflinger/MIPS64Assembler.cpp",
+ "codeflinger/mips64_disassem.c",
+ "arch-mips64/col32cb16blend.S",
+ "arch-mips64/t32cb16blend.S",
+ ],
+ },
+ },
+}
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
deleted file mode 100644
index 14883f4..0000000
--- a/libpixelflinger/Android.mk
+++ /dev/null
@@ -1,80 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-#
-# C/C++ and ARMv5 objects
-#
-
-include $(CLEAR_VARS)
-PIXELFLINGER_SRC_FILES:= \
- codeflinger/ARMAssemblerInterface.cpp \
- codeflinger/ARMAssemblerProxy.cpp \
- codeflinger/CodeCache.cpp \
- codeflinger/GGLAssembler.cpp \
- codeflinger/load_store.cpp \
- codeflinger/blending.cpp \
- codeflinger/texturing.cpp \
- fixed.cpp.arm \
- picker.cpp.arm \
- pixelflinger.cpp.arm \
- trap.cpp.arm \
- scanline.cpp.arm \
- format.cpp \
- clear.cpp \
- raster.cpp \
- buffer.cpp
-
-PIXELFLINGER_CFLAGS := -fstrict-aliasing -fomit-frame-pointer
-PIXELFLINGER_CFLAGS += -Wall -Werror
-PIXELFLINGER_CFLAGS += -Wno-unused-function
-
-PIXELFLINGER_SRC_FILES_arm := \
- codeflinger/ARMAssembler.cpp \
- codeflinger/disassem.c \
- col32cb16blend.S \
- t32cb16blend.S \
-
-ifeq ($(ARCH_ARM_HAVE_NEON),true)
-PIXELFLINGER_SRC_FILES_arm += col32cb16blend_neon.S
-PIXELFLINGER_CFLAGS_arm += -D__ARM_HAVE_NEON
-endif
-
-PIXELFLINGER_SRC_FILES_arm64 := \
- codeflinger/Arm64Assembler.cpp \
- codeflinger/Arm64Disassembler.cpp \
- arch-arm64/col32cb16blend.S \
- arch-arm64/t32cb16blend.S \
-
-ifndef ARCH_MIPS_REV6
-PIXELFLINGER_SRC_FILES_mips := \
- codeflinger/MIPSAssembler.cpp \
- codeflinger/mips_disassem.c \
- arch-mips/t32cb16blend.S \
-
-endif
-
-PIXELFLINGER_SRC_FILES_mips64 := \
- codeflinger/MIPSAssembler.cpp \
- codeflinger/MIPS64Assembler.cpp \
- codeflinger/mips64_disassem.c \
- arch-mips64/col32cb16blend.S \
- arch-mips64/t32cb16blend.S \
-
-#
-# Shared library
-#
-
-LOCAL_MODULE:= libpixelflinger
-LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES)
-LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm)
-LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64)
-LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips)
-LOCAL_SRC_FILES_mips64 := $(PIXELFLINGER_SRC_FILES_mips64)
-LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS)
-LOCAL_SHARED_LIBRARIES := libcutils liblog libutils
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libpixelflinger/buffer.cpp b/libpixelflinger/buffer.cpp
index dcb95c5..ea9514c 100644
--- a/libpixelflinger/buffer.cpp
+++ b/libpixelflinger/buffer.cpp
@@ -18,6 +18,8 @@
#include <assert.h>
+#include <android-base/macros.h>
+
#include "buffer.h"
namespace android {
@@ -266,8 +268,11 @@
p = downshift_component(p, b, hbits, lbits, f->bh, f->bl, 0, 1, -1);
p = downshift_component(p, a, hbits, lbits, f->ah, f->al, 0, 1, -1);
switch (f->size) {
- case 1: p |= p << 8; // fallthrough
- case 2: p |= p << 16;
+ case 1:
+ p |= p << 8;
+ FALLTHROUGH_INTENDED;
+ case 2:
+ p |= p << 16;
}
return p;
}
diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp
index ac009a9..f47b6e4 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.cpp
+++ b/libpixelflinger/codeflinger/ARMAssembler.cpp
@@ -171,7 +171,7 @@
}
mAssembly->resize( int(pc()-base())*4 );
-
+
// the instruction cache is flushed by CodeCache
const int64_t duration = ggl_system_time() - mDuration;
const char * const format = "generated %s (%d ins) at [%p:%p] in %lld ns\n";
@@ -183,8 +183,8 @@
printf(format, name, int(pc()-base()), base(), pc(), duration);
disassemble(name);
}
-
- return NO_ERROR;
+
+ return OK;
}
uint32_t* ARMAssembler::pcForLabel(const char* label)
@@ -213,14 +213,14 @@
// multiply...
void ARMAssembler::MLA(int cc, int s,
int Rd, int Rm, int Rs, int Rn) {
- if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
+ if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
LOG_FATAL_IF(Rd==Rm, "MLA(r%u,r%u,r%u,r%u)", Rd,Rm,Rs,Rn);
*mPC++ = (cc<<28) | (1<<21) | (s<<20) |
(Rd<<16) | (Rn<<12) | (Rs<<8) | 0x90 | Rm;
}
void ARMAssembler::MUL(int cc, int s,
int Rd, int Rm, int Rs) {
- if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
+ if (Rd == Rm) { int t = Rm; Rm=Rs; Rs=t; }
LOG_FATAL_IF(Rd==Rm, "MUL(r%u,r%u,r%u)", Rd,Rm,Rs);
*mPC++ = (cc<<28) | (s<<20) | (Rd<<16) | (Rs<<8) | 0x90 | Rm;
}
@@ -577,4 +577,3 @@
}
}; // namespace android
-
diff --git a/libpixelflinger/codeflinger/Arm64Assembler.cpp b/libpixelflinger/codeflinger/Arm64Assembler.cpp
index aebc129..8926776 100644
--- a/libpixelflinger/codeflinger/Arm64Assembler.cpp
+++ b/libpixelflinger/codeflinger/Arm64Assembler.cpp
@@ -325,7 +325,7 @@
printf(format, name, int(pc()-base()), base(), pc(), duration);
disassemble(name);
}
- return NO_ERROR;
+ return OK;
}
uint32_t* ArmToArm64Assembler::pcForLabel(const char* label)
@@ -1238,4 +1238,3 @@
}
}; // namespace android
-
diff --git a/libpixelflinger/codeflinger/CodeCache.cpp b/libpixelflinger/codeflinger/CodeCache.cpp
index 8516640..32691a3 100644
--- a/libpixelflinger/codeflinger/CodeCache.cpp
+++ b/libpixelflinger/codeflinger/CodeCache.cpp
@@ -61,7 +61,11 @@
#define USAGE_ERROR_ACTION(m,p) \
heap_error("ARGUMENT IS INVALID HEAP ADDRESS", __FUNCTION__, p)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wexpansion-to-defined"
+#pragma GCC diagnostic ignored "-Wnull-pointer-arithmetic"
#include "../../../../external/dlmalloc/malloc.c"
+#pragma GCC diagnostic pop
static void heap_error(const char* msg, const char* function, void* p) {
ALOG(LOG_FATAL, LOG_TAG, "@@@ ABORTING: CODE FLINGER: %s IN %s addr=%p",
diff --git a/libpixelflinger/codeflinger/MIPSAssembler.cpp b/libpixelflinger/codeflinger/MIPSAssembler.cpp
index 039a725..7de8cc1 100644
--- a/libpixelflinger/codeflinger/MIPSAssembler.cpp
+++ b/libpixelflinger/codeflinger/MIPSAssembler.cpp
@@ -1421,7 +1421,7 @@
disassemble(name);
}
- return NO_ERROR;
+ return OK;
}
uint32_t* MIPSAssembler::pcForLabel(const char* label)
@@ -1953,5 +1953,3 @@
}; // namespace android:
-
-
diff --git a/libpixelflinger/codeflinger/blending.cpp b/libpixelflinger/codeflinger/blending.cpp
index a55dfe3..2cbb00f 100644
--- a/libpixelflinger/codeflinger/blending.cpp
+++ b/libpixelflinger/codeflinger/blending.cpp
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <sys/types.h>
+#include <android-base/macros.h>
#include <log/log.h>
#include "GGLAssembler.h"
@@ -301,7 +302,7 @@
return;
}
}
- // fall-through...
+ FALLTHROUGH_INTENDED;
case GGL_ONE_MINUS_DST_COLOR:
case GGL_DST_COLOR:
case GGL_ONE_MINUS_SRC_COLOR:
diff --git a/libpixelflinger/tests/Android.bp b/libpixelflinger/tests/Android.bp
new file mode 100644
index 0000000..820a84d
--- /dev/null
+++ b/libpixelflinger/tests/Android.bp
@@ -0,0 +1,16 @@
+cc_defaults {
+ name: "pixelflinger-tests",
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ header_libs: ["libpixelflinger_internal"],
+ static_libs: [
+ "libcutils",
+ "liblog",
+ "libpixelflinger",
+ "libutils",
+ ],
+}
diff --git a/libpixelflinger/tests/Android.mk b/libpixelflinger/tests/Android.mk
deleted file mode 100644
index 6571161..0000000
--- a/libpixelflinger/tests/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(all-subdir-makefiles)
diff --git a/libpixelflinger/tests/arch-arm64/Android.bp b/libpixelflinger/tests/arch-arm64/Android.bp
new file mode 100644
index 0000000..2f5586a
--- /dev/null
+++ b/libpixelflinger/tests/arch-arm64/Android.bp
@@ -0,0 +1,11 @@
+cc_defaults {
+ name: "pixelflinger-tests-arm64",
+ defaults: ["pixelflinger-tests"],
+
+ enabled: false,
+ arch: {
+ arm64: {
+ enabled: true,
+ },
+ },
+}
diff --git a/libpixelflinger/tests/arch-arm64/Android.mk b/libpixelflinger/tests/arch-arm64/Android.mk
deleted file mode 100644
index ca58b4b..0000000
--- a/libpixelflinger/tests/arch-arm64/Android.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-ifeq ($(TARGET_ARCH),arm64)
-include $(all-subdir-makefiles)
-endif
diff --git a/libpixelflinger/tests/arch-arm64/assembler/Android.bp b/libpixelflinger/tests/arch-arm64/assembler/Android.bp
new file mode 100644
index 0000000..003f485
--- /dev/null
+++ b/libpixelflinger/tests/arch-arm64/assembler/Android.bp
@@ -0,0 +1,9 @@
+cc_test {
+ name: "test-pixelflinger-arm64-assembler-test",
+ defaults: ["pixelflinger-tests-arm64"],
+
+ srcs: [
+ "arm64_assembler_test.cpp",
+ "asm_test_jacket.S",
+ ],
+}
diff --git a/libpixelflinger/tests/arch-arm64/assembler/Android.mk b/libpixelflinger/tests/arch-arm64/assembler/Android.mk
deleted file mode 100644
index db5dc4d..0000000
--- a/libpixelflinger/tests/arch-arm64/assembler/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- arm64_assembler_test.cpp\
- asm_test_jacket.S
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libpixelflinger
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../../..
-
-LOCAL_MODULE:= test-pixelflinger-arm64-assembler-test
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MULTILIB := 64
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.bp b/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.bp
new file mode 100644
index 0000000..e640aeb
--- /dev/null
+++ b/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.bp
@@ -0,0 +1,6 @@
+cc_test {
+ name: "test-pixelflinger-arm64-col32cb16blend",
+ defaults: ["pixelflinger-tests-arm64"],
+
+ srcs: ["col32cb16blend_test.c"],
+}
diff --git a/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.mk b/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.mk
deleted file mode 100644
index 3096232..0000000
--- a/libpixelflinger/tests/arch-arm64/col32cb16blend/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- col32cb16blend_test.c \
- ../../../arch-arm64/col32cb16blend.S
-
-LOCAL_SHARED_LIBRARIES :=
-
-LOCAL_C_INCLUDES :=
-
-LOCAL_MODULE:= test-pixelflinger-arm64-col32cb16blend
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MULTILIB := 64
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-arm64/disassembler/Android.bp b/libpixelflinger/tests/arch-arm64/disassembler/Android.bp
new file mode 100644
index 0000000..38dc99a
--- /dev/null
+++ b/libpixelflinger/tests/arch-arm64/disassembler/Android.bp
@@ -0,0 +1,6 @@
+cc_test {
+ name: "test-pixelflinger-arm64-disassembler-test",
+ defaults: ["pixelflinger-tests-arm64"],
+
+ srcs: ["arm64_diassembler_test.cpp"],
+}
diff --git a/libpixelflinger/tests/arch-arm64/disassembler/Android.mk b/libpixelflinger/tests/arch-arm64/disassembler/Android.mk
deleted file mode 100644
index 78f12af..0000000
--- a/libpixelflinger/tests/arch-arm64/disassembler/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- arm64_diassembler_test.cpp \
- ../../../codeflinger/Arm64Disassembler.cpp
-
-LOCAL_SHARED_LIBRARIES :=
-
-LOCAL_MODULE:= test-pixelflinger-arm64-disassembler-test
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MULTILIB := 64
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.bp b/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.bp
new file mode 100644
index 0000000..9d060d1
--- /dev/null
+++ b/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.bp
@@ -0,0 +1,6 @@
+cc_test {
+ name: "test-pixelflinger-arm64-t32cb16blend",
+ defaults: ["pixelflinger-tests-arm64"],
+
+ srcs: ["t32cb16blend_test.c"],
+}
diff --git a/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.mk b/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.mk
deleted file mode 100644
index 664347f..0000000
--- a/libpixelflinger/tests/arch-arm64/t32cb16blend/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- t32cb16blend_test.c \
- ../../../arch-arm64/t32cb16blend.S
-
-LOCAL_SHARED_LIBRARIES :=
-
-LOCAL_C_INCLUDES :=
-
-LOCAL_MODULE:= test-pixelflinger-arm64-t32cb16blend
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MULTILIB := 64
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-mips/Android.bp b/libpixelflinger/tests/arch-mips/Android.bp
new file mode 100644
index 0000000..2ca2721
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips/Android.bp
@@ -0,0 +1,11 @@
+cc_defaults {
+ name: "pixelflinger-tests-mips",
+ defaults: ["pixelflinger-tests"],
+
+ enabled: false,
+ arch: {
+ mips: {
+ enabled: true,
+ },
+ },
+}
diff --git a/libpixelflinger/tests/arch-mips/Android.mk b/libpixelflinger/tests/arch-mips/Android.mk
deleted file mode 100644
index fe6979e..0000000
--- a/libpixelflinger/tests/arch-mips/Android.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-ifeq ($(TARGET_ARCH),mips)
-include $(all-subdir-makefiles)
-endif
-ifeq ($(TARGET_ARCH),mipsel)
-include $(all-subdir-makefiles)
-endif
diff --git a/libpixelflinger/tests/arch-mips/col32cb16blend/Android.bp b/libpixelflinger/tests/arch-mips/col32cb16blend/Android.bp
new file mode 100644
index 0000000..45bfe29
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips/col32cb16blend/Android.bp
@@ -0,0 +1,6 @@
+cc_test {
+ name: "test-pixelflinger-mips-col32cb16blend",
+ defaults: ["pixelflinger-tests-mips"],
+
+ srcs: ["col32cb16blend_test.c"],
+}
diff --git a/libpixelflinger/tests/arch-mips/col32cb16blend/Android.mk b/libpixelflinger/tests/arch-mips/col32cb16blend/Android.mk
deleted file mode 100644
index 40f197f..0000000
--- a/libpixelflinger/tests/arch-mips/col32cb16blend/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- col32cb16blend_test.c \
- ../../../arch-mips/col32cb16blend.S
-
-LOCAL_SHARED_LIBRARIES :=
-
-LOCAL_C_INCLUDES :=
-
-LOCAL_MODULE:= test-pixelflinger-mips-col32cb16blend
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MULTILIB := 32
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-mips/t32cb16blend/Android.bp b/libpixelflinger/tests/arch-mips/t32cb16blend/Android.bp
new file mode 100644
index 0000000..069e97c
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips/t32cb16blend/Android.bp
@@ -0,0 +1,6 @@
+cc_test {
+ name: "test-pixelflinger-mips-t32cb16blend",
+ defaults: ["pixelflinger-tests-mips"],
+
+ srcs: ["t32cb16blend_test.c"],
+}
diff --git a/libpixelflinger/tests/arch-mips/t32cb16blend/Android.mk b/libpixelflinger/tests/arch-mips/t32cb16blend/Android.mk
deleted file mode 100644
index d0c0ae4..0000000
--- a/libpixelflinger/tests/arch-mips/t32cb16blend/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- t32cb16blend_test.c \
- ../../../arch-mips/t32cb16blend.S
-
-LOCAL_SHARED_LIBRARIES :=
-
-LOCAL_C_INCLUDES :=
-
-LOCAL_MODULE:= test-pixelflinger-mips-t32cb16blend
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MULTILIB := 32
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-mips64/Android.bp b/libpixelflinger/tests/arch-mips64/Android.bp
new file mode 100644
index 0000000..ba55d62
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips64/Android.bp
@@ -0,0 +1,11 @@
+cc_defaults {
+ name: "pixelflinger-tests-mips64",
+ defaults: ["pixelflinger-tests"],
+
+ enabled: false,
+ arch: {
+ mips64: {
+ enabled: true,
+ },
+ },
+}
diff --git a/libpixelflinger/tests/arch-mips64/Android.mk b/libpixelflinger/tests/arch-mips64/Android.mk
deleted file mode 100644
index 3b1c64e..0000000
--- a/libpixelflinger/tests/arch-mips64/Android.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-ifeq ($(TARGET_ARCH),mips64)
-include $(all-subdir-makefiles)
-endif
diff --git a/libpixelflinger/tests/arch-mips64/assembler/Android.bp b/libpixelflinger/tests/arch-mips64/assembler/Android.bp
new file mode 100644
index 0000000..b672053
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips64/assembler/Android.bp
@@ -0,0 +1,9 @@
+cc_test {
+ name: "test-pixelflinger-mips64-assembler-test",
+ defaults: ["pixelflinger-tests-mips64"],
+
+ srcs: [
+ "mips64_assembler_test.cpp",
+ "asm_mips_test_jacket.S",
+ ],
+}
diff --git a/libpixelflinger/tests/arch-mips64/assembler/Android.mk b/libpixelflinger/tests/arch-mips64/assembler/Android.mk
deleted file mode 100644
index 4699961..0000000
--- a/libpixelflinger/tests/arch-mips64/assembler/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- mips64_assembler_test.cpp\
- asm_mips_test_jacket.S
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libpixelflinger
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../../..
-
-LOCAL_MODULE:= test-pixelflinger-mips64-assembler-test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MULTILIB := 64
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.bp b/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.bp
new file mode 100644
index 0000000..bfc6ae9
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.bp
@@ -0,0 +1,6 @@
+cc_test {
+ name: "test-pixelflinger-mips64-col32cb16blend",
+ defaults: ["pixelflinger-tests-mips64"],
+
+ srcs: ["col32cb16blend_test.c"],
+}
diff --git a/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.mk b/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.mk
deleted file mode 100644
index 7d4177e..0000000
--- a/libpixelflinger/tests/arch-mips64/col32cb16blend/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- col32cb16blend_test.c \
- ../../../arch-mips64/col32cb16blend.S
-
-LOCAL_SHARED_LIBRARIES :=
-
-LOCAL_C_INCLUDES :=
-
-LOCAL_MODULE:= test-pixelflinger-mips64-col32cb16blend
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MULTILIB := 64
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/arch-mips64/disassembler/Android.bp b/libpixelflinger/tests/arch-mips64/disassembler/Android.bp
new file mode 100644
index 0000000..96bf9e9
--- /dev/null
+++ b/libpixelflinger/tests/arch-mips64/disassembler/Android.bp
@@ -0,0 +1,6 @@
+cc_test {
+ name: "test-pixelflinger-mips64-disassembler-test",
+ defaults: ["pixelflinger-tests-mips64"],
+
+ srcs: ["mips64_disassembler_test.cpp"],
+}
diff --git a/libpixelflinger/tests/arch-mips64/disassembler/Android.mk b/libpixelflinger/tests/arch-mips64/disassembler/Android.mk
deleted file mode 100644
index 4e72b57..0000000
--- a/libpixelflinger/tests/arch-mips64/disassembler/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- mips64_disassembler_test.cpp \
- ../../../codeflinger/mips64_disassem.c
-
-LOCAL_SHARED_LIBRARIES :=
-
-LOCAL_MODULE:= test-pixelflinger-mips64-disassembler-test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MULTILIB := 64
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/codegen/Android.bp b/libpixelflinger/tests/codegen/Android.bp
new file mode 100644
index 0000000..7e4bcfb
--- /dev/null
+++ b/libpixelflinger/tests/codegen/Android.bp
@@ -0,0 +1,12 @@
+cc_test {
+ name: "test-opengl-codegen",
+ defaults: ["pixelflinger-tests"],
+
+ srcs: ["codegen.cpp"],
+
+ arch: {
+ arm: {
+ instruction_set: "arm",
+ },
+ },
+}
diff --git a/libpixelflinger/tests/codegen/Android.mk b/libpixelflinger/tests/codegen/Android.mk
deleted file mode 100644
index 72d71ef..0000000
--- a/libpixelflinger/tests/codegen/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- codegen.cpp.arm
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libpixelflinger
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../..
-
-LOCAL_MODULE:= test-opengl-codegen
-
-LOCAL_CFLAGS:= -Wall -Werror
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libpixelflinger/tests/gglmul/Android.bp b/libpixelflinger/tests/gglmul/Android.bp
new file mode 100644
index 0000000..288337b
--- /dev/null
+++ b/libpixelflinger/tests/gglmul/Android.bp
@@ -0,0 +1,12 @@
+cc_test {
+ name: "test-pixelflinger-gglmul",
+
+ srcs: ["gglmul_test.cpp"],
+
+ header_libs: ["libpixelflinger_internal"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/libpixelflinger/tests/gglmul/Android.mk b/libpixelflinger/tests/gglmul/Android.mk
deleted file mode 100644
index 67f358f..0000000
--- a/libpixelflinger/tests/gglmul/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- gglmul_test.cpp
-
-LOCAL_SHARED_LIBRARIES :=
-
-LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../../include
-
-LOCAL_MODULE:= test-pixelflinger-gglmul
-
-LOCAL_CFLAGS:= -Wall -Werror
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_NATIVE_TEST)
diff --git a/libprocessgroup/Android.bp b/libprocessgroup/Android.bp
index c38279d..d04a79a 100644
--- a/libprocessgroup/Android.bp
+++ b/libprocessgroup/Android.bp
@@ -1,10 +1,45 @@
+cc_library_headers {
+ name: "libprocessgroup_headers",
+ vendor_available: true,
+ recovery_available: true,
+ host_supported: true,
+ export_include_dirs: ["include"],
+ target: {
+ linux_bionic: {
+ enabled: true,
+ },
+ windows: {
+ enabled: true,
+ },
+ },
+}
+
cc_library {
- srcs: ["processgroup.cpp"],
+ srcs: [
+ "processgroup.cpp",
+ "sched_policy.cpp",
+ ],
name: "libprocessgroup",
host_supported: true,
recovery_available: true,
- shared_libs: ["libbase"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ shared_libs: [
+ "libbase",
+ "liblog",
+ ],
+ // for cutils/android_filesystem_config.h
+ header_libs: [
+ "libcutils_headers",
+ "libprocessgroup_headers",
+ ],
export_include_dirs: ["include"],
+ export_header_lib_headers: [
+ "libprocessgroup_headers",
+ ],
cflags: [
"-Wall",
"-Werror",
diff --git a/libprocessgroup/OWNERS b/libprocessgroup/OWNERS
new file mode 100644
index 0000000..bfa730a
--- /dev/null
+++ b/libprocessgroup/OWNERS
@@ -0,0 +1,2 @@
+ccross@google.com
+tomcherry@google.com
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index 9fa4154..2412f3c 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -31,8 +31,10 @@
// 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 createProcessGroup(uid_t uid, int initialPid);
+int createProcessGroup(uid_t uid, int initialPid, bool memControl = false);
+// Set various properties of a process group. For these functions to work, the process group must
+// have been created by passing memControl=true to createProcessGroup.
bool setProcessGroupSwappiness(uid_t uid, int initialPid, int swappiness);
bool setProcessGroupSoftLimit(uid_t uid, int initialPid, int64_t softLimitInBytes);
bool setProcessGroupLimit(uid_t uid, int initialPid, int64_t limitInBytes);
diff --git a/libprocessgroup/include/processgroup/sched_policy.h b/libprocessgroup/include/processgroup/sched_policy.h
new file mode 100644
index 0000000..79a32fd
--- /dev/null
+++ b/libprocessgroup/include/processgroup/sched_policy.h
@@ -0,0 +1,80 @@
+/*
+ * 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 <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Check if Linux kernel enables CPUSETS feature.
+ *
+ * Return value: 1 if Linux kernel CONFIG_CPUSETS=y; 0 otherwise.
+ */
+extern bool cpusets_enabled();
+
+/*
+ * Check if Linux kernel enables SCHEDTUNE feature (only available in Android
+ * common kernel or Linaro LSK, not in mainline Linux as of v4.9)
+ *
+ * Return value: 1 if Linux kernel CONFIG_CGROUP_SCHEDTUNE=y; 0 otherwise.
+ */
+extern bool schedboost_enabled();
+
+/* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
+typedef enum {
+ SP_DEFAULT = -1,
+ SP_BACKGROUND = 0,
+ SP_FOREGROUND = 1,
+ SP_SYSTEM = 2, // can't be used with set_sched_policy()
+ SP_AUDIO_APP = 3,
+ SP_AUDIO_SYS = 4,
+ SP_TOP_APP = 5,
+ SP_RT_APP = 6,
+ SP_RESTRICTED = 7,
+ SP_CNT,
+ SP_MAX = SP_CNT - 1,
+ SP_SYSTEM_DEFAULT = SP_FOREGROUND,
+} SchedPolicy;
+
+extern int set_cpuset_policy(int tid, SchedPolicy policy);
+
+/* Assign thread tid to the cgroup associated with the specified policy.
+ * If the thread is a thread group leader, that is it's gettid() == getpid(),
+ * then the other threads in the same thread group are _not_ affected.
+ * On platforms which support gettid(), zero tid means current thread.
+ * Return value: 0 for success, or -errno for error.
+ */
+extern int set_sched_policy(int tid, SchedPolicy policy);
+
+/* Return the policy associated with the cgroup of thread tid via policy pointer.
+ * On platforms which support gettid(), zero tid means current thread.
+ * Return value: 0 for success, or -1 for error and set errno.
+ */
+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;
+ * the caller is responsible for displaying the useful part of the string.
+ */
+extern const char *get_sched_policy_name(SchedPolicy policy);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 1cebb5d..8d2ac3d 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -42,7 +42,7 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <private/android_filesystem_config.h>
+#include <cutils/android_filesystem_config.h>
#include <processgroup/processgroup.h>
@@ -53,49 +53,31 @@
using namespace std::chrono_literals;
-#define MEM_CGROUP_PATH "/dev/memcg/apps"
-#define MEM_CGROUP_TASKS "/dev/memcg/apps/tasks"
-#define ACCT_CGROUP_PATH "/acct"
+static const char kCpuacctCgroup[] = "/acct";
+static const char kMemoryCgroup[] = "/dev/memcg/apps";
#define PROCESSGROUP_CGROUP_PROCS_FILE "/cgroup.procs"
-std::once_flag init_path_flag;
-
-static const std::string& GetCgroupRootPath() {
- static std::string cgroup_root_path;
- std::call_once(init_path_flag, [&]() {
- // low-ram devices use per-app memcg by default, unlike high-end ones
- bool low_ram_device = GetBoolProperty("ro.config.low_ram", false);
- bool per_app_memcg =
- GetBoolProperty("ro.config.per_app_memcg", low_ram_device);
- if (per_app_memcg) {
- // Check if mem cgroup is mounted, only then check for
- // write-access to avoid SELinux denials
- cgroup_root_path =
- (access(MEM_CGROUP_TASKS, F_OK) || access(MEM_CGROUP_PATH, W_OK) ?
- ACCT_CGROUP_PATH : MEM_CGROUP_PATH);
- } else {
- cgroup_root_path = ACCT_CGROUP_PATH;
- }
- });
- return cgroup_root_path;
+static bool isMemoryCgroupSupported() {
+ static bool memcg_supported = !access("/dev/memcg/memory.limit_in_bytes", F_OK);
+ return memcg_supported;
}
-static std::string ConvertUidToPath(uid_t uid) {
- return StringPrintf("%s/uid_%d", GetCgroupRootPath().c_str(), uid);
+static std::string ConvertUidToPath(const char* cgroup, uid_t uid) {
+ return StringPrintf("%s/uid_%d", cgroup, uid);
}
-static std::string ConvertUidPidToPath(uid_t uid, int pid) {
- return StringPrintf("%s/uid_%d/pid_%d", GetCgroupRootPath().c_str(), uid, pid);
+static std::string ConvertUidPidToPath(const char* cgroup, uid_t uid, int pid) {
+ return StringPrintf("%s/uid_%d/pid_%d", cgroup, uid, pid);
}
-static int RemoveProcessGroup(uid_t uid, int pid) {
+static int RemoveProcessGroup(const char* cgroup, uid_t uid, int pid) {
int ret;
- auto uid_pid_path = ConvertUidPidToPath(uid, pid);
+ auto uid_pid_path = ConvertUidPidToPath(cgroup, uid, pid);
ret = rmdir(uid_pid_path.c_str());
- auto uid_path = ConvertUidToPath(uid);
+ auto uid_path = ConvertUidToPath(cgroup, uid);
rmdir(uid_path.c_str());
return ret;
@@ -124,25 +106,26 @@
void removeAllProcessGroups()
{
LOG(VERBOSE) << "removeAllProcessGroups()";
- const auto& cgroup_root_path = GetCgroupRootPath();
- std::unique_ptr<DIR, decltype(&closedir)> root(opendir(cgroup_root_path.c_str()), closedir);
- if (root == NULL) {
- PLOG(ERROR) << "Failed to open " << cgroup_root_path;
- } else {
- dirent* dir;
- while ((dir = readdir(root.get())) != nullptr) {
- if (dir->d_type != DT_DIR) {
- continue;
- }
+ for (const char* cgroup_root_path : {kCpuacctCgroup, kMemoryCgroup}) {
+ std::unique_ptr<DIR, decltype(&closedir)> root(opendir(cgroup_root_path), closedir);
+ if (root == NULL) {
+ PLOG(ERROR) << "Failed to open " << cgroup_root_path;
+ } else {
+ dirent* dir;
+ while ((dir = readdir(root.get())) != nullptr) {
+ if (dir->d_type != DT_DIR) {
+ continue;
+ }
- if (!StartsWith(dir->d_name, "uid_")) {
- continue;
- }
+ if (!StartsWith(dir->d_name, "uid_")) {
+ continue;
+ }
- auto path = StringPrintf("%s/%s", cgroup_root_path.c_str(), dir->d_name);
- RemoveUidProcessGroups(path);
- LOG(VERBOSE) << "Removing " << path;
- if (rmdir(path.c_str()) == -1) PLOG(WARNING) << "Failed to remove " << path;
+ auto path = StringPrintf("%s/%s", cgroup_root_path, dir->d_name);
+ RemoveUidProcessGroups(path);
+ LOG(VERBOSE) << "Removing " << path;
+ if (rmdir(path.c_str()) == -1) PLOG(WARNING) << "Failed to remove " << path;
+ }
}
}
}
@@ -150,8 +133,8 @@
// Returns number of processes killed on success
// Returns 0 if there are no processes in the process cgroup left to kill
// Returns -1 on error
-static int DoKillProcessGroupOnce(uid_t uid, int initialPid, int signal) {
- auto path = ConvertUidPidToPath(uid, initialPid) + PROCESSGROUP_CGROUP_PROCS_FILE;
+static int DoKillProcessGroupOnce(const char* cgroup, uid_t uid, int initialPid, int signal) {
+ auto path = ConvertUidPidToPath(cgroup, uid, initialPid) + PROCESSGROUP_CGROUP_PROCS_FILE;
std::unique_ptr<FILE, decltype(&fclose)> fd(fopen(path.c_str(), "re"), fclose);
if (!fd) {
PLOG(WARNING) << "Failed to open process cgroup uid " << uid << " pid " << initialPid;
@@ -185,7 +168,7 @@
// Erase all pids that will be killed when we kill the process groups.
for (auto it = pids.begin(); it != pids.end();) {
- pid_t pgid = getpgid(pid);
+ pid_t pgid = getpgid(*it);
if (pgids.count(pgid) == 1) {
it = pids.erase(it);
} else {
@@ -217,11 +200,16 @@
}
static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries) {
+ const char* cgroup =
+ (!access(ConvertUidPidToPath(kCpuacctCgroup, uid, initialPid).c_str(), F_OK))
+ ? kCpuacctCgroup
+ : kMemoryCgroup;
+
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
int retry = retries;
int processes;
- while ((processes = DoKillProcessGroupOnce(uid, initialPid, signal)) > 0) {
+ while ((processes = DoKillProcessGroupOnce(cgroup, uid, initialPid, signal)) > 0) {
LOG(VERBOSE) << "Killed " << processes << " processes for processgroup " << initialPid;
if (retry > 0) {
std::this_thread::sleep_for(5ms);
@@ -251,7 +239,7 @@
LOG(INFO) << "Successfully killed process cgroup uid " << uid << " pid " << initialPid
<< " in " << static_cast<int>(ms) << "ms";
}
- return RemoveProcessGroup(uid, initialPid);
+ return RemoveProcessGroup(cgroup, uid, initialPid);
} else {
if (retries > 0) {
LOG(ERROR) << "Failed to kill process cgroup uid " << uid << " pid " << initialPid
@@ -285,16 +273,29 @@
return true;
}
-int createProcessGroup(uid_t uid, int initialPid)
+static bool isPerAppMemcgEnabled() {
+ static bool per_app_memcg =
+ GetBoolProperty("ro.config.per_app_memcg", GetBoolProperty("ro.config.low_ram", false));
+ return per_app_memcg;
+}
+
+int createProcessGroup(uid_t uid, int initialPid, bool memControl)
{
- auto uid_path = ConvertUidToPath(uid);
+ const char* cgroup;
+ if (isMemoryCgroupSupported() && (memControl || isPerAppMemcgEnabled())) {
+ cgroup = kMemoryCgroup;
+ } else {
+ cgroup = kCpuacctCgroup;
+ }
+
+ auto uid_path = ConvertUidToPath(cgroup, uid);
if (!MkdirAndChown(uid_path, 0750, AID_SYSTEM, AID_SYSTEM)) {
PLOG(ERROR) << "Failed to make and chown " << uid_path;
return -errno;
}
- auto uid_pid_path = ConvertUidPidToPath(uid, initialPid);
+ auto uid_pid_path = ConvertUidPidToPath(cgroup, uid, initialPid);
if (!MkdirAndChown(uid_pid_path, 0750, AID_SYSTEM, AID_SYSTEM)) {
PLOG(ERROR) << "Failed to make and chown " << uid_pid_path;
@@ -313,12 +314,12 @@
}
static bool SetProcessGroupValue(uid_t uid, int pid, const std::string& file_name, int64_t value) {
- if (GetCgroupRootPath() != MEM_CGROUP_PATH) {
+ if (!isMemoryCgroupSupported()) {
PLOG(ERROR) << "Memcg is not mounted.";
return false;
}
- auto path = ConvertUidPidToPath(uid, pid) + file_name;
+ auto path = ConvertUidPidToPath(kMemoryCgroup, uid, pid) + file_name;
if (!WriteStringToFile(std::to_string(value), path)) {
PLOG(ERROR) << "Failed to write '" << value << "' to " << path;
diff --git a/libcutils/sched_policy.cpp b/libprocessgroup/sched_policy.cpp
similarity index 99%
rename from libcutils/sched_policy.cpp
rename to libprocessgroup/sched_policy.cpp
index 3fa548f..f95d7e4 100644
--- a/libcutils/sched_policy.cpp
+++ b/libprocessgroup/sched_policy.cpp
@@ -14,7 +14,7 @@
** limitations under the License.
*/
-#include <cutils/sched_policy.h>
+#include <processgroup/sched_policy.h>
#define LOG_TAG "SchedPolicy"
diff --git a/libprocinfo/include/procinfo/process_map.h b/libprocinfo/include/procinfo/process_map.h
index 3771f9f..981241e 100644
--- a/libprocinfo/include/procinfo/process_map.h
+++ b/libprocinfo/include/procinfo/process_map.h
@@ -17,11 +17,13 @@
#pragma once
#include <stdlib.h>
+#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <functional>
#include <string>
+#include <vector>
#include <android-base/file.h>
@@ -147,5 +149,23 @@
return ReadMapFile("/proc/" + std::to_string(pid) + "/maps", callback);
}
+struct MapInfo {
+ uint64_t start;
+ uint64_t end;
+ uint16_t flags;
+ uint64_t pgoff;
+ std::string name;
+
+ MapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, const char* name)
+ : start(start), end(end), flags(flags), pgoff(pgoff), name(name) {}
+};
+
+inline bool ReadProcessMaps(pid_t pid, std::vector<MapInfo>* maps) {
+ return ReadProcessMaps(
+ pid, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, const char* name) {
+ maps->emplace_back(start, end, flags, pgoff, name);
+ });
+}
+
} /* namespace procinfo */
} /* namespace android */
diff --git a/libprocinfo/process_map_benchmark.cpp b/libprocinfo/process_map_benchmark.cpp
index d9e8a4d..04995d4 100644
--- a/libprocinfo/process_map_benchmark.cpp
+++ b/libprocinfo/process_map_benchmark.cpp
@@ -27,21 +27,10 @@
#include <benchmark/benchmark.h>
-struct MapInfo {
- uint64_t start;
- uint64_t end;
- uint16_t flags;
- uint64_t pgoff;
- const std::string name;
-
- MapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, const char* name)
- : start(start), end(end), flags(flags), pgoff(pgoff), name(name) {}
-};
-
static void BM_ReadMapFile(benchmark::State& state) {
std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps";
for (auto _ : state) {
- std::vector<MapInfo> maps;
+ std::vector<android::procinfo::MapInfo> maps;
android::procinfo::ReadMapFile(
map_file, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff,
const char* name) { maps.emplace_back(start, end, flags, pgoff, name); });
diff --git a/libprocinfo/process_map_test.cpp b/libprocinfo/process_map_test.cpp
index 4b93c5b..170a806 100644
--- a/libprocinfo/process_map_test.cpp
+++ b/libprocinfo/process_map_test.cpp
@@ -22,20 +22,9 @@
#include <gtest/gtest.h>
-struct MapInfo {
- uint64_t start;
- uint64_t end;
- uint16_t flags;
- uint64_t pgoff;
- const std::string name;
-
- MapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, const char* name)
- : start(start), end(end), flags(flags), pgoff(pgoff), name(name) {}
-};
-
-TEST(process_map, smoke) {
+TEST(process_map, ReadMapFile) {
std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps";
- std::vector<MapInfo> maps;
+ std::vector<android::procinfo::MapInfo> maps;
ASSERT_TRUE(android::procinfo::ReadMapFile(
map_file, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff,
const char* name) { maps.emplace_back(start, end, flags, pgoff, name); }));
@@ -58,3 +47,14 @@
"[anon:dalvik-classes.dex extracted in memory from "
"/data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/base.apk]");
}
+
+TEST(process_map, ReadProcessMaps) {
+ std::vector<android::procinfo::MapInfo> maps;
+ ASSERT_TRUE(android::procinfo::ReadProcessMaps(
+ getpid(), [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff,
+ const char* name) { maps.emplace_back(start, end, flags, pgoff, name); }));
+ ASSERT_GT(maps.size(), 0u);
+ maps.clear();
+ ASSERT_TRUE(android::procinfo::ReadProcessMaps(getpid(), &maps));
+ ASSERT_GT(maps.size(), 0u);
+}
diff --git a/libsparse/output_file.cpp b/libsparse/output_file.cpp
index fe314b3..5b8179f 100644
--- a/libsparse/output_file.cpp
+++ b/libsparse/output_file.cpp
@@ -508,7 +508,7 @@
out->len = len;
out->block_size = block_size;
- out->cur_out_ptr = 0ll;
+ out->cur_out_ptr = 0LL;
out->chunk_cnt = 0;
out->crc32 = 0;
out->use_crc = crc;
diff --git a/libstats/Android.bp b/libstats/Android.bp
index d58f294..f5ee1da 100644
--- a/libstats/Android.bp
+++ b/libstats/Android.bp
@@ -17,12 +17,13 @@
// ==========================================================
// Native library to write stats log to statsd socket
// ==========================================================
-cc_library_static {
+cc_library {
name: "libstatssocket",
srcs: [
"stats_event_list.c",
"statsd_writer.c",
],
+ host_supported: true,
cflags: [
"-Wall",
"-Werror",
@@ -32,6 +33,7 @@
],
export_include_dirs: ["include"],
shared_libs: [
+ "libcutils",
"liblog",
],
}
diff --git a/libstats/include/stats_event_list.h b/libstats/include/stats_event_list.h
index 5d174ae..b5bc5af 100644
--- a/libstats/include/stats_event_list.h
+++ b/libstats/include/stats_event_list.h
@@ -24,7 +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);
+void stats_log_close();
+int android_log_write_char_array(android_log_context ctx, const char* value, size_t len);
#ifdef __cplusplus
}
#endif
@@ -49,10 +51,6 @@
explicit stats_event_list(int tag) : ret(0) {
ctx = create_android_logger(static_cast<uint32_t>(tag));
}
- explicit stats_event_list(log_msg& log_msg) : ret(0) {
- ctx = create_android_log_parser(log_msg.msg() + sizeof(uint32_t),
- log_msg.entry.len - sizeof(uint32_t));
- }
~stats_event_list() { android_log_destroy(&ctx); }
int close() {
@@ -242,8 +240,13 @@
return ret >= 0;
}
- android_log_list_element read() { return android_log_read_next(ctx); }
- android_log_list_element peek() { return android_log_peek_next(ctx); }
+ bool AppendCharArray(const char* value, size_t len) {
+ int retval = android_log_write_char_array(ctx, value, len);
+ if (retval < 0) {
+ ret = retval;
+ }
+ return ret >= 0;
+ }
};
#endif
diff --git a/libstats/stats_event_list.c b/libstats/stats_event_list.c
index 3d746db..5b90361 100644
--- a/libstats/stats_event_list.c
+++ b/libstats/stats_event_list.c
@@ -17,6 +17,7 @@
#include "include/stats_event_list.h"
#include <string.h>
+#include <sys/time.h>
#include "statsd_writer.h"
#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
@@ -119,6 +120,19 @@
return retValue;
}
+void note_log_drop(int error) {
+ statsdLoggerWrite.noteDrop(error);
+}
+
+void stats_log_close() {
+ statsd_writer_init_lock();
+ write_to_statsd = __write_to_statsd_init;
+ if (statsdLoggerWrite.close) {
+ (*statsdLoggerWrite.close)();
+ }
+ statsd_writer_init_unlock();
+}
+
/* log_init_lock assumed */
static int __write_to_statsd_initialize_locked() {
if (!statsdLoggerWrite.open || ((*statsdLoggerWrite.open)() < 0)) {
@@ -143,7 +157,14 @@
}
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;
@@ -172,3 +193,47 @@
errno = save_errno;
return ret;
}
+
+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/statsd_writer.c
index 9953bba..f5be95c 100644
--- a/libstats/statsd_writer.c
+++ b/libstats/statsd_writer.c
@@ -15,8 +15,9 @@
*/
#include "statsd_writer.h"
+#include <cutils/fs.h>
#include <cutils/sockets.h>
-#include <endian.h>
+#include <cutils/threads.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -30,6 +31,7 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/uio.h>
#include <sys/un.h>
#include <time.h>
#include <unistd.h>
@@ -37,7 +39,17 @@
/* 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
+
static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static atomic_int dropped = 0;
+static atomic_int log_error = 0;
void statsd_writer_init_lock() {
/*
@@ -59,14 +71,16 @@
static int statsdOpen();
static void statsdClose();
static int statsdWrite(struct timespec* ts, struct iovec* vec, size_t nr);
+static void statsdNoteDrop();
struct android_log_transport_write statsdLoggerWrite = {
- .name = "statsd",
- .sock = -EBADF,
- .available = statsdAvailable,
- .open = statsdOpen,
- .close = statsdClose,
- .write = statsdWrite,
+ .name = "statsd",
+ .sock = -EBADF,
+ .available = statsdAvailable,
+ .open = statsdOpen,
+ .close = statsdClose,
+ .write = statsdWrite,
+ .noteDrop = statsdNoteDrop,
};
/* log_init_lock assumed */
@@ -75,7 +89,14 @@
i = atomic_load(&statsdLoggerWrite.sock);
if (i < 0) {
- int sock = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
+ int flags = SOCK_DGRAM;
+#ifdef SOCK_CLOEXEC
+ flags |= SOCK_CLOEXEC;
+#endif
+#ifdef SOCK_NONBLOCK
+ flags |= SOCK_NONBLOCK;
+#endif
+ int sock = TEMP_FAILURE_RETRY(socket(PF_UNIX, flags, 0));
if (sock < 0) {
ret = -errno;
} else {
@@ -131,6 +152,11 @@
return 1;
}
+static void statsdNoteDrop(int error) {
+ atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
+ atomic_exchange_explicit(&log_error, error, memory_order_relaxed);
+}
+
static int statsdWrite(struct timespec* ts, struct iovec* vec, size_t nr) {
ssize_t ret;
int sock;
@@ -138,7 +164,6 @@
struct iovec newVec[nr + headerLength];
android_log_header_t header;
size_t i, payloadSize;
- static atomic_int dropped;
sock = atomic_load(&statsdLoggerWrite.sock);
if (sock < 0) switch (sock) {
@@ -180,7 +205,8 @@
if (snapshot) {
android_log_event_int_t buffer;
header.id = LOG_ID_STATS;
- buffer.header.tag = htole32(LIBLOG_LOG_TAG);
+ // 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.payload.type = EVENT_TYPE_INT;
buffer.payload.data = htole32(snapshot);
@@ -252,8 +278,6 @@
if (ret > (ssize_t)sizeof(header)) {
ret -= sizeof(header);
- } else if (ret == -EAGAIN) {
- atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
}
return ret;
diff --git a/libstats/statsd_writer.h b/libstats/statsd_writer.h
index 82e14e0..4fc3f8b 100644
--- a/libstats/statsd_writer.h
+++ b/libstats/statsd_writer.h
@@ -38,6 +38,8 @@
void (*close)(); /* free up resources */
/* write log to transport, returns number of bytes propagated, or -errno */
int (*write)(struct timespec* ts, struct iovec* vec, size_t nr);
+ /* note one log drop */
+ void (*noteDrop)(int error);
};
#endif // ANDROID_STATS_LOG_STATS_WRITER_H
diff --git a/libsystem/include/system/camera.h b/libsystem/include/system/camera.h
index 7d79673..2ca90c3 100644
--- a/libsystem/include/system/camera.h
+++ b/libsystem/include/system/camera.h
@@ -158,8 +158,8 @@
*
* When any camera method returns error, the client can use ping command
* to see if the camera has been taken away by other clients. If the result
- * is NO_ERROR, it means the camera hardware is not released. If the result
- * is not NO_ERROR, the camera has been released and the existing client
+ * is OK, it means the camera hardware is not released. If the result
+ * is not OK, the camera has been released and the existing client
* can silently finish itself or show a dialog.
*/
CAMERA_CMD_PING = 9,
diff --git a/libsysutils/Android.bp b/libsysutils/Android.bp
index 29d23c8..da5d86c 100644
--- a/libsysutils/Android.bp
+++ b/libsysutils/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
name: "libsysutils",
vendor_available: true,
vndk: {
diff --git a/libsysutils/include/sysutils/FrameworkCommand.h b/libsysutils/include/sysutils/FrameworkCommand.h
index 3e6264b..db17ba7 100644
--- a/libsysutils/include/sysutils/FrameworkCommand.h
+++ b/libsysutils/include/sysutils/FrameworkCommand.h
@@ -16,8 +16,6 @@
#ifndef __FRAMEWORK_CMD_HANDLER_H
#define __FRAMEWORK_CMD_HANDLER_H
-#include "List.h"
-
class SocketClient;
class FrameworkCommand {
@@ -31,8 +29,7 @@
virtual int runCommand(SocketClient *c, int argc, char **argv) = 0;
- const char *getCommand() { return mCommand; }
+ const char* getCommand() const { return mCommand; }
};
-typedef android::sysutils::List<FrameworkCommand *> FrameworkCommandCollection;
#endif
diff --git a/libsysutils/include/sysutils/FrameworkListener.h b/libsysutils/include/sysutils/FrameworkListener.h
index d9a561a..93d99c4 100644
--- a/libsysutils/include/sysutils/FrameworkListener.h
+++ b/libsysutils/include/sysutils/FrameworkListener.h
@@ -17,8 +17,10 @@
#define _FRAMEWORKSOCKETLISTENER_H
#include "SocketListener.h"
-#include "FrameworkCommand.h"
+#include <vector>
+
+class FrameworkCommand;
class SocketClient;
class FrameworkListener : public SocketListener {
@@ -31,7 +33,7 @@
private:
int mCommandCount;
bool mWithSeq;
- FrameworkCommandCollection *mCommands;
+ std::vector<FrameworkCommand*> mCommands;
bool mSkipToNextNullByte;
public:
diff --git a/libsysutils/include/sysutils/List.h b/libsysutils/include/sysutils/List.h
deleted file mode 100644
index 31f7b37..0000000
--- a/libsysutils/include/sysutils/List.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2005 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//
-// Templated list class. Normally we'd use STL, but we don't have that.
-// This class mimics STL's interfaces.
-//
-// Objects are copied into the list with the '=' operator or with copy-
-// construction, so if the compiler's auto-generated versions won't work for
-// you, define your own.
-//
-// The only class you want to use from here is "List".
-//
-#ifndef _SYSUTILS_LIST_H
-#define _SYSUTILS_LIST_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-namespace android {
-namespace sysutils {
-
-/*
- * Doubly-linked list. Instantiate with "List<MyClass> myList".
- *
- * Objects added to the list are copied using the assignment operator,
- * so this must be defined.
- */
-template<typename T>
-class List
-{
-protected:
- /*
- * One element in the list.
- */
- class _Node {
- public:
- explicit _Node(const T& val) : mVal(val) {}
- ~_Node() {}
- inline T& getRef() { return mVal; }
- inline const T& getRef() const { return mVal; }
- inline _Node* getPrev() const { return mpPrev; }
- inline _Node* getNext() const { return mpNext; }
- inline void setVal(const T& val) { mVal = val; }
- inline void setPrev(_Node* ptr) { mpPrev = ptr; }
- inline void setNext(_Node* ptr) { mpNext = ptr; }
- private:
- friend class List;
- friend class _ListIterator;
- T mVal;
- _Node* mpPrev;
- _Node* mpNext;
- };
-
- /*
- * Iterator for walking through the list.
- */
-
- template <typename TYPE>
- struct CONST_ITERATOR {
- typedef _Node const * NodePtr;
- typedef const TYPE Type;
- };
-
- template <typename TYPE>
- struct NON_CONST_ITERATOR {
- typedef _Node* NodePtr;
- typedef TYPE Type;
- };
-
- template<
- typename U,
- template <class> class Constness
- >
- class _ListIterator {
- typedef _ListIterator<U, Constness> _Iter;
- typedef typename Constness<U>::NodePtr _NodePtr;
- typedef typename Constness<U>::Type _Type;
-
- explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}
-
- public:
- _ListIterator() {}
- _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
- ~_ListIterator() {}
-
- // this will handle conversions from iterator to const_iterator
- // (and also all convertible iterators)
- // Here, in this implementation, the iterators can be converted
- // if the nodes can be converted
- template<typename V> explicit
- _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
-
-
- /*
- * Dereference operator. Used to get at the juicy insides.
- */
- _Type& operator*() const { return mpNode->getRef(); }
- _Type* operator->() const { return &(mpNode->getRef()); }
-
- /*
- * Iterator comparison.
- */
- inline bool operator==(const _Iter& right) const {
- return mpNode == right.mpNode; }
-
- inline bool operator!=(const _Iter& right) const {
- return mpNode != right.mpNode; }
-
- /*
- * handle comparisons between iterator and const_iterator
- */
- template<typename OTHER>
- inline bool operator==(const OTHER& right) const {
- return mpNode == right.mpNode; }
-
- template<typename OTHER>
- inline bool operator!=(const OTHER& right) const {
- return mpNode != right.mpNode; }
-
- /*
- * Incr/decr, used to move through the list.
- */
- inline _Iter& operator++() { // pre-increment
- mpNode = mpNode->getNext();
- return *this;
- }
- const _Iter operator++(int) { // post-increment
- _Iter tmp(*this);
- mpNode = mpNode->getNext();
- return tmp;
- }
- inline _Iter& operator--() { // pre-increment
- mpNode = mpNode->getPrev();
- return *this;
- }
- const _Iter operator--(int) { // post-increment
- _Iter tmp(*this);
- mpNode = mpNode->getPrev();
- return tmp;
- }
-
- inline _NodePtr getNode() const { return mpNode; }
-
- _NodePtr mpNode; /* should be private, but older gcc fails */
- private:
- friend class List;
- };
-
-public:
- List() {
- prep();
- }
- List(const List<T>& src) { // copy-constructor
- prep();
- insert(begin(), src.begin(), src.end());
- }
- virtual ~List() {
- clear();
- delete[] (unsigned char*) mpMiddle;
- }
-
- typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
- typedef _ListIterator<T, CONST_ITERATOR> const_iterator;
-
- List<T>& operator=(const List<T>& right);
-
- /* returns true if the list is empty */
- inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }
-
- /* return #of elements in list */
- size_t size() const {
- return size_t(distance(begin(), end()));
- }
-
- /*
- * Return the first element or one past the last element. The
- * _Node* we're returning is converted to an "iterator" by a
- * constructor in _ListIterator.
- */
- inline iterator begin() {
- return iterator(mpMiddle->getNext());
- }
- inline const_iterator begin() const {
- return const_iterator(const_cast<_Node const*>(mpMiddle->getNext()));
- }
- inline iterator end() {
- return iterator(mpMiddle);
- }
- inline const_iterator end() const {
- return const_iterator(const_cast<_Node const*>(mpMiddle));
- }
-
- /* add the object to the head or tail of the list */
- void push_front(const T& val) { insert(begin(), val); }
- void push_back(const T& val) { insert(end(), val); }
-
- /* insert before the current node; returns iterator at new node */
- iterator insert(iterator posn, const T& val)
- {
- _Node* newNode = new _Node(val); // alloc & copy-construct
- newNode->setNext(posn.getNode());
- newNode->setPrev(posn.getNode()->getPrev());
- posn.getNode()->getPrev()->setNext(newNode);
- posn.getNode()->setPrev(newNode);
- return iterator(newNode);
- }
-
- /* insert a range of elements before the current node */
- void insert(iterator posn, const_iterator first, const_iterator last) {
- for ( ; first != last; ++first)
- insert(posn, *first);
- }
-
- /* remove one entry; returns iterator at next node */
- iterator erase(iterator posn) {
- _Node* pNext = posn.getNode()->getNext();
- _Node* pPrev = posn.getNode()->getPrev();
- pPrev->setNext(pNext);
- pNext->setPrev(pPrev);
- delete posn.getNode();
- return iterator(pNext);
- }
-
- /* remove a range of elements */
- iterator erase(iterator first, iterator last) {
- while (first != last)
- erase(first++); // don't erase than incr later!
- return iterator(last);
- }
-
- /* remove all contents of the list */
- void clear() {
- _Node* pCurrent = mpMiddle->getNext();
- _Node* pNext;
-
- while (pCurrent != mpMiddle) {
- pNext = pCurrent->getNext();
- delete pCurrent;
- pCurrent = pNext;
- }
- mpMiddle->setPrev(mpMiddle);
- mpMiddle->setNext(mpMiddle);
- }
-
- /*
- * Measure the distance between two iterators. On exist, "first"
- * will be equal to "last". The iterators must refer to the same
- * list.
- *
- * FIXME: This is actually a generic iterator function. It should be a
- * template function at the top-level with specializations for things like
- * vector<>, which can just do pointer math). Here we limit it to
- * _ListIterator of the same type but different constness.
- */
- template<
- typename U,
- template <class> class CL,
- template <class> class CR
- >
- ptrdiff_t distance(
- _ListIterator<U, CL> first, _ListIterator<U, CR> last) const
- {
- ptrdiff_t count = 0;
- while (first != last) {
- ++first;
- ++count;
- }
- return count;
- }
-
-private:
- /*
- * I want a _Node but don't need it to hold valid data. More
- * to the point, I don't want T's constructor to fire, since it
- * might have side-effects or require arguments. So, we do this
- * slightly uncouth storage alloc.
- */
- void prep() {
- mpMiddle = (_Node*) new unsigned char[sizeof(_Node)];
- mpMiddle->setPrev(mpMiddle);
- mpMiddle->setNext(mpMiddle);
- }
-
- /*
- * This node plays the role of "pointer to head" and "pointer to tail".
- * It sits in the middle of a circular list of nodes. The iterator
- * runs around the circle until it encounters this one.
- */
- _Node* mpMiddle;
-};
-
-/*
- * Assignment operator.
- *
- * The simplest way to do this would be to clear out the target list and
- * fill it with the source. However, we can speed things along by
- * re-using existing elements.
- */
-template<class T>
-List<T>& List<T>::operator=(const List<T>& right)
-{
- if (this == &right)
- return *this; // self-assignment
- iterator firstDst = begin();
- iterator lastDst = end();
- const_iterator firstSrc = right.begin();
- const_iterator lastSrc = right.end();
- while (firstSrc != lastSrc && firstDst != lastDst)
- *firstDst++ = *firstSrc++;
- if (firstSrc == lastSrc) // ran out of elements in source?
- erase(firstDst, lastDst); // yes, erase any extras
- else
- insert(lastDst, firstSrc, lastSrc); // copy remaining over
- return *this;
-}
-
-}; // namespace sysutils
-}; // namespace android
-
-#endif // _SYSUTILS_LIST_H
diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp
index 835e226..b07853a 100644
--- a/libsysutils/src/FrameworkListener.cpp
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -28,8 +28,6 @@
static const int CMD_BUF_SIZE = 1024;
-#define UNUSED __attribute__((unused))
-
FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) :
SocketListener(socketName, true, withSeq) {
init(socketName, withSeq);
@@ -45,8 +43,7 @@
init(nullptr, false);
}
-void FrameworkListener::init(const char *socketName UNUSED, bool withSeq) {
- mCommands = new FrameworkCommandCollection();
+void FrameworkListener::init(const char* /*socketName*/, bool withSeq) {
errorRate = 0;
mCommandCount = 0;
mWithSeq = withSeq;
@@ -91,11 +88,10 @@
}
void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
- mCommands->push_back(cmd);
+ mCommands.push_back(cmd);
}
void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
- FrameworkCommandCollection::iterator i;
int argc = 0;
char *argv[FrameworkListener::CMD_ARGS_MAX];
char tmp[CMD_BUF_SIZE];
@@ -193,9 +189,7 @@
goto out;
}
- for (i = mCommands->begin(); i != mCommands->end(); ++i) {
- FrameworkCommand *c = *i;
-
+ for (auto* c : mCommands) {
if (!strcmp(argv[0], c->getCommand())) {
if (c->runCommand(cli, argc, argv)) {
SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 24ea7aa..9dc2699 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -374,6 +374,7 @@
continue;
if (!if_indextoname(* (int *) RTA_DATA(rta), dev))
return false;
+ continue;
default:
continue;
}
diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp
index 0625db7..fe2f3d6 100644
--- a/libsysutils/src/SocketClient.cpp
+++ b/libsysutils/src/SocketClient.cpp
@@ -27,6 +27,8 @@
#include <sys/types.h>
#include <unistd.h>
+#include <android-base/file.h>
+#include <android-base/macros.h>
#include <log/log.h>
#include <sysutils/SocketClient.h>
@@ -145,7 +147,8 @@
switch (*arg) {
case '\\':
case '"':
- *(current++) = '\\'; // fallthrough
+ *(current++) = '\\';
+ FALLTHROUGH_INTENDED;
default:
*(current++) = *(arg++);
}
diff --git a/libsysutils/src/SocketListener_test.cpp b/libsysutils/src/SocketListener_test.cpp
index fed4546..d6bfd02 100644
--- a/libsysutils/src/SocketListener_test.cpp
+++ b/libsysutils/src/SocketListener_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <sysutils/FrameworkCommand.h>
#include <sysutils/FrameworkListener.h>
#include <poll.h>
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index be2145d..d1b8271 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -58,6 +58,7 @@
"Elf.cpp",
"ElfInterface.cpp",
"ElfInterfaceArm.cpp",
+ "Global.cpp",
"JitDebug.cpp",
"Log.cpp",
"MapInfo.cpp",
@@ -93,7 +94,10 @@
"DexFile.cpp",
"DexFiles.cpp",
],
- exclude_shared_libs: ["libdexfile"],
+ exclude_shared_libs: [
+ "libdexfile_external",
+ "libdexfile_support",
+ ],
},
recovery: {
cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
@@ -101,7 +105,10 @@
"DexFile.cpp",
"DexFiles.cpp",
],
- exclude_shared_libs: ["libdexfile"],
+ exclude_shared_libs: [
+ "libdexfile_external",
+ "libdexfile_support",
+ ],
},
},
@@ -120,13 +127,18 @@
},
},
+ whole_static_libs: [
+ "libdemangle"
+ ],
+
static_libs: [
"libprocinfo",
],
shared_libs: [
"libbase",
- "libdexfile",
+ "libdexfile_external",
+ "libdexfile_support",
"liblog",
"liblzma",
],
@@ -178,16 +190,21 @@
"tests/JitDebugTest.cpp",
"tests/LocalUnwinderTest.cpp",
"tests/LogFake.cpp",
+ "tests/MapInfoCreateMemoryTest.cpp",
+ "tests/MapInfoGetBuildIDTest.cpp",
"tests/MapInfoGetElfTest.cpp",
"tests/MapInfoGetLoadBiasTest.cpp",
+ "tests/MapInfoTest.cpp",
"tests/MapsTest.cpp",
"tests/MemoryBufferTest.cpp",
+ "tests/MemoryCacheTest.cpp",
"tests/MemoryFake.cpp",
"tests/MemoryFileTest.cpp",
"tests/MemoryLocalTest.cpp",
"tests/MemoryOfflineBufferTest.cpp",
"tests/MemoryOfflineTest.cpp",
"tests/MemoryRangeTest.cpp",
+ "tests/MemoryRangesTest.cpp",
"tests/MemoryRemoteTest.cpp",
"tests/MemoryTest.cpp",
"tests/RegsInfoTest.cpp",
@@ -210,7 +227,7 @@
"liblog",
"liblzma",
"libunwindstack",
- "libdexfile",
+ "libdexfile_support",
],
static_libs: [
@@ -231,6 +248,8 @@
"tests/files/offline/jit_map_arm/*",
"tests/files/offline/gnu_debugdata_arm/*",
"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/straddle_arm/*",
"tests/files/offline/straddle_arm64/*",
],
@@ -307,6 +326,29 @@
],
}
+//-------------------------------------------------------------------------
+// Benchmarks
+//-------------------------------------------------------------------------
+cc_benchmark {
+ name: "unwind_benchmarks",
+ host_supported: true,
+ defaults: ["libunwindstack_flags"],
+
+ // Disable optimizations so that all of the calls are not optimized away.
+ cflags: [
+ "-O0",
+ ],
+
+ srcs: [
+ "benchmarks/unwind_benchmarks.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libunwindstack",
+ ],
+}
+
// Generates the elf data for use in the tests for .gnu_debugdata frames.
// Once these files are generated, use the xz command to compress the data.
cc_binary_host {
diff --git a/libunwindstack/DexFile.cpp b/libunwindstack/DexFile.cpp
index 8ec560c..eaf867f 100644
--- a/libunwindstack/DexFile.cpp
+++ b/libunwindstack/DexFile.cpp
@@ -23,13 +23,7 @@
#include <memory>
#include <android-base/unique_fd.h>
-
-#include <dex/class_accessor-inl.h>
-#include <dex/code_item_accessors-inl.h>
-#include <dex/compact_dex_file.h>
-#include <dex/dex_file-inl.h>
-#include <dex/dex_file_loader.h>
-#include <dex/standard_dex_file.h>
+#include <art_api/dex_file_support.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Memory.h>
@@ -38,169 +32,71 @@
namespace unwindstack {
-DexFile* DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory, MapInfo* info) {
+std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory,
+ MapInfo* info) {
if (!info->name.empty()) {
- std::unique_ptr<DexFileFromFile> dex_file(new DexFileFromFile);
- if (dex_file->Open(dex_file_offset_in_memory - info->start + info->offset, info->name)) {
- return dex_file.release();
+ std::unique_ptr<DexFile> dex_file =
+ DexFileFromFile::Create(dex_file_offset_in_memory - info->start + info->offset, info->name);
+ if (dex_file) {
+ return dex_file;
}
}
-
- std::unique_ptr<DexFileFromMemory> dex_file(new DexFileFromMemory);
- if (dex_file->Open(dex_file_offset_in_memory, memory)) {
- return dex_file.release();
- }
- return nullptr;
-}
-
-DexFileFromFile::~DexFileFromFile() {
- if (size_ != 0) {
- munmap(mapped_memory_, size_);
- }
+ return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name);
}
bool DexFile::GetMethodInformation(uint64_t dex_offset, std::string* method_name,
uint64_t* method_offset) {
- if (dex_file_ == nullptr) {
+ art_api::dex::MethodInfo method_info = GetMethodInfoForOffset(dex_offset, false);
+ if (method_info.offset == 0) {
return false;
}
-
- if (!dex_file_->IsInDataSection(dex_file_->Begin() + dex_offset)) {
- return false; // The DEX offset is not within the bytecode of this dex file.
- }
-
- if (dex_file_->IsCompactDexFile()) {
- // The data section of compact dex files might be shared.
- // Check the subrange unique to this compact dex.
- const auto& cdex_header = dex_file_->AsCompactDexFile()->GetHeader();
- uint32_t begin = cdex_header.data_off_ + cdex_header.OwnedDataBegin();
- uint32_t end = cdex_header.data_off_ + cdex_header.OwnedDataEnd();
- if (dex_offset < begin || dex_offset >= end) {
- return false; // The DEX offset is not within the bytecode of this dex file.
- }
- }
-
- // The method data is cached in a std::map indexed by method end offset and
- // contains the start offset and the method member index.
- // Only cache the method data as it is searched. Do not read the entire
- // set of method data into the cache at once.
- // This is done because many unwinds only find a single frame with dex file
- // info, so reading the entire method data is wasteful. However, still cache
- // the data so that anything doing multiple unwinds will have this data
- // cached for future use.
-
- // First look in the method cache.
- auto entry = method_cache_.upper_bound(dex_offset);
- if (entry != method_cache_.end() && dex_offset >= entry->second.first) {
- *method_name = dex_file_->PrettyMethod(entry->second.second, false);
- *method_offset = dex_offset - entry->second.first;
- return true;
- }
-
- // Check the methods we haven't cached.
- for (; class_def_index_ < dex_file_->NumClassDefs(); class_def_index_++) {
- art::ClassAccessor accessor(*dex_file_, dex_file_->GetClassDef(class_def_index_));
-
- for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
- art::CodeItemInstructionAccessor code = method.GetInstructions();
- if (!code.HasCodeItem()) {
- continue;
- }
- uint32_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
- uint32_t offset_end = offset + code.InsnsSizeInBytes();
- uint32_t member_index = method.GetIndex();
- method_cache_[offset_end] = std::make_pair(offset, member_index);
- if (offset <= dex_offset && dex_offset < offset_end) {
- *method_name = dex_file_->PrettyMethod(member_index, false);
- *method_offset = dex_offset - offset;
- return true;
- }
- }
- }
- return false;
+ *method_name = method_info.name;
+ *method_offset = dex_offset - method_info.offset;
+ return true;
}
-bool DexFileFromFile::Open(uint64_t dex_file_offset_in_file, const std::string& file) {
+std::unique_ptr<DexFileFromFile> DexFileFromFile::Create(uint64_t dex_file_offset_in_file,
+ const std::string& file) {
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
if (fd == -1) {
- return false;
- }
- struct stat buf;
- if (fstat(fd, &buf) == -1) {
- return false;
- }
- uint64_t length;
- if (buf.st_size < 0 ||
- __builtin_add_overflow(dex_file_offset_in_file, sizeof(art::DexFile::Header), &length) ||
- static_cast<uint64_t>(buf.st_size) < length) {
- return false;
+ return nullptr;
}
- mapped_memory_ = mmap(nullptr, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (mapped_memory_ == MAP_FAILED) {
- return false;
- }
- size_ = buf.st_size;
-
- uint8_t* memory = reinterpret_cast<uint8_t*>(mapped_memory_);
-
- art::DexFile::Header* header =
- reinterpret_cast<art::DexFile::Header*>(&memory[dex_file_offset_in_file]);
- if (!art::StandardDexFile::IsMagicValid(header->magic_) &&
- !art::CompactDexFile::IsMagicValid(header->magic_)) {
- return false;
- }
-
- if (__builtin_add_overflow(dex_file_offset_in_file, header->file_size_, &length) ||
- static_cast<uint64_t>(buf.st_size) < length) {
- return false;
- }
-
- art::DexFileLoader loader;
std::string error_msg;
- auto dex = loader.Open(&memory[dex_file_offset_in_file], header->file_size_, "", 0, nullptr,
- false, false, &error_msg);
- dex_file_.reset(dex.release());
- return dex_file_ != nullptr;
+ std::unique_ptr<art_api::dex::DexFile> art_dex_file =
+ OpenFromFd(fd, dex_file_offset_in_file, file, &error_msg);
+ if (art_dex_file == nullptr) {
+ return nullptr;
+ }
+
+ return std::unique_ptr<DexFileFromFile>(new DexFileFromFile(std::move(*art_dex_file.release())));
}
-bool DexFileFromMemory::Open(uint64_t dex_file_offset_in_memory, Memory* memory) {
- memory_.resize(sizeof(art::DexFile::Header));
- if (!memory->ReadFully(dex_file_offset_in_memory, memory_.data(), memory_.size())) {
- return false;
- }
+std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory,
+ Memory* memory,
+ const std::string& name) {
+ std::vector<uint8_t> backing_memory;
- art::DexFile::Header* header = reinterpret_cast<art::DexFile::Header*>(memory_.data());
- uint32_t file_size = header->file_size_;
- if (art::CompactDexFile::IsMagicValid(header->magic_)) {
- // Compact dex file store data section separately so that it can be shared.
- // Therefore we need to extend the read memory range to include it.
- // TODO: This might be wasteful as we might read data in between as well.
- // In practice, this should be fine, as such sharing only happens on disk.
- uint32_t computed_file_size;
- if (__builtin_add_overflow(header->data_off_, header->data_size_, &computed_file_size)) {
- return false;
+ for (size_t size = 0;;) {
+ std::string error_msg;
+ std::unique_ptr<art_api::dex::DexFile> art_dex_file =
+ OpenFromMemory(backing_memory.data(), &size, name, &error_msg);
+
+ if (art_dex_file != nullptr) {
+ return std::unique_ptr<DexFileFromMemory>(
+ new DexFileFromMemory(std::move(*art_dex_file.release()), std::move(backing_memory)));
}
- if (computed_file_size > file_size) {
- file_size = computed_file_size;
+
+ if (!error_msg.empty()) {
+ return nullptr;
}
- } else if (!art::StandardDexFile::IsMagicValid(header->magic_)) {
- return false;
+
+ backing_memory.resize(size);
+ if (!memory->ReadFully(dex_file_offset_in_memory, backing_memory.data(),
+ backing_memory.size())) {
+ return nullptr;
+ }
}
-
- memory_.resize(file_size);
- if (!memory->ReadFully(dex_file_offset_in_memory, memory_.data(), memory_.size())) {
- return false;
- }
-
- header = reinterpret_cast<art::DexFile::Header*>(memory_.data());
-
- art::DexFileLoader loader;
- std::string error_msg;
- auto dex =
- loader.Open(memory_.data(), header->file_size_, "", 0, nullptr, false, false, &error_msg);
- dex_file_.reset(dex.release());
- return dex_file_ != nullptr;
}
} // namespace unwindstack
diff --git a/libunwindstack/DexFile.h b/libunwindstack/DexFile.h
index c123158..ca658e6 100644
--- a/libunwindstack/DexFile.h
+++ b/libunwindstack/DexFile.h
@@ -25,48 +25,41 @@
#include <utility>
#include <vector>
-#include <dex/dex_file-inl.h>
+#include <art_api/dex_file_support.h>
namespace unwindstack {
-class DexFile {
+class DexFile : protected art_api::dex::DexFile {
public:
- DexFile() = default;
virtual ~DexFile() = default;
bool GetMethodInformation(uint64_t dex_offset, std::string* method_name, uint64_t* method_offset);
- static DexFile* Create(uint64_t dex_file_offset_in_memory, Memory* memory, MapInfo* info);
+ static std::unique_ptr<DexFile> Create(uint64_t dex_file_offset_in_memory, Memory* memory,
+ MapInfo* info);
protected:
- void Init();
-
- std::unique_ptr<const art::DexFile> dex_file_;
- std::map<uint32_t, std::pair<uint64_t, uint32_t>> method_cache_; // dex offset to method index.
-
- uint32_t class_def_index_ = 0;
+ DexFile(art_api::dex::DexFile&& art_dex_file) : art_api::dex::DexFile(std::move(art_dex_file)) {}
};
class DexFileFromFile : public DexFile {
public:
- DexFileFromFile() = default;
- virtual ~DexFileFromFile();
-
- bool Open(uint64_t dex_file_offset_in_file, const std::string& name);
+ static std::unique_ptr<DexFileFromFile> Create(uint64_t dex_file_offset_in_file,
+ const std::string& file);
private:
- void* mapped_memory_ = nullptr;
- size_t size_ = 0;
+ DexFileFromFile(art_api::dex::DexFile&& art_dex_file) : DexFile(std::move(art_dex_file)) {}
};
class DexFileFromMemory : public DexFile {
public:
- DexFileFromMemory() = default;
- virtual ~DexFileFromMemory() = default;
-
- bool Open(uint64_t dex_file_offset_in_memory, Memory* memory);
+ static std::unique_ptr<DexFileFromMemory> Create(uint64_t dex_file_offset_in_memory,
+ Memory* memory, const std::string& name);
private:
+ DexFileFromMemory(art_api::dex::DexFile&& art_dex_file, std::vector<uint8_t>&& memory)
+ : DexFile(std::move(art_dex_file)), memory_(std::move(memory)) {}
+
std::vector<uint8_t> memory_;
};
diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp
index 430f6c5..63a77e5 100644
--- a/libunwindstack/DexFiles.cpp
+++ b/libunwindstack/DexFiles.cpp
@@ -43,19 +43,15 @@
uint64_t dex_file;
};
-DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : memory_(memory) {}
+DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : Global(memory) {}
DexFiles::DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
- : memory_(memory), search_libs_(search_libs) {}
+ : Global(memory, search_libs) {}
-DexFiles::~DexFiles() {
- for (auto& entry : files_) {
- delete entry.second;
- }
-}
+DexFiles::~DexFiles() {}
-void DexFiles::SetArch(ArchEnum arch) {
- switch (arch) {
+void DexFiles::ProcessArch() {
+ switch (arch()) {
case ARCH_ARM:
case ARCH_MIPS:
case ARCH_X86:
@@ -117,6 +113,11 @@
return true;
}
+bool DexFiles::ReadVariableData(uint64_t ptr_offset) {
+ entry_addr_ = (this->*read_entry_ptr_func_)(ptr_offset);
+ return entry_addr_ != 0;
+}
+
void DexFiles::Init(Maps* maps) {
if (initialized_) {
return;
@@ -124,36 +125,7 @@
initialized_ = true;
entry_addr_ = 0;
- const std::string dex_debug_name("__dex_debug_descriptor");
- for (MapInfo* info : *maps) {
- if (!(info->flags & PROT_EXEC) || !(info->flags & PROT_READ) || info->offset != 0) {
- continue;
- }
-
- 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) {
- continue;
- }
- }
-
- Elf* elf = info->GetElf(memory_, true);
- uint64_t ptr;
- // Find first non-empty list (libart might be loaded multiple times).
- if (elf->GetGlobalVariable(dex_debug_name, &ptr) && ptr != 0) {
- entry_addr_ = (this->*read_entry_ptr_func_)(ptr + info->start);
- if (entry_addr_ != 0) {
- break;
- }
- }
- }
+ FindAndReadVariable(maps, "__dex_debug_descriptor");
}
DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) {
@@ -161,10 +133,11 @@
DexFile* dex_file;
auto entry = files_.find(dex_file_offset);
if (entry == files_.end()) {
- dex_file = DexFile::Create(dex_file_offset, memory_.get(), info);
- files_[dex_file_offset] = dex_file;
+ std::unique_ptr<DexFile> new_dex_file = DexFile::Create(dex_file_offset, memory_.get(), info);
+ dex_file = new_dex_file.get();
+ files_[dex_file_offset] = std::move(new_dex_file);
} else {
- dex_file = entry->second;
+ dex_file = entry->second.get();
}
return dex_file;
}
diff --git a/libunwindstack/DwarfCfa.cpp b/libunwindstack/DwarfCfa.cpp
index cd9ef61..c128b9b 100644
--- a/libunwindstack/DwarfCfa.cpp
+++ b/libunwindstack/DwarfCfa.cpp
@@ -21,6 +21,7 @@
#include <type_traits>
#include <vector>
+#include <android-base/macros.h>
#include <android-base/stringprintf.h>
#include <unwindstack/DwarfError.h>
@@ -154,13 +155,15 @@
break;
case DwarfCfaInfo::DWARF_DISPLAY_ADVANCE_LOC:
*cur_pc += value;
- // Fall through to log the value.
+ FALLTHROUGH_INTENDED;
+ // Fall through to log the value.
case DwarfCfaInfo::DWARF_DISPLAY_NUMBER:
string += " " + std::to_string(value);
break;
case DwarfCfaInfo::DWARF_DISPLAY_SET_LOC:
*cur_pc = value;
- // Fall through to log the value.
+ FALLTHROUGH_INTENDED;
+ // Fall through to log the value.
case DwarfCfaInfo::DWARF_DISPLAY_ADDRESS:
if (std::is_same<AddressType, uint32_t>::value) {
string += android::base::StringPrintf(" 0x%" PRIx32, static_cast<uint32_t>(value));
@@ -201,7 +204,7 @@
bool DwarfCfa<AddressType>::LogInstruction(uint32_t indent, uint64_t cfa_offset, uint8_t op,
uint64_t* cur_pc) {
const auto* cfa = &DwarfCfaInfo::kTable[op];
- if (cfa->name == nullptr) {
+ if (cfa->name[0] == '\0') {
log(indent, "Illegal");
log(indent, "Raw Data: 0x%02x", op);
return true;
@@ -257,7 +260,7 @@
}
// Log any of the expression data.
- for (const auto line : expression_lines) {
+ for (const auto& line : expression_lines) {
log(indent + 1, "%s", line.c_str());
}
return true;
@@ -674,29 +677,29 @@
{DW_EH_PE_uleb128, DW_EH_PE_block},
{DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_EVAL_BLOCK},
},
- {nullptr, 0, 0, {}, {}}, // 0x17 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x18 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x19 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x1a illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x1b illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x1c DW_CFA_lo_user (Treat as illegal)
- {nullptr, 0, 0, {}, {}}, // 0x1d illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x1e illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x1f illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x20 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x21 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x22 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x23 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x24 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x25 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x26 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x27 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x28 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x29 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x2a illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x2b illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x2c illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x2d DW_CFA_GNU_window_save (Treat as illegal)
+ {"", 0, 0, {}, {}}, // 0x17 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x18 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x19 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x1a illegal cfa
+ {"", 0, 0, {}, {}}, // 0x1b illegal cfa
+ {"", 0, 0, {}, {}}, // 0x1c DW_CFA_lo_user (Treat as illegal)
+ {"", 0, 0, {}, {}}, // 0x1d illegal cfa
+ {"", 0, 0, {}, {}}, // 0x1e illegal cfa
+ {"", 0, 0, {}, {}}, // 0x1f illegal cfa
+ {"", 0, 0, {}, {}}, // 0x20 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x21 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x22 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x23 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x24 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x25 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x26 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x27 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x28 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x29 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x2a illegal cfa
+ {"", 0, 0, {}, {}}, // 0x2b illegal cfa
+ {"", 0, 0, {}, {}}, // 0x2c illegal cfa
+ {"", 0, 0, {}, {}}, // 0x2d DW_CFA_GNU_window_save (Treat as illegal)
{
"DW_CFA_GNU_args_size", // 0x2e DW_CFA_GNU_args_size
2,
@@ -711,21 +714,21 @@
{DW_EH_PE_uleb128, DW_EH_PE_uleb128},
{DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER},
},
- {nullptr, 0, 0, {}, {}}, // 0x31 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x32 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x33 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x34 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x35 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x36 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x37 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x38 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x39 illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x3a illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x3b illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x3c illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x3d illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x3e illegal cfa
- {nullptr, 0, 0, {}, {}}, // 0x3f DW_CFA_hi_user (Treat as illegal)
+ {"", 0, 0, {}, {}}, // 0x31 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x32 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x33 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x34 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x35 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x36 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x37 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x38 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x39 illegal cfa
+ {"", 0, 0, {}, {}}, // 0x3a illegal cfa
+ {"", 0, 0, {}, {}}, // 0x3b illegal cfa
+ {"", 0, 0, {}, {}}, // 0x3c illegal cfa
+ {"", 0, 0, {}, {}}, // 0x3d illegal cfa
+ {"", 0, 0, {}, {}}, // 0x3e illegal cfa
+ {"", 0, 0, {}, {}}, // 0x3f DW_CFA_hi_user (Treat as illegal)
};
// Explicitly instantiate DwarfCfa.
diff --git a/libunwindstack/DwarfCfa.h b/libunwindstack/DwarfCfa.h
index c5ffb8e..569c17c 100644
--- a/libunwindstack/DwarfCfa.h
+++ b/libunwindstack/DwarfCfa.h
@@ -49,7 +49,14 @@
};
struct Info {
- const char* name;
+ // It may seem cleaner to just change the type of 'name' to 'const char *'.
+ // However, having a pointer here would require relocation at runtime,
+ // causing 'kTable' to be placed in data.rel.ro section instead of rodata
+ // section, adding memory pressure to the system. Note that this is only
+ // safe because this is only used in C++ code. C++ standard, unlike C
+ // standard, mandates the array size to be large enough to hold the NULL
+ // terminator when initialized with a string literal.
+ const char name[36];
uint8_t supported_version;
uint8_t num_operands;
uint8_t operands[2];
diff --git a/libunwindstack/DwarfMemory.cpp b/libunwindstack/DwarfMemory.cpp
index 6ffdc0d..b505900 100644
--- a/libunwindstack/DwarfMemory.cpp
+++ b/libunwindstack/DwarfMemory.cpp
@@ -104,7 +104,6 @@
bool DwarfMemory::AdjustEncodedValue(uint8_t encoding, uint64_t* value) {
CHECK((encoding & 0x0f) == 0);
- CHECK(encoding != DW_EH_PE_aligned);
// Handle the encoding.
switch (encoding) {
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 6061f61..57a780e 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -461,6 +461,7 @@
if (reg == eval_info->cie->return_address_register) {
eval_info->return_address_undefined = true;
}
+ break;
default:
break;
}
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index 4723606..2f5eed9 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -40,7 +40,7 @@
std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>* Elf::cache_;
std::mutex* Elf::cache_lock_;
-bool Elf::Init(bool init_gnu_debugdata) {
+bool Elf::Init() {
load_bias_ = 0;
if (!memory_) {
return false;
@@ -54,11 +54,7 @@
valid_ = interface_->Init(&load_bias_);
if (valid_) {
interface_->InitHeaders(load_bias_);
- if (init_gnu_debugdata) {
- InitGnuDebugdata();
- } else {
- gnu_debugdata_interface_.reset(nullptr);
- }
+ InitGnuDebugdata();
} else {
interface_.reset(nullptr);
}
@@ -92,6 +88,11 @@
}
}
+void Elf::Invalidate() {
+ interface_.reset(nullptr);
+ valid_ = false;
+}
+
bool Elf::GetSoname(std::string* name) {
std::lock_guard<std::mutex> guard(lock_);
return valid_ && interface_->GetSoname(name);
@@ -139,6 +140,13 @@
return true;
}
+std::string Elf::GetBuildID() {
+ if (!valid_) {
+ return "";
+ }
+ return interface_->GetBuildID();
+}
+
void Elf::GetLastError(ErrorData* data) {
if (valid_) {
*data = interface_->last_error();
@@ -194,26 +202,26 @@
return true;
}
-void Elf::GetInfo(Memory* memory, bool* valid, uint64_t* size) {
+bool Elf::GetInfo(Memory* memory, uint64_t* size) {
if (!IsValidElf(memory)) {
- *valid = false;
- return;
+ return false;
}
*size = 0;
- *valid = true;
- // Now read the section header information.
uint8_t class_type;
if (!memory->ReadFully(EI_CLASS, &class_type, 1)) {
- return;
+ return false;
}
+
+ // Get the maximum size of the elf data from the header.
if (class_type == ELFCLASS32) {
ElfInterface32::GetMaxSize(memory, size);
} else if (class_type == ELFCLASS64) {
ElfInterface64::GetMaxSize(memory, size);
} else {
- *valid = false;
+ return false;
}
+ return true;
}
bool Elf::IsValidPc(uint64_t pc) {
@@ -379,4 +387,22 @@
return false;
}
+std::string Elf::GetBuildID(Memory* memory) {
+ if (!IsValidElf(memory)) {
+ return "";
+ }
+
+ uint8_t class_type;
+ if (!memory->Read(EI_CLASS, &class_type, 1)) {
+ return "";
+ }
+
+ if (class_type == ELFCLASS32) {
+ return ElfInterface::ReadBuildIDFromMemory<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr>(memory);
+ } else if (class_type == ELFCLASS64) {
+ return ElfInterface::ReadBuildIDFromMemory<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr>(memory);
+ }
+ return "";
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index f59a472..c1b98d9 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -177,14 +177,14 @@
template <typename EhdrType, typename PhdrType>
uint64_t ElfInterface::GetLoadBias(Memory* memory) {
EhdrType ehdr;
- if (!memory->Read(0, &ehdr, sizeof(ehdr))) {
+ if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
return false;
}
uint64_t offset = ehdr.e_phoff;
for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
PhdrType phdr;
- if (!memory->Read(offset, &phdr, sizeof(phdr))) {
+ if (!memory->ReadFully(offset, &phdr, sizeof(phdr))) {
return 0;
}
if (phdr.p_type == PT_LOAD && phdr.p_offset == 0) {
@@ -237,6 +237,58 @@
}
}
+template <typename NhdrType>
+std::string ElfInterface::ReadBuildID() {
+ // Ensure there is no overflow in any of the calulations below.
+ uint64_t tmp;
+ if (__builtin_add_overflow(gnu_build_id_offset_, gnu_build_id_size_, &tmp)) {
+ return "";
+ }
+
+ uint64_t offset = 0;
+ while (offset < gnu_build_id_size_) {
+ if (gnu_build_id_size_ - offset < sizeof(NhdrType)) {
+ return "";
+ }
+ NhdrType hdr;
+ if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &hdr, sizeof(hdr))) {
+ return "";
+ }
+ offset += sizeof(hdr);
+
+ if (gnu_build_id_size_ - offset < hdr.n_namesz) {
+ return "";
+ }
+ if (hdr.n_namesz > 0) {
+ std::string name(hdr.n_namesz, '\0');
+ if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &(name[0]), hdr.n_namesz)) {
+ return "";
+ }
+
+ // Trim trailing \0 as GNU is stored as a C string in the ELF file.
+ if (name.back() == '\0')
+ name.resize(name.size() - 1);
+
+ // Align hdr.n_namesz to next power multiple of 4. See man 5 elf.
+ offset += (hdr.n_namesz + 3) & ~3;
+
+ if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) {
+ if (gnu_build_id_size_ - offset < hdr.n_descsz || hdr.n_descsz == 0) {
+ return "";
+ }
+ std::string build_id(hdr.n_descsz - 1, '\0');
+ if (memory_->ReadFully(gnu_build_id_offset_ + offset, &build_id[0], hdr.n_descsz)) {
+ return build_id;
+ }
+ return "";
+ }
+ }
+ // Align hdr.n_descsz to next power multiple of 4. See man 5 elf.
+ offset += (hdr.n_descsz + 3) & ~3;
+ }
+ return "";
+}
+
template <typename EhdrType, typename ShdrType>
void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
uint64_t offset = ehdr.e_shoff;
@@ -258,7 +310,7 @@
// Skip the first header, it's always going to be NULL.
offset += ehdr.e_shentsize;
for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
- if (!memory_->Read(offset, &shdr, sizeof(shdr))) {
+ if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) {
return;
}
@@ -270,7 +322,7 @@
continue;
}
uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
- if (!memory_->Read(str_offset, &str_shdr, sizeof(str_shdr))) {
+ if (!memory_->ReadFully(str_offset, &str_shdr, sizeof(str_shdr))) {
continue;
}
if (str_shdr.sh_type != SHT_STRTAB) {
@@ -308,6 +360,15 @@
// In order to read soname, keep track of address to offset mapping.
strtabs_.push_back(std::make_pair<uint64_t, uint64_t>(static_cast<uint64_t>(shdr.sh_addr),
static_cast<uint64_t>(shdr.sh_offset)));
+ } else if (shdr.sh_type == SHT_NOTE) {
+ if (shdr.sh_name < sec_size) {
+ std::string name;
+ if (memory_->ReadString(sec_offset + shdr.sh_name, &name) &&
+ name == ".note.gnu.build-id") {
+ gnu_build_id_offset_ = shdr.sh_offset;
+ gnu_build_id_size_ = shdr.sh_size;
+ }
+ }
}
}
}
@@ -477,6 +538,103 @@
*size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum;
}
+template <typename EhdrType, typename ShdrType>
+bool GetBuildIDInfo(Memory* memory, uint64_t* build_id_offset, uint64_t* build_id_size) {
+ EhdrType ehdr;
+ if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
+ return false;
+ }
+
+ uint64_t offset = ehdr.e_shoff;
+ uint64_t sec_offset;
+ uint64_t sec_size;
+ ShdrType shdr;
+ if (ehdr.e_shstrndx >= ehdr.e_shnum) {
+ return false;
+ }
+
+ uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize;
+ if (!memory->ReadFully(sh_offset, &shdr, sizeof(shdr))) {
+ return false;
+ }
+ sec_offset = shdr.sh_offset;
+ sec_size = shdr.sh_size;
+
+ // Skip the first header, it's always going to be NULL.
+ offset += ehdr.e_shentsize;
+ for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
+ if (!memory->ReadFully(offset, &shdr, sizeof(shdr))) {
+ return false;
+ }
+ std::string name;
+ if (shdr.sh_type == SHT_NOTE && shdr.sh_name < sec_size &&
+ memory->ReadString(sec_offset + shdr.sh_name, &name) && name == ".note.gnu.build-id") {
+ *build_id_offset = shdr.sh_offset;
+ *build_id_size = shdr.sh_size;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+template <typename EhdrType, typename ShdrType, typename NhdrType>
+std::string ElfInterface::ReadBuildIDFromMemory(Memory* memory) {
+ uint64_t note_offset;
+ uint64_t note_size;
+ if (!GetBuildIDInfo<EhdrType, ShdrType>(memory, ¬e_offset, ¬e_size)) {
+ return "";
+ }
+
+ // Ensure there is no overflow in any of the calculations below.
+ uint64_t tmp;
+ if (__builtin_add_overflow(note_offset, note_size, &tmp)) {
+ return "";
+ }
+
+ uint64_t offset = 0;
+ while (offset < note_size) {
+ if (note_size - offset < sizeof(NhdrType)) {
+ return "";
+ }
+ NhdrType hdr;
+ if (!memory->ReadFully(note_offset + offset, &hdr, sizeof(hdr))) {
+ return "";
+ }
+ offset += sizeof(hdr);
+
+ if (note_size - offset < hdr.n_namesz) {
+ return "";
+ }
+ if (hdr.n_namesz > 0) {
+ std::string name(hdr.n_namesz, '\0');
+ if (!memory->ReadFully(note_offset + offset, &(name[0]), hdr.n_namesz)) {
+ return "";
+ }
+
+ // Trim trailing \0 as GNU is stored as a C string in the ELF file.
+ if (name.back() == '\0') name.resize(name.size() - 1);
+
+ // Align hdr.n_namesz to next power multiple of 4. See man 5 elf.
+ offset += (hdr.n_namesz + 3) & ~3;
+
+ if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) {
+ if (note_size - offset < hdr.n_descsz || hdr.n_descsz == 0) {
+ return "";
+ }
+ std::string build_id(hdr.n_descsz - 1, '\0');
+ if (memory->ReadFully(note_offset + offset, &build_id[0], hdr.n_descsz)) {
+ return build_id;
+ }
+ return "";
+ }
+ }
+ // Align hdr.n_descsz to next power multiple of 4. See man 5 elf.
+ offset += (hdr.n_descsz + 3) & ~3;
+ }
+ return "";
+}
+
// Instantiate all of the needed template functions.
template void ElfInterface::InitHeadersWithTemplate<uint32_t>(uint64_t);
template void ElfInterface::InitHeadersWithTemplate<uint64_t>(uint64_t);
@@ -492,6 +650,9 @@
template void ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
template void ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);
+template std::string ElfInterface::ReadBuildID<Elf32_Nhdr>();
+template std::string ElfInterface::ReadBuildID<Elf64_Nhdr>();
+
template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*);
template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*);
@@ -509,4 +670,9 @@
template uint64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
template uint64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
+template std::string ElfInterface::ReadBuildIDFromMemory<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr>(
+ Memory*);
+template std::string ElfInterface::ReadBuildIDFromMemory<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr>(
+ Memory*);
+
} // namespace unwindstack
diff --git a/libunwindstack/Global.cpp b/libunwindstack/Global.cpp
new file mode 100644
index 0000000..fdfd705
--- /dev/null
+++ b/libunwindstack/Global.cpp
@@ -0,0 +1,104 @@
+/*
+ * 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 <stdint.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <string>
+#include <vector>
+
+#include <unwindstack/Global.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
+
+namespace unwindstack {
+
+Global::Global(std::shared_ptr<Memory>& memory) : memory_(memory) {}
+Global::Global(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
+ : memory_(memory), search_libs_(search_libs) {}
+
+void Global::SetArch(ArchEnum arch) {
+ if (arch_ == ARCH_UNKNOWN) {
+ arch_ = arch;
+ ProcessArch();
+ }
+}
+
+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;
+ }
+ }
+
+ 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;
+ }
+ return 0;
+}
+
+void Global::FindAndReadVariable(Maps* maps, const char* var_str) {
+ std::string variable(var_str);
+ // When looking for global variables, do not arbitrarily search every
+ // readable map. Instead look for a specific pattern that must exist.
+ // The pattern should be a readable map, followed by a read-write
+ // map with a non-zero offset.
+ // For example:
+ // f0000-f1000 0 r-- /system/lib/libc.so
+ // f1000-f2000 1000 r-x /system/lib/libc.so
+ // f2000-f3000 2000 rw- /system/lib/libc.so
+ // This also works:
+ // f0000-f2000 0 r-- /system/lib/libc.so
+ // f2000-f3000 2000 rw- /system/lib/libc.so
+ MapInfo* map_start = nullptr;
+ for (MapInfo* 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;
+ }
+ }
+ } else {
+ map_start = nullptr;
+ }
+ }
+ if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 &&
+ !info->name.empty()) {
+ map_start = info;
+ }
+ }
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/JitDebug.cpp b/libunwindstack/JitDebug.cpp
index 0c319ec..20bc4b9 100644
--- a/libunwindstack/JitDebug.cpp
+++ b/libunwindstack/JitDebug.cpp
@@ -69,10 +69,10 @@
uint64_t first_entry;
};
-JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : memory_(memory) {}
+JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : Global(memory) {}
JitDebug::JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
- : memory_(memory), search_libs_(search_libs) {}
+ : Global(memory, search_libs) {}
JitDebug::~JitDebug() {
for (auto* elf : elf_list_) {
@@ -141,8 +141,8 @@
return code.next;
}
-void JitDebug::SetArch(ArchEnum arch) {
- switch (arch) {
+void JitDebug::ProcessArch() {
+ switch (arch()) {
case ARCH_X86:
read_descriptor_func_ = &JitDebug::ReadDescriptor32;
read_entry_func_ = &JitDebug::ReadEntry32Pack;
@@ -165,6 +165,11 @@
}
}
+bool JitDebug::ReadVariableData(uint64_t ptr) {
+ entry_addr_ = (this->*read_descriptor_func_)(ptr);
+ return entry_addr_ != 0;
+}
+
void JitDebug::Init(Maps* maps) {
if (initialized_) {
return;
@@ -172,37 +177,7 @@
// Regardless of what happens below, consider the init finished.
initialized_ = true;
- const std::string descriptor_name("__jit_debug_descriptor");
- for (MapInfo* info : *maps) {
- if (!(info->flags & PROT_EXEC) || !(info->flags & PROT_READ) || info->offset != 0) {
- continue;
- }
-
- if (!search_libs_.empty()) {
- bool found = false;
- const char* lib = basename(info->name.c_str());
- for (std::string& name : search_libs_) {
- if (strcmp(name.c_str(), lib) == 0) {
- found = true;
- break;
- }
- }
- if (!found) {
- continue;
- }
- }
-
- Elf* elf = info->GetElf(memory_, true);
- uint64_t descriptor_addr;
- if (elf->GetGlobalVariable(descriptor_name, &descriptor_addr)) {
- // Search for the first non-zero entry.
- descriptor_addr += info->start;
- entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr);
- if (entry_addr_ != 0) {
- break;
- }
- }
- }
+ FindAndReadVariable(maps, "__jit_debug_descriptor");
}
Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) {
@@ -226,7 +201,7 @@
entry_addr_ = (this->*read_entry_func_)(&start, &size);
Elf* elf = new Elf(new MemoryRange(memory_, start, size, 0));
- elf->Init(true);
+ elf->Init();
if (!elf->valid()) {
// The data is not formatted in a way we understand, do not attempt
// to process any other entries.
diff --git a/libunwindstack/LocalUnwinder.cpp b/libunwindstack/LocalUnwinder.cpp
index 952b332..5b2fadf 100644
--- a/libunwindstack/LocalUnwinder.cpp
+++ b/libunwindstack/LocalUnwinder.cpp
@@ -88,6 +88,7 @@
bool LocalUnwinder::Unwind(std::vector<LocalFrameData>* frame_info, size_t max_frames) {
std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
unwindstack::RegsGetLocal(regs.get());
+ ArchEnum arch = regs->Arch();
size_t num_frames = 0;
bool adjust_pc = false;
@@ -100,7 +101,7 @@
break;
}
- Elf* elf = map_info->GetElf(process_memory_, true);
+ Elf* elf = map_info->GetElf(process_memory_, arch);
uint64_t rel_pc = elf->GetRelPc(cur_pc, map_info);
uint64_t step_pc = rel_pc;
uint64_t pc_adjustment;
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 39378a3..f319971 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -29,6 +29,32 @@
namespace unwindstack {
+bool MapInfo::InitFileMemoryFromPreviousReadOnlyMap(MemoryFileAtOffset* memory) {
+ // One last attempt, see if the previous map is read-only with the
+ // same name and stretches across this map.
+ if (prev_map == nullptr || prev_map->flags != PROT_READ) {
+ return false;
+ }
+
+ uint64_t map_size = end - prev_map->end;
+ if (!memory->Init(name, prev_map->offset, map_size)) {
+ return false;
+ }
+
+ uint64_t max_size;
+ if (!Elf::GetInfo(memory, &max_size) || max_size < map_size) {
+ return false;
+ }
+
+ if (!memory->Init(name, prev_map->offset, max_size)) {
+ return false;
+ }
+
+ elf_offset = offset - prev_map->offset;
+ elf_start_offset = prev_map->offset;
+ return true;
+}
+
Memory* MapInfo::GetFileMemory() {
std::unique_ptr<MemoryFileAtOffset> memory(new MemoryFileAtOffset);
if (offset == 0) {
@@ -38,8 +64,12 @@
return nullptr;
}
- // There are two possibilities when the offset is non-zero.
- // - There is an elf file embedded in a file.
+ // These are the possibilities when the offset is non-zero.
+ // - There is an elf file embedded in a file, and the offset is the
+ // the start of the elf in the file.
+ // - There is an elf file embedded in a file, and the offset is the
+ // the start of the executable part of the file. The actual start
+ // of the elf is in the read-only segment preceeding this map.
// - The whole file is an elf file, and the offset needs to be saved.
//
// Map in just the part of the file for the map. If this is not
@@ -53,29 +83,47 @@
return nullptr;
}
- bool valid;
- uint64_t max_size;
- Elf::GetInfo(memory.get(), &valid, &max_size);
- if (!valid) {
- // Init as if the whole file is an elf.
- if (memory->Init(name, 0)) {
- elf_offset = offset;
- return memory.release();
+ // Check if the start of this map is an embedded elf.
+ uint64_t max_size = 0;
+ if (Elf::GetInfo(memory.get(), &max_size)) {
+ if (max_size > map_size) {
+ if (memory->Init(name, offset, max_size)) {
+ return memory.release();
+ }
+ // Try to reinit using the default map_size.
+ if (memory->Init(name, offset, map_size)) {
+ return memory.release();
+ }
+ return nullptr;
}
- return nullptr;
+ return memory.release();
}
- if (max_size > map_size) {
- if (memory->Init(name, offset, max_size)) {
- return memory.release();
+ // No elf at offset, try to init as if the whole file is an elf.
+ if (memory->Init(name, 0) && Elf::IsValidElf(memory.get())) {
+ elf_offset = offset;
+ // Need to check how to set the elf start offset. If this map is not
+ // the r-x map of a r-- map, then use the real offset value. Otherwise,
+ // use 0.
+ if (prev_map == nullptr || prev_map->offset != 0 || prev_map->flags != PROT_READ ||
+ prev_map->name != name) {
+ elf_start_offset = offset;
}
- // Try to reinit using the default map_size.
- if (memory->Init(name, offset, map_size)) {
- return memory.release();
- }
- return nullptr;
+ return memory.release();
}
- return memory.release();
+
+ // See if the map previous to this one contains a read-only map
+ // that represents the real start of the elf data.
+ if (InitFileMemoryFromPreviousReadOnlyMap(memory.get())) {
+ return memory.release();
+ }
+
+ // Failed to find elf at start of file or at read-only map, return
+ // file object from the current map.
+ if (memory->Init(name, offset, map_size)) {
+ return memory.release();
+ }
+ return nullptr;
}
Memory* MapInfo::CreateMemory(const std::shared_ptr<Memory>& process_memory) {
@@ -98,14 +146,44 @@
}
}
- // If the map isn't readable, don't bother trying to read from process memory.
- if (!(flags & PROT_READ)) {
+ if (process_memory == nullptr) {
return nullptr;
}
- return new MemoryRange(process_memory, start, end - start, 0);
+
+ // Need to verify that this elf is valid. It's possible that
+ // only part of the elf file to be mapped into memory is in the executable
+ // map. In this case, there will be another read-only map that includes the
+ // first part of the elf file. This is done if the linker rosegment
+ // option is used.
+ std::unique_ptr<MemoryRange> memory(new MemoryRange(process_memory, start, end - start, 0));
+ if (Elf::IsValidElf(memory.get())) {
+ return memory.release();
+ }
+
+ // Find the read-only map by looking at the previous map. The linker
+ // doesn't guarantee that this invariant will always be true. However,
+ // if that changes, there is likely something else that will change and
+ // break something.
+ if (offset == 0 || name.empty() || prev_map == nullptr || prev_map->name != name ||
+ prev_map->offset >= offset) {
+ return nullptr;
+ }
+
+ // Make sure that relative pc values are corrected properly.
+ elf_offset = offset - prev_map->offset;
+ // Use this as the elf start offset, otherwise, you always get offsets into
+ // the r-x section, which is not quite the right information.
+ elf_start_offset = prev_map->offset;
+
+ MemoryRanges* ranges = new MemoryRanges;
+ ranges->Insert(
+ new MemoryRange(process_memory, prev_map->start, prev_map->end - prev_map->start, 0));
+ ranges->Insert(new MemoryRange(process_memory, start, end - start, elf_offset));
+
+ return ranges;
}
-Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata) {
+Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch) {
// Make sure no other thread is trying to add the elf to this map.
std::lock_guard<std::mutex> guard(mutex_);
@@ -134,7 +212,11 @@
elf.reset(new Elf(memory));
// If the init fails, keep the elf around as an invalid object so we
// don't try to reinit the object.
- elf->Init(init_gnu_debugdata);
+ elf->Init();
+ if (elf->valid() && expected_arch != elf->arch()) {
+ // Make the elf invalid, mismatch between arch and expected arch.
+ elf->Invalidate();
+ }
if (locked) {
Elf::CacheAdd(this);
@@ -143,6 +225,19 @@
return elf.get();
}
+bool MapInfo::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) {
+ {
+ // Make sure no other thread is trying to update this elf object.
+ std::lock_guard<std::mutex> guard(mutex_);
+ if (elf == nullptr) {
+ return false;
+ }
+ }
+ // No longer need the lock, once the elf object is created, it is not deleted
+ // until this object is deleted.
+ return elf->GetFunctionName(addr, name, func_offset);
+}
+
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)) {
@@ -172,4 +267,48 @@
return cur_load_bias;
}
+MapInfo::~MapInfo() {
+ uintptr_t id = build_id.load();
+ if (id != 0) {
+ delete reinterpret_cast<std::string*>(id);
+ }
+}
+
+std::string MapInfo::GetBuildID() {
+ uintptr_t id = build_id.load();
+ if (build_id != 0) {
+ return *reinterpret_cast<std::string*>(id);
+ }
+
+ // No need to lock, at worst if multiple threads do this at the same
+ // time it should be detected and only one thread should win and
+ // save the data.
+ std::unique_ptr<std::string> cur_build_id(new std::string);
+
+ // Now need to see if the elf object exists.
+ // Make sure no other thread is trying to add the elf to this map.
+ mutex_.lock();
+ Elf* elf_obj = elf.get();
+ mutex_.unlock();
+ if (elf_obj != nullptr) {
+ *cur_build_id = elf_obj->GetBuildID();
+ } else {
+ // This will only work if we can get the file associated with this memory.
+ // If this is only available in memory, then the section name information
+ // is not present and we will not be able to find the build id info.
+ std::unique_ptr<Memory> memory(GetFileMemory());
+ if (memory != nullptr) {
+ *cur_build_id = Elf::GetBuildID(memory.get());
+ }
+ }
+
+ id = reinterpret_cast<uintptr_t>(cur_build_id.get());
+ uintptr_t expected_id = 0;
+ if (build_id.compare_exchange_weak(expected_id, id)) {
+ // Value saved, so make sure the memory is not freed.
+ cur_build_id.release();
+ }
+ return *reinterpret_cast<std::string*>(id);
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp
index e676a5a..c90e383 100644
--- a/libunwindstack/Maps.cpp
+++ b/libunwindstack/Maps.cpp
@@ -19,6 +19,7 @@
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
+#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
@@ -66,13 +67,15 @@
if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
}
- maps_.push_back(new MapInfo(start, end, pgoff, flags, name));
+ maps_.push_back(
+ new MapInfo(maps_.empty() ? nullptr : maps_.back(), start, end, pgoff, flags, name));
});
}
void Maps::Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
const std::string& name, uint64_t load_bias) {
- MapInfo* map_info = new MapInfo(start, end, offset, flags, name);
+ MapInfo* map_info =
+ new MapInfo(maps_.empty() ? nullptr : maps_.back(), start, end, offset, flags, name);
map_info->load_bias = load_bias;
maps_.push_back(map_info);
}
@@ -80,6 +83,13 @@
void Maps::Sort() {
std::sort(maps_.begin(), maps_.end(),
[](const MapInfo* a, const MapInfo* b) { return a->start < b->start; });
+
+ // Set the prev_map values on the info objects.
+ MapInfo* prev_map = nullptr;
+ for (MapInfo* map_info : maps_) {
+ map_info->prev_map = prev_map;
+ prev_map = map_info;
+ }
}
Maps::~Maps() {
@@ -97,7 +107,8 @@
if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
}
- maps_.push_back(new MapInfo(start, end, pgoff, flags, name));
+ maps_.push_back(
+ new MapInfo(maps_.empty() ? nullptr : maps_.back(), start, end, pgoff, flags, name));
});
}
diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp
index beb2aad..9904fef 100644
--- a/libunwindstack/Memory.cpp
+++ b/libunwindstack/Memory.cpp
@@ -16,6 +16,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <string.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/stat.h>
@@ -174,6 +175,13 @@
return std::shared_ptr<Memory>(new MemoryRemote(pid));
}
+std::shared_ptr<Memory> Memory::CreateProcessMemoryCached(pid_t pid) {
+ if (pid == getpid()) {
+ return std::shared_ptr<Memory>(new MemoryCache(new MemoryLocal()));
+ }
+ return std::shared_ptr<Memory>(new MemoryCache(new MemoryRemote(pid)));
+}
+
size_t MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) {
if (addr >= raw_.size()) {
return 0;
@@ -316,6 +324,18 @@
return memory_->Read(read_addr, dst, read_length);
}
+void MemoryRanges::Insert(MemoryRange* memory) {
+ maps_.emplace(memory->offset() + memory->length(), memory);
+}
+
+size_t MemoryRanges::Read(uint64_t addr, void* dst, size_t size) {
+ auto entry = maps_.upper_bound(addr);
+ if (entry != maps_.end()) {
+ return entry->second->Read(addr, dst, size);
+ }
+ return 0;
+}
+
bool MemoryOffline::Init(const std::string& file, uint64_t offset) {
auto memory_file = std::make_shared<MemoryFileAtOffset>();
if (!memory_file->Init(file, offset)) {
@@ -386,4 +406,50 @@
return 0;
}
+size_t MemoryCache::Read(uint64_t addr, void* dst, size_t size) {
+ // Only bother caching and looking at the cache if this is a small read for now.
+ if (size > 64) {
+ return impl_->Read(addr, dst, size);
+ }
+
+ uint64_t addr_page = addr >> kCacheBits;
+ auto entry = cache_.find(addr_page);
+ uint8_t* cache_dst;
+ if (entry != cache_.end()) {
+ cache_dst = entry->second;
+ } else {
+ cache_dst = cache_[addr_page];
+ if (!impl_->ReadFully(addr_page << kCacheBits, cache_dst, kCacheSize)) {
+ // Erase the entry.
+ cache_.erase(addr_page);
+ return impl_->Read(addr, dst, size);
+ }
+ }
+ size_t max_read = ((addr_page + 1) << kCacheBits) - addr;
+ if (size <= max_read) {
+ memcpy(dst, &cache_dst[addr & kCacheMask], size);
+ return size;
+ }
+
+ // The read crossed into another cached entry, since a read can only cross
+ // into one extra cached page, duplicate the code rather than looping.
+ memcpy(dst, &cache_dst[addr & kCacheMask], max_read);
+ dst = &reinterpret_cast<uint8_t*>(dst)[max_read];
+ addr_page++;
+
+ entry = cache_.find(addr_page);
+ if (entry != cache_.end()) {
+ cache_dst = entry->second;
+ } else {
+ cache_dst = cache_[addr_page];
+ if (!impl_->ReadFully(addr_page << kCacheBits, cache_dst, kCacheSize)) {
+ // Erase the entry.
+ cache_.erase(addr_page);
+ return impl_->Read(addr_page << kCacheBits, dst, size - max_read) + max_read;
+ }
+ }
+ memcpy(dst, cache_dst, size - max_read);
+ return size;
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp
index de22bde..885dc94 100644
--- a/libunwindstack/RegsArm.cpp
+++ b/libunwindstack/RegsArm.cpp
@@ -15,6 +15,7 @@
*/
#include <stdint.h>
+#include <string.h>
#include <functional>
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index a68f6e0..e9787aa 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -15,6 +15,7 @@
*/
#include <stdint.h>
+#include <string.h>
#include <functional>
diff --git a/libunwindstack/RegsInfo.h b/libunwindstack/RegsInfo.h
index e6dd33c..e445a91 100644
--- a/libunwindstack/RegsInfo.h
+++ b/libunwindstack/RegsInfo.h
@@ -41,7 +41,7 @@
}
inline AddressType* Save(uint32_t reg) {
- if (reg > MAX_REGISTERS) {
+ if (reg >= MAX_REGISTERS) {
// This should never happen since all currently supported
// architectures have < 64 total registers.
abort();
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
index 2e6908c..f330fe0 100644
--- a/libunwindstack/RegsMips.cpp
+++ b/libunwindstack/RegsMips.cpp
@@ -15,6 +15,7 @@
*/
#include <stdint.h>
+#include <string.h>
#include <functional>
@@ -134,7 +135,7 @@
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->ReadFully(rel_pc, &data, sizeof(data))) {
return false;
}
@@ -159,7 +160,7 @@
// read sc_pc and sc_regs[32] from stack
uint64_t values[MIPS_REG_LAST];
- if (!process_memory->Read(regs_[MIPS_REG_SP] + offset, values, sizeof(values))) {
+ if (!process_memory->ReadFully(regs_[MIPS_REG_SP] + offset, values, sizeof(values))) {
return false;
}
diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp
index 0b835a1..3f67d92 100644
--- a/libunwindstack/RegsMips64.cpp
+++ b/libunwindstack/RegsMips64.cpp
@@ -15,6 +15,7 @@
*/
#include <stdint.h>
+#include <string.h>
#include <functional>
diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp
index ebad3f4..74cd1cb 100644
--- a/libunwindstack/RegsX86_64.cpp
+++ b/libunwindstack/RegsX86_64.cpp
@@ -15,6 +15,7 @@
*/
#include <stdint.h>
+#include <string.h>
#include <functional>
diff --git a/libunwindstack/Symbols.cpp b/libunwindstack/Symbols.cpp
index 14ebdbb..e3c15a2 100644
--- a/libunwindstack/Symbols.cpp
+++ b/libunwindstack/Symbols.cpp
@@ -17,6 +17,7 @@
#include <elf.h>
#include <stdint.h>
+#include <algorithm>
#include <string>
#include <unwindstack/Memory.h>
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 099cc9e..0dd95cf 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -26,10 +26,13 @@
#include <android-base/stringprintf.h>
+#include <demangle.h>
+
#include <unwindstack/Elf.h>
#include <unwindstack/JitDebug.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
#include <unwindstack/Unwinder.h>
#if !defined(NO_LIBDEXFILE_SUPPORT)
@@ -59,7 +62,8 @@
if (info != nullptr) {
frame->map_start = info->start;
frame->map_end = info->end;
- frame->map_offset = info->offset;
+ frame->map_elf_start_offset = info->elf_start_offset;
+ frame->map_exact_offset = info->offset;
frame->map_load_bias = info->load_bias;
frame->map_flags = info->flags;
if (resolve_names_) {
@@ -102,7 +106,8 @@
if (resolve_names_) {
frame->map_name = map_info->name;
}
- frame->map_offset = map_info->offset;
+ frame->map_elf_start_offset = map_info->elf_start_offset;
+ frame->map_exact_offset = map_info->offset;
frame->map_start = map_info->start;
frame->map_end = map_info->end;
frame->map_flags = map_info->flags;
@@ -135,9 +140,10 @@
last_error_.code = ERROR_NONE;
last_error_.address = 0;
+ ArchEnum arch = regs_->Arch();
+
bool return_address_attempt = false;
bool adjust_pc = false;
- std::unique_ptr<JitDebug> jit_debug;
for (; frames_.size() < max_frames_;) {
uint64_t cur_pc = regs_->pc();
uint64_t cur_sp = regs_->sp();
@@ -155,7 +161,7 @@
if (ShouldStop(map_suffixes_to_ignore, map_info->name)) {
break;
}
- elf = map_info->GetElf(process_memory_, true);
+ elf = map_info->GetElf(process_memory_, arch);
step_pc = regs_->pc();
rel_pc = elf->GetRelPc(step_pc, map_info);
// Everyone except elf data in gdb jit debug maps uses the relative pc.
@@ -190,6 +196,12 @@
FillInDexFrame();
// Clear the dex pc so that we don't repeat this frame later.
regs_->set_dex_pc(0);
+
+ // Make sure there is enough room for the real frame.
+ if (frames_.size() == max_frames_) {
+ last_error_.code = ERROR_MAX_FRAMES_EXCEEDED;
+ break;
+ }
}
FillInFrame(map_info, elf, rel_pc, step_pc, pc_adjustment);
@@ -231,8 +243,14 @@
if (!stepped) {
if (return_address_attempt) {
- // Remove the speculative frame.
- frames_.pop_back();
+ // Only remove the speculative frame if there are more than two frames
+ // or the pc in the first frame is in a valid map.
+ // This allows for a case where the code jumps into the middle of
+ // nowhere, but there is no other unwind information after that.
+ if (frames_.size() != 2 || maps_->Find(frames_[0].pc) != nullptr) {
+ // Remove the speculative frame.
+ frames_.pop_back();
+ }
break;
} else if (in_device_map) {
// Do not attempt any other unwinding, pc or sp is in a device
@@ -276,10 +294,6 @@
data += android::base::StringPrintf(" #%02zu pc %016" PRIx64, frame.num, frame.rel_pc);
}
- if (frame.map_offset != 0) {
- data += android::base::StringPrintf(" (offset 0x%" PRIx64 ")", frame.map_offset);
- }
-
if (frame.map_start == frame.map_end) {
// No valid map associated with this frame.
data += " <unknown>";
@@ -288,8 +302,13 @@
} else {
data += android::base::StringPrintf(" <anonymous:%" PRIx64 ">", frame.map_start);
}
+
+ if (frame.map_elf_start_offset != 0) {
+ data += android::base::StringPrintf(" (offset 0x%" PRIx64 ")", frame.map_elf_start_offset);
+ }
+
if (!frame.function_name.empty()) {
- data += " (" + frame.function_name;
+ data += " (" + demangle(frame.function_name.c_str());
if (frame.function_offset != 0) {
data += android::base::StringPrintf("+%" PRId64, frame.function_offset);
}
@@ -310,4 +329,29 @@
}
#endif
+bool UnwinderFromPid::Init(ArchEnum arch) {
+ if (pid_ == getpid()) {
+ maps_ptr_.reset(new LocalMaps());
+ } else {
+ maps_ptr_.reset(new RemoteMaps(pid_));
+ }
+ if (!maps_ptr_->Parse()) {
+ return false;
+ }
+ maps_ = maps_ptr_.get();
+
+ process_memory_ = Memory::CreateProcessMemoryCached(pid_);
+
+ jit_debug_ptr_.reset(new JitDebug(process_memory_));
+ jit_debug_ = jit_debug_ptr_.get();
+ SetJitDebug(jit_debug_, arch);
+#if !defined(NO_LIBDEXFILE_SUPPORT)
+ dex_files_ptr_.reset(new DexFiles(process_memory_));
+ dex_files_ = dex_files_ptr_.get();
+ SetDexFiles(dex_files_, arch);
+#endif
+
+ return true;
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/benchmarks/unwind_benchmarks.cpp b/libunwindstack/benchmarks/unwind_benchmarks.cpp
new file mode 100644
index 0000000..8caecc7
--- /dev/null
+++ b/libunwindstack/benchmarks/unwind_benchmarks.cpp
@@ -0,0 +1,145 @@
+/*
+ * 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 <stdint.h>
+
+#include <memory>
+
+#include <benchmark/benchmark.h>
+
+#include <android-base/strings.h>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
+#include <unwindstack/Regs.h>
+#include <unwindstack/RegsGetLocal.h>
+#include <unwindstack/Unwinder.h>
+
+size_t Call6(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
+ std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
+ unwindstack::RegsGetLocal(regs.get());
+ unwindstack::Unwinder unwinder(32, maps, regs.get(), process_memory);
+ unwinder.Unwind();
+ return unwinder.NumFrames();
+}
+
+size_t Call5(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
+ return Call6(process_memory, maps);
+}
+
+size_t Call4(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
+ return Call5(process_memory, maps);
+}
+
+size_t Call3(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
+ return Call4(process_memory, maps);
+}
+
+size_t Call2(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
+ return Call3(process_memory, maps);
+}
+
+size_t Call1(std::shared_ptr<unwindstack::Memory>& process_memory, unwindstack::Maps* maps) {
+ return Call2(process_memory, maps);
+}
+
+static void BM_uncached_unwind(benchmark::State& state) {
+ auto process_memory = unwindstack::Memory::CreateProcessMemory(getpid());
+ unwindstack::LocalMaps maps;
+ if (!maps.Parse()) {
+ state.SkipWithError("Failed to parse local maps.");
+ }
+
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(Call1(process_memory, &maps));
+ }
+}
+BENCHMARK(BM_uncached_unwind);
+
+static void BM_cached_unwind(benchmark::State& state) {
+ auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid());
+ unwindstack::LocalMaps maps;
+ if (!maps.Parse()) {
+ state.SkipWithError("Failed to parse local maps.");
+ }
+
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(Call1(process_memory, &maps));
+ }
+}
+BENCHMARK(BM_cached_unwind);
+
+static void Initialize(benchmark::State& state, unwindstack::Maps& maps,
+ unwindstack::MapInfo** build_id_map_info) {
+ if (!maps.Parse()) {
+ state.SkipWithError("Failed to parse local maps.");
+ return;
+ }
+
+ // Find the libc.so share library and use that for benchmark purposes.
+ *build_id_map_info = nullptr;
+ for (unwindstack::MapInfo* map_info : maps) {
+ if (map_info->offset == 0 && map_info->GetBuildID() != "") {
+ *build_id_map_info = map_info;
+ break;
+ }
+ }
+
+ if (*build_id_map_info == nullptr) {
+ state.SkipWithError("Failed to find a map with a BuildID.");
+ }
+}
+
+static void BM_get_build_id_from_elf(benchmark::State& state) {
+ unwindstack::LocalMaps maps;
+ unwindstack::MapInfo* build_id_map_info;
+ Initialize(state, maps, &build_id_map_info);
+
+ unwindstack::Elf* elf = build_id_map_info->GetElf(std::shared_ptr<unwindstack::Memory>(),
+ unwindstack::Regs::CurrentArch());
+ if (!elf->valid()) {
+ state.SkipWithError("Cannot get valid elf from map.");
+ }
+
+ for (auto _ : state) {
+ uintptr_t id = build_id_map_info->build_id;
+ if (id != 0) {
+ delete reinterpret_cast<std::string*>(id);
+ build_id_map_info->build_id = 0;
+ }
+ benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
+ }
+}
+BENCHMARK(BM_get_build_id_from_elf);
+
+static void BM_get_build_id_from_file(benchmark::State& state) {
+ unwindstack::LocalMaps maps;
+ unwindstack::MapInfo* build_id_map_info;
+ Initialize(state, maps, &build_id_map_info);
+
+ for (auto _ : state) {
+ uintptr_t id = build_id_map_info->build_id;
+ if (id != 0) {
+ delete reinterpret_cast<std::string*>(id);
+ build_id_map_info->build_id = 0;
+ }
+ benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
+ }
+}
+BENCHMARK(BM_get_build_id_from_file);
+
+BENCHMARK_MAIN();
diff --git a/libunwindstack/include/unwindstack/DexFiles.h b/libunwindstack/include/unwindstack/DexFiles.h
index 26f5d35..0336173 100644
--- a/libunwindstack/include/unwindstack/DexFiles.h
+++ b/libunwindstack/include/unwindstack/DexFiles.h
@@ -25,16 +25,18 @@
#include <unordered_map>
#include <vector>
+#include <unwindstack/Global.h>
+#include <unwindstack/Memory.h>
+
namespace unwindstack {
// Forward declarations.
class DexFile;
class Maps;
struct MapInfo;
-class Memory;
enum ArchEnum : uint8_t;
-class DexFiles {
+class DexFiles : public Global {
public:
explicit DexFiles(std::shared_ptr<Memory>& memory);
DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
@@ -45,8 +47,6 @@
void GetMethodInformation(Maps* maps, MapInfo* info, uint64_t dex_pc, std::string* method_name,
uint64_t* method_offset);
- void SetArch(ArchEnum arch);
-
private:
void Init(Maps* maps);
@@ -60,12 +60,13 @@
bool ReadEntry64();
- std::shared_ptr<Memory> memory_;
- std::vector<std::string> search_libs_;
+ bool ReadVariableData(uint64_t ptr_offset) override;
+
+ void ProcessArch() override;
std::mutex lock_;
bool initialized_ = false;
- std::unordered_map<uint64_t, DexFile*> files_;
+ std::unordered_map<uint64_t, std::unique_ptr<DexFile>> files_;
uint64_t entry_addr_ = 0;
uint64_t (DexFiles::*read_entry_ptr_func_)(uint64_t) = nullptr;
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index f4cdbda..00a249f 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -53,10 +53,12 @@
Elf(Memory* memory) : memory_(memory) {}
virtual ~Elf() = default;
- bool Init(bool init_gnu_debugdata);
+ bool Init();
void InitGnuDebugdata();
+ void Invalidate();
+
bool GetSoname(std::string* name);
bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);
@@ -70,6 +72,8 @@
ElfInterface* CreateInterfaceFromMemory(Memory* memory);
+ std::string GetBuildID();
+
uint64_t GetLoadBias() { return load_bias_; }
bool IsValidPc(uint64_t pc);
@@ -94,10 +98,12 @@
static bool IsValidElf(Memory* memory);
- static void GetInfo(Memory* memory, bool* valid, uint64_t* size);
+ static bool GetInfo(Memory* memory, uint64_t* size);
static uint64_t GetLoadBias(Memory* memory);
+ static std::string GetBuildID(Memory* memory);
+
static void SetCachingEnabled(bool enable);
static bool CachingEnabled() { return cache_enabled_; }
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index a45eba8..d41bb13 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -62,6 +62,8 @@
virtual bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) = 0;
+ virtual std::string GetBuildID() = 0;
+
virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished);
virtual bool IsValidPc(uint64_t pc);
@@ -85,6 +87,8 @@
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_; }
+ uint64_t gnu_build_id_offset() { return gnu_build_id_offset_; }
+ uint64_t gnu_build_id_size() { return gnu_build_id_size_; }
DwarfSection* eh_frame() { return eh_frame_.get(); }
DwarfSection* debug_frame() { return debug_frame_.get(); }
@@ -96,6 +100,9 @@
template <typename EhdrType, typename PhdrType>
static uint64_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);
@@ -123,6 +130,9 @@
template <typename EhdrType>
static void GetMaxSizeWithTemplate(Memory* memory, uint64_t* size);
+ template <typename NhdrType>
+ std::string ReadBuildID();
+
Memory* memory_;
std::unordered_map<uint64_t, LoadInfo> pt_loads_;
@@ -143,6 +153,9 @@
uint64_t gnu_debugdata_offset_ = 0;
uint64_t gnu_debugdata_size_ = 0;
+ uint64_t gnu_build_id_offset_ = 0;
+ uint64_t gnu_build_id_size_ = 0;
+
uint8_t soname_type_ = SONAME_UNKNOWN;
std::string soname_;
@@ -182,6 +195,8 @@
return ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(name, memory_address);
}
+ std::string GetBuildID() override { return ElfInterface::ReadBuildID<Elf32_Nhdr>(); }
+
static void GetMaxSize(Memory* memory, uint64_t* size) {
GetMaxSizeWithTemplate<Elf32_Ehdr>(memory, size);
}
@@ -212,6 +227,8 @@
return ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(name, memory_address);
}
+ std::string GetBuildID() override { return ElfInterface::ReadBuildID<Elf64_Nhdr>(); }
+
static void GetMaxSize(Memory* memory, uint64_t* size) {
GetMaxSizeWithTemplate<Elf64_Ehdr>(memory, size);
}
diff --git a/libunwindstack/include/unwindstack/Global.h b/libunwindstack/include/unwindstack/Global.h
new file mode 100644
index 0000000..a7e6c15
--- /dev/null
+++ b/libunwindstack/include/unwindstack/Global.h
@@ -0,0 +1,63 @@
+/*
+ * 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 _LIBUNWINDSTACK_GLOBAL_H
+#define _LIBUNWINDSTACK_GLOBAL_H
+
+#include <stdint.h>
+
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/Memory.h>
+
+namespace unwindstack {
+
+// Forward declarations.
+class Maps;
+struct MapInfo;
+
+class Global {
+ public:
+ explicit Global(std::shared_ptr<Memory>& memory);
+ Global(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
+ virtual ~Global() = default;
+
+ void SetArch(ArchEnum arch);
+
+ ArchEnum arch() { return arch_; }
+
+ protected:
+ uint64_t GetVariableOffset(MapInfo* info, const std::string& variable);
+ void FindAndReadVariable(Maps* maps, const char* variable);
+
+ virtual bool ReadVariableData(uint64_t offset) = 0;
+
+ virtual void ProcessArch() = 0;
+
+ ArchEnum arch_ = ARCH_UNKNOWN;
+
+ std::shared_ptr<Memory> memory_;
+ std::vector<std::string> search_libs_;
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_GLOBAL_H
diff --git a/libunwindstack/include/unwindstack/JitDebug.h b/libunwindstack/include/unwindstack/JitDebug.h
index 0bcd0b0..f64b04f 100644
--- a/libunwindstack/include/unwindstack/JitDebug.h
+++ b/libunwindstack/include/unwindstack/JitDebug.h
@@ -24,15 +24,17 @@
#include <string>
#include <vector>
+#include <unwindstack/Global.h>
+#include <unwindstack/Memory.h>
+
namespace unwindstack {
// Forward declarations.
class Elf;
class Maps;
-class Memory;
enum ArchEnum : uint8_t;
-class JitDebug {
+class JitDebug : public Global {
public:
explicit JitDebug(std::shared_ptr<Memory>& memory);
JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
@@ -40,19 +42,9 @@
Elf* GetElf(Maps* maps, uint64_t pc);
- void SetArch(ArchEnum arch);
-
private:
void Init(Maps* maps);
- std::shared_ptr<Memory> memory_;
- uint64_t entry_addr_ = 0;
- bool initialized_ = false;
- std::vector<Elf*> elf_list_;
- std::vector<std::string> search_libs_;
-
- std::mutex lock_;
-
uint64_t (JitDebug::*read_descriptor_func_)(uint64_t) = nullptr;
uint64_t (JitDebug::*read_entry_func_)(uint64_t*, uint64_t*) = nullptr;
@@ -62,6 +54,16 @@
uint64_t ReadEntry32Pack(uint64_t* start, uint64_t* size);
uint64_t ReadEntry32Pad(uint64_t* start, uint64_t* size);
uint64_t ReadEntry64(uint64_t* start, uint64_t* size);
+
+ bool ReadVariableData(uint64_t ptr_offset) override;
+
+ void ProcessArch() override;
+
+ uint64_t entry_addr_ = 0;
+ bool initialized_ = false;
+ std::vector<Elf*> elf_list_;
+
+ std::mutex lock_;
};
} // namespace unwindstack
diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h
index ac0df41..5143ff1 100644
--- a/libunwindstack/include/unwindstack/MapInfo.h
+++ b/libunwindstack/include/unwindstack/MapInfo.h
@@ -25,30 +25,32 @@
#include <string>
#include <unwindstack/Elf.h>
+#include <unwindstack/Memory.h>
namespace unwindstack {
-// Forward declarations.
-class Memory;
-
struct MapInfo {
- MapInfo() = default;
- MapInfo(uint64_t start, uint64_t end) : start(start), end(end) {}
- MapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const char* name)
+ MapInfo(MapInfo* map_info, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
+ const char* name)
: start(start),
end(end),
offset(offset),
flags(flags),
name(name),
- load_bias(static_cast<uint64_t>(-1)) {}
- MapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const std::string& name)
+ prev_map(map_info),
+ load_bias(static_cast<uint64_t>(-1)),
+ build_id(0) {}
+ MapInfo(MapInfo* map_info, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
+ const std::string& name)
: start(start),
end(end),
offset(offset),
flags(flags),
name(name),
- load_bias(static_cast<uint64_t>(-1)) {}
- ~MapInfo() = default;
+ prev_map(map_info),
+ load_bias(static_cast<uint64_t>(-1)),
+ build_id(0) {}
+ ~MapInfo();
uint64_t start = 0;
uint64_t end = 0;
@@ -57,25 +59,39 @@
std::string name;
std::shared_ptr<Elf> elf;
// This value is only non-zero if the offset is non-zero but there is
- // no elf signature found at that offset. This indicates that the
- // entire file is represented by the Memory object returned by CreateMemory,
- // instead of a portion of the file.
+ // 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
+ // 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;
+ // This is a pointer to a new'd std::string.
+ // Using an atomic value means that we don't need to lock and will
+ // make it easier to move to a fine grained lock in the future.
+ std::atomic_uintptr_t build_id;
+
// This function guarantees it will never return nullptr.
- Elf* GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata = false);
+ Elf* GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch);
uint64_t GetLoadBias(const std::shared_ptr<Memory>& process_memory);
+ Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory);
+
+ bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);
+
+ std::string GetBuildID();
+
private:
MapInfo(const MapInfo&) = delete;
void operator=(const MapInfo&) = delete;
Memory* GetFileMemory();
-
- Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory);
+ bool InitFileMemoryFromPreviousReadOnlyMap(MemoryFileAtOffset* memory);
// Protect the creation of the elf object.
std::mutex mutex_;
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
index dee5e98..dba41d1 100644
--- a/libunwindstack/include/unwindstack/Memory.h
+++ b/libunwindstack/include/unwindstack/Memory.h
@@ -22,8 +22,10 @@
#include <unistd.h>
#include <atomic>
+#include <map>
#include <memory>
#include <string>
+#include <unordered_map>
#include <vector>
namespace unwindstack {
@@ -34,9 +36,12 @@
virtual ~Memory() = default;
static std::shared_ptr<Memory> CreateProcessMemory(pid_t pid);
+ static std::shared_ptr<Memory> CreateProcessMemoryCached(pid_t pid);
virtual bool ReadString(uint64_t addr, std::string* string, uint64_t max_read = UINT64_MAX);
+ virtual void Clear() {}
+
virtual size_t Read(uint64_t addr, void* dst, size_t size) = 0;
bool ReadFully(uint64_t addr, void* dst, size_t size);
@@ -50,6 +55,24 @@
}
};
+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;
@@ -119,6 +142,9 @@
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_;
@@ -126,6 +152,19 @@
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;
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index 56b0581..ab239c1 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -24,7 +24,9 @@
#include <string>
#include <vector>
+#include <unwindstack/DexFiles.h>
#include <unwindstack/Error.h>
+#include <unwindstack/JitDebug.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
@@ -32,9 +34,7 @@
namespace unwindstack {
// Forward declarations.
-class DexFiles;
class Elf;
-class JitDebug;
enum ArchEnum : uint8_t;
struct FrameData {
@@ -48,7 +48,13 @@
uint64_t function_offset = 0;
std::string map_name;
- uint64_t map_offset = 0;
+ // The offset from the first map representing the frame. When there are
+ // two maps (read-only and read-execute) this will be the offset from
+ // the read-only map. When there is only one map, this will be the
+ // same as the actual offset of the map and match map_exact_offset.
+ uint64_t map_elf_start_offset = 0;
+ // The actual offset from the map where the pc lies.
+ uint64_t map_exact_offset = 0;
uint64_t map_start = 0;
uint64_t map_end = 0;
uint64_t map_load_bias = 0;
@@ -61,6 +67,11 @@
: max_frames_(max_frames), maps_(maps), regs_(regs), process_memory_(process_memory) {
frames_.reserve(max_frames);
}
+ Unwinder(size_t max_frames, Maps* maps, std::shared_ptr<Memory> process_memory)
+ : max_frames_(max_frames), maps_(maps), process_memory_(process_memory) {
+ frames_.reserve(max_frames);
+ }
+
~Unwinder() = default;
void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
@@ -75,6 +86,10 @@
void SetJitDebug(JitDebug* jit_debug, ArchEnum arch);
+ void SetRegs(Regs* regs) { regs_ = regs; }
+ Maps* GetMaps() { return maps_; }
+ std::shared_ptr<Memory>& GetProcessMemory() { return process_memory_; }
+
// Disabling the resolving of names results in the function name being
// set to an empty string and the function offset being set to zero.
void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
@@ -86,7 +101,9 @@
ErrorCode LastErrorCode() { return last_error_.code; }
uint64_t LastErrorAddress() { return last_error_.address; }
- private:
+ protected:
+ Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); }
+
void FillInDexFrame();
void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t func_pc,
uint64_t pc_adjustment);
@@ -104,6 +121,22 @@
ErrorData last_error_;
};
+class UnwinderFromPid : public Unwinder {
+ public:
+ UnwinderFromPid(size_t max_frames, pid_t pid) : Unwinder(max_frames), pid_(pid) {}
+ ~UnwinderFromPid() = default;
+
+ bool Init(ArchEnum arch);
+
+ private:
+ 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
#endif // _LIBUNWINDSTACK_UNWINDER_H
diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp
index 4dd8cb0..0149a42 100644
--- a/libunwindstack/tests/DexFileTest.cpp
+++ b/libunwindstack/tests/DexFileTest.cpp
@@ -20,45 +20,35 @@
#include <unordered_map>
-#include <android-base/test_utils.h>
-
+#include <android-base/file.h>
+#include <gtest/gtest.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Memory.h>
-#include <dex/code_item_accessors-inl.h>
-#include <dex/standard_dex_file.h>
-
-#include <gtest/gtest.h>
-
#include "DexFile.h"
-
#include "DexFileData.h"
#include "MemoryFake.h"
namespace unwindstack {
TEST(DexFileTest, from_file_open_non_exist) {
- DexFileFromFile dex_file;
- ASSERT_FALSE(dex_file.Open(0, "/file/does/not/exist"));
+ EXPECT_TRUE(DexFileFromFile::Create(0, "/file/does/not/exist") == nullptr);
}
TEST(DexFileTest, from_file_open_too_small) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
- ASSERT_EQ(sizeof(art::DexFile::Header) - 2,
- static_cast<size_t>(
- TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header)) - 2)));
+ ASSERT_EQ(size_t{10}, static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, 10))));
// Header too small.
- DexFileFromFile dex_file;
- ASSERT_FALSE(dex_file.Open(0, tf.path));
+ EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
// Header correct, file too small.
ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
- ASSERT_EQ(sizeof(art::DexFile::Header), static_cast<size_t>(TEMP_FAILURE_RETRY(write(
- tf.fd, kDexData, sizeof(art::DexFile::Header)))));
- ASSERT_FALSE(dex_file.Open(0, tf.path));
+ ASSERT_EQ(sizeof(kDexData) - 1,
+ static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 1))));
+ EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
}
TEST(DexFileTest, from_file_open) {
@@ -68,8 +58,7 @@
ASSERT_EQ(sizeof(kDexData),
static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
- DexFileFromFile dex_file;
- ASSERT_TRUE(dex_file.Open(0, tf.path));
+ EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) != nullptr);
}
TEST(DexFileTest, from_file_open_non_zero_offset) {
@@ -80,35 +69,31 @@
ASSERT_EQ(sizeof(kDexData),
static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
- DexFileFromFile dex_file;
- ASSERT_TRUE(dex_file.Open(0x100, tf.path));
+ EXPECT_TRUE(DexFileFromFile::Create(0x100, tf.path) != nullptr);
}
TEST(DexFileTest, from_memory_fail_too_small_for_header) {
MemoryFake memory;
- memory.SetMemory(0x1000, kDexData, sizeof(art::DexFile::Header) - 1);
- DexFileFromMemory dex_file;
+ memory.SetMemory(0x1000, kDexData, 10);
- ASSERT_FALSE(dex_file.Open(0x1000, &memory));
+ EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
}
TEST(DexFileTest, from_memory_fail_too_small_for_data) {
MemoryFake memory;
memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
- DexFileFromMemory dex_file;
- ASSERT_FALSE(dex_file.Open(0x1000, &memory));
+ EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
}
TEST(DexFileTest, from_memory_open) {
MemoryFake memory;
memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
- DexFileFromMemory dex_file;
- ASSERT_TRUE(dex_file.Open(0x1000, &memory));
+ EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr);
}
TEST(DexFileTest, create_using_file) {
@@ -120,9 +105,8 @@
static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
MemoryFake memory;
- MapInfo info(0, 0x10000, 0, 0x5, tf.path);
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x500, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
+ MapInfo info(nullptr, 0, 0x10000, 0, 0x5, tf.path);
+ EXPECT_TRUE(DexFile::Create(0x500, &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_file_non_zero_start) {
@@ -134,9 +118,8 @@
static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
MemoryFake memory;
- MapInfo info(0x100, 0x10000, 0, 0x5, tf.path);
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x600, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
+ MapInfo info(nullptr, 0x100, 0x10000, 0, 0x5, tf.path);
+ EXPECT_TRUE(DexFile::Create(0x600, &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_file_non_zero_offset) {
@@ -148,25 +131,22 @@
static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
MemoryFake memory;
- MapInfo info(0x100, 0x10000, 0x200, 0x5, tf.path);
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x400, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
+ MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, tf.path);
+ EXPECT_TRUE(DexFile::Create(0x400, &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_memory_empty_file) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
+ MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
+ EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_memory_file_does_not_exist) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file != nullptr);
+ MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
+ EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_memory_file_is_malformed) {
@@ -178,29 +158,20 @@
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
+ MapInfo info(nullptr, 0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
+ std::unique_ptr<DexFile> dex_file = DexFile::Create(0x4000, &memory, &info);
ASSERT_TRUE(dex_file != nullptr);
// Check it came from memory by clearing memory and verifying it fails.
memory.Clear();
- dex_file.reset(DexFile::Create(0x4000, &memory, &info));
- ASSERT_TRUE(dex_file == nullptr);
-}
-
-TEST(DexFileTest, get_method_not_opened) {
- std::string method("something");
- uint64_t method_offset = 100;
- DexFile dex_file;
- dex_file.GetMethodInformation(0x100, &method, &method_offset);
- EXPECT_EQ("something", method);
- EXPECT_EQ(100U, method_offset);
+ dex_file = DexFile::Create(0x4000, &memory, &info);
+ EXPECT_TRUE(dex_file == nullptr);
}
TEST(DexFileTest, get_method) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
+ MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
ASSERT_TRUE(dex_file != nullptr);
@@ -213,21 +184,12 @@
ASSERT_TRUE(dex_file->GetMethodInformation(0x118, &method, &method_offset));
EXPECT_EQ("Main.main", method);
EXPECT_EQ(0U, method_offset);
-
- // Make sure that any data that is cached is still retrievable.
- ASSERT_TRUE(dex_file->GetMethodInformation(0x104, &method, &method_offset));
- EXPECT_EQ("Main.<init>", method);
- EXPECT_EQ(4U, method_offset);
-
- ASSERT_TRUE(dex_file->GetMethodInformation(0x119, &method, &method_offset));
- EXPECT_EQ("Main.main", method);
- EXPECT_EQ(1U, method_offset);
}
TEST(DexFileTest, get_method_empty) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
+ MapInfo info(nullptr, 0x100, 0x10000, 0x200, 0x5, "");
std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
ASSERT_TRUE(dex_file != nullptr);
@@ -236,12 +198,6 @@
EXPECT_FALSE(dex_file->GetMethodInformation(0x100000, &method, &method_offset));
EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
-
- // Make sure that once the whole dex file has been cached, no problems occur.
- EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
-
- // Choose a value that is in the cached map, but not in a valid method.
- EXPECT_FALSE(dex_file->GetMethodInformation(0x110, &method, &method_offset));
}
} // namespace unwindstack
diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp
index d029bb0..1ea9e5c 100644
--- a/libunwindstack/tests/DexFilesTest.cpp
+++ b/libunwindstack/tests/DexFilesTest.cpp
@@ -36,57 +36,54 @@
class DexFilesTest : public ::testing::Test {
protected:
- void SetUp() override {
- memory_ = new MemoryFake;
- process_memory_.reset(memory_);
-
- dex_files_.reset(new DexFiles(process_memory_));
- dex_files_->SetArch(ARCH_ARM);
-
- maps_.reset(
- new BufferMaps("1000-4000 ---s 00000000 00:00 0\n"
- "4000-6000 r--s 00000000 00:00 0\n"
- "6000-8000 -w-s 00000000 00:00 0\n"
- "a000-c000 r-xp 00000000 00:00 0\n"
- "c000-f000 rwxp 00000000 00:00 0\n"
- "f000-11000 r-xp 00000000 00:00 0\n"
- "100000-110000 rw-p 0000000 00:00 0\n"
- "200000-210000 rw-p 0000000 00:00 0\n"
- "300000-400000 rw-p 0000000 00:00 0\n"));
- ASSERT_TRUE(maps_->Parse());
-
- // Global variable in a section that is not readable/executable.
- MapInfo* map_info = maps_->Get(kMapGlobalNonReadableExectable);
- ASSERT_TRUE(map_info != nullptr);
+ void CreateFakeElf(MapInfo* map_info) {
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);
map_info->elf.reset(elf);
+ }
+
+ void Init(ArchEnum arch) {
+ dex_files_.reset(new DexFiles(process_memory_));
+ dex_files_->SetArch(arch);
+
+ 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"
+ "a000-c000 r--p 00000000 00:00 0 /fake/elf2\n"
+ "c000-f000 rw-p 00001000 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"
+ "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());
+
+ // Global variable in a section that is not readable.
+ MapInfo* map_info = maps_->Get(kMapGlobalNonReadable);
+ ASSERT_TRUE(map_info != nullptr);
+ CreateFakeElf(map_info);
// Global variable not set by default.
map_info = maps_->Get(kMapGlobalSetToZero);
ASSERT_TRUE(map_info != nullptr);
- memory = new MemoryFake;
- elf = new ElfFake(memory);
- elf->FakeSetValid(true);
- interface = new ElfInterfaceFake(memory);
- elf->FakeSetInterface(interface);
- interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
- map_info->elf.reset(elf);
+ CreateFakeElf(map_info);
// Global variable set in this map.
map_info = maps_->Get(kMapGlobal);
ASSERT_TRUE(map_info != nullptr);
- memory = new MemoryFake;
- elf = new ElfFake(memory);
- elf->FakeSetValid(true);
- interface = new ElfInterfaceFake(memory);
- elf->FakeSetInterface(interface);
- interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
- map_info->elf.reset(elf);
+ CreateFakeElf(map_info);
+ }
+
+ void SetUp() override {
+ memory_ = new MemoryFake;
+ process_memory_.reset(memory_);
+
+ Init(ARCH_ARM);
}
void WriteDescriptor32(uint64_t addr, uint32_t head);
@@ -95,9 +92,10 @@
void WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, uint64_t dex_file);
void WriteDex(uint64_t dex_file);
- static constexpr size_t kMapGlobalNonReadableExectable = 3;
- static constexpr size_t kMapGlobalSetToZero = 4;
+ static constexpr size_t kMapGlobalNonReadable = 2;
+ static constexpr size_t kMapGlobalSetToZero = 3;
static constexpr size_t kMapGlobal = 5;
+ static constexpr size_t kMapGlobalRw = 6;
static constexpr size_t kMapDexFileEntries = 7;
static constexpr size_t kMapDexFiles = 8;
@@ -168,11 +166,12 @@
}
TEST_F(DexFilesTest, get_method_information_64) {
+ Init(ARCH_ARM64);
+
std::string method_name = "nothing";
uint64_t method_offset = 0x124;
MapInfo* info = maps_->Get(kMapDexFiles);
- dex_files_->SetArch(ARCH_ARM64);
WriteDescriptor64(0xf800, 0x200000);
WriteEntry64(0x200000, 0, 0, 0x301000);
WriteDex(0x301000);
@@ -198,11 +197,12 @@
}
TEST_F(DexFilesTest, get_method_information_not_first_entry_64) {
+ Init(ARCH_ARM64);
+
std::string method_name = "nothing";
uint64_t method_offset = 0x124;
MapInfo* info = maps_->Get(kMapDexFiles);
- dex_files_->SetArch(ARCH_ARM64);
WriteDescriptor64(0xf800, 0x200000);
WriteEntry64(0x200000, 0x200100, 0, 0x100000);
WriteEntry64(0x200100, 0, 0x200000, 0x300000);
@@ -256,6 +256,9 @@
map_info->name = "/system/lib/libart.so";
dex_files_.reset(new DexFiles(process_memory_, libs));
dex_files_->SetArch(ARCH_ARM);
+ // Set the rw map to the same name or this will not scan this entry.
+ map_info = maps_->Get(kMapGlobalRw);
+ map_info->name = "/system/lib/libart.so";
// Make sure that clearing out copy of the libs doesn't affect the
// DexFiles object.
libs.clear();
@@ -271,7 +274,7 @@
MapInfo* info = maps_->Get(kMapDexFiles);
// First global variable found, but value is zero.
- WriteDescriptor32(0xc800, 0);
+ WriteDescriptor32(0xa800, 0);
WriteDescriptor32(0xf800, 0x200000);
WriteEntry32(0x200000, 0, 0, 0x300000);
@@ -286,25 +289,26 @@
dex_files_->SetArch(ARCH_ARM);
method_name = "fail";
method_offset = 0x123;
- WriteDescriptor32(0xc800, 0x100000);
+ WriteDescriptor32(0xa800, 0x100000);
dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
EXPECT_EQ("fail", method_name);
EXPECT_EQ(0x123U, method_offset);
}
TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) {
+ Init(ARCH_ARM64);
+
std::string method_name = "nothing";
uint64_t method_offset = 0x124;
MapInfo* info = maps_->Get(kMapDexFiles);
// First global variable found, but value is zero.
- WriteDescriptor64(0xc800, 0);
+ WriteDescriptor64(0xa800, 0);
WriteDescriptor64(0xf800, 0x200000);
WriteEntry64(0x200000, 0, 0, 0x300000);
WriteDex(0x300000);
- dex_files_->SetArch(ARCH_ARM64);
dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
EXPECT_EQ("Main.<init>", method_name);
EXPECT_EQ(0U, method_offset);
@@ -314,7 +318,7 @@
dex_files_->SetArch(ARCH_ARM64);
method_name = "fail";
method_offset = 0x123;
- WriteDescriptor64(0xc800, 0x100000);
+ WriteDescriptor64(0xa800, 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/DwarfMemoryTest.cpp b/libunwindstack/tests/DwarfMemoryTest.cpp
index f12d2fe..650e965 100644
--- a/libunwindstack/tests/DwarfMemoryTest.cpp
+++ b/libunwindstack/tests/DwarfMemoryTest.cpp
@@ -54,6 +54,8 @@
void ReadEncodedValue_overflow();
template <typename AddressType>
void ReadEncodedValue_high_bit_set();
+ template <typename AddressType>
+ void ReadEncodedValue_all();
MemoryFake memory_;
std::unique_ptr<DwarfMemory> dwarf_mem_;
@@ -457,6 +459,27 @@
ReadEncodedValue_high_bit_set<uint64_t>();
}
+template <typename AddressType>
+void DwarfMemoryTest::ReadEncodedValue_all() {
+ MemoryFakeAlwaysReadZero memory;
+ DwarfMemory dwarf_mem(&memory);
+
+ for (size_t i = 0; i <= 0xff; i++) {
+ uint64_t value;
+ if (dwarf_mem.ReadEncodedValue<AddressType>(static_cast<uint8_t>(i), &value)) {
+ ASSERT_EQ(0U, value);
+ }
+ }
+}
+
+TEST_F(DwarfMemoryTest, ReadEncodedValue_all_uint32_t) {
+ ReadEncodedValue_all<uint32_t>();
+}
+
+TEST_F(DwarfMemoryTest, ReadEncodedValue_all_uint64_t) {
+ ReadEncodedValue_all<uint64_t>();
+}
+
TEST_F(DwarfMemoryTest, AdjustEncodedValue_absptr) {
uint64_t value = 0x1234;
ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x00, &value));
diff --git a/libunwindstack/tests/ElfCacheTest.cpp b/libunwindstack/tests/ElfCacheTest.cpp
index 89331ea..07fd6f6 100644
--- a/libunwindstack/tests/ElfCacheTest.cpp
+++ b/libunwindstack/tests/ElfCacheTest.cpp
@@ -18,7 +18,6 @@
#include <unistd.h>
#include <android-base/file.h>
-#include <android-base/test_utils.h>
#include <gtest/gtest.h>
@@ -79,12 +78,12 @@
uint64_t start = 0x1000;
uint64_t end = 0x20000;
- MapInfo info1(start, end, 0, 0x5, tf.path);
- MapInfo info2(start, end, 0, 0x5, tf.path);
+ MapInfo info1(nullptr, start, end, 0, 0x5, tf.path);
+ MapInfo info2(nullptr, start, end, 0, 0x5, tf.path);
- Elf* elf1 = info1.GetElf(memory_, true);
+ Elf* elf1 = info1.GetElf(memory_, ARCH_ARM);
ASSERT_TRUE(elf1->valid());
- Elf* elf2 = info2.GetElf(memory_, true);
+ Elf* elf2 = info2.GetElf(memory_, ARCH_ARM);
ASSERT_TRUE(elf2->valid());
if (cache_enabled) {
@@ -120,22 +119,22 @@
uint64_t start = 0x1000;
uint64_t end = 0x20000;
// Will have an elf at offset 0 in file.
- MapInfo info0_1(start, end, 0, 0x5, tf.path);
- MapInfo info0_2(start, end, 0, 0x5, tf.path);
+ MapInfo info0_1(nullptr, start, end, 0, 0x5, tf.path);
+ MapInfo info0_2(nullptr, start, end, 0, 0x5, tf.path);
// Will have an elf at offset 0x100 in file.
- MapInfo info100_1(start, end, 0x100, 0x5, tf.path);
- MapInfo info100_2(start, end, 0x100, 0x5, tf.path);
+ MapInfo info100_1(nullptr, start, end, 0x100, 0x5, tf.path);
+ MapInfo info100_2(nullptr, start, end, 0x100, 0x5, tf.path);
// Will have an elf at offset 0x200 in file.
- MapInfo info200_1(start, end, 0x200, 0x5, tf.path);
- MapInfo info200_2(start, end, 0x200, 0x5, tf.path);
+ MapInfo info200_1(nullptr, start, end, 0x200, 0x5, tf.path);
+ MapInfo info200_2(nullptr, start, end, 0x200, 0x5, tf.path);
// Will have an elf at offset 0 in file.
- MapInfo info300_1(start, end, 0x300, 0x5, tf.path);
- MapInfo info300_2(start, end, 0x300, 0x5, tf.path);
+ MapInfo info300_1(nullptr, start, end, 0x300, 0x5, tf.path);
+ MapInfo info300_2(nullptr, start, end, 0x300, 0x5, tf.path);
- Elf* elf0_1 = info0_1.GetElf(memory_, true);
+ Elf* elf0_1 = info0_1.GetElf(memory_, ARCH_ARM);
ASSERT_TRUE(elf0_1->valid());
EXPECT_EQ(ARCH_ARM, elf0_1->arch());
- Elf* elf0_2 = info0_2.GetElf(memory_, true);
+ Elf* elf0_2 = info0_2.GetElf(memory_, ARCH_ARM);
ASSERT_TRUE(elf0_2->valid());
EXPECT_EQ(ARCH_ARM, elf0_2->arch());
EXPECT_EQ(0U, info0_1.elf_offset);
@@ -146,10 +145,10 @@
EXPECT_NE(elf0_1, elf0_2);
}
- Elf* elf100_1 = info100_1.GetElf(memory_, true);
+ Elf* elf100_1 = info100_1.GetElf(memory_, ARCH_X86);
ASSERT_TRUE(elf100_1->valid());
EXPECT_EQ(ARCH_X86, elf100_1->arch());
- Elf* elf100_2 = info100_2.GetElf(memory_, true);
+ Elf* elf100_2 = info100_2.GetElf(memory_, ARCH_X86);
ASSERT_TRUE(elf100_2->valid());
EXPECT_EQ(ARCH_X86, elf100_2->arch());
EXPECT_EQ(0U, info100_1.elf_offset);
@@ -160,10 +159,10 @@
EXPECT_NE(elf100_1, elf100_2);
}
- Elf* elf200_1 = info200_1.GetElf(memory_, true);
+ Elf* elf200_1 = info200_1.GetElf(memory_, ARCH_X86_64);
ASSERT_TRUE(elf200_1->valid());
EXPECT_EQ(ARCH_X86_64, elf200_1->arch());
- Elf* elf200_2 = info200_2.GetElf(memory_, true);
+ Elf* elf200_2 = info200_2.GetElf(memory_, ARCH_X86_64);
ASSERT_TRUE(elf200_2->valid());
EXPECT_EQ(ARCH_X86_64, elf200_2->arch());
EXPECT_EQ(0U, info200_1.elf_offset);
@@ -174,10 +173,10 @@
EXPECT_NE(elf200_1, elf200_2);
}
- Elf* elf300_1 = info300_1.GetElf(memory_, true);
+ Elf* elf300_1 = info300_1.GetElf(memory_, ARCH_ARM);
ASSERT_TRUE(elf300_1->valid());
EXPECT_EQ(ARCH_ARM, elf300_1->arch());
- Elf* elf300_2 = info300_2.GetElf(memory_, true);
+ Elf* elf300_2 = info300_2.GetElf(memory_, ARCH_ARM);
ASSERT_TRUE(elf300_2->valid());
EXPECT_EQ(ARCH_ARM, elf300_2->arch());
EXPECT_EQ(0x300U, info300_1.elf_offset);
@@ -217,15 +216,15 @@
uint64_t start = 0x1000;
uint64_t end = 0x20000;
// Multiple info sections at different offsets will have non-zero elf offsets.
- MapInfo info300_1(start, end, 0x300, 0x5, tf.path);
- MapInfo info300_2(start, end, 0x300, 0x5, tf.path);
- MapInfo info400_1(start, end, 0x400, 0x5, tf.path);
- MapInfo info400_2(start, end, 0x400, 0x5, tf.path);
+ MapInfo info300_1(nullptr, start, end, 0x300, 0x5, tf.path);
+ MapInfo info300_2(nullptr, start, end, 0x300, 0x5, tf.path);
+ MapInfo info400_1(nullptr, start, end, 0x400, 0x5, tf.path);
+ MapInfo info400_2(nullptr, start, end, 0x400, 0x5, tf.path);
- Elf* elf300_1 = info300_1.GetElf(memory_, true);
+ Elf* elf300_1 = info300_1.GetElf(memory_, ARCH_ARM);
ASSERT_TRUE(elf300_1->valid());
EXPECT_EQ(ARCH_ARM, elf300_1->arch());
- Elf* elf300_2 = info300_2.GetElf(memory_, true);
+ Elf* elf300_2 = info300_2.GetElf(memory_, ARCH_ARM);
ASSERT_TRUE(elf300_2->valid());
EXPECT_EQ(ARCH_ARM, elf300_2->arch());
EXPECT_EQ(0x300U, info300_1.elf_offset);
@@ -236,10 +235,10 @@
EXPECT_NE(elf300_1, elf300_2);
}
- Elf* elf400_1 = info400_1.GetElf(memory_, true);
+ Elf* elf400_1 = info400_1.GetElf(memory_, ARCH_ARM);
ASSERT_TRUE(elf400_1->valid());
EXPECT_EQ(ARCH_ARM, elf400_1->arch());
- Elf* elf400_2 = info400_2.GetElf(memory_, true);
+ Elf* elf400_2 = info400_2.GetElf(memory_, ARCH_ARM);
ASSERT_TRUE(elf400_2->valid());
EXPECT_EQ(ARCH_ARM, elf400_2->arch());
EXPECT_EQ(0x400U, info400_1.elf_offset);
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
index a3bf5ce..946bc3c 100644
--- a/libunwindstack/tests/ElfFake.h
+++ b/libunwindstack/tests/ElfFake.h
@@ -72,6 +72,7 @@
bool GetFunctionName(uint64_t, std::string*, uint64_t*) override;
bool GetGlobalVariable(const std::string&, uint64_t*) override;
+ std::string GetBuildID() override { return fake_build_id_; }
bool Step(uint64_t, Regs*, Memory*, bool*) override;
@@ -79,6 +80,9 @@
globals_[global] = offset;
}
+ void FakeSetBuildID(std::string& build_id) { fake_build_id_ = build_id; }
+ void FakeSetBuildID(const char* build_id) { fake_build_id_ = build_id; }
+
static void FakePushFunctionData(const FunctionData data) { functions_.push_back(data); }
static void FakePushStepData(const StepData data) { steps_.push_back(data); }
@@ -93,6 +97,7 @@
private:
std::unordered_map<std::string, uint64_t> globals_;
+ std::string fake_build_id_;
static std::deque<FunctionData> functions_;
static std::deque<StepData> steps_;
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index 9326bff..7239749 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -116,6 +116,21 @@
void InitSym(uint64_t offset, uint32_t value, uint32_t size, uint32_t name_offset,
uint64_t sym_offset, const char* name);
+ template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
+ void BuildID();
+
+ template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
+ void BuildIDTwoNotes();
+
+ template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
+ void BuildIDSectionTooSmallForName();
+
+ template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
+ void BuildIDSectionTooSmallForDesc();
+
+ template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
+ void BuildIDSectionTooSmallForHeader();
+
MemoryFake memory_;
};
@@ -898,7 +913,7 @@
Ehdr ehdr = {};
ehdr.e_shoff = offset;
- ehdr.e_shnum = 6;
+ ehdr.e_shnum = 7;
ehdr.e_shentsize = sizeof(Shdr);
ehdr.e_shstrndx = 2;
memory_.SetMemory(0, &ehdr, sizeof(ehdr));
@@ -958,10 +973,19 @@
memory_.SetMemory(offset, &shdr, sizeof(shdr));
offset += ehdr.e_shentsize;
+ memset(&shdr, 0, sizeof(shdr));
+ shdr.sh_type = SHT_NOTE;
+ shdr.sh_name = 0x500;
+ 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"));
memory_.SetMemory(0xf300, ".eh_frame", sizeof(".eh_frame"));
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;
ASSERT_TRUE(elf->Init(&load_bias));
@@ -974,6 +998,8 @@
EXPECT_EQ(0x800U, elf->eh_frame_size());
EXPECT_EQ(0xa000U, elf->eh_frame_hdr_offset());
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) {
@@ -1153,4 +1179,314 @@
EXPECT_FALSE(elf->IsValidPc(0x2a00));
}
+template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
+void ElfInterfaceTest::BuildID() {
+ std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+ uint64_t offset = 0x2000;
+
+ Ehdr ehdr = {};
+ ehdr.e_shoff = offset;
+ ehdr.e_shnum = 3;
+ ehdr.e_shentsize = sizeof(Shdr);
+ ehdr.e_shstrndx = 2;
+ memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+ offset += ehdr.e_shentsize;
+
+ char note_section[128];
+ Nhdr note_header = {};
+ note_header.n_namesz = 4; // "GNU"
+ note_header.n_descsz = 8; // "BUILDID"
+ note_header.n_type = NT_GNU_BUILD_ID;
+ memcpy(¬e_section, ¬e_header, sizeof(note_header));
+ size_t note_offset = sizeof(note_header);
+ memcpy(¬e_section[note_offset], "GNU", sizeof("GNU"));
+ note_offset += sizeof("GNU");
+ memcpy(¬e_section[note_offset], "BUILDID", sizeof("BUILDID"));
+ note_offset += sizeof("BUILDID");
+
+ Shdr shdr = {};
+ shdr.sh_type = SHT_NOTE;
+ shdr.sh_name = 0x500;
+ shdr.sh_offset = 0xb000;
+ shdr.sh_size = sizeof(note_section);
+ memory_.SetMemory(offset, &shdr, sizeof(shdr));
+ 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(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;
+ ASSERT_TRUE(elf->Init(&load_bias));
+ ASSERT_EQ("BUILDID", elf->GetBuildID());
+}
+
+template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
+void ElfInterfaceTest::BuildIDTwoNotes() {
+ std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+ uint64_t offset = 0x2000;
+
+ Ehdr ehdr = {};
+ ehdr.e_shoff = offset;
+ ehdr.e_shnum = 3;
+ ehdr.e_shentsize = sizeof(Shdr);
+ ehdr.e_shstrndx = 2;
+ memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+ offset += ehdr.e_shentsize;
+
+ char note_section[128];
+ Nhdr note_header = {};
+ note_header.n_namesz = 8; // "WRONG" aligned to 4
+ note_header.n_descsz = 8; // "BUILDID"
+ note_header.n_type = NT_GNU_BUILD_ID;
+ memcpy(¬e_section, ¬e_header, sizeof(note_header));
+ size_t note_offset = sizeof(note_header);
+ memcpy(¬e_section[note_offset], "WRONG", sizeof("WRONG"));
+ note_offset += 8;
+ memcpy(¬e_section[note_offset], "BUILDID", sizeof("BUILDID"));
+ note_offset += sizeof("BUILDID");
+
+ note_header.n_namesz = 4; // "GNU"
+ note_header.n_descsz = 8; // "BUILDID"
+ note_header.n_type = NT_GNU_BUILD_ID;
+ memcpy(¬e_section[note_offset], ¬e_header, sizeof(note_header));
+ note_offset += sizeof(note_header);
+ memcpy(¬e_section[note_offset], "GNU", sizeof("GNU"));
+ note_offset += sizeof("GNU");
+ memcpy(¬e_section[note_offset], "BUILDID", sizeof("BUILDID"));
+ note_offset += sizeof("BUILDID");
+
+ Shdr shdr = {};
+ shdr.sh_type = SHT_NOTE;
+ shdr.sh_name = 0x500;
+ shdr.sh_offset = 0xb000;
+ shdr.sh_size = sizeof(note_section);
+ memory_.SetMemory(offset, &shdr, sizeof(shdr));
+ 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(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;
+ ASSERT_TRUE(elf->Init(&load_bias));
+ ASSERT_EQ("BUILDID", elf->GetBuildID());
+}
+
+template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
+void ElfInterfaceTest::BuildIDSectionTooSmallForName () {
+ std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+ uint64_t offset = 0x2000;
+
+ Ehdr ehdr = {};
+ ehdr.e_shoff = offset;
+ ehdr.e_shnum = 3;
+ ehdr.e_shentsize = sizeof(Shdr);
+ ehdr.e_shstrndx = 2;
+ memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+ offset += ehdr.e_shentsize;
+
+ char note_section[128];
+ Nhdr note_header = {};
+ note_header.n_namesz = 4; // "GNU"
+ note_header.n_descsz = 8; // "BUILDID"
+ note_header.n_type = NT_GNU_BUILD_ID;
+ memcpy(¬e_section, ¬e_header, sizeof(note_header));
+ size_t note_offset = sizeof(note_header);
+ memcpy(¬e_section[note_offset], "GNU", sizeof("GNU"));
+ note_offset += sizeof("GNU");
+ memcpy(¬e_section[note_offset], "BUILDID", sizeof("BUILDID"));
+ note_offset += sizeof("BUILDID");
+
+ Shdr shdr = {};
+ shdr.sh_type = SHT_NOTE;
+ shdr.sh_name = 0x500;
+ shdr.sh_offset = 0xb000;
+ shdr.sh_size = sizeof(note_header) + 1;
+ memory_.SetMemory(offset, &shdr, sizeof(shdr));
+ 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(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;
+ ASSERT_TRUE(elf->Init(&load_bias));
+ ASSERT_EQ("", elf->GetBuildID());
+}
+
+template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
+void ElfInterfaceTest::BuildIDSectionTooSmallForDesc () {
+ std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+ uint64_t offset = 0x2000;
+
+ Ehdr ehdr = {};
+ ehdr.e_shoff = offset;
+ ehdr.e_shnum = 3;
+ ehdr.e_shentsize = sizeof(Shdr);
+ ehdr.e_shstrndx = 2;
+ memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+ offset += ehdr.e_shentsize;
+
+ char note_section[128];
+ Nhdr note_header = {};
+ note_header.n_namesz = 4; // "GNU"
+ note_header.n_descsz = 8; // "BUILDID"
+ note_header.n_type = NT_GNU_BUILD_ID;
+ memcpy(¬e_section, ¬e_header, sizeof(note_header));
+ size_t note_offset = sizeof(note_header);
+ memcpy(¬e_section[note_offset], "GNU", sizeof("GNU"));
+ note_offset += sizeof("GNU");
+ memcpy(¬e_section[note_offset], "BUILDID", sizeof("BUILDID"));
+ note_offset += sizeof("BUILDID");
+
+ Shdr shdr = {};
+ shdr.sh_type = SHT_NOTE;
+ shdr.sh_name = 0x500;
+ shdr.sh_offset = 0xb000;
+ shdr.sh_size = sizeof(note_header) + sizeof("GNU") + 1;
+ memory_.SetMemory(offset, &shdr, sizeof(shdr));
+ 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(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;
+ ASSERT_TRUE(elf->Init(&load_bias));
+ ASSERT_EQ("", elf->GetBuildID());
+}
+
+template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
+void ElfInterfaceTest::BuildIDSectionTooSmallForHeader () {
+ std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+ uint64_t offset = 0x2000;
+
+ Ehdr ehdr = {};
+ ehdr.e_shoff = offset;
+ ehdr.e_shnum = 3;
+ ehdr.e_shentsize = sizeof(Shdr);
+ ehdr.e_shstrndx = 2;
+ memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+ offset += ehdr.e_shentsize;
+
+ char note_section[128];
+ Nhdr note_header = {};
+ note_header.n_namesz = 4; // "GNU"
+ note_header.n_descsz = 8; // "BUILDID"
+ note_header.n_type = NT_GNU_BUILD_ID;
+ memcpy(¬e_section, ¬e_header, sizeof(note_header));
+ size_t note_offset = sizeof(note_header);
+ memcpy(¬e_section[note_offset], "GNU", sizeof("GNU"));
+ note_offset += sizeof("GNU");
+ memcpy(¬e_section[note_offset], "BUILDID", sizeof("BUILDID"));
+ note_offset += sizeof("BUILDID");
+
+ Shdr shdr = {};
+ shdr.sh_type = SHT_NOTE;
+ shdr.sh_name = 0x500;
+ shdr.sh_offset = 0xb000;
+ shdr.sh_size = sizeof(note_header) - 1;
+ memory_.SetMemory(offset, &shdr, sizeof(shdr));
+ 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(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;
+ 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) {
+ BuildIDSectionTooSmallForHeader<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
+}
+
+TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header64) {
+ BuildIDSectionTooSmallForHeader<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index 55fe16f..1ff2306 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -110,7 +110,7 @@
TEST_F(ElfTest, invalid_memory) {
Elf elf(memory_);
- ASSERT_FALSE(elf.Init(false));
+ ASSERT_FALSE(elf.Init());
ASSERT_FALSE(elf.valid());
}
@@ -122,7 +122,7 @@
// Corrupt the ELF signature.
memory_->SetData32(0, 0x7f000000);
- ASSERT_FALSE(elf.Init(false));
+ ASSERT_FALSE(elf.Init());
ASSERT_FALSE(elf.valid());
ASSERT_TRUE(elf.interface() == nullptr);
@@ -142,7 +142,7 @@
InitElf32(EM_PPC);
ResetLogs();
- ASSERT_FALSE(elf.Init(false));
+ ASSERT_FALSE(elf.Init());
ASSERT_EQ("", GetFakeLogBuf());
ASSERT_EQ("4 unwind 32 bit elf that is neither arm nor x86 nor mips: e_machine = 20\n\n",
@@ -155,7 +155,7 @@
InitElf64(EM_PPC64);
ResetLogs();
- ASSERT_FALSE(elf.Init(false));
+ ASSERT_FALSE(elf.Init());
ASSERT_EQ("", GetFakeLogBuf());
ASSERT_EQ("4 unwind 64 bit elf that is neither aarch64 nor x86_64 nor mips64: e_machine = 21\n\n",
@@ -167,7 +167,7 @@
InitElf32(EM_ARM);
- ASSERT_TRUE(elf.Init(false));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.valid());
ASSERT_EQ(static_cast<uint32_t>(EM_ARM), elf.machine_type());
ASSERT_EQ(ELFCLASS32, elf.class_type());
@@ -179,7 +179,7 @@
InitElf32(EM_MIPS);
- ASSERT_TRUE(elf.Init(false));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.valid());
ASSERT_EQ(static_cast<uint32_t>(EM_MIPS), elf.machine_type());
ASSERT_EQ(ELFCLASS32, elf.class_type());
@@ -191,7 +191,7 @@
InitElf32(EM_386);
- ASSERT_TRUE(elf.Init(false));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.valid());
ASSERT_EQ(static_cast<uint32_t>(EM_386), elf.machine_type());
ASSERT_EQ(ELFCLASS32, elf.class_type());
@@ -203,7 +203,7 @@
InitElf64(EM_AARCH64);
- ASSERT_TRUE(elf.Init(false));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.valid());
ASSERT_EQ(static_cast<uint32_t>(EM_AARCH64), elf.machine_type());
ASSERT_EQ(ELFCLASS64, elf.class_type());
@@ -215,7 +215,7 @@
InitElf64(EM_X86_64);
- ASSERT_TRUE(elf.Init(false));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.valid());
ASSERT_EQ(static_cast<uint32_t>(EM_X86_64), elf.machine_type());
ASSERT_EQ(ELFCLASS64, elf.class_type());
@@ -227,41 +227,13 @@
InitElf64(EM_MIPS);
- ASSERT_TRUE(elf.Init(false));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.valid());
ASSERT_EQ(static_cast<uint32_t>(EM_MIPS), elf.machine_type());
ASSERT_EQ(ELFCLASS64, elf.class_type());
ASSERT_TRUE(elf.interface() != nullptr);
}
-TEST_F(ElfTest, gnu_debugdata_init_fail32) {
- TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
- [&](uint64_t offset, const void* ptr, size_t size) {
- memory_->SetMemory(offset, ptr, size);
- });
-
- Elf elf(memory_);
- ASSERT_TRUE(elf.Init(false));
- ASSERT_TRUE(elf.interface() != nullptr);
- ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
- EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
- EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
-}
-
-TEST_F(ElfTest, gnu_debugdata_init_fail64) {
- TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
- [&](uint64_t offset, const void* ptr, size_t size) {
- memory_->SetMemory(offset, ptr, size);
- });
-
- Elf elf(memory_);
- ASSERT_TRUE(elf.Init(false));
- ASSERT_TRUE(elf.interface() != nullptr);
- ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
- EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
- EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
-}
-
TEST_F(ElfTest, gnu_debugdata_init32) {
TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
[&](uint64_t offset, const void* ptr, size_t size) {
@@ -269,7 +241,7 @@
});
Elf elf(memory_);
- ASSERT_TRUE(elf.Init(true));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.interface() != nullptr);
ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
@@ -283,7 +255,7 @@
});
Elf elf(memory_);
- ASSERT_TRUE(elf.Init(true));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.interface() != nullptr);
ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
@@ -297,7 +269,7 @@
elf.FakeSetInterface(interface);
elf.FakeSetValid(true);
- MapInfo map_info(0x1000, 0x2000);
+ MapInfo map_info(nullptr, 0x1000, 0x2000, 0, 0, "");
ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
@@ -339,6 +311,7 @@
void InitHeaders(uint64_t) override {}
bool GetSoname(std::string*) override { return false; }
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*));
diff --git a/libunwindstack/tests/JitDebugTest.cpp b/libunwindstack/tests/JitDebugTest.cpp
index c1c45f8..b1ca111 100644
--- a/libunwindstack/tests/JitDebugTest.cpp
+++ b/libunwindstack/tests/JitDebugTest.cpp
@@ -35,27 +35,7 @@
class JitDebugTest : public ::testing::Test {
protected:
- void SetUp() override {
- memory_ = new MemoryFake;
- process_memory_.reset(memory_);
-
- jit_debug_.reset(new JitDebug(process_memory_));
- jit_debug_->SetArch(ARCH_ARM);
-
- maps_.reset(
- new BufferMaps("1000-4000 ---s 00000000 00:00 0\n"
- "4000-6000 r--s 00000000 00:00 0\n"
- "6000-8000 -w-s 00000000 00:00 0\n"
- "a000-c000 --xp 00000000 00:00 0\n"
- "c000-f000 rwxp 00000000 00:00 0\n"
- "f000-11000 r-xp 00000000 00:00 0\n"
- "12000-14000 r-xp 00000000 00:00 0\n"
- "100000-110000 rw-p 0000000 00:00 0\n"
- "200000-210000 rw-p 0000000 00:00 0\n"));
- ASSERT_TRUE(maps_->Parse());
-
- MapInfo* map_info = maps_->Get(3);
- ASSERT_TRUE(map_info != nullptr);
+ void CreateFakeElf(MapInfo* map_info) {
MemoryFake* memory = new MemoryFake;
ElfFake* elf = new ElfFake(memory);
elf->FakeSetValid(true);
@@ -63,26 +43,43 @@
elf->FakeSetInterface(interface);
interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800);
map_info->elf.reset(elf);
+ }
+
+ void Init(ArchEnum arch) {
+ jit_debug_.reset(new JitDebug(process_memory_));
+ jit_debug_->SetArch(arch);
+
+ 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"
+ "a000-c000 --xp 00000000 00:00 0 /fake/elf2\n"
+ "c000-f000 rw-p 00001000 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"
+ "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"));
+ ASSERT_TRUE(maps_->Parse());
+
+ MapInfo* map_info = maps_->Get(3);
+ ASSERT_TRUE(map_info != nullptr);
+ CreateFakeElf(map_info);
map_info = maps_->Get(5);
ASSERT_TRUE(map_info != nullptr);
- memory = new MemoryFake;
- elf = new ElfFake(memory);
- elf->FakeSetValid(true);
- interface = new ElfInterfaceFake(memory);
- elf->FakeSetInterface(interface);
- interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800);
- map_info->elf.reset(elf);
+ CreateFakeElf(map_info);
- map_info = maps_->Get(6);
+ map_info = maps_->Get(7);
ASSERT_TRUE(map_info != nullptr);
- memory = new MemoryFake;
- elf = new ElfFake(memory);
- elf->FakeSetValid(true);
- interface = new ElfInterfaceFake(memory);
- elf->FakeSetInterface(interface);
- interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800);
- map_info->elf.reset(elf);
+ CreateFakeElf(map_info);
+ }
+
+ void SetUp() override {
+ memory_ = new MemoryFake;
+ process_memory_.reset(memory_);
+
+ Init(ARCH_ARM);
}
template <typename EhdrType, typename ShdrType>
@@ -325,6 +322,8 @@
}
TEST_F(JitDebugTest, get_elf_x86) {
+ Init(ARCH_X86);
+
CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
WriteDescriptor32(0xf800, 0x200000);
@@ -342,12 +341,13 @@
}
TEST_F(JitDebugTest, get_elf_64) {
+ Init(ARCH_ARM64);
+
CreateElf<Elf64_Ehdr, Elf64_Shdr>(0x4000, ELFCLASS64, EM_AARCH64, 0x1500, 0x200);
WriteDescriptor64(0xf800, 0x200000);
WriteEntry64(0x200000, 0, 0, 0x4000, 0x1000);
- jit_debug_->SetArch(ARCH_ARM64);
Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
ASSERT_TRUE(elf != nullptr);
@@ -397,6 +397,8 @@
// Change the name of the map that includes the value and verify this works.
MapInfo* map_info = maps_->Get(5);
map_info->name = "/system/lib/libart.so";
+ map_info = maps_->Get(6);
+ map_info->name = "/system/lib/libart.so";
jit_debug_.reset(new JitDebug(process_memory_, libs));
// Make sure that clearing our copy of the libs doesn't affect the
// JitDebug object.
diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
index 866b5b4..a66685a 100644
--- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
+++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
@@ -27,13 +27,14 @@
#include <vector>
#include <android-base/file.h>
-#include <android-base/test_utils.h>
#include <gtest/gtest.h>
#include <unwindstack/Elf.h>
#include <unwindstack/MapInfo.h>
+#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
+#include "ElfTestUtils.h"
#include "MemoryFake.h"
namespace unwindstack {
@@ -58,16 +59,16 @@
}
static void SetUpTestCase() {
- std::vector<uint8_t> buffer(1024);
- memset(buffer.data(), 0, buffer.size());
+ std::vector<uint8_t> buffer(12288, 0);
memcpy(buffer.data(), ELFMAG, SELFMAG);
buffer[EI_CLASS] = ELFCLASS32;
- ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
+ ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), 1024));
memset(buffer.data(), 0, buffer.size());
- memcpy(&buffer[0x100], ELFMAG, SELFMAG);
- buffer[0x100 + EI_CLASS] = ELFCLASS64;
- ASSERT_TRUE(android::base::WriteFully(elf_at_100_.fd, buffer.data(), buffer.size()));
+ memcpy(&buffer[0x1000], ELFMAG, SELFMAG);
+ buffer[0x1000 + EI_CLASS] = ELFCLASS64;
+ buffer[0x2000] = 0xff;
+ ASSERT_TRUE(android::base::WriteFully(elf_at_1000_.fd, buffer.data(), buffer.size()));
InitElf<Elf32_Ehdr, Elf32_Shdr>(elf32_at_map_.fd, 0x1000, 0x2000, ELFCLASS32);
InitElf<Elf64_Ehdr, Elf64_Shdr>(elf64_at_map_.fd, 0x2000, 0x3000, ELFCLASS64);
@@ -83,18 +84,18 @@
static TemporaryFile elf_;
- static TemporaryFile elf_at_100_;
+ static TemporaryFile elf_at_1000_;
static TemporaryFile elf32_at_map_;
static TemporaryFile elf64_at_map_;
};
TemporaryFile MapInfoCreateMemoryTest::elf_;
-TemporaryFile MapInfoCreateMemoryTest::elf_at_100_;
+TemporaryFile MapInfoCreateMemoryTest::elf_at_1000_;
TemporaryFile MapInfoCreateMemoryTest::elf32_at_map_;
TemporaryFile MapInfoCreateMemoryTest::elf64_at_map_;
TEST_F(MapInfoCreateMemoryTest, end_le_start) {
- MapInfo info(0x100, 0x100, 0, 0, elf_.path);
+ MapInfo info(nullptr, 0x100, 0x100, 0, 0, elf_.path);
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() == nullptr);
@@ -112,11 +113,12 @@
// Verify that if the offset is non-zero but there is no elf at the offset,
// that the full file is used.
TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) {
- MapInfo info(0x100, 0x200, 0x100, 0, elf_.path);
+ MapInfo info(nullptr, 0x100, 0x200, 0x100, 0, elf_.path);
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
ASSERT_EQ(0x100U, info.elf_offset);
+ EXPECT_EQ(0x100U, info.elf_start_offset);
// Read the entire file.
std::vector<uint8_t> buffer(1024);
@@ -128,16 +130,55 @@
}
ASSERT_FALSE(memory->ReadFully(1024, buffer.data(), 1));
+
+ // Now verify the elf start offset is set correctly based on the previous
+ // info.
+ MapInfo prev_info(nullptr, 0, 0x100, 0x10, 0, "");
+ info.prev_map = &prev_info;
+
+ // No preconditions met, change each one until it should set the elf start
+ // offset to zero.
+ info.elf_offset = 0;
+ info.elf_start_offset = 0;
+ memory.reset(info.CreateMemory(process_memory_));
+ ASSERT_TRUE(memory.get() != nullptr);
+ ASSERT_EQ(0x100U, info.elf_offset);
+ EXPECT_EQ(0x100U, info.elf_start_offset);
+
+ prev_info.offset = 0;
+ info.elf_offset = 0;
+ info.elf_start_offset = 0;
+ memory.reset(info.CreateMemory(process_memory_));
+ ASSERT_TRUE(memory.get() != nullptr);
+ ASSERT_EQ(0x100U, info.elf_offset);
+ EXPECT_EQ(0x100U, info.elf_start_offset);
+
+ prev_info.flags = PROT_READ;
+ info.elf_offset = 0;
+ info.elf_start_offset = 0;
+ memory.reset(info.CreateMemory(process_memory_));
+ ASSERT_TRUE(memory.get() != nullptr);
+ ASSERT_EQ(0x100U, info.elf_offset);
+ EXPECT_EQ(0x100U, info.elf_start_offset);
+
+ prev_info.name = info.name;
+ info.elf_offset = 0;
+ info.elf_start_offset = 0;
+ memory.reset(info.CreateMemory(process_memory_));
+ ASSERT_TRUE(memory.get() != nullptr);
+ ASSERT_EQ(0x100U, info.elf_offset);
+ EXPECT_EQ(0U, info.elf_start_offset);
}
// Verify that if the offset is non-zero and there is an elf at that
// offset, that only part of the file is used.
TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) {
- MapInfo info(0x100, 0x200, 0x100, 0, elf_at_100_.path);
+ MapInfo info(nullptr, 0x100, 0x200, 0x1000, 0, elf_at_1000_.path);
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
ASSERT_EQ(0U, info.elf_offset);
+ EXPECT_EQ(0U, info.elf_start_offset);
// Read the valid part of the file.
std::vector<uint8_t> buffer(0x100);
@@ -156,11 +197,12 @@
// embedded elf is bigger than the initial map, the new object is larger
// than the original map size. Do this for a 32 bit elf and a 64 bit elf.
TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
- MapInfo info(0x5000, 0x6000, 0x1000, 0, elf32_at_map_.path);
+ MapInfo info(nullptr, 0x5000, 0x6000, 0x1000, 0, elf32_at_map_.path);
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
ASSERT_EQ(0U, info.elf_offset);
+ EXPECT_EQ(0U, info.elf_start_offset);
// Verify the memory is a valid elf.
uint8_t e_ident[SELFMAG + 1];
@@ -172,11 +214,12 @@
}
TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
- MapInfo info(0x7000, 0x8000, 0x2000, 0, elf64_at_map_.path);
+ MapInfo info(nullptr, 0x7000, 0x8000, 0x2000, 0, elf64_at_map_.path);
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
ASSERT_EQ(0U, info.elf_offset);
+ EXPECT_EQ(0U, info.elf_start_offset);
// Verify the memory is a valid elf.
uint8_t e_ident[SELFMAG + 1];
@@ -192,27 +235,24 @@
// Set up some memory so that a valid local memory object would
// be returned if the file mapping fails, but the device check is incorrect.
std::vector<uint8_t> buffer(1024);
- MapInfo info;
- info.start = reinterpret_cast<uint64_t>(buffer.data());
- info.end = info.start + buffer.size();
- info.offset = 0;
+ uint64_t start = reinterpret_cast<uint64_t>(buffer.data());
+ MapInfo info(nullptr, start, start + buffer.size(), 0, 0x8000, "/dev/something");
- info.flags = 0x8000;
- info.name = "/dev/something";
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() == nullptr);
}
TEST_F(MapInfoCreateMemoryTest, process_memory) {
- MapInfo info;
- info.start = 0x2000;
- info.end = 0x3000;
- info.offset = 0;
+ MapInfo info(nullptr, 0x2000, 0x3000, 0, PROT_READ, "");
+
+ Elf32_Ehdr ehdr = {};
+ TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
+ std::vector<uint8_t> buffer(1024);
+ memcpy(buffer.data(), &ehdr, sizeof(ehdr));
// Verify that the the process_memory object is used, so seed it
// with memory.
- std::vector<uint8_t> buffer(1024);
- for (size_t i = 0; i < buffer.size(); i++) {
+ for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
buffer[i] = i % 256;
}
memory_->SetMemory(info.start, buffer.data(), buffer.size());
@@ -222,7 +262,8 @@
memset(buffer.data(), 0, buffer.size());
ASSERT_TRUE(memory->ReadFully(0, buffer.data(), buffer.size()));
- for (size_t i = 0; i < buffer.size(); i++) {
+ ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
+ for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
ASSERT_EQ(i % 256, buffer[i]) << "Failed at byte " << i;
}
@@ -230,4 +271,130 @@
ASSERT_FALSE(memory->ReadFully(buffer.size(), buffer.data(), 1));
}
+TEST_F(MapInfoCreateMemoryTest, valid_rosegment_zero_offset) {
+ Maps maps;
+ maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
+ maps.Add(0x1000, 0x2600, 0, PROT_READ, "/only/in/memory.so", 0);
+ maps.Add(0x3000, 0x5000, 0x4000, PROT_READ | PROT_EXEC, "/only/in/memory.so", 0);
+
+ Elf32_Ehdr ehdr = {};
+ TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
+ memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
+ memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x1600 - sizeof(ehdr), 0xab);
+
+ // Set the memory in the r-x map.
+ memory_->SetMemoryBlock(0x3000, 0x2000, 0x5d);
+
+ MapInfo* map_info = maps.Find(0x3000);
+ ASSERT_TRUE(map_info != nullptr);
+
+ std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
+ ASSERT_TRUE(mem.get() != nullptr);
+ EXPECT_EQ(0x4000UL, map_info->elf_offset);
+ EXPECT_EQ(0x4000UL, map_info->offset);
+ EXPECT_EQ(0U, map_info->elf_start_offset);
+
+ // Verify that reading values from this memory works properly.
+ std::vector<uint8_t> buffer(0x4000);
+ size_t bytes = mem->Read(0, buffer.data(), buffer.size());
+ ASSERT_EQ(0x1600UL, bytes);
+ ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
+ for (size_t i = sizeof(ehdr); i < bytes; i++) {
+ ASSERT_EQ(0xab, buffer[i]) << "Failed at byte " << i;
+ }
+
+ bytes = mem->Read(0x4000, buffer.data(), buffer.size());
+ ASSERT_EQ(0x2000UL, bytes);
+ for (size_t i = 0; i < bytes; i++) {
+ ASSERT_EQ(0x5d, buffer[i]) << "Failed at byte " << i;
+ }
+}
+
+TEST_F(MapInfoCreateMemoryTest, valid_rosegment_non_zero_offset) {
+ Maps maps;
+ maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
+ maps.Add(0x1000, 0x2000, 0, PROT_READ, "/only/in/memory.apk", 0);
+ maps.Add(0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
+ maps.Add(0x3000, 0x4000, 0xa000, PROT_READ, "/only/in/memory.apk", 0);
+ maps.Add(0x4000, 0x5000, 0xb000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0);
+
+ Elf32_Ehdr ehdr = {};
+ TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
+
+ // Setup an elf at offset 0x1000 in memory.
+ memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr));
+ memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x2000 - sizeof(ehdr), 0x12);
+ memory_->SetMemoryBlock(0x2000, 0x1000, 0x23);
+
+ // Setup an elf at offset 0x3000 in memory..
+ memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
+ memory_->SetMemoryBlock(0x3000 + sizeof(ehdr), 0x4000 - sizeof(ehdr), 0x34);
+ memory_->SetMemoryBlock(0x4000, 0x1000, 0x43);
+
+ MapInfo* map_info = maps.Find(0x4000);
+ ASSERT_TRUE(map_info != nullptr);
+
+ std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
+ ASSERT_TRUE(mem.get() != nullptr);
+ EXPECT_EQ(0x1000UL, map_info->elf_offset);
+ EXPECT_EQ(0xb000UL, map_info->offset);
+ EXPECT_EQ(0xa000UL, map_info->elf_start_offset);
+
+ // Verify that reading values from this memory works properly.
+ std::vector<uint8_t> buffer(0x4000);
+ size_t bytes = mem->Read(0, buffer.data(), buffer.size());
+ ASSERT_EQ(0x1000UL, bytes);
+ ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr)));
+ for (size_t i = sizeof(ehdr); i < bytes; i++) {
+ ASSERT_EQ(0x34, buffer[i]) << "Failed at byte " << i;
+ }
+
+ bytes = mem->Read(0x1000, buffer.data(), buffer.size());
+ ASSERT_EQ(0x1000UL, bytes);
+ for (size_t i = 0; i < bytes; i++) {
+ ASSERT_EQ(0x43, buffer[i]) << "Failed at byte " << i;
+ }
+}
+
+TEST_F(MapInfoCreateMemoryTest, rosegment_from_file) {
+ Maps maps;
+ maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0);
+ maps.Add(0x1000, 0x2000, 0x1000, PROT_READ, elf_at_1000_.path, 0);
+ maps.Add(0x2000, 0x3000, 0x2000, PROT_READ | PROT_EXEC, elf_at_1000_.path, 0);
+
+ MapInfo* map_info = maps.Find(0x2000);
+ ASSERT_TRUE(map_info != nullptr);
+
+ // Set up the size
+ Elf64_Ehdr ehdr;
+ ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET));
+ ASSERT_TRUE(android::base::ReadFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr)));
+
+ // Will not give the elf memory, because the read-only entry does not
+ // extend over the executable segment.
+ std::unique_ptr<Memory> memory(map_info->CreateMemory(process_memory_));
+ ASSERT_TRUE(memory.get() != nullptr);
+ std::vector<uint8_t> buffer(0x100);
+ EXPECT_EQ(0x2000U, map_info->offset);
+ EXPECT_EQ(0U, map_info->elf_offset);
+ EXPECT_EQ(0U, map_info->elf_start_offset);
+ ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 0x100));
+ EXPECT_EQ(0xffU, buffer[0]);
+
+ // Now init the elf data enough so that the file memory object will be used.
+ ehdr.e_shoff = 0x4000;
+ ehdr.e_shnum = 1;
+ ehdr.e_shentsize = 0x100;
+ ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET));
+ ASSERT_TRUE(android::base::WriteFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr)));
+
+ memory.reset(map_info->CreateMemory(process_memory_));
+ EXPECT_EQ(0x2000U, map_info->offset);
+ EXPECT_EQ(0x1000U, map_info->elf_offset);
+ EXPECT_EQ(0x1000U, map_info->elf_start_offset);
+ Elf64_Ehdr ehdr_mem;
+ ASSERT_TRUE(memory->ReadFully(0, &ehdr_mem, sizeof(ehdr_mem)));
+ EXPECT_TRUE(memcmp(&ehdr, &ehdr_mem, sizeof(ehdr)) == 0);
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoGetBuildIDTest.cpp b/libunwindstack/tests/MapInfoGetBuildIDTest.cpp
new file mode 100644
index 0000000..3b89c59
--- /dev/null
+++ b/libunwindstack/tests/MapInfoGetBuildIDTest.cpp
@@ -0,0 +1,183 @@
+/*
+ * 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 <elf.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <atomic>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <android-base/test_utils.h>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
+
+#include "ElfFake.h"
+#include "ElfTestUtils.h"
+#include "MemoryFake.h"
+
+namespace unwindstack {
+
+class MapInfoGetBuildIDTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ tf_.reset(new TemporaryFile);
+
+ memory_ = new MemoryFake;
+ elf_ = new ElfFake(new MemoryFake);
+ elf_interface_ = new ElfInterfaceFake(memory_);
+ elf_->FakeSetInterface(elf_interface_);
+ elf_container_.reset(elf_);
+ map_info_.reset(new MapInfo(nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, tf_->path));
+ }
+
+ void MultipleThreadTest(std::string expected_build_id);
+
+ MemoryFake* memory_;
+ ElfFake* elf_;
+ ElfInterfaceFake* elf_interface_;
+ std::unique_ptr<ElfFake> elf_container_;
+ std::unique_ptr<MapInfo> map_info_;
+ std::unique_ptr<TemporaryFile> tf_;
+};
+
+TEST_F(MapInfoGetBuildIDTest, no_elf_and_no_valid_elf_in_memory) {
+ MapInfo info(nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
+
+ EXPECT_EQ("", info.GetBuildID());
+}
+
+TEST_F(MapInfoGetBuildIDTest, from_elf) {
+ map_info_->elf.reset(elf_container_.release());
+ elf_interface_->FakeSetBuildID("FAKE_BUILD_ID");
+
+ EXPECT_EQ("FAKE_BUILD_ID", map_info_->GetBuildID());
+}
+
+void MapInfoGetBuildIDTest::MultipleThreadTest(std::string expected_build_id) {
+ static constexpr size_t kNumConcurrentThreads = 100;
+
+ std::string build_id_values[kNumConcurrentThreads];
+ std::vector<std::thread*> threads;
+
+ std::atomic_bool wait;
+ wait = true;
+ // Create all of the threads and have them do the GetLoadBias at the same time
+ // to make it likely that a race will occur.
+ for (size_t i = 0; i < kNumConcurrentThreads; i++) {
+ std::thread* thread = new std::thread([i, this, &wait, &build_id_values]() {
+ while (wait)
+ ;
+ build_id_values[i] = map_info_->GetBuildID();
+ });
+ threads.push_back(thread);
+ }
+
+ // Set them all going and wait for the threads to finish.
+ wait = false;
+ for (auto thread : threads) {
+ thread->join();
+ delete thread;
+ }
+
+ // Now verify that all of the elf files are exactly the same and valid.
+ for (size_t i = 0; i < kNumConcurrentThreads; i++) {
+ EXPECT_EQ(expected_build_id, build_id_values[i]) << "Thread " << i << " mismatched.";
+ }
+}
+
+TEST_F(MapInfoGetBuildIDTest, multiple_thread_elf_exists) {
+ map_info_->elf.reset(elf_container_.release());
+ elf_interface_->FakeSetBuildID("FAKE_BUILD_ID");
+
+ MultipleThreadTest("FAKE_BUILD_ID");
+}
+
+static void InitElfData(int fd) {
+ Elf32_Ehdr ehdr;
+ TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM);
+ ehdr.e_shoff = 0x2000;
+ ehdr.e_shnum = 3;
+ ehdr.e_shentsize = sizeof(Elf32_Shdr);
+ ehdr.e_shstrndx = 2;
+ off_t offset = 0;
+ ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(ehdr)), write(fd, &ehdr, sizeof(ehdr)));
+
+ char note_section[128];
+ Elf32_Nhdr note_header = {};
+ note_header.n_namesz = 4; // "GNU"
+ note_header.n_descsz = 12; // "ELF_BUILDID"
+ note_header.n_type = NT_GNU_BUILD_ID;
+ memcpy(¬e_section, ¬e_header, sizeof(note_header));
+ size_t note_offset = sizeof(note_header);
+ memcpy(¬e_section[note_offset], "GNU", sizeof("GNU"));
+ note_offset += sizeof("GNU");
+ memcpy(¬e_section[note_offset], "ELF_BUILDID", sizeof("ELF_BUILDID"));
+ note_offset += sizeof("ELF_BUILDID");
+
+ Elf32_Shdr shdr = {};
+ shdr.sh_type = SHT_NOTE;
+ shdr.sh_name = 0x500;
+ shdr.sh_offset = 0xb000;
+ shdr.sh_size = sizeof(note_section);
+ offset += ehdr.e_shoff + sizeof(shdr);
+ ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(shdr)), write(fd, &shdr, sizeof(shdr)));
+
+ // 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;
+ offset += sizeof(shdr);
+ ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(shdr)), write(fd, &shdr, sizeof(shdr)));
+
+ offset = 0xf500;
+ ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(".note.gnu.build-id")),
+ write(fd, ".note.gnu.build-id", sizeof(".note.gnu.build-id")));
+
+ offset = 0xb000;
+ ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(note_section)),
+ write(fd, note_section, sizeof(note_section)));
+}
+
+TEST_F(MapInfoGetBuildIDTest, from_memory) {
+ InitElfData(tf_->fd);
+
+ EXPECT_EQ("ELF_BUILDID", map_info_->GetBuildID());
+}
+
+TEST_F(MapInfoGetBuildIDTest, multiple_thread_elf_exists_in_memory) {
+ InitElfData(tf_->fd);
+
+ MultipleThreadTest("ELF_BUILDID");
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp
index 861b82f..d7b8485 100644
--- a/libunwindstack/tests/MapInfoGetElfTest.cpp
+++ b/libunwindstack/tests/MapInfoGetElfTest.cpp
@@ -29,7 +29,6 @@
#include <vector>
#include <android-base/file.h>
-#include <android-base/test_utils.h>
#include <gtest/gtest.h>
#include <unwindstack/Elf.h>
@@ -69,83 +68,69 @@
};
TEST_F(MapInfoGetElfTest, invalid) {
- MapInfo info(0x1000, 0x2000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
// The map is empty, but this should still create an invalid elf object.
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
ASSERT_TRUE(elf != nullptr);
ASSERT_FALSE(elf->valid());
}
TEST_F(MapInfoGetElfTest, valid32) {
- MapInfo info(0x3000, 0x4000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x3000, 0x4000, 0, PROT_READ, "");
Elf32_Ehdr ehdr;
TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
EXPECT_EQ(ELFCLASS32, elf->class_type());
+
+ // Now verify that an empty process memory returns an invalid elf object.
+ info.elf.reset();
+ elf = info.GetElf(std::shared_ptr<Memory>(), ARCH_ARM);
+ ASSERT_TRUE(elf != nullptr);
+ ASSERT_FALSE(elf->valid());
}
TEST_F(MapInfoGetElfTest, valid64) {
- MapInfo info(0x8000, 0x9000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x8000, 0x9000, 0, PROT_READ, "");
Elf64_Ehdr ehdr;
TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_, ARCH_ARM64);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
EXPECT_EQ(ELFCLASS64, elf->class_type());
}
-TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) {
- MapInfo info(0x4000, 0x8000, 0, PROT_READ, "");
+TEST_F(MapInfoGetElfTest, invalid_arch_mismatch) {
+ MapInfo info(nullptr, 0x3000, 0x4000, 0, PROT_READ, "");
- TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
- [&](uint64_t offset, const void* ptr, size_t size) {
- memory_->SetMemory(0x4000 + offset, ptr, size);
- });
+ Elf32_Ehdr ehdr;
+ TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
+ memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_, ARCH_X86);
ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
- EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
- EXPECT_EQ(ELFCLASS32, elf->class_type());
- EXPECT_TRUE(elf->gnu_debugdata_interface() == nullptr);
-}
-
-TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) {
- MapInfo info(0x6000, 0x8000, 0, PROT_READ, "");
-
- TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
- [&](uint64_t offset, const void* ptr, size_t size) {
- memory_->SetMemory(0x6000 + offset, ptr, size);
- });
-
- Elf* elf = info.GetElf(process_memory_, false);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
- EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
- EXPECT_EQ(ELFCLASS64, elf->class_type());
- EXPECT_TRUE(elf->gnu_debugdata_interface() == nullptr);
+ ASSERT_FALSE(elf->valid());
}
TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
- MapInfo info(0x2000, 0x3000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x2000, 0x3000, 0, PROT_READ, "");
TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
[&](uint64_t offset, const void* ptr, size_t size) {
memory_->SetMemory(0x2000 + offset, ptr, size);
});
- Elf* elf = info.GetElf(process_memory_, true);
+ Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
@@ -154,14 +139,14 @@
}
TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
- MapInfo info(0x5000, 0x8000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x5000, 0x8000, 0, PROT_READ, "");
TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
[&](uint64_t offset, const void* ptr, size_t size) {
memory_->SetMemory(0x5000 + offset, ptr, size);
});
- Elf* elf = info.GetElf(process_memory_, true);
+ Elf* elf = info.GetElf(process_memory_, ARCH_ARM64);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
@@ -170,26 +155,26 @@
}
TEST_F(MapInfoGetElfTest, end_le_start) {
- MapInfo info(0x1000, 0x1000, 0, PROT_READ, elf_.path);
+ MapInfo info(nullptr, 0x1000, 0x1000, 0, PROT_READ, elf_.path);
Elf32_Ehdr ehdr;
TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr)));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
ASSERT_TRUE(elf != nullptr);
ASSERT_FALSE(elf->valid());
info.elf.reset();
info.end = 0xfff;
- elf = info.GetElf(process_memory_, false);
+ elf = info.GetElf(process_memory_, ARCH_ARM);
ASSERT_TRUE(elf != nullptr);
ASSERT_FALSE(elf->valid());
// Make sure this test is valid.
info.elf.reset();
info.end = 0x2000;
- elf = info.GetElf(process_memory_, false);
+ elf = info.GetElf(process_memory_, ARCH_ARM);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
}
@@ -197,7 +182,7 @@
// Verify that if the offset is non-zero but there is no elf at the offset,
// that the full file is used.
TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) {
- MapInfo info(0x1000, 0x2000, 0x100, PROT_READ, elf_.path);
+ MapInfo info(nullptr, 0x1000, 0x2000, 0x100, PROT_READ, elf_.path);
std::vector<uint8_t> buffer(0x1000);
memset(buffer.data(), 0, buffer.size());
@@ -206,7 +191,7 @@
memcpy(buffer.data(), &ehdr, sizeof(ehdr));
ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
ASSERT_TRUE(elf->memory() != nullptr);
@@ -226,7 +211,7 @@
// Verify that if the offset is non-zero and there is an elf at that
// offset, that only part of the file is used.
TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) {
- MapInfo info(0x1000, 0x2000, 0x2000, PROT_READ, elf_.path);
+ MapInfo info(nullptr, 0x1000, 0x2000, 0x2000, PROT_READ, elf_.path);
std::vector<uint8_t> buffer(0x4000);
memset(buffer.data(), 0, buffer.size());
@@ -235,7 +220,7 @@
memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
ASSERT_TRUE(elf->memory() != nullptr);
@@ -256,7 +241,7 @@
// embedded elf is bigger than the initial map, the new object is larger
// than the original map size. Do this for a 32 bit elf and a 64 bit elf.
TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
- MapInfo info(0x5000, 0x6000, 0x1000, PROT_READ, elf_.path);
+ MapInfo info(nullptr, 0x5000, 0x6000, 0x1000, PROT_READ, elf_.path);
std::vector<uint8_t> buffer(0x4000);
memset(buffer.data(), 0, buffer.size());
@@ -268,7 +253,7 @@
memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_, ARCH_ARM);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
ASSERT_TRUE(elf->memory() != nullptr);
@@ -284,7 +269,7 @@
}
TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
- MapInfo info(0x7000, 0x8000, 0x1000, PROT_READ, elf_.path);
+ MapInfo info(nullptr, 0x7000, 0x8000, 0x1000, PROT_READ, elf_.path);
std::vector<uint8_t> buffer(0x4000);
memset(buffer.data(), 0, buffer.size());
@@ -296,7 +281,7 @@
memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_, ARCH_ARM64);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
ASSERT_TRUE(elf->memory() != nullptr);
@@ -311,29 +296,9 @@
ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
}
-TEST_F(MapInfoGetElfTest, process_memory_not_read_only) {
- MapInfo info(0x9000, 0xa000, 0x1000, 0, "");
-
- // Create valid elf data in process memory only.
- Elf64_Ehdr ehdr;
- TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
- ehdr.e_shoff = 0x2000;
- ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
- ehdr.e_shnum = 0;
- memory_->SetMemory(0x9000, &ehdr, sizeof(ehdr));
-
- Elf* elf = info.GetElf(process_memory_, false);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_FALSE(elf->valid());
-
- info.elf.reset();
- info.flags = PROT_READ;
- elf = info.GetElf(process_memory_, false);
- ASSERT_TRUE(elf->valid());
-}
-
TEST_F(MapInfoGetElfTest, check_device_maps) {
- MapInfo info(0x7000, 0x8000, 0x1000, PROT_READ | MAPS_FLAGS_DEVICE_MAP, "/dev/something");
+ MapInfo info(nullptr, 0x7000, 0x8000, 0x1000, PROT_READ | MAPS_FLAGS_DEVICE_MAP,
+ "/dev/something");
// Create valid elf data in process memory for this to verify that only
// the name is causing invalid elf data.
@@ -344,20 +309,20 @@
ehdr.e_shnum = 0;
memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_, ARCH_X86_64);
ASSERT_TRUE(elf != nullptr);
ASSERT_FALSE(elf->valid());
// Set the name to nothing to verify that it still fails.
info.elf.reset();
info.name = "";
- elf = info.GetElf(process_memory_, false);
+ elf = info.GetElf(process_memory_, ARCH_X86_64);
ASSERT_FALSE(elf->valid());
// Change the flags and verify the elf is valid now.
info.elf.reset();
info.flags = PROT_READ;
- elf = info.GetElf(process_memory_, false);
+ elf = info.GetElf(process_memory_, ARCH_X86_64);
ASSERT_TRUE(elf->valid());
}
@@ -378,12 +343,12 @@
wait = true;
// Create all of the threads and have them do the GetElf at the same time
// to make it likely that a race will occur.
- MapInfo info(0x7000, 0x8000, 0x1000, PROT_READ, "");
+ MapInfo info(nullptr, 0x7000, 0x8000, 0x1000, PROT_READ, "");
for (size_t i = 0; i < kNumConcurrentThreads; i++) {
std::thread* thread = new std::thread([i, this, &wait, &info, &elf_in_threads]() {
while (wait)
;
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_, ARCH_X86_64);
elf_in_threads[i] = elf;
});
threads.push_back(thread);
diff --git a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
index 7e64a8a..f5ac6cb 100644
--- a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
+++ b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
@@ -50,7 +50,7 @@
process_memory_.reset(memory_);
elf_ = new ElfFake(new MemoryFake);
elf_container_.reset(elf_);
- map_info_.reset(new MapInfo(0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, ""));
+ map_info_.reset(new MapInfo(nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, ""));
}
void MultipleThreadTest(uint64_t expected_load_bias);
@@ -63,7 +63,7 @@
};
TEST_F(MapInfoGetLoadBiasTest, no_elf_and_no_valid_elf_in_memory) {
- MapInfo info(0x1000, 0x2000, 0, PROT_READ, "");
+ MapInfo info(nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
EXPECT_EQ(0U, info.GetLoadBias(process_memory_));
}
diff --git a/libunwindstack/tests/MapInfoTest.cpp b/libunwindstack/tests/MapInfoTest.cpp
new file mode 100644
index 0000000..e2cbb98
--- /dev/null
+++ b/libunwindstack/tests/MapInfoTest.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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 <stdint.h>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Maps.h>
+
+#include "ElfFake.h"
+
+namespace unwindstack {
+
+TEST(MapInfoTest, maps_constructor_const_char) {
+ MapInfo prev_map(nullptr, 0, 0, 0, 0, "");
+ MapInfo map_info(&prev_map, 1, 2, 3, 4, "map");
+
+ EXPECT_EQ(&prev_map, map_info.prev_map);
+ EXPECT_EQ(1UL, map_info.start);
+ EXPECT_EQ(2UL, map_info.end);
+ 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(0UL, map_info.elf_offset);
+ EXPECT_TRUE(map_info.elf.get() == nullptr);
+}
+
+TEST(MapInfoTest, maps_constructor_string) {
+ std::string name("string_map");
+ MapInfo prev_map(nullptr, 0, 0, 0, 0, "");
+ MapInfo map_info(&prev_map, 1, 2, 3, 4, name);
+
+ EXPECT_EQ(&prev_map, map_info.prev_map);
+ EXPECT_EQ(1UL, map_info.start);
+ EXPECT_EQ(2UL, map_info.end);
+ 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(0UL, map_info.elf_offset);
+ EXPECT_TRUE(map_info.elf.get() == nullptr);
+}
+
+TEST(MapInfoTest, get_function_name) {
+ ElfFake* elf = new ElfFake(nullptr);
+ ElfInterfaceFake* interface = new ElfInterfaceFake(nullptr);
+ elf->FakeSetInterface(interface);
+ interface->FakePushFunctionData(FunctionData("function", 1000));
+
+ MapInfo map_info(nullptr, 1, 2, 3, 4, "");
+ map_info.elf.reset(elf);
+
+ std::string name;
+ uint64_t offset;
+ ASSERT_TRUE(map_info.GetFunctionName(1000, &name, &offset));
+ EXPECT_EQ("function", name);
+ EXPECT_EQ(1000UL, offset);
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/tests/MapsTest.cpp b/libunwindstack/tests/MapsTest.cpp
index 9622ba5..b4197f2 100644
--- a/libunwindstack/tests/MapsTest.cpp
+++ b/libunwindstack/tests/MapsTest.cpp
@@ -19,7 +19,6 @@
#include <android-base/file.h>
#include <android-base/stringprintf.h>
-#include <android-base/test_utils.h>
#include <gtest/gtest.h>
#include <unwindstack/Maps.h>
@@ -63,7 +62,7 @@
}
TEST(MapsTest, verify_parse_line) {
- MapInfo info;
+ MapInfo info(nullptr, 0, 0, 0, 0, "");
VerifyLine("01-02 rwxp 03 04:05 06\n", &info);
EXPECT_EQ(1U, info.start);
@@ -136,7 +135,7 @@
}
TEST(MapsTest, verify_large_values) {
- MapInfo info;
+ MapInfo info(nullptr, 0, 0, 0, 0, "");
#if defined(__LP64__)
VerifyLine("fabcdef012345678-f12345678abcdef8 rwxp f0b0d0f010305070 00:00 0\n", &info);
EXPECT_EQ(0xfabcdef012345678UL, info.start);
diff --git a/libunwindstack/tests/MemoryCacheTest.cpp b/libunwindstack/tests/MemoryCacheTest.cpp
new file mode 100644
index 0000000..a3def20
--- /dev/null
+++ b/libunwindstack/tests/MemoryCacheTest.cpp
@@ -0,0 +1,143 @@
+/*
+ * 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 <stdint.h>
+
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/Memory.h>
+
+#include "MemoryFake.h"
+
+namespace unwindstack {
+
+class MemoryCacheTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ memory_ = new MemoryFake;
+ memory_cache_.reset(new MemoryCache(memory_));
+
+ memory_->SetMemoryBlock(0x8000, 4096, 0xab);
+ memory_->SetMemoryBlock(0x9000, 4096, 0xde);
+ memory_->SetMemoryBlock(0xa000, 3000, 0x50);
+ }
+
+ MemoryFake* memory_;
+ std::unique_ptr<MemoryCache> memory_cache_;
+
+ constexpr static size_t kMaxCachedSize = 64;
+};
+
+TEST_F(MemoryCacheTest, cached_read) {
+ for (size_t i = 1; i <= kMaxCachedSize; i++) {
+ std::vector<uint8_t> buffer(i);
+ ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
+ << "Read failed at size " << i;
+ ASSERT_EQ(std::vector<uint8_t>(i, 0xab), buffer) << "Failed at size " << i;
+ }
+
+ // Verify the cached data is used.
+ memory_->SetMemoryBlock(0x8000, 4096, 0xff);
+ for (size_t i = 1; i <= kMaxCachedSize; i++) {
+ std::vector<uint8_t> buffer(i);
+ ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
+ << "Read failed at size " << i;
+ ASSERT_EQ(std::vector<uint8_t>(i, 0xab), buffer) << "Failed at size " << i;
+ }
+}
+
+TEST_F(MemoryCacheTest, no_cached_read_after_clear) {
+ for (size_t i = 1; i <= kMaxCachedSize; i++) {
+ std::vector<uint8_t> buffer(i);
+ ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
+ << "Read failed at size " << i;
+ ASSERT_EQ(std::vector<uint8_t>(i, 0xab), buffer) << "Failed at size " << i;
+ }
+
+ // Verify the cached data is not used after a reset.
+ memory_cache_->Clear();
+ memory_->SetMemoryBlock(0x8000, 4096, 0xff);
+ for (size_t i = 1; i <= kMaxCachedSize; i++) {
+ std::vector<uint8_t> buffer(i);
+ ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
+ << "Read failed at size " << i;
+ ASSERT_EQ(std::vector<uint8_t>(i, 0xff), buffer) << "Failed at size " << i;
+ }
+}
+
+TEST_F(MemoryCacheTest, cached_read_across_caches) {
+ std::vector<uint8_t> expect(16, 0xab);
+ expect.resize(32, 0xde);
+
+ std::vector<uint8_t> buffer(32);
+ ASSERT_TRUE(memory_cache_->ReadFully(0x8ff0, buffer.data(), 32));
+ ASSERT_EQ(expect, buffer);
+
+ // Verify the cached data is used.
+ memory_->SetMemoryBlock(0x8000, 4096, 0xff);
+ memory_->SetMemoryBlock(0x9000, 4096, 0xff);
+ ASSERT_TRUE(memory_cache_->ReadFully(0x8ff0, buffer.data(), 32));
+ ASSERT_EQ(expect, buffer);
+}
+
+TEST_F(MemoryCacheTest, no_cache_read) {
+ for (size_t i = kMaxCachedSize + 1; i < 2 * kMaxCachedSize; i++) {
+ std::vector<uint8_t> buffer(i);
+ ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
+ << "Read failed at size " << i;
+ ASSERT_EQ(std::vector<uint8_t>(i, 0xab), buffer) << "Failed at size " << i;
+ }
+
+ // Verify the cached data is not used.
+ memory_->SetMemoryBlock(0x8000, 4096, 0xff);
+ for (size_t i = kMaxCachedSize + 1; i < 2 * kMaxCachedSize; i++) {
+ std::vector<uint8_t> buffer(i);
+ ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i))
+ << "Read failed at size " << i;
+ ASSERT_EQ(std::vector<uint8_t>(i, 0xff), buffer) << "Failed at size " << i;
+ }
+}
+
+TEST_F(MemoryCacheTest, read_for_cache_fail) {
+ std::vector<uint8_t> buffer(kMaxCachedSize);
+ ASSERT_TRUE(memory_cache_->ReadFully(0xa010, buffer.data(), kMaxCachedSize));
+ ASSERT_EQ(std::vector<uint8_t>(kMaxCachedSize, 0x50), buffer);
+
+ // Verify the cached data is not used.
+ memory_->SetMemoryBlock(0xa000, 3000, 0xff);
+ ASSERT_TRUE(memory_cache_->ReadFully(0xa010, buffer.data(), kMaxCachedSize));
+ ASSERT_EQ(std::vector<uint8_t>(kMaxCachedSize, 0xff), buffer);
+}
+
+TEST_F(MemoryCacheTest, read_for_cache_fail_cross) {
+ std::vector<uint8_t> expect(16, 0xde);
+ expect.resize(32, 0x50);
+
+ std::vector<uint8_t> buffer(32);
+ ASSERT_TRUE(memory_cache_->ReadFully(0x9ff0, buffer.data(), 32));
+ ASSERT_EQ(expect, buffer);
+
+ // Verify the cached data is not used for the second half but for the first.
+ memory_->SetMemoryBlock(0xa000, 3000, 0xff);
+ ASSERT_TRUE(memory_cache_->ReadFully(0x9ff0, buffer.data(), 32));
+ expect.resize(16);
+ expect.resize(32, 0xff);
+ ASSERT_EQ(expect, buffer);
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryFake.cpp b/libunwindstack/tests/MemoryFake.cpp
index 60936cd..5695dfc 100644
--- a/libunwindstack/tests/MemoryFake.cpp
+++ b/libunwindstack/tests/MemoryFake.cpp
@@ -23,6 +23,17 @@
namespace unwindstack {
+void MemoryFake::SetMemoryBlock(uint64_t addr, size_t length, uint8_t value) {
+ for (size_t i = 0; i < length; i++, addr++) {
+ auto entry = data_.find(addr);
+ if (entry != data_.end()) {
+ entry->second = value;
+ } else {
+ data_.insert({addr, value});
+ }
+ }
+}
+
void MemoryFake::SetMemory(uint64_t addr, const void* memory, size_t length) {
const uint8_t* src = reinterpret_cast<const uint8_t*>(memory);
for (size_t i = 0; i < length; i++, addr++) {
diff --git a/libunwindstack/tests/MemoryFake.h b/libunwindstack/tests/MemoryFake.h
index 764a6c3..20610a5 100644
--- a/libunwindstack/tests/MemoryFake.h
+++ b/libunwindstack/tests/MemoryFake.h
@@ -36,6 +36,8 @@
void SetMemory(uint64_t addr, const void* memory, size_t length);
+ void SetMemoryBlock(uint64_t addr, size_t length, uint8_t value);
+
void SetData8(uint64_t addr, uint8_t value) {
SetMemory(addr, &value, sizeof(value));
}
diff --git a/libunwindstack/tests/MemoryOfflineTest.cpp b/libunwindstack/tests/MemoryOfflineTest.cpp
index 14d58e6..ab9aa9d 100644
--- a/libunwindstack/tests/MemoryOfflineTest.cpp
+++ b/libunwindstack/tests/MemoryOfflineTest.cpp
@@ -19,7 +19,6 @@
#include <gtest/gtest.h>
#include <android-base/file.h>
-#include <android-base/test_utils.h>
#include <unwindstack/Memory.h>
namespace unwindstack {
diff --git a/libunwindstack/tests/MemoryRangeTest.cpp b/libunwindstack/tests/MemoryRangeTest.cpp
index cb1a0c9..2bac95b 100644
--- a/libunwindstack/tests/MemoryRangeTest.cpp
+++ b/libunwindstack/tests/MemoryRangeTest.cpp
@@ -15,7 +15,6 @@
*/
#include <stdint.h>
-#include <string.h>
#include <memory>
#include <vector>
@@ -28,30 +27,34 @@
namespace unwindstack {
-TEST(MemoryRangeTest, read) {
- std::vector<uint8_t> src(1024);
- memset(src.data(), 0x4c, 1024);
- MemoryFake* memory_fake = new MemoryFake;
- std::shared_ptr<Memory> process_memory(memory_fake);
- memory_fake->SetMemory(9001, src);
+class MemoryRangeTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ process_memory_.reset();
+ memory_fake_ = new MemoryFake;
+ process_memory_.reset(memory_fake_);
+ }
- MemoryRange range(process_memory, 9001, src.size(), 0);
+ std::shared_ptr<Memory> process_memory_;
+ MemoryFake* memory_fake_ = nullptr;
+};
+
+TEST_F(MemoryRangeTest, read_fully) {
+ memory_fake_->SetMemoryBlock(9000, 2048, 0x4c);
+
+ MemoryRange range(process_memory_, 9001, 1024, 0);
std::vector<uint8_t> dst(1024);
- ASSERT_TRUE(range.ReadFully(0, dst.data(), src.size()));
- for (size_t i = 0; i < 1024; i++) {
+ ASSERT_TRUE(range.ReadFully(0, dst.data(), dst.size()));
+ for (size_t i = 0; i < dst.size(); i++) {
ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
}
}
-TEST(MemoryRangeTest, read_near_limit) {
- std::vector<uint8_t> src(4096);
- memset(src.data(), 0x4c, 4096);
- MemoryFake* memory_fake = new MemoryFake;
- std::shared_ptr<Memory> process_memory(memory_fake);
- memory_fake->SetMemory(1000, src);
+TEST_F(MemoryRangeTest, read_fully_near_limit) {
+ memory_fake_->SetMemoryBlock(0, 8192, 0x4c);
- MemoryRange range(process_memory, 1000, 1024, 0);
+ MemoryRange range(process_memory_, 1000, 1024, 0);
std::vector<uint8_t> dst(1024);
ASSERT_TRUE(range.ReadFully(1020, dst.data(), 4));
@@ -68,7 +71,7 @@
ASSERT_TRUE(range.ReadFully(1020, dst.data(), 4));
}
-TEST(MemoryRangeTest, read_overflow) {
+TEST_F(MemoryRangeTest, read_fully_overflow) {
std::vector<uint8_t> buffer(100);
std::shared_ptr<Memory> process_memory(new MemoryFakeAlwaysReadZero);
@@ -76,19 +79,28 @@
ASSERT_FALSE(overflow->ReadFully(UINT64_MAX - 10, buffer.data(), 100));
}
-TEST(MemoryRangeTest, Read) {
- std::vector<uint8_t> src(4096);
- memset(src.data(), 0x4c, 4096);
- MemoryFake* memory_fake = new MemoryFake;
- std::shared_ptr<Memory> process_memory(memory_fake);
- memory_fake->SetMemory(1000, src);
+TEST_F(MemoryRangeTest, read) {
+ memory_fake_->SetMemoryBlock(0, 4096, 0x4c);
- MemoryRange range(process_memory, 1000, 1024, 0);
+ MemoryRange range(process_memory_, 1000, 1024, 0);
+
std::vector<uint8_t> dst(1024);
- ASSERT_EQ(4U, range.Read(1020, dst.data(), 1024));
+ ASSERT_EQ(4U, range.Read(1020, dst.data(), dst.size()));
for (size_t i = 0; i < 4; i++) {
ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
}
}
+TEST_F(MemoryRangeTest, read_non_zero_offset) {
+ memory_fake_->SetMemoryBlock(1000, 1024, 0x12);
+
+ MemoryRange range(process_memory_, 1000, 1024, 400);
+
+ std::vector<uint8_t> dst(1024);
+ ASSERT_EQ(1024U, range.Read(400, dst.data(), dst.size()));
+ for (size_t i = 0; i < dst.size(); i++) {
+ ASSERT_EQ(0x12U, dst[i]) << "Failed at byte " << i;
+ }
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryRangesTest.cpp b/libunwindstack/tests/MemoryRangesTest.cpp
new file mode 100644
index 0000000..d24fcd2
--- /dev/null
+++ b/libunwindstack/tests/MemoryRangesTest.cpp
@@ -0,0 +1,90 @@
+/*
+ * 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 <stdint.h>
+
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/Memory.h>
+
+#include "MemoryFake.h"
+
+namespace unwindstack {
+
+class MemoryRangesTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ MemoryFake* memory = new MemoryFake;
+ process_memory_.reset(memory);
+ memory->SetMemoryBlock(1000, 5000, 0x15);
+ memory->SetMemoryBlock(6000, 12000, 0x26);
+ memory->SetMemoryBlock(14000, 20000, 0x37);
+ memory->SetMemoryBlock(20000, 22000, 0x48);
+
+ ranges_.reset(new MemoryRanges);
+ ranges_->Insert(new MemoryRange(process_memory_, 15000, 100, 4000));
+ ranges_->Insert(new MemoryRange(process_memory_, 10000, 2000, 2000));
+ ranges_->Insert(new MemoryRange(process_memory_, 3000, 1000, 0));
+ ranges_->Insert(new MemoryRange(process_memory_, 19000, 1000, 6000));
+ ranges_->Insert(new MemoryRange(process_memory_, 20000, 1000, 7000));
+ }
+
+ std::shared_ptr<Memory> process_memory_;
+ std::unique_ptr<MemoryRanges> ranges_;
+};
+
+TEST_F(MemoryRangesTest, read) {
+ std::vector<uint8_t> dst(2000);
+ size_t bytes = ranges_->Read(0, dst.data(), dst.size());
+ ASSERT_EQ(1000UL, bytes);
+ for (size_t i = 0; i < bytes; i++) {
+ ASSERT_EQ(0x15U, dst[i]) << "Failed at byte " << i;
+ }
+
+ bytes = ranges_->Read(2000, dst.data(), dst.size());
+ ASSERT_EQ(2000UL, bytes);
+ for (size_t i = 0; i < bytes; i++) {
+ ASSERT_EQ(0x26U, dst[i]) << "Failed at byte " << i;
+ }
+
+ bytes = ranges_->Read(4000, dst.data(), dst.size());
+ ASSERT_EQ(100UL, bytes);
+ for (size_t i = 0; i < bytes; i++) {
+ ASSERT_EQ(0x37U, dst[i]) << "Failed at byte " << i;
+ }
+}
+
+TEST_F(MemoryRangesTest, read_fail) {
+ std::vector<uint8_t> dst(4096);
+ ASSERT_EQ(0UL, ranges_->Read(1000, dst.data(), dst.size()));
+ ASSERT_EQ(0UL, ranges_->Read(5000, dst.data(), dst.size()));
+ ASSERT_EQ(0UL, ranges_->Read(8000, dst.data(), dst.size()));
+}
+
+TEST_F(MemoryRangesTest, read_across_ranges) {
+ // The MemoryRanges object does not support reading across a range,
+ // so this will only read in the first range.
+ std::vector<uint8_t> dst(4096);
+ size_t bytes = ranges_->Read(6000, dst.data(), dst.size());
+ ASSERT_EQ(1000UL, bytes);
+ for (size_t i = 0; i < bytes; i++) {
+ ASSERT_EQ(0x37U, dst[i]) << "Failed at byte " << i;
+ }
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsInfoTest.cpp b/libunwindstack/tests/RegsInfoTest.cpp
index 052b5bf..a6bc2c5 100644
--- a/libunwindstack/tests/RegsInfoTest.cpp
+++ b/libunwindstack/tests/RegsInfoTest.cpp
@@ -82,4 +82,11 @@
}
}
+TEST(RegsInfoTest, invalid_register) {
+ RegsImplFake<uint64_t> regs(64);
+ RegsInfo<uint64_t> info(®s);
+
+ EXPECT_DEATH(info.Save(RegsInfo<uint64_t>::MAX_REGISTERS), "");
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index 90c3fe6..472d1cf 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -182,7 +182,7 @@
RegsX86_64 regs_x86_64;
RegsMips regs_mips;
RegsMips64 regs_mips64;
- MapInfo map_info(0x1000, 0x2000);
+ MapInfo map_info(nullptr, 0x1000, 0x2000, 0, 0, "");
Elf* invalid_elf = new Elf(nullptr);
map_info.elf.reset(invalid_elf);
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index a65c077..0588a84 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -210,8 +210,8 @@
ASSERT_EQ(4U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
EXPECT_EQ(
" #00 pc 0001a9f8 libc.so (abort+64)\n"
- " #01 pc 00006a1b libbase.so (_ZN7android4base14DefaultAborterEPKc+6)\n"
- " #02 pc 00007441 libbase.so (_ZN7android4base10LogMessageD2Ev+748)\n"
+ " #01 pc 00006a1b libbase.so (android::base::DefaultAborter(char const*)+6)\n"
+ " #02 pc 00007441 libbase.so (android::base::LogMessage::~LogMessage()+748)\n"
" #03 pc 00015147 /does/not/exist/libhidlbase.so\n",
frame_info);
EXPECT_EQ(0xf31ea9f8U, unwinder.frames()[0].pc);
@@ -234,9 +234,10 @@
ASSERT_EQ(2U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
EXPECT_EQ(
" #00 pc 0006dc49 libandroid_runtime.so "
- "(_ZN7android14AndroidRuntime15javaThreadShellEPv+80)\n"
+ "(android::AndroidRuntime::javaThreadShell(void*)+80)\n"
" #01 pc 0006dce5 libandroid_runtime.so "
- "(_ZN7android14AndroidRuntime19javaCreateThreadEtcEPFiPvES1_PKcijPS1_)\n",
+ "(android::AndroidRuntime::javaCreateThreadEtc(int (*)(void*), void*, char const*, int, "
+ "unsigned int, void**))\n",
frame_info);
EXPECT_EQ(0xf1f6dc49U, unwinder.frames()[0].pc);
EXPECT_EQ(0xd8fe6930U, unwinder.frames()[0].sp);
@@ -257,10 +258,10 @@
" #01 pc 000000000042a078 libunwindstack_test (SignalMiddleFunction+8)\n"
" #02 pc 000000000042a08c libunwindstack_test (SignalOuterFunction+8)\n"
" #03 pc 000000000042d8fc libunwindstack_test "
- "(_ZN11unwindstackL19RemoteThroughSignalEij+20)\n"
+ "(unwindstack::RemoteThroughSignal(int, unsigned int)+20)\n"
" #04 pc 000000000042d8d8 libunwindstack_test "
- "(_ZN11unwindstack37UnwindTest_remote_through_signal_Test8TestBodyEv+32)\n"
- " #05 pc 0000000000455d70 libunwindstack_test (_ZN7testing4Test3RunEv+392)\n",
+ "(unwindstack::UnwindTest_remote_through_signal_Test::TestBody()+32)\n"
+ " #05 pc 0000000000455d70 libunwindstack_test (testing::Test::Run()+392)\n",
frame_info);
EXPECT_EQ(0x64d09d4fd8U, unwinder.frames()[0].pc);
EXPECT_EQ(0x7fe0d84040U, unwinder.frames()[0].sp);
@@ -296,54 +297,57 @@
std::string frame_info(DumpFrames(unwinder));
ASSERT_EQ(69U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
EXPECT_EQ(
- " #00 pc 00068fb8 libarttestd.so (_ZN3artL13CauseSegfaultEv+72)\n"
+ " #00 pc 00068fb8 libarttestd.so (art::CauseSegfault()+72)\n"
" #01 pc 00067f00 libarttestd.so (Java_Main_unwindInProcess+10032)\n"
- " #02 pc 000021a8 (offset 0x2000) 137-cfi.odex (boolean Main.unwindInProcess(boolean, int, "
+ " #02 pc 000021a8 137-cfi.odex (offset 0x2000) (boolean Main.unwindInProcess(boolean, int, "
"boolean)+136)\n"
" #03 pc 0000fe80 anonymous:ee74c000 (boolean Main.bar(boolean)+64)\n"
" #04 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
" #05 pc 00146ab5 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+885)\n"
" #06 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #07 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #08 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #09 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #10 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #11 pc 0000fe03 anonymous:ee74c000 (int Main.compare(Main, Main)+51)\n"
" #12 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
" #13 pc 00146ab5 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+885)\n"
" #14 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #15 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #16 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #17 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #18 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #19 pc 0000fd3b anonymous:ee74c000 (int Main.compare(java.lang.Object, "
"java.lang.Object)+107)\n"
" #20 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
" #21 pc 00146ab5 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+885)\n"
" #22 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #23 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #24 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #25 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #26 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #27 pc 0000fbdb anonymous:ee74c000 (int "
@@ -351,81 +355,86 @@
"java.util.Comparator)+331)\n"
" #28 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n"
" #29 pc 00146acb libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+907)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+907)\n"
" #30 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #31 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #32 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #33 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #34 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #35 pc 0000f624 anonymous:ee74c000 (boolean Main.foo()+164)\n"
" #36 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
" #37 pc 00146ab5 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+885)\n"
" #38 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #39 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #40 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #41 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #42 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #43 pc 0000eedb anonymous:ee74c000 (void Main.runPrimary()+59)\n"
" #44 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
" #45 pc 00146ab5 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+885)\n"
" #46 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #47 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #48 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #49 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #50 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #51 pc 0000ac21 anonymous:ee74c000 (void Main.main(java.lang.String[])+97)\n"
" #52 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n"
" #53 pc 00146acb libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+907)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+907)\n"
" #54 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #55 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #56 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #57 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #58 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #59 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n"
" #60 pc 00146acb libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+907)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+907)\n"
" #61 pc 005aac95 libartd.so "
- "(_ZN3artL18InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_9ArtMethodEPNS_"
- "8ArgArrayEPNS_6JValueEPKc+85)\n"
+ "(art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, "
+ "art::ArgArray*, art::JValue*, char const*)+85)\n"
" #62 pc 005aab5a libartd.so "
- "(_ZN3art17InvokeWithVarArgsERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectP10_"
- "jmethodIDPc+362)\n"
+ "(art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, "
+ "_jmethodID*, char*)+362)\n"
" #63 pc 0048a3dd libartd.so "
- "(_ZN3art3JNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDPc+125)\n"
+ "(art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+125)\n"
" #64 pc 0018448c libartd.so "
- "(_ZN3art8CheckJNI11CallMethodVEPKcP7_JNIEnvP8_jobjectP7_jclassP10_jmethodIDPcNS_"
- "9Primitive4TypeENS_10InvokeTypeE+1964)\n"
+ "(art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, char*, "
+ "art::Primitive::Type, art::InvokeType)+1964)\n"
" #65 pc 0017cf06 libartd.so "
- "(_ZN3art8CheckJNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDPc+70)\n"
+ "(art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+70)\n"
" #66 pc 00001d8c dalvikvm32 "
- "(_ZN7_JNIEnv20CallStaticVoidMethodEP7_jclassP10_jmethodIDz+60)\n"
+ "(_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+60)\n"
" #67 pc 00001a80 dalvikvm32 (main+1312)\n"
" #68 pc 00018275 libc.so\n",
frame_info);
@@ -591,38 +600,40 @@
ASSERT_EQ(76U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
EXPECT_EQ(
" #00 pc 00018a5e libarttestd.so (Java_Main_unwindInProcess+866)\n"
- " #01 pc 0000212d (offset 0x2000) 137-cfi.odex (boolean Main.unwindInProcess(boolean, int, "
+ " #01 pc 0000212d 137-cfi.odex (offset 0x2000) (boolean Main.unwindInProcess(boolean, int, "
"boolean)+92)\n"
" #02 pc 00011cb1 anonymous:e2796000 (boolean Main.bar(boolean)+72)\n"
" #03 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #04 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
" #05 pc 000bf7a9 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+864)\n"
" #06 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #07 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #08 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #09 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #10 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #11 pc 00011c31 anonymous:e2796000 (int Main.compare(Main, Main)+64)\n"
" #12 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #13 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
" #14 pc 000bf7a9 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+864)\n"
" #15 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #16 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #17 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #18 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #19 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #20 pc 00011b77 anonymous:e2796000 (int Main.compare(java.lang.Object, "
@@ -630,16 +641,17 @@
" #21 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #22 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
" #23 pc 000bf7a9 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+864)\n"
" #24 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #25 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #26 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #27 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #28 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #29 pc 00011a29 anonymous:e2796000 (int "
@@ -648,85 +660,90 @@
" #30 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #31 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n"
" #32 pc 000bf7bb libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+882)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+882)\n"
" #33 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #34 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #35 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #36 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #37 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #38 pc 0001139b anonymous:e2796000 (boolean Main.foo()+178)\n"
" #39 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #40 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
" #41 pc 000bf7a9 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+864)\n"
" #42 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #43 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #44 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #45 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #46 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #47 pc 00010aa7 anonymous:e2796000 (void Main.runPrimary()+70)\n"
" #48 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #49 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
" #50 pc 000bf7a9 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+864)\n"
" #51 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #52 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #53 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #54 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #55 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #56 pc 0000ba99 anonymous:e2796000 (void Main.main(java.lang.String[])+144)\n"
" #57 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #58 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n"
" #59 pc 000bf7bb libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+882)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+882)\n"
" #60 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #61 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #62 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #63 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #64 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #65 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #66 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n"
" #67 pc 000bf7bb libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+882)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+882)\n"
" #68 pc 003b292d libartd.so "
- "(_ZN3artL18InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_9ArtMethodEPNS_"
- "8ArgArrayEPNS_6JValueEPKc+52)\n"
+ "(art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, "
+ "art::ArgArray*, art::JValue*, char const*)+52)\n"
" #69 pc 003b26c3 libartd.so "
- "(_ZN3art17InvokeWithVarArgsERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectP10_"
- "jmethodIDSt9__va_list+210)\n"
+ "(art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, "
+ "_jmethodID*, std::__va_list)+210)\n"
" #70 pc 00308411 libartd.so "
- "(_ZN3art3JNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDSt9__va_list+76)\n"
+ "(art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+76)\n"
" #71 pc 000e6a9f libartd.so "
- "(_ZN3art8CheckJNI11CallMethodVEPKcP7_JNIEnvP8_jobjectP7_jclassP10_jmethodIDSt9__va_listNS_"
- "9Primitive4TypeENS_10InvokeTypeE+1486)\n"
+ "(art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, "
+ "std::__va_list, art::Primitive::Type, art::InvokeType)+1486)\n"
" #72 pc 000e19b9 libartd.so "
- "(_ZN3art8CheckJNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDSt9__va_list+40)\n"
+ "(art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+40)\n"
" #73 pc 0000159f dalvikvm32 "
- "(_ZN7_JNIEnv20CallStaticVoidMethodEP7_jclassP10_jmethodIDz+30)\n"
+ "(_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+30)\n"
" #74 pc 00001349 dalvikvm32 (main+896)\n"
" #75 pc 000850c9 libc.so\n",
frame_info);
@@ -997,41 +1014,44 @@
"(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n"
" #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n"
" #03 pc 002657a5 libart.so "
- "(_ZN3art3jit3Jit25MaybeDoOnStackReplacementEPNS_6ThreadEPNS_9ArtMethodEjiPNS_6JValueE+876)\n"
+ "(art::jit::Jit::MaybeDoOnStackReplacement(art::Thread*, art::ArtMethod*, unsigned int, int, "
+ "art::JValue*)+876)\n"
" #04 pc 004021a7 libart.so (MterpMaybeDoOnStackReplacement+86)\n"
" #05 pc 00412474 libart.so (ExecuteMterpImpl+66164)\n"
" #06 pc cd8365b0 <unknown>\n" // symbol in dex file
" #07 pc 001d7f1b libart.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+374)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+374)\n"
" #08 pc 001dc593 libart.so "
- "(_ZN3art11interpreter33ArtInterpreterToInterpreterBridgeEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameEPNS_6JValueE+154)\n"
+ "(art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, "
+ "art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*)+154)\n"
" #09 pc 001f4d01 libart.so "
- "(_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_"
- "11InstructionEtPNS_6JValueE+732)\n"
+ "(bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, "
+ "art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+732)\n"
" #10 pc 003fe427 libart.so (MterpInvokeInterface+1354)\n"
" #11 pc 00405b94 libart.so (ExecuteMterpImpl+14740)\n"
" #12 pc 7004873e <unknown>\n" // symbol in dex file
" #13 pc 001d7f1b libart.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+374)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+374)\n"
" #14 pc 001dc4d5 libart.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+92)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+92)\n"
" #15 pc 003f25ab libart.so (artQuickToInterpreterBridge+970)\n"
" #16 pc 00417aff libart.so (art_quick_to_interpreter_bridge+30)\n"
" #17 pc 00413575 libart.so (art_quick_invoke_stub_internal+68)\n"
" #18 pc 00418531 libart.so (art_quick_invoke_stub+236)\n"
- " #19 pc 000b468d libart.so (_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+136)\n"
+ " #19 pc 000b468d libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned "
+ "int, art::JValue*, char const*)+136)\n"
" #20 pc 00362f49 libart.so "
- "(_ZN3art12_GLOBAL__N_118InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_"
- "9ArtMethodEPNS0_8ArgArrayEPNS_6JValueEPKc+52)\n"
+ "(art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable "
+ "const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char "
+ "const*)+52)\n"
" #21 pc 00363cd9 libart.so "
- "(_ZN3art35InvokeVirtualOrInterfaceWithJValuesERKNS_33ScopedObjectAccessAlreadyRunnableEP8_"
- "jobjectP10_jmethodIDP6jvalue+332)\n"
- " #22 pc 003851dd libart.so (_ZN3art6Thread14CreateCallbackEPv+868)\n"
- " #23 pc 00062925 libc.so (_ZL15__pthread_startPv+22)\n"
+ "(art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, "
+ "_jobject*, _jmethodID*, jvalue*)+332)\n"
+ " #22 pc 003851dd libart.so (art::Thread::CreateCallback(void*)+868)\n"
+ " #23 pc 00062925 libc.so (__pthread_start(void*)+22)\n"
" #24 pc 0001de39 libc.so (__start_thread+24)\n",
frame_info);
EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc);
@@ -1107,8 +1127,8 @@
"(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n"
" #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n"
- " #03 pc 003851dd libart.so (_ZN3art6Thread14CreateCallbackEPv+868)\n"
- " #04 pc 00062925 libc.so (_ZL15__pthread_startPv+22)\n"
+ " #03 pc 003851dd libart.so (art::Thread::CreateCallback(void*)+868)\n"
+ " #04 pc 00062925 libc.so (__pthread_start(void*)+22)\n"
" #05 pc 0001de39 libc.so (__start_thread+24)\n",
frame_info);
@@ -1135,29 +1155,29 @@
std::string frame_info(DumpFrames(unwinder));
ASSERT_EQ(19U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
EXPECT_EQ(
- " #00 pc 0032bfa0 (offset 0x42000) libunwindstack_test (SignalInnerFunction+40)\n"
- " #01 pc 0032bfeb (offset 0x42000) libunwindstack_test (SignalMiddleFunction+2)\n"
- " #02 pc 0032bff3 (offset 0x42000) libunwindstack_test (SignalOuterFunction+2)\n"
- " #03 pc 0032fed3 (offset 0x42000) libunwindstack_test "
- "(_ZN11unwindstackL19SignalCallerHandlerEiP7siginfoPv+26)\n"
- " #04 pc 00026528 (offset 0x25000) libc.so\n"
+ " #00 pc 0032bfa0 libunwindstack_test (SignalInnerFunction+40)\n"
+ " #01 pc 0032bfeb libunwindstack_test (SignalMiddleFunction+2)\n"
+ " #02 pc 0032bff3 libunwindstack_test (SignalOuterFunction+2)\n"
+ " #03 pc 0032fed3 libunwindstack_test "
+ "(unwindstack::SignalCallerHandler(int, siginfo*, void*)+26)\n"
+ " #04 pc 00026528 libc.so\n"
" #05 pc 00000000 <unknown>\n"
- " #06 pc 0032c2d9 (offset 0x42000) libunwindstack_test (InnerFunction+736)\n"
- " #07 pc 0032cc4f (offset 0x42000) libunwindstack_test (MiddleFunction+42)\n"
- " #08 pc 0032cc81 (offset 0x42000) libunwindstack_test (OuterFunction+42)\n"
- " #09 pc 0032e547 (offset 0x42000) libunwindstack_test "
- "(_ZN11unwindstackL19RemoteThroughSignalEij+270)\n"
- " #10 pc 0032ed99 (offset 0x42000) libunwindstack_test "
- "(_ZN11unwindstack55UnwindTest_remote_through_signal_with_invalid_func_Test8TestBodyEv+16)\n"
- " #11 pc 00354453 (offset 0x42000) libunwindstack_test (_ZN7testing4Test3RunEv+154)\n"
- " #12 pc 00354de7 (offset 0x42000) libunwindstack_test (_ZN7testing8TestInfo3RunEv+194)\n"
- " #13 pc 00355105 (offset 0x42000) libunwindstack_test (_ZN7testing8TestCase3RunEv+180)\n"
- " #14 pc 0035a215 (offset 0x42000) libunwindstack_test "
- "(_ZN7testing8internal12UnitTestImpl11RunAllTestsEv+664)\n"
- " #15 pc 00359f4f (offset 0x42000) libunwindstack_test (_ZN7testing8UnitTest3RunEv+110)\n"
- " #16 pc 0034d3db (offset 0x42000) libunwindstack_test (main+38)\n"
- " #17 pc 00092c0d (offset 0x25000) libc.so (__libc_init+48)\n"
- " #18 pc 0004202f (offset 0x42000) libunwindstack_test (_start_main+38)\n",
+ " #06 pc 0032c2d9 libunwindstack_test (InnerFunction+736)\n"
+ " #07 pc 0032cc4f libunwindstack_test (MiddleFunction+42)\n"
+ " #08 pc 0032cc81 libunwindstack_test (OuterFunction+42)\n"
+ " #09 pc 0032e547 libunwindstack_test "
+ "(unwindstack::RemoteThroughSignal(int, unsigned int)+270)\n"
+ " #10 pc 0032ed99 libunwindstack_test "
+ "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+16)\n"
+ " #11 pc 00354453 libunwindstack_test (testing::Test::Run()+154)\n"
+ " #12 pc 00354de7 libunwindstack_test (testing::TestInfo::Run()+194)\n"
+ " #13 pc 00355105 libunwindstack_test (testing::TestCase::Run()+180)\n"
+ " #14 pc 0035a215 libunwindstack_test "
+ "(testing::internal::UnitTestImpl::RunAllTests()+664)\n"
+ " #15 pc 00359f4f libunwindstack_test (testing::UnitTest::Run()+110)\n"
+ " #16 pc 0034d3db libunwindstack_test (main+38)\n"
+ " #17 pc 00092c0d libc.so (__libc_init+48)\n"
+ " #18 pc 0004202f libunwindstack_test (_start_main+38)\n",
frame_info);
EXPECT_EQ(0x2e55fa0U, unwinder.frames()[0].pc);
@@ -1213,9 +1233,9 @@
EXPECT_EQ(
" #00 pc 0005138c libc.so (__ioctl+8)\n"
" #01 pc 0002140f libc.so (ioctl+30)\n"
- " #02 pc 00039535 libbinder.so (_ZN7android14IPCThreadState14talkWithDriverEb+204)\n"
- " #03 pc 00039633 libbinder.so (_ZN7android14IPCThreadState20getAndExecuteCommandEv+10)\n"
- " #04 pc 00039b57 libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb+38)\n"
+ " #02 pc 00039535 libbinder.so (android::IPCThreadState::talkWithDriver(bool)+204)\n"
+ " #03 pc 00039633 libbinder.so (android::IPCThreadState::getAndExecuteCommand()+10)\n"
+ " #04 pc 00039b57 libbinder.so (android::IPCThreadState::joinThreadPool(bool)+38)\n"
" #05 pc 00000c21 mediaserver (main+104)\n"
" #06 pc 00084b89 libc.so (__libc_init+48)\n"
" #07 pc 00000b77 mediaserver (_start_main+38)\n",
@@ -1239,4 +1259,79 @@
EXPECT_EQ(0xffd4a718U, unwinder.frames()[7].sp);
}
+TEST_F(UnwindOfflineTest, shared_lib_in_apk_arm64) {
+ ASSERT_NO_FATAL_FAILURE(Init("shared_lib_in_apk_arm64/", ARCH_ARM64));
+
+ Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+ unwinder.Unwind();
+
+ std::string frame_info(DumpFrames(unwinder));
+ ASSERT_EQ(7U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+ EXPECT_EQ(
+ " #00 pc 000000000014ccbc linker64 (__dl_syscall+28)\n"
+ " #01 pc 000000000005426c linker64 "
+ "(__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)\n"
+ " #02 pc 00000000000008bc vdso.so\n"
+ " #03 pc 00000000000846f4 libc.so (abort+172)\n"
+ " #04 pc 0000000000084ad4 libc.so (__assert2+36)\n"
+ " #05 pc 000000000003d5b4 ANGLEPrebuilt.apk (offset 0x4000) (ANGLEGetUtilityAPI+56)\n"
+ " #06 pc 000000000007fe68 libc.so (__libc_init)\n",
+ frame_info);
+
+ EXPECT_EQ(0x7e82c4fcbcULL, unwinder.frames()[0].pc);
+ EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[0].sp);
+ EXPECT_EQ(0x7e82b5726cULL, unwinder.frames()[1].pc);
+ EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[1].sp);
+ EXPECT_EQ(0x7e82b018bcULL, unwinder.frames()[2].pc);
+ EXPECT_EQ(0x7df8ca3da0ULL, unwinder.frames()[2].sp);
+ EXPECT_EQ(0x7e7eecc6f4ULL, unwinder.frames()[3].pc);
+ EXPECT_EQ(0x7dabf3db60ULL, unwinder.frames()[3].sp);
+ EXPECT_EQ(0x7e7eeccad4ULL, unwinder.frames()[4].pc);
+ EXPECT_EQ(0x7dabf3dc40ULL, unwinder.frames()[4].sp);
+ EXPECT_EQ(0x7dabc405b4ULL, unwinder.frames()[5].pc);
+ EXPECT_EQ(0x7dabf3dc50ULL, unwinder.frames()[5].sp);
+ EXPECT_EQ(0x7e7eec7e68ULL, unwinder.frames()[6].pc);
+ EXPECT_EQ(0x7dabf3dc70ULL, unwinder.frames()[6].sp);
+ // Ignore top frame since the test code was modified to end in __libc_init.
+}
+
+TEST_F(UnwindOfflineTest, shared_lib_in_apk_memory_only_arm64) {
+ ASSERT_NO_FATAL_FAILURE(Init("shared_lib_in_apk_memory_only_arm64/", ARCH_ARM64));
+ // Add the memory that represents the shared library.
+ MemoryOfflineParts* memory = reinterpret_cast<MemoryOfflineParts*>(process_memory_.get());
+ AddMemory(dir_ + "lib_mem.data", memory);
+
+ Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+ unwinder.Unwind();
+
+ std::string frame_info(DumpFrames(unwinder));
+ ASSERT_EQ(7U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+ EXPECT_EQ(
+ " #00 pc 000000000014ccbc linker64 (__dl_syscall+28)\n"
+ " #01 pc 000000000005426c linker64 "
+ "(__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)\n"
+ " #02 pc 00000000000008bc vdso.so\n"
+ " #03 pc 00000000000846f4 libc.so (abort+172)\n"
+ " #04 pc 0000000000084ad4 libc.so (__assert2+36)\n"
+ " #05 pc 000000000003d5b4 ANGLEPrebuilt.apk (offset 0x21d5000)\n"
+ " #06 pc 000000000007fe68 libc.so (__libc_init)\n",
+ frame_info);
+
+ EXPECT_EQ(0x7e82c4fcbcULL, unwinder.frames()[0].pc);
+ EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[0].sp);
+ EXPECT_EQ(0x7e82b5726cULL, unwinder.frames()[1].pc);
+ EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[1].sp);
+ EXPECT_EQ(0x7e82b018bcULL, unwinder.frames()[2].pc);
+ EXPECT_EQ(0x7df8ca3da0ULL, unwinder.frames()[2].sp);
+ EXPECT_EQ(0x7e7eecc6f4ULL, unwinder.frames()[3].pc);
+ EXPECT_EQ(0x7dabf3db60ULL, unwinder.frames()[3].sp);
+ EXPECT_EQ(0x7e7eeccad4ULL, unwinder.frames()[4].pc);
+ EXPECT_EQ(0x7dabf3dc40ULL, unwinder.frames()[4].sp);
+ EXPECT_EQ(0x7dabc405b4ULL, unwinder.frames()[5].pc);
+ EXPECT_EQ(0x7dabf3dc50ULL, unwinder.frames()[5].sp);
+ EXPECT_EQ(0x7e7eec7e68ULL, unwinder.frames()[6].pc);
+ EXPECT_EQ(0x7dabf3dc70ULL, unwinder.frames()[6].sp);
+ // Ignore top frame since the test code was modified to end in __libc_init.
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
index ea992c7..a91bd95 100644
--- a/libunwindstack/tests/UnwindTest.cpp
+++ b/libunwindstack/tests/UnwindTest.cpp
@@ -44,6 +44,13 @@
namespace unwindstack {
+enum TestTypeEnum : uint8_t {
+ TEST_TYPE_LOCAL_UNWINDER = 0,
+ TEST_TYPE_LOCAL_UNWINDER_FROM_PID,
+ TEST_TYPE_REMOTE,
+ TEST_TYPE_REMOTE_WITH_INVALID_CALL,
+};
+
static std::atomic_bool g_ready;
static volatile bool g_ready_for_remote;
static volatile bool g_signal_ready_for_remote;
@@ -88,10 +95,10 @@
SignalOuterFunction();
}
-static std::string ErrorMsg(const std::vector<const char*>& function_names, Unwinder& unwinder) {
+static std::string ErrorMsg(const std::vector<const char*>& function_names, Unwinder* unwinder) {
std::string unwind;
- for (size_t i = 0; i < unwinder.NumFrames(); i++) {
- unwind += unwinder.FormatFrame(i) + '\n';
+ for (size_t i = 0; i < unwinder->NumFrames(); i++) {
+ unwind += unwinder->FormatFrame(i) + '\n';
}
return std::string(
@@ -100,14 +107,10 @@
function_names.front() + "\n" + "Unwind data:\n" + unwind;
}
-static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs,
- std::vector<const char*> expected_function_names) {
- auto process_memory(Memory::CreateProcessMemory(pid));
+static void VerifyUnwind(Unwinder* unwinder, std::vector<const char*> expected_function_names) {
+ unwinder->Unwind();
- Unwinder unwinder(512, maps, regs, process_memory);
- unwinder.Unwind();
-
- for (auto& frame : unwinder.frames()) {
+ for (auto& frame : unwinder->frames()) {
if (frame.function_name == expected_function_names.back()) {
expected_function_names.pop_back();
if (expected_function_names.empty()) {
@@ -119,35 +122,55 @@
ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, unwinder);
}
+static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs,
+ std::vector<const char*> expected_function_names) {
+ auto process_memory(Memory::CreateProcessMemory(pid));
+
+ Unwinder unwinder(512, maps, regs, process_memory);
+ VerifyUnwind(&unwinder, expected_function_names);
+}
+
// This test assumes that this code is compiled with optimizations turned
// off. If this doesn't happen, then all of the calls will be optimized
// away.
-extern "C" void InnerFunction(bool local, bool trigger_invalid_call) {
- if (local) {
- LocalMaps maps;
- ASSERT_TRUE(maps.Parse());
- std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
- RegsGetLocal(regs.get());
-
- VerifyUnwind(getpid(), &maps, regs.get(), kFunctionOrder);
- } else {
+extern "C" void InnerFunction(TestTypeEnum test_type) {
+ if (test_type == TEST_TYPE_REMOTE || test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) {
g_ready_for_remote = true;
g_ready = true;
- if (trigger_invalid_call) {
+ if (test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) {
void (*crash_func)() = nullptr;
crash_func();
}
while (!g_finish.load()) {
}
+ return;
}
+
+ std::unique_ptr<Unwinder> unwinder;
+ std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
+ RegsGetLocal(regs.get());
+ std::unique_ptr<Maps> maps;
+
+ if (test_type == TEST_TYPE_LOCAL_UNWINDER) {
+ maps.reset(new LocalMaps());
+ ASSERT_TRUE(maps->Parse());
+ auto process_memory(Memory::CreateProcessMemory(getpid()));
+ unwinder.reset(new Unwinder(512, maps.get(), regs.get(), process_memory));
+ } else {
+ UnwinderFromPid* unwinder_from_pid = new UnwinderFromPid(512, getpid());
+ ASSERT_TRUE(unwinder_from_pid->Init(regs->Arch()));
+ unwinder_from_pid->SetRegs(regs.get());
+ unwinder.reset(unwinder_from_pid);
+ }
+ VerifyUnwind(unwinder.get(), kFunctionOrder);
}
-extern "C" void MiddleFunction(bool local, bool trigger_invalid_call) {
- InnerFunction(local, trigger_invalid_call);
+extern "C" void MiddleFunction(TestTypeEnum test_type) {
+ InnerFunction(test_type);
}
-extern "C" void OuterFunction(bool local, bool trigger_invalid_call) {
- MiddleFunction(local, trigger_invalid_call);
+extern "C" void OuterFunction(TestTypeEnum test_type) {
+ MiddleFunction(test_type);
}
class UnwindTest : public ::testing::Test {
@@ -156,7 +179,11 @@
};
TEST_F(UnwindTest, local) {
- OuterFunction(true, false);
+ OuterFunction(TEST_TYPE_LOCAL_UNWINDER);
+}
+
+TEST_F(UnwindTest, local_use_from_pid) {
+ OuterFunction(TEST_TYPE_LOCAL_UNWINDER_FROM_PID);
}
void WaitForRemote(pid_t pid, uint64_t addr, bool leave_attached, bool* completed) {
@@ -191,7 +218,7 @@
TEST_F(UnwindTest, remote) {
pid_t pid;
if ((pid = fork()) == 0) {
- OuterFunction(false, false);
+ OuterFunction(TEST_TYPE_REMOTE);
exit(0);
}
ASSERT_NE(-1, pid);
@@ -212,11 +239,39 @@
<< "ptrace detach failed with unexpected error: " << strerror(errno);
}
+TEST_F(UnwindTest, unwind_from_pid_remote) {
+ pid_t pid;
+ if ((pid = fork()) == 0) {
+ OuterFunction(TEST_TYPE_REMOTE);
+ exit(0);
+ }
+ ASSERT_NE(-1, pid);
+ TestScopedPidReaper reap(pid);
+
+ bool completed;
+ WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
+ ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
+
+ std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
+ ASSERT_TRUE(regs.get() != nullptr);
+
+ UnwinderFromPid unwinder(512, pid);
+ ASSERT_TRUE(unwinder.Init(regs->Arch()));
+ unwinder.SetRegs(regs.get());
+
+ VerifyUnwind(&unwinder, kFunctionOrder);
+
+ // Verify that calling the same object works again.
+
+ ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
+ << "ptrace detach failed with unexpected error: " << strerror(errno);
+}
+
TEST_F(UnwindTest, from_context) {
std::atomic_int tid(0);
std::thread thread([&]() {
tid = syscall(__NR_gettid);
- OuterFunction(false, false);
+ OuterFunction(TEST_TYPE_REMOTE);
});
struct sigaction act, oldact;
@@ -266,7 +321,7 @@
act.sa_flags = SA_RESTART | SA_ONSTACK | sa_flags;
ASSERT_EQ(0, sigaction(signal, &act, &oldact));
- OuterFunction(false, signal == SIGSEGV);
+ OuterFunction(signal != SIGSEGV ? TEST_TYPE_REMOTE : TEST_TYPE_REMOTE_WITH_INVALID_CALL);
exit(0);
}
ASSERT_NE(-1, pid);
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 2428f68..49aeeb3 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -42,81 +42,64 @@
namespace unwindstack {
-class MapsFake : public Maps {
- public:
- MapsFake() = default;
- virtual ~MapsFake() = default;
-
- bool Parse() { return true; }
-
- void FakeClear() { maps_.clear(); }
-
- void FakeAddMapInfo(MapInfo* map_info) { maps_.push_back(map_info); }
-};
-
class UnwinderTest : public ::testing::Test {
protected:
+ static void AddMapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
+ const char* name, Elf* elf = nullptr) {
+ std::string str_name(name);
+ maps_->Add(start, end, offset, flags, name, static_cast<uint64_t>(-1));
+ if (elf != nullptr) {
+ MapInfo* map_info = *--maps_->end();
+ map_info->elf.reset(elf);
+ }
+ }
+
static void SetUpTestCase() {
- maps_.FakeClear();
- MapInfo* info = new MapInfo(0x1000, 0x8000, 0, PROT_READ | PROT_WRITE, "/system/fake/libc.so");
+ maps_.reset(new Maps);
+
ElfFake* elf = new ElfFake(new MemoryFake);
- info->elf.reset(elf);
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- maps_.FakeAddMapInfo(info);
+ AddMapInfo(0x1000, 0x8000, 0, PROT_READ | PROT_WRITE, "/system/fake/libc.so", elf);
- info = new MapInfo(0x10000, 0x12000, 0, PROT_READ | PROT_WRITE, "[stack]");
- maps_.FakeAddMapInfo(info);
+ AddMapInfo(0x10000, 0x12000, 0, PROT_READ | PROT_WRITE, "[stack]");
- info = new MapInfo(0x13000, 0x15000, 0, PROT_READ | PROT_WRITE | MAPS_FLAGS_DEVICE_MAP,
- "/dev/fake_device");
- maps_.FakeAddMapInfo(info);
+ AddMapInfo(0x13000, 0x15000, 0, PROT_READ | PROT_WRITE | MAPS_FLAGS_DEVICE_MAP,
+ "/dev/fake_device");
- info = new MapInfo(0x20000, 0x22000, 0, PROT_READ | PROT_WRITE, "/system/fake/libunwind.so");
elf = new ElfFake(new MemoryFake);
- info->elf.reset(elf);
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- maps_.FakeAddMapInfo(info);
+ AddMapInfo(0x20000, 0x22000, 0, PROT_READ | PROT_WRITE, "/system/fake/libunwind.so", elf);
- info = new MapInfo(0x23000, 0x24000, 0, PROT_READ | PROT_WRITE, "/fake/libanother.so");
elf = new ElfFake(new MemoryFake);
- info->elf.reset(elf);
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- maps_.FakeAddMapInfo(info);
+ AddMapInfo(0x23000, 0x24000, 0, PROT_READ | PROT_WRITE, "/fake/libanother.so", elf);
- info = new MapInfo(0x33000, 0x34000, 0, PROT_READ | PROT_WRITE, "/fake/compressed.so");
elf = new ElfFake(new MemoryFake);
- info->elf.reset(elf);
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- maps_.FakeAddMapInfo(info);
+ AddMapInfo(0x33000, 0x34000, 0, PROT_READ | PROT_WRITE, "/fake/compressed.so", elf);
- info = new MapInfo(0x43000, 0x44000, 0x1d000, PROT_READ | PROT_WRITE, "/fake/fake.apk");
elf = new ElfFake(new MemoryFake);
- info->elf.reset(elf);
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
- maps_.FakeAddMapInfo(info);
+ AddMapInfo(0x43000, 0x44000, 0x1d000, PROT_READ | PROT_WRITE, "/fake/fake.apk", elf);
- info = new MapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat");
- maps_.FakeAddMapInfo(info);
+ AddMapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat");
- info = new MapInfo(0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.vdex");
+ AddMapInfo(0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.vdex");
+ MapInfo* info = *--maps_->end();
info->load_bias = 0;
- maps_.FakeAddMapInfo(info);
- info = new MapInfo(0xa5000, 0xa6000, 0, PROT_READ | PROT_WRITE | PROT_EXEC,
- "/fake/fake_load_bias.so");
elf = new ElfFake(new MemoryFake);
- info->elf.reset(elf);
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
elf->FakeSetLoadBias(0x5000);
- maps_.FakeAddMapInfo(info);
+ AddMapInfo(0xa5000, 0xa6000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake_load_bias.so",
+ elf);
- info = new MapInfo(0xa7000, 0xa8000, 0, PROT_READ | PROT_WRITE | PROT_EXEC,
- "/fake/fake_offset.oat");
elf = new ElfFake(new MemoryFake);
- info->elf.reset(elf);
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
+ AddMapInfo(0xa7000, 0xa8000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake_offset.oat",
+ elf);
+ info = *--maps_->end();
info->elf_offset = 0x8000;
- maps_.FakeAddMapInfo(info);
process_memory_.reset(new MemoryFake);
}
@@ -127,12 +110,12 @@
regs_.FakeSetReturnAddressValid(false);
}
- static MapsFake maps_;
+ static std::unique_ptr<Maps> maps_;
static RegsFake regs_;
static std::shared_ptr<Memory> process_memory_;
};
-MapsFake UnwinderTest::maps_;
+std::unique_ptr<Maps> UnwinderTest::maps_;
RegsFake UnwinderTest::regs_(5);
std::shared_ptr<Memory> UnwinderTest::process_memory_(nullptr);
@@ -147,7 +130,7 @@
ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -161,7 +144,8 @@
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_offset);
+ 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);
@@ -175,7 +159,8 @@
EXPECT_EQ("Frame1", frame->function_name);
EXPECT_EQ(1U, frame->function_offset);
EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ 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);
@@ -189,7 +174,8 @@
EXPECT_EQ("Frame2", frame->function_name);
EXPECT_EQ(2U, frame->function_offset);
EXPECT_EQ("/system/fake/libc.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ 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);
@@ -207,7 +193,7 @@
ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.SetResolveNames(false);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -222,7 +208,8 @@
EXPECT_EQ("", frame->function_name);
EXPECT_EQ(0U, frame->function_offset);
EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ 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);
@@ -236,7 +223,8 @@
EXPECT_EQ("", frame->function_name);
EXPECT_EQ(0U, frame->function_offset);
EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ 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);
@@ -250,7 +238,8 @@
EXPECT_EQ("", frame->function_name);
EXPECT_EQ(0U, frame->function_offset);
EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ 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);
@@ -264,7 +253,7 @@
regs_.set_sp(0x10000);
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -278,7 +267,8 @@
EXPECT_EQ("Frame0", frame->function_name);
EXPECT_EQ(0U, frame->function_offset);
EXPECT_EQ("/fake/fake_load_bias.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0xa5000U, frame->map_start);
EXPECT_EQ(0xa6000U, frame->map_end);
EXPECT_EQ(0x5000U, frame->map_load_bias);
@@ -292,7 +282,7 @@
regs_.set_sp(0x10000);
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -306,7 +296,8 @@
EXPECT_EQ("Frame0", frame->function_name);
EXPECT_EQ(0U, frame->function_offset);
EXPECT_EQ("/fake/fake_offset.oat", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0xa7000U, frame->map_start);
EXPECT_EQ(0xa8000U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -320,7 +311,7 @@
regs_.set_sp(0x10000);
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -334,7 +325,8 @@
EXPECT_EQ("Frame0", frame->function_name);
EXPECT_EQ(0U, frame->function_offset);
EXPECT_EQ("/fake/fake.apk", frame->map_name);
- EXPECT_EQ(0x1d000U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0x1d000U, frame->map_exact_offset);
EXPECT_EQ(0x43000U, frame->map_start);
EXPECT_EQ(0x44000U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -355,7 +347,7 @@
ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -369,7 +361,8 @@
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_offset);
+ 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);
@@ -386,7 +379,7 @@
regs_.set_pc(0x1000);
regs_.set_sp(0x10000);
- Unwinder unwinder(20, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(20, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode());
@@ -401,7 +394,8 @@
EXPECT_EQ("Frame" + std::to_string(i), frame->function_name) << "Failed at frame " << i;
EXPECT_EQ(i, frame->function_offset) << "Failed at frame " << i;
EXPECT_EQ("/system/fake/libc.so", frame->map_name) << "Failed at frame " << i;
- EXPECT_EQ(0U, frame->map_offset) << "Failed at frame " << i;
+ EXPECT_EQ(0U, frame->map_elf_start_offset) << "Failed at frame " << i;
+ EXPECT_EQ(0U, frame->map_exact_offset) << "Failed at frame " << i;
EXPECT_EQ(0x1000U, frame->map_start) << "Failed at frame " << i;
EXPECT_EQ(0x8000U, frame->map_end) << "Failed at frame " << i;
EXPECT_EQ(0U, frame->map_load_bias) << "Failed at frame " << i;
@@ -426,7 +420,7 @@
ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10070, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
std::vector<std::string> skip_libs{"libunwind.so", "libanother.so"};
unwinder.Unwind(&skip_libs);
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -441,7 +435,8 @@
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_offset);
+ 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);
@@ -455,7 +450,8 @@
EXPECT_EQ("Frame1", frame->function_name);
EXPECT_EQ(1U, frame->function_offset);
EXPECT_EQ("/system/fake/libunwind.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0x20000U, frame->map_start);
EXPECT_EQ(0x22000U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -469,7 +465,7 @@
EXPECT_EQ("Frame2", frame->function_name);
EXPECT_EQ(2U, frame->function_offset);
EXPECT_EQ("/fake/libanother.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0x23000U, frame->map_start);
EXPECT_EQ(0x24000U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -486,7 +482,7 @@
ElfInterfaceFake::FakePushStepData(StepData(0x21002, 0x50020, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -500,7 +496,7 @@
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_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);
@@ -514,7 +510,7 @@
EXPECT_EQ("Frame1", frame->function_name);
EXPECT_EQ(1U, frame->function_offset);
EXPECT_EQ("/system/fake/libunwind.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0x20000U, frame->map_start);
EXPECT_EQ(0x22000U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -533,7 +529,7 @@
ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -552,7 +548,7 @@
ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -566,7 +562,7 @@
regs_.set_pc(0x41000);
regs_.set_sp(0x13000);
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode());
@@ -580,7 +576,8 @@
EXPECT_EQ("", frame->function_name);
EXPECT_EQ(0U, frame->function_offset);
EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0U, frame->map_start);
EXPECT_EQ(0U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -601,7 +598,7 @@
ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -615,7 +612,8 @@
EXPECT_EQ("", frame->function_name);
EXPECT_EQ(0U, frame->function_offset);
EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0U, frame->map_start);
EXPECT_EQ(0U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -629,7 +627,8 @@
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_offset);
+ 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);
@@ -643,7 +642,8 @@
EXPECT_EQ("Frame1", frame->function_name);
EXPECT_EQ(1U, frame->function_offset);
EXPECT_EQ("/fake/libanother.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0x23000U, frame->map_start);
EXPECT_EQ(0x24000U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -657,16 +657,66 @@
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
// Fake as if code called a nullptr function.
+ regs_.set_pc(0x20000);
+ regs_.set_sp(0x10000);
+ ElfInterfaceFake::FakePushStepData(StepData(0, 0x10010, false));
+ regs_.FakeSetReturnAddress(0x12);
+ regs_.FakeSetReturnAddressValid(true);
+
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
+ unwinder.Unwind();
+ EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode());
+
+ ASSERT_EQ(2U, unwinder.NumFrames());
+
+ auto* frame = &unwinder.frames()[0];
+ EXPECT_EQ(0U, frame->num);
+ EXPECT_EQ(0U, frame->rel_pc);
+ EXPECT_EQ(0x20000U, frame->pc);
+ EXPECT_EQ(0x10000U, frame->sp);
+ EXPECT_EQ("Frame0", frame->function_name);
+ EXPECT_EQ(0U, frame->function_offset);
+ EXPECT_EQ("/system/fake/libunwind.so", frame->map_name);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
+ EXPECT_EQ(0x20000U, frame->map_start);
+ EXPECT_EQ(0x22000U, frame->map_end);
+ EXPECT_EQ(0U, frame->map_load_bias);
+ EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
+
+ frame = &unwinder.frames()[1];
+ EXPECT_EQ(1U, frame->num);
+ EXPECT_EQ(0U, frame->rel_pc);
+ EXPECT_EQ(0U, frame->pc);
+ EXPECT_EQ(0x10010U, frame->sp);
+ EXPECT_EQ("", frame->function_name);
+ EXPECT_EQ(0U, frame->function_offset);
+ EXPECT_EQ("", frame->map_name);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
+ EXPECT_EQ(0U, frame->map_start);
+ EXPECT_EQ(0U, frame->map_end);
+ EXPECT_EQ(0U, frame->map_load_bias);
+ EXPECT_EQ(0, frame->map_flags);
+}
+
+// Verify that a speculative frame is added and left if there are only
+// two frames and the pc is in the middle nowhere.
+TEST_F(UnwinderTest, speculative_frame_not_removed_pc_bad) {
+ ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
+ ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
+
+ // Fake as if code called a nullptr function.
regs_.set_pc(0);
regs_.set_sp(0x10000);
regs_.FakeSetReturnAddress(0x1202);
regs_.FakeSetReturnAddressValid(true);
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
- ASSERT_EQ(1U, unwinder.NumFrames());
+ ASSERT_EQ(2U, unwinder.NumFrames());
auto* frame = &unwinder.frames()[0];
EXPECT_EQ(0U, frame->num);
@@ -676,11 +726,27 @@
EXPECT_EQ("", frame->function_name);
EXPECT_EQ(0U, frame->function_offset);
EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0U, frame->map_start);
EXPECT_EQ(0U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
EXPECT_EQ(0, frame->map_flags);
+
+ frame = &unwinder.frames()[1];
+ EXPECT_EQ(1U, frame->num);
+ EXPECT_EQ(0x200U, frame->rel_pc);
+ EXPECT_EQ(0x1200U, 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);
}
// Verify that an unwind stops when a frame is in given suffix.
@@ -697,14 +763,14 @@
ElfInterfaceFake::FakePushStepData(StepData(0x53502, 0x10020, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
std::vector<std::string> suffixes{"oat"};
unwinder.Unwind(nullptr, &suffixes);
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
ASSERT_EQ(2U, unwinder.NumFrames());
// Make sure the elf was not initialized.
- MapInfo* map_info = maps_.Find(0x53000);
+ MapInfo* map_info = maps_->Find(0x53000);
ASSERT_TRUE(map_info != nullptr);
EXPECT_TRUE(map_info->elf == nullptr);
@@ -716,7 +782,8 @@
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_offset);
+ 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);
@@ -730,7 +797,8 @@
EXPECT_EQ("Frame1", frame->function_name);
EXPECT_EQ(1U, frame->function_offset);
EXPECT_EQ("/fake/fake.apk", frame->map_name);
- EXPECT_EQ(0x1d000U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0x1d000U, frame->map_exact_offset);
EXPECT_EQ(0x43000U, frame->map_start);
EXPECT_EQ(0x44000U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -754,7 +822,7 @@
ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_REPEATED_FRAME, unwinder.LastErrorCode());
@@ -768,7 +836,8 @@
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_offset);
+ 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);
@@ -782,7 +851,8 @@
EXPECT_EQ("Frame1", frame->function_name);
EXPECT_EQ(1U, frame->function_offset);
EXPECT_EQ("/fake/compressed.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0x33000U, frame->map_start);
EXPECT_EQ(0x34000U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -796,7 +866,8 @@
EXPECT_EQ("Frame2", frame->function_name);
EXPECT_EQ(2U, frame->function_offset);
EXPECT_EQ("/fake/compressed.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0x33000U, frame->map_start);
EXPECT_EQ(0x34000U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -809,7 +880,7 @@
regs_.set_sp(0x10000);
regs_.FakeSetDexPc(0xa3400);
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -823,7 +894,8 @@
EXPECT_EQ("", frame->function_name);
EXPECT_EQ(0U, frame->function_offset);
EXPECT_EQ("/fake/fake.vdex", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0xa3000U, frame->map_start);
EXPECT_EQ(0xa4000U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -837,7 +909,8 @@
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_offset);
+ 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);
@@ -850,7 +923,7 @@
regs_.set_sp(0x10000);
regs_.FakeSetDexPc(0x50000);
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -864,7 +937,8 @@
EXPECT_EQ("", frame->function_name);
EXPECT_EQ(0U, frame->function_offset);
EXPECT_EQ("", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0U, frame->map_start);
EXPECT_EQ(0U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -878,7 +952,8 @@
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_offset);
+ 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);
@@ -894,7 +969,7 @@
ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
- Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
@@ -908,7 +983,8 @@
EXPECT_EQ("", frame->function_name);
EXPECT_EQ(0U, frame->function_offset);
EXPECT_EQ("/fake/fake.vdex", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0xa3000U, frame->map_start);
EXPECT_EQ(0xa4000U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
@@ -922,7 +998,8 @@
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_offset);
+ 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);
@@ -936,13 +1013,42 @@
EXPECT_EQ("Frame1", frame->function_name);
EXPECT_EQ(1U, frame->function_offset);
EXPECT_EQ("/fake/compressed.so", frame->map_name);
- EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
EXPECT_EQ(0x33000U, frame->map_start);
EXPECT_EQ(0x34000U, frame->map_end);
EXPECT_EQ(0U, frame->map_load_bias);
EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
}
+TEST_F(UnwinderTest, dex_pc_max_frames) {
+ ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
+ regs_.set_pc(0x1000);
+ regs_.set_sp(0x10000);
+ regs_.FakeSetDexPc(0xa3400);
+
+ Unwinder unwinder(1, maps_.get(), ®s_, process_memory_);
+ unwinder.Unwind();
+ EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode());
+
+ ASSERT_EQ(1U, unwinder.NumFrames());
+
+ auto* frame = &unwinder.frames()[0];
+ EXPECT_EQ(0U, frame->num);
+ EXPECT_EQ(0x400U, frame->rel_pc);
+ EXPECT_EQ(0xa3400U, frame->pc);
+ EXPECT_EQ(0x10000U, frame->sp);
+ EXPECT_EQ("", frame->function_name);
+ EXPECT_EQ(0U, frame->function_offset);
+ EXPECT_EQ("/fake/fake.vdex", frame->map_name);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
+ EXPECT_EQ(0xa3000U, frame->map_start);
+ EXPECT_EQ(0xa4000U, frame->map_end);
+ EXPECT_EQ(0U, frame->map_load_bias);
+ EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
+}
+
// Verify format frame code.
TEST_F(UnwinderTest, format_frame_static) {
FrameData frame;
@@ -953,17 +1059,17 @@
frame.function_name = "function";
frame.function_offset = 100;
frame.map_name = "/fake/libfake.so";
- frame.map_offset = 0x2000;
+ frame.map_elf_start_offset = 0x2000;
frame.map_start = 0x3000;
frame.map_end = 0x6000;
frame.map_flags = PROT_READ;
- EXPECT_EQ(" #01 pc 0000000000001000 (offset 0x2000) /fake/libfake.so (function+100)",
+ EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (offset 0x2000) (function+100)",
Unwinder::FormatFrame(frame, false));
- EXPECT_EQ(" #01 pc 00001000 (offset 0x2000) /fake/libfake.so (function+100)",
+ EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (offset 0x2000) (function+100)",
Unwinder::FormatFrame(frame, true));
- frame.map_offset = 0;
+ frame.map_elf_start_offset = 0;
EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (function+100)",
Unwinder::FormatFrame(frame, false));
EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function+100)",
@@ -974,6 +1080,12 @@
Unwinder::FormatFrame(frame, false));
EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function)", Unwinder::FormatFrame(frame, true));
+ // Verify the function name is demangled.
+ frame.function_name = "_ZN4funcEv";
+ EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (func())",
+ Unwinder::FormatFrame(frame, false));
+ EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (func())", Unwinder::FormatFrame(frame, true));
+
frame.function_name = "";
EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so", Unwinder::FormatFrame(frame, false));
EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so", Unwinder::FormatFrame(frame, true));
@@ -1038,7 +1150,7 @@
for (auto regs : reg_list) {
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 10));
- Unwinder unwinder(64, &maps_, regs, process_memory_);
+ Unwinder unwinder(64, maps_.get(), regs, process_memory_);
unwinder.Unwind();
ASSERT_EQ(1U, unwinder.NumFrames());
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 55aaaf6..5657373 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,3 +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
e7d91000-e7e31000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
index f25c781..3cd9d40 100644
--- a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
+++ b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
@@ -2,7 +2,9 @@
dfe4e000-dfe7b000 r-xp 0 00:00 0 libarttestd.so
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 00000000 00:00 0 libart.so
+e648e000-e690f000 r-xp 0 00:00 0 libart.so
+e690f000-e6910000 rw-p 1000 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
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 db4f9f7..a8d215c 100644
--- a/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
+++ b/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
@@ -3,4 +3,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
f734b000-f74fc000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/offset_arm/maps.txt b/libunwindstack/tests/files/offline/offset_arm/maps.txt
index 6224464..768dd9f 100644
--- a/libunwindstack/tests/files/offline/offset_arm/maps.txt
+++ b/libunwindstack/tests/files/offline/offset_arm/maps.txt
@@ -1,2 +1,4 @@
+2b2a000-2b6c000 r--p 0 00:00 0 libunwindstack_test
2b6c000-2e92000 r-xp 42000 00:00 0 libunwindstack_test
+f4110000-f4135000 r--p 0 00:00 0 libc.so
f4135000-f41a9000 r-xp 25000 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk
new file mode 100644
index 0000000..0277359
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/libc.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/libc.so
new file mode 100644
index 0000000..20008fd
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/linker64 b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/linker64
new file mode 100644
index 0000000..b90933b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/linker64
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/maps.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/maps.txt
new file mode 100644
index 0000000..c4fc067
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/maps.txt
@@ -0,0 +1,7 @@
+7dabc03000-7dabc3f000 r--p 4000 00:00 0 ANGLEPrebuilt.apk
+7dabc3f000-7dabcf0000 r-xp 40000 00:00 0 ANGLEPrebuilt.apk
+7e7ee48000-7e7ee88000 r--p 0 00:00 0 libc.so
+7e7ee88000-7e7ef32000 r-xp 40000 00:00 0 libc.so
+7e82b01000-7e82b03000 r-xp 0 00:00 0 vdso.so
+7e82b03000-7e82b3c000 r--p 0 00:00 0 linker64
+7e82b3c000-7e82c77000 r-xp 39000 00:00 0 linker64
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/regs.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/regs.txt
new file mode 100644
index 0000000..1e2ea32
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/regs.txt
@@ -0,0 +1,33 @@
+x0: 7df8ca3c24
+x1: 0
+x2: ffffffff
+x3: 0
+x4: 0
+x5: 0
+x6: 0
+x7: 7f7f7f7f7f7f7f7f
+x8: 62
+x9: 20dd5829922a93ac
+x10: 7e82b57420
+x11: 4100
+x12: 7df8ca3b70
+x13: 7df8ca3b98
+x14: 73d015e5
+x15: 39a36122467299
+x16: 76ac
+x17: 0
+x18: 7df8cfc000
+x19: 7dabf3e7a0
+x20: 7df8ca3da0
+x21: 59616d61
+x22: 1
+x23: 7df8ca3c24
+x24: 1894
+x25: 62
+x26: 2
+x27: 0
+x28: 7dabf3e790
+x29: 7df8ca3d90
+sp: 7df8ca3bf0
+lr: 7e82b57270
+pc: 7e82c4fcbc
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack0.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack0.data
new file mode 100644
index 0000000..ec07e15
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack0.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack1.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack1.data
new file mode 100644
index 0000000..825bb1a
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/vdso.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/vdso.so
new file mode 100644
index 0000000..205ebd4
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/vdso.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/lib_mem.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/lib_mem.data
new file mode 100644
index 0000000..f39d127
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/lib_mem.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/libc.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/libc.so
new file mode 100644
index 0000000..20008fd
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/linker64 b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/linker64
new file mode 100644
index 0000000..b90933b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/linker64
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/maps.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/maps.txt
new file mode 100644
index 0000000..386d57a
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/maps.txt
@@ -0,0 +1,7 @@
+7dabc03000-7dabc3f000 r--p 21d5000 00:00 0 ANGLEPrebuilt.apk
+7dabc3f000-7dabcf0000 r-xp 2211000 00:00 0 ANGLEPrebuilt.apk
+7e7ee48000-7e7ee88000 r--p 0 00:00 0 libc.so
+7e7ee88000-7e7ef32000 r-xp 40000 00:00 0 libc.so
+7e82b01000-7e82b03000 r-xp 0 00:00 0 vdso.so
+7e82b03000-7e82b3c000 r--p 0 00:00 0 linker64
+7e82b3c000-7e82c77000 r-xp 39000 00:00 0 linker64
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/regs.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/regs.txt
new file mode 100644
index 0000000..1e2ea32
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/regs.txt
@@ -0,0 +1,33 @@
+x0: 7df8ca3c24
+x1: 0
+x2: ffffffff
+x3: 0
+x4: 0
+x5: 0
+x6: 0
+x7: 7f7f7f7f7f7f7f7f
+x8: 62
+x9: 20dd5829922a93ac
+x10: 7e82b57420
+x11: 4100
+x12: 7df8ca3b70
+x13: 7df8ca3b98
+x14: 73d015e5
+x15: 39a36122467299
+x16: 76ac
+x17: 0
+x18: 7df8cfc000
+x19: 7dabf3e7a0
+x20: 7df8ca3da0
+x21: 59616d61
+x22: 1
+x23: 7df8ca3c24
+x24: 1894
+x25: 62
+x26: 2
+x27: 0
+x28: 7dabf3e790
+x29: 7df8ca3d90
+sp: 7df8ca3bf0
+lr: 7e82b57270
+pc: 7e82c4fcbc
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack0.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack0.data
new file mode 100644
index 0000000..ec07e15
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack0.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack1.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack1.data
new file mode 100644
index 0000000..825bb1a
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/vdso.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/vdso.so
new file mode 100644
index 0000000..205ebd4
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/vdso.so
Binary files differ
diff --git a/libunwindstack/tools/unwind.cpp b/libunwindstack/tools/unwind.cpp
index 22ca7bf..1812e50 100644
--- a/libunwindstack/tools/unwind.cpp
+++ b/libunwindstack/tools/unwind.cpp
@@ -35,7 +35,12 @@
#include <unwindstack/Unwinder.h>
static bool Attach(pid_t pid) {
- if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) {
+ if (ptrace(PTRACE_SEIZE, pid, 0, 0) == -1) {
+ return false;
+ }
+
+ if (ptrace(PTRACE_INTERRUPT, pid, 0, 0) == -1) {
+ ptrace(PTRACE_DETACH, pid, 0, 0);
return false;
}
@@ -52,12 +57,6 @@
}
void DoUnwind(pid_t pid) {
- unwindstack::RemoteMaps remote_maps(pid);
- if (!remote_maps.Parse()) {
- printf("Failed to parse map data.\n");
- return;
- }
-
unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid);
if (regs == nullptr) {
printf("Unable to get remote reg data\n");
@@ -90,15 +89,13 @@
}
printf("\n");
- auto process_memory = unwindstack::Memory::CreateProcessMemory(pid);
- unwindstack::Unwinder unwinder(128, &remote_maps, regs, process_memory);
+ unwindstack::UnwinderFromPid unwinder(1024, pid);
+ if (!unwinder.Init(regs->Arch())) {
+ printf("Failed to init unwinder object.\n");
+ return;
+ }
- unwindstack::JitDebug jit_debug(process_memory);
- unwinder.SetJitDebug(&jit_debug, regs->Arch());
-
- unwindstack::DexFiles dex_files(process_memory);
- unwinder.SetDexFiles(&dex_files, regs->Arch());
-
+ unwinder.SetRegs(regs);
unwinder.Unwind();
// Print the frames.
diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp
index 640992f..4f67d67 100644
--- a/libunwindstack/tools/unwind_for_offline.cpp
+++ b/libunwindstack/tools/unwind_for_offline.cpp
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <unistd.h>
@@ -46,11 +47,17 @@
uint64_t start;
uint64_t end;
uint64_t offset;
+ uint64_t flags;
std::string name;
};
static bool Attach(pid_t pid) {
- if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) {
+ if (ptrace(PTRACE_SEIZE, pid, 0, 0) == -1) {
+ return false;
+ }
+
+ if (ptrace(PTRACE_INTERRUPT, pid, 0, 0) == -1) {
+ ptrace(PTRACE_DETACH, pid, 0, 0);
return false;
}
@@ -158,14 +165,19 @@
return true;
}
-bool CopyElfFromFile(map_info_t* info) {
+bool CopyElfFromFile(map_info_t* info, bool* file_copied) {
+ std::string cur_name = basename(info->name.c_str());
+ if (*file_copied) {
+ info->name = cur_name;
+ return true;
+ }
+
std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(info->name.c_str(), "r"), &fclose);
if (fp == nullptr) {
perror((std::string("Cannot open ") + info->name).c_str());
return false;
}
- std::string cur_name = basename(info->name.c_str());
std::unique_ptr<FILE, decltype(&fclose)> output(fopen(cur_name.c_str(), "w+"), &fclose);
if (output == nullptr) {
perror((std::string("Cannot create file " + cur_name)).c_str());
@@ -188,6 +200,39 @@
return true;
}
+map_info_t* FillInAndGetMapInfo(std::unordered_map<uint64_t, map_info_t>& maps_by_start,
+ unwindstack::MapInfo* map_info) {
+ auto info = &maps_by_start[map_info->start];
+ info->start = map_info->start;
+ info->end = map_info->end;
+ info->offset = map_info->offset;
+ info->name = map_info->name;
+ info->flags = map_info->flags;
+
+ return info;
+}
+
+void SaveMapInformation(std::shared_ptr<unwindstack::Memory>& process_memory, map_info_t* info,
+ bool* file_copied) {
+ if (CopyElfFromFile(info, file_copied)) {
+ return;
+ }
+ *file_copied = false;
+
+ // Try to create the elf from memory, this will handle cases where
+ // the data only exists in memory such as vdso data on x86.
+ if (CreateElfFromMemory(process_memory, info)) {
+ return;
+ }
+
+ printf("Cannot save memory or file for map ");
+ if (!info->name.empty()) {
+ printf("%s\n", info->name.c_str());
+ } else {
+ printf("anonymous:%" PRIx64 "\n", info->start);
+ }
+}
+
int SaveData(pid_t pid) {
unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid);
if (regs == nullptr) {
@@ -195,12 +240,6 @@
return 1;
}
- unwindstack::RemoteMaps maps(pid);
- if (!maps.Parse()) {
- printf("Unable to parse maps.\n");
- return 1;
- }
-
// Save the current state of the registers.
if (!SaveRegs(regs)) {
return 1;
@@ -208,46 +247,48 @@
// Do an unwind so we know how much of the stack to save, and what
// elf files are involved.
+ unwindstack::UnwinderFromPid unwinder(1024, pid);
+ if (!unwinder.Init(regs->Arch())) {
+ printf("Unable to init unwinder object.\n");
+ return 1;
+ }
+ unwinder.SetRegs(regs);
uint64_t sp = regs->sp();
- auto process_memory = unwindstack::Memory::CreateProcessMemory(pid);
- unwindstack::JitDebug jit_debug(process_memory);
- unwindstack::Unwinder unwinder(1024, &maps, regs, process_memory);
- unwinder.SetJitDebug(&jit_debug, regs->Arch());
unwinder.Unwind();
std::unordered_map<uint64_t, map_info_t> maps_by_start;
std::vector<std::pair<uint64_t, uint64_t>> stacks;
+ unwindstack::Maps* maps = unwinder.GetMaps();
uint64_t sp_map_start = 0;
- unwindstack::MapInfo* map_info = maps.Find(sp);
+ unwindstack::MapInfo* map_info = maps->Find(sp);
if (map_info != nullptr) {
stacks.emplace_back(std::make_pair(sp, map_info->end));
sp_map_start = map_info->start;
}
- for (auto frame : unwinder.frames()) {
- map_info = maps.Find(frame.sp);
+ for (const auto& frame : unwinder.frames()) {
+ map_info = maps->Find(frame.sp);
if (map_info != nullptr && sp_map_start != map_info->start) {
stacks.emplace_back(std::make_pair(frame.sp, map_info->end));
sp_map_start = map_info->start;
}
if (maps_by_start.count(frame.map_start) == 0) {
- auto info = &maps_by_start[frame.map_start];
- info->start = frame.map_start;
- info->end = frame.map_end;
- info->offset = frame.map_offset;
- info->name = frame.map_name;
- if (!CopyElfFromFile(info)) {
- // Try to create the elf from memory, this will handle cases where
- // the data only exists in memory such as vdso data on x86.
- if (!CreateElfFromMemory(process_memory, info)) {
- printf("Ignoring map ");
- if (!info->name.empty()) {
- printf("%s\n", info->name.c_str());
- } else {
- printf("anonymous:%" PRIx64 "\n", info->start);
- }
- }
+ map_info = maps->Find(frame.map_start);
+
+ auto info = FillInAndGetMapInfo(maps_by_start, map_info);
+ bool file_copied = false;
+ SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied);
+
+ // If you are using a a linker that creates two maps (one read-only, one
+ // read-executable), it's necessary to capture the previous map
+ // information if needed.
+ unwindstack::MapInfo* prev_map = map_info->prev_map;
+ if (prev_map != nullptr && map_info->offset != 0 && prev_map->offset == 0 &&
+ prev_map->flags == PROT_READ && map_info->name == prev_map->name &&
+ maps_by_start.count(prev_map->start) == 0) {
+ info = FillInAndGetMapInfo(maps_by_start, prev_map);
+ SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied);
}
}
}
@@ -272,8 +313,18 @@
}
for (auto& element : sorted_maps) {
+ char perms[5] = {"---p"};
map_info_t& map = element.second;
- fprintf(fp.get(), "%" PRIx64 "-%" PRIx64 " r-xp %" PRIx64 " 00:00 0", map.start, map.end,
+ if (map.flags & PROT_READ) {
+ perms[0] = 'r';
+ }
+ if (map.flags & PROT_WRITE) {
+ perms[1] = 'w';
+ }
+ if (map.flags & PROT_EXEC) {
+ perms[2] = 'x';
+ }
+ fprintf(fp.get(), "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " 00:00 0", map.start, map.end, perms,
map.offset);
if (!map.name.empty()) {
fprintf(fp.get(), " %s", map.name.c_str());
diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp
index 266a6db..3f5b88b 100644
--- a/libunwindstack/tools/unwind_info.cpp
+++ b/libunwindstack/tools/unwind_info.cpp
@@ -113,7 +113,7 @@
}
Elf elf(memory);
- if (!elf.Init(true) || !elf.valid()) {
+ if (!elf.Init() || !elf.valid()) {
printf("%s is not a valid elf file.\n", file);
return 1;
}
@@ -123,6 +123,15 @@
printf("Soname: %s\n", soname.c_str());
}
+ std::string build_id = elf.GetBuildID();
+ if (!build_id.empty()) {
+ printf("Build ID: ");
+ for (size_t i = 0; i < build_id.size(); ++i) {
+ printf("%02hhx", build_id[i]);
+ }
+ printf("\n");
+ }
+
ElfInterface* interface = elf.interface();
if (elf.machine_type() == EM_ARM) {
DumpArm(&elf, reinterpret_cast<ElfInterfaceArm*>(interface));
diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp
index 0f01566..4b6f49a 100644
--- a/libunwindstack/tools/unwind_reg_info.cpp
+++ b/libunwindstack/tools/unwind_reg_info.cpp
@@ -173,7 +173,7 @@
}
Elf elf(memory);
- if (!elf.Init(true) || !elf.valid()) {
+ if (!elf.Init() || !elf.valid()) {
printf("%s is not a valid elf file.\n", file);
return 1;
}
diff --git a/libunwindstack/tools/unwind_symbols.cpp b/libunwindstack/tools/unwind_symbols.cpp
index f8e3e92..9128430 100644
--- a/libunwindstack/tools/unwind_symbols.cpp
+++ b/libunwindstack/tools/unwind_symbols.cpp
@@ -66,7 +66,7 @@
}
unwindstack::Elf elf(memory);
- if (!elf.Init(true) || !elf.valid()) {
+ 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 1c1bdf7..fb7ca32 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -22,11 +22,13 @@
"liblog_headers",
"libsystem_headers",
"libcutils_headers",
+ "libprocessgroup_headers",
],
export_header_lib_headers: [
"liblog_headers",
"libsystem_headers",
"libcutils_headers",
+ "libprocessgroup_headers",
],
export_include_dirs: ["include"],
@@ -59,6 +61,7 @@
"-Werror",
],
header_libs: [
+ "libbase_headers",
"libutils_headers",
],
export_header_lib_headers: [
@@ -81,6 +84,7 @@
shared_libs: [
"libcutils",
+ "libprocessgroup",
"libdl",
"libvndksupport",
],
@@ -154,7 +158,7 @@
],
},
linux: {
- shared_libs: ["libbase"],
+ header_libs: ["libbase_headers"],
srcs: [
"Looper.cpp",
],
diff --git a/libutils/FileMap.cpp b/libutils/FileMap.cpp
index 583c6b9..5feb2aa 100644
--- a/libutils/FileMap.cpp
+++ b/libutils/FileMap.cpp
@@ -62,11 +62,17 @@
}
// Move Constructor.
-FileMap::FileMap(FileMap&& other)
- : mFileName(other.mFileName), mBasePtr(other.mBasePtr), mBaseLength(other.mBaseLength),
- mDataOffset(other.mDataOffset), mDataPtr(other.mDataPtr), mDataLength(other.mDataLength)
+FileMap::FileMap(FileMap&& other) noexcept
+ : mFileName(other.mFileName),
+ mBasePtr(other.mBasePtr),
+ mBaseLength(other.mBaseLength),
+ mDataOffset(other.mDataOffset),
+ mDataPtr(other.mDataPtr),
+ mDataLength(other.mDataLength)
#if defined(__MINGW32__)
- , mFileHandle(other.mFileHandle), mFileMapping(other.mFileMapping)
+ ,
+ mFileHandle(other.mFileHandle),
+ mFileMapping(other.mFileMapping)
#endif
{
other.mFileName = nullptr;
@@ -79,7 +85,7 @@
}
// Move assign operator.
-FileMap& FileMap::operator=(FileMap&& other) {
+FileMap& FileMap::operator=(FileMap&& other) noexcept {
mFileName = other.mFileName;
mBasePtr = other.mBasePtr;
mBaseLength = other.mBaseLength;
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 102fdf0..b3f943d 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -51,9 +51,6 @@
// --- Looper ---
-// Hint for number of file descriptors to be associated with the epoll instance.
-static const int EPOLL_SIZE_HINT = 8;
-
// Maximum number of file descriptors for which to retrieve poll events each iteration.
static const int EPOLL_MAX_EVENTS = 16;
@@ -139,7 +136,7 @@
}
// Allocate the new epoll instance and register the wake pipe.
- mEpollFd.reset(epoll_create(EPOLL_SIZE_HINT));
+ mEpollFd.reset(epoll_create1(EPOLL_CLOEXEC));
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
struct epoll_event eventItem;
diff --git a/libutils/PropertyMap.cpp b/libutils/PropertyMap.cpp
index b8c065d..f00272a 100644
--- a/libutils/PropertyMap.cpp
+++ b/libutils/PropertyMap.cpp
@@ -208,7 +208,7 @@
mTokenizer->nextLine();
}
- return NO_ERROR;
+ return OK;
}
} // namespace android
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index 3f1e79a..ae10789 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -19,6 +19,8 @@
#include <memory>
+#include <android-base/macros.h>
+
#include <utils/RefBase.h>
#include <utils/CallStack.h>
@@ -479,7 +481,7 @@
case INITIAL_STRONG_VALUE:
refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
std::memory_order_relaxed);
- // fall through...
+ FALLTHROUGH_INTENDED;
case 0:
refs->mBase->onFirstRef();
}
diff --git a/libutils/String16.cpp b/libutils/String16.cpp
index 5c0b406..818b171 100644
--- a/libutils/String16.cpp
+++ b/libutils/String16.cpp
@@ -157,12 +157,12 @@
if (begin >= N) {
SharedBuffer::bufferFromData(mString)->release();
mString = getEmptyString();
- return NO_ERROR;
+ return OK;
}
if ((begin+len) > N) len = N-begin;
if (begin == 0 && len == N) {
setTo(other);
- return NO_ERROR;
+ return OK;
}
if (&other == this) {
@@ -191,7 +191,7 @@
memmove(str, other, len*sizeof(char16_t));
str[len] = 0;
mString = str;
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -202,9 +202,9 @@
const size_t otherLen = other.size();
if (myLen == 0) {
setTo(other);
- return NO_ERROR;
+ return OK;
} else if (otherLen == 0) {
- return NO_ERROR;
+ return OK;
}
if (myLen >= SIZE_MAX / sizeof(char16_t) - otherLen) {
@@ -218,7 +218,7 @@
char16_t* str = (char16_t*)buf->data();
memcpy(str+myLen, other, (otherLen+1)*sizeof(char16_t));
mString = str;
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -228,9 +228,9 @@
const size_t myLen = size();
if (myLen == 0) {
setTo(chrs, otherLen);
- return NO_ERROR;
+ return OK;
} else if (otherLen == 0) {
- return NO_ERROR;
+ return OK;
}
if (myLen >= SIZE_MAX / sizeof(char16_t) - otherLen) {
@@ -245,7 +245,7 @@
memcpy(str+myLen, chrs, otherLen*sizeof(char16_t));
str[myLen+otherLen] = 0;
mString = str;
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -260,9 +260,9 @@
const size_t myLen = size();
if (myLen == 0) {
return setTo(chrs, len);
- return NO_ERROR;
+ return OK;
} else if (len == 0) {
- return NO_ERROR;
+ return OK;
}
if (pos > myLen) pos = myLen;
@@ -286,7 +286,7 @@
#if 0
printf("Result (%d chrs): %s\n", size(), String8(*this).string());
#endif
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -357,7 +357,7 @@
edit[i] = tolower((char)v);
}
}
- return NO_ERROR;
+ return OK;
}
status_t String16::replaceAll(char16_t replaceThis, char16_t withThis)
@@ -378,7 +378,7 @@
edit[i] = withThis;
}
}
- return NO_ERROR;
+ return OK;
}
status_t String16::remove(size_t len, size_t begin)
@@ -387,11 +387,11 @@
if (begin >= N) {
SharedBuffer::bufferFromData(mString)->release();
mString = getEmptyString();
- return NO_ERROR;
+ return OK;
}
if ((begin+len) > N) len = N-begin;
if (begin == 0 && len == N) {
- return NO_ERROR;
+ return OK;
}
if (begin > 0) {
@@ -410,7 +410,7 @@
char16_t* str = (char16_t*)buf->data();
str[len] = 0;
mString = str;
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index 8d318f7..0025c56 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -230,7 +230,7 @@
const char *newString = allocFromUTF8(other, strlen(other));
SharedBuffer::bufferFromData(mString)->release();
mString = newString;
- if (mString) return NO_ERROR;
+ if (mString) return OK;
mString = getEmptyString();
return NO_MEMORY;
@@ -241,7 +241,7 @@
const char *newString = allocFromUTF8(other, len);
SharedBuffer::bufferFromData(mString)->release();
mString = newString;
- if (mString) return NO_ERROR;
+ if (mString) return OK;
mString = getEmptyString();
return NO_MEMORY;
@@ -252,7 +252,7 @@
const char *newString = allocFromUTF16(other, len);
SharedBuffer::bufferFromData(mString)->release();
mString = newString;
- if (mString) return NO_ERROR;
+ if (mString) return OK;
mString = getEmptyString();
return NO_MEMORY;
@@ -263,7 +263,7 @@
const char *newString = allocFromUTF32(other, len);
SharedBuffer::bufferFromData(mString)->release();
mString = newString;
- if (mString) return NO_ERROR;
+ if (mString) return OK;
mString = getEmptyString();
return NO_MEMORY;
@@ -274,9 +274,9 @@
const size_t otherLen = other.bytes();
if (bytes() == 0) {
setTo(other);
- return NO_ERROR;
+ return OK;
} else if (otherLen == 0) {
- return NO_ERROR;
+ return OK;
}
return real_append(other.string(), otherLen);
@@ -292,7 +292,7 @@
if (bytes() == 0) {
return setTo(other, otherLen);
} else if (otherLen == 0) {
- return NO_ERROR;
+ return OK;
}
return real_append(other, otherLen);
@@ -311,7 +311,7 @@
status_t String8::appendFormatV(const char* fmt, va_list args)
{
- int n, result = NO_ERROR;
+ int n, result = OK;
va_list tmp_args;
/* args is undefined after vsnprintf.
@@ -346,7 +346,7 @@
str += myLen;
memcpy(str, other, otherLen);
str[otherLen] = '\0';
- return NO_ERROR;
+ return OK;
}
return NO_MEMORY;
}
@@ -382,7 +382,7 @@
mString = str;
}
- return NO_ERROR;
+ return OK;
}
ssize_t String8::find(const char* other, size_t start) const
diff --git a/libutils/Threads.cpp b/libutils/Threads.cpp
index 43ec6c1..31ca138 100644
--- a/libutils/Threads.cpp
+++ b/libutils/Threads.cpp
@@ -36,7 +36,7 @@
#include <utils/Log.h>
-#include <cutils/sched_policy.h>
+#include <processgroup/sched_policy.h>
#if defined(__ANDROID__)
# define __android_unused
@@ -379,7 +379,7 @@
{
DWORD dwWaitResult;
dwWaitResult = WaitForSingleObject((HANDLE) mState, INFINITE);
- return dwWaitResult != WAIT_OBJECT_0 ? -1 : NO_ERROR;
+ return dwWaitResult != WAIT_OBJECT_0 ? -1 : OK;
}
void Mutex::unlock()
@@ -506,7 +506,7 @@
ReleaseMutex(condState->internalMutex);
WaitForSingleObject(hMutex, INFINITE);
- return res == WAIT_OBJECT_0 ? NO_ERROR : -1;
+ return res == WAIT_OBJECT_0 ? OK : -1;
}
} WinCondition;
@@ -639,13 +639,15 @@
*/
Thread::Thread(bool canCallJava)
- : mCanCallJava(canCallJava),
- mThread(thread_id_t(-1)),
- mLock("Thread::mLock"),
- mStatus(NO_ERROR),
- mExitPending(false), mRunning(false)
+ : mCanCallJava(canCallJava),
+ mThread(thread_id_t(-1)),
+ mLock("Thread::mLock"),
+ mStatus(OK),
+ mExitPending(false),
+ mRunning(false)
#if defined(__ANDROID__)
- , mTid(-1)
+ ,
+ mTid(-1)
#endif
{
}
@@ -656,7 +658,7 @@
status_t Thread::readyToRun()
{
- return NO_ERROR;
+ return OK;
}
status_t Thread::run(const char* name, int32_t priority, size_t stack)
@@ -672,7 +674,7 @@
// reset status and exitPending to their default value, so we can
// try again after an error happened (either below, or in readyToRun())
- mStatus = NO_ERROR;
+ mStatus = OK;
mExitPending = false;
mThread = thread_id_t(-1);
@@ -700,10 +702,10 @@
}
// Do not refer to mStatus here: The thread is already running (may, in fact
- // already have exited with a valid mStatus result). The NO_ERROR indication
+ // already have exited with a valid mStatus result). The OK indication
// here merely indicates successfully starting the thread and does not
// imply successful termination/execution.
- return NO_ERROR;
+ return OK;
// Exiting scope of mLock is a memory barrier and allows new thread to run
}
@@ -728,7 +730,7 @@
if (first) {
first = false;
self->mStatus = self->readyToRun();
- result = (self->mStatus == NO_ERROR);
+ result = (self->mStatus == OK);
if (result && !self->exitPending()) {
// Binder threads (and maybe others) rely on threadLoop
diff --git a/libutils/Tokenizer.cpp b/libutils/Tokenizer.cpp
index f73d699..98dd2fd 100644
--- a/libutils/Tokenizer.cpp
+++ b/libutils/Tokenizer.cpp
@@ -48,7 +48,7 @@
status_t Tokenizer::open(const String8& filename, Tokenizer** outTokenizer) {
*outTokenizer = nullptr;
- int result = NO_ERROR;
+ int result = OK;
int fd = ::open(filename.string(), O_RDONLY);
if (fd < 0) {
result = -errno;
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
index 82f650d..5f0a51f 100644
--- a/libutils/Unicode.cpp
+++ b/libutils/Unicode.cpp
@@ -16,8 +16,9 @@
#define LOG_TAG "unicode"
-#include <utils/Unicode.h>
+#include <android-base/macros.h>
#include <limits.h>
+#include <utils/Unicode.h>
#include <log/log.h>
@@ -105,8 +106,11 @@
switch (bytes)
{ /* note: everything falls through. */
case 4: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6;
+ FALLTHROUGH_INTENDED;
case 3: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6;
+ FALLTHROUGH_INTENDED;
case 2: *--dstP = (uint8_t)((srcChar | kByteMark) & kByteMask); srcChar >>= 6;
+ FALLTHROUGH_INTENDED;
case 1: *--dstP = (uint8_t)(srcChar | kFirstByteMark[bytes]);
}
}
diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp
index e16f88d..c97a19b 100644
--- a/libutils/VectorImpl.cpp
+++ b/libutils/VectorImpl.cpp
@@ -61,7 +61,7 @@
"[%p] subclasses of VectorImpl must call finish_vector()"
" in their destructor. Leaking %d bytes.",
this, (int)(mCount*mItemSize));
- // We can't call _do_destroy() here because the vtable is already gone.
+ // We can't call _do_destroy() here because the vtable is already gone.
}
VectorImpl& VectorImpl::operator = (const VectorImpl& rhs)
@@ -197,7 +197,7 @@
_do_copy(temp, item, 1);
ssize_t j = i-1;
- void* next = reinterpret_cast<char*>(array) + mItemSize*(i);
+ void* next = reinterpret_cast<char*>(array) + mItemSize*(i);
do {
_do_destroy(next, 1);
_do_copy(next, curr, 1);
@@ -214,13 +214,13 @@
}
i++;
}
-
+
if (temp) {
_do_destroy(temp, 1);
free(temp);
}
}
- return NO_ERROR;
+ return OK;
}
void VectorImpl::pop()
@@ -354,7 +354,7 @@
}
ssize_t VectorImpl::resize(size_t size) {
- ssize_t result = NO_ERROR;
+ ssize_t result = OK;
if (size > mCount) {
result = insertAt(mCount, size - mCount);
} else if (size < mCount) {
@@ -370,7 +370,7 @@
if (sb->release(SharedBuffer::eKeepStorage) == 1) {
_do_destroy(mStorage, mCount);
SharedBuffer::dealloc(sb);
- }
+ }
}
}
@@ -644,13 +644,13 @@
}
}
}
- return NO_ERROR;
+ return OK;
}
ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector)
{
// we've merging a sorted vector... nice!
- ssize_t err = NO_ERROR;
+ ssize_t err = OK;
if (!vector.isEmpty()) {
// first take care of the case where the vectors are sorted together
if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) {
@@ -677,4 +677,3 @@
/*****************************************************************************/
}; // namespace android
-
diff --git a/libutils/include/utils/CallStack.h b/libutils/include/utils/CallStack.h
index 56004fe..7a4a345 100644
--- a/libutils/include/utils/CallStack.h
+++ b/libutils/include/utils/CallStack.h
@@ -123,13 +123,14 @@
if (reinterpret_cast<uintptr_t>(logStackInternal) != 0 && stack != nullptr) {
logStackInternal(logtag, stack, priority);
} else {
- ALOGW("CallStack::logStackInternal not linked");
+ ALOG(LOG_WARN, logtag, "CallStack::logStackInternal not linked");
}
}
#else
- static void ALWAYS_INLINE logStack(const char*, CallStack* = getCurrent().get(),
+ static void ALWAYS_INLINE logStack(const char* logtag, CallStack* = getCurrent().get(),
android_LogPriority = ANDROID_LOG_DEBUG) {
+ ALOG(LOG_WARN, logtag, "CallStack::logStackInternal not linked");
}
#endif // !WEAKS_AVAILABLE
@@ -139,13 +140,13 @@
if (reinterpret_cast<uintptr_t>(stackToStringInternal) != 0 && stack != nullptr) {
return stackToStringInternal(prefix, stack);
} else {
- return String8("<CallStack package not linked>");
+ return String8::format("%s<CallStack package not linked>", (prefix ? prefix : ""));
}
}
#else // !WEAKS_AVAILABLE
- static String8 ALWAYS_INLINE stackToString(const char* = nullptr,
+ static String8 ALWAYS_INLINE stackToString(const char* prefix = nullptr,
const CallStack* = getCurrent().get()) {
- return String8("<CallStack package not linked>");
+ return String8::format("%s<CallStack package not linked>", (prefix ? prefix : ""));
}
#endif // !WEAKS_AVAILABLE
diff --git a/libutils/include/utils/Errors.h b/libutils/include/utils/Errors.h
index 7093a20..1e03677 100644
--- a/libutils/include/utils/Errors.h
+++ b/libutils/include/utils/Errors.h
@@ -14,22 +14,19 @@
* limitations under the License.
*/
-#ifndef ANDROID_ERRORS_H
-#define ANDROID_ERRORS_H
+#pragma once
-#include <sys/types.h>
#include <errno.h>
+#include <stdint.h>
+#include <sys/types.h>
namespace android {
-// use this type to return error codes
-#ifdef _WIN32
-typedef int status_t;
-#else
-typedef int32_t status_t;
-#endif
-
-/* the MS C runtime lacks a few error codes */
+/**
+ * The type used to return success/failure from frameworks APIs.
+ * See the anonymous enum below for valid values.
+ */
+typedef int32_t status_t;
/*
* Error codes.
@@ -43,8 +40,8 @@
#endif
enum {
- OK = 0, // Everything's swell.
- NO_ERROR = 0, // No errors.
+ OK = 0, // Preferred constant for checking success.
+ NO_ERROR = OK, // Deprecated synonym for `OK`. Prefer `OK` because it doesn't conflict with Windows.
UNKNOWN_ERROR = (-2147483647-1), // INT32_MIN value
@@ -82,7 +79,3 @@
#endif
} // namespace android
-
-// ---------------------------------------------------------------------------
-
-#endif // ANDROID_ERRORS_H
diff --git a/libutils/include/utils/FileMap.h b/libutils/include/utils/FileMap.h
index 8d402a3..f9f8f3c 100644
--- a/libutils/include/utils/FileMap.h
+++ b/libutils/include/utils/FileMap.h
@@ -52,8 +52,8 @@
public:
FileMap(void);
- FileMap(FileMap&& f);
- FileMap& operator=(FileMap&& f);
+ FileMap(FileMap&& f) noexcept;
+ FileMap& operator=(FileMap&& f) noexcept;
/*
* Create a new mapping on an open file.
diff --git a/libutils/include/utils/Flattenable.h b/libutils/include/utils/Flattenable.h
index 0a19019..9d00602 100644
--- a/libutils/include/utils/Flattenable.h
+++ b/libutils/include/utils/Flattenable.h
@@ -190,11 +190,11 @@
inline status_t flatten(void* buffer, size_t size) const {
if (size < sizeof(T)) return NO_MEMORY;
memcpy(buffer, static_cast<T const*>(this), sizeof(T));
- return NO_ERROR;
+ return OK;
}
inline status_t unflatten(void const* buffer, size_t) {
memcpy(static_cast<T*>(this), buffer, sizeof(T));
- return NO_ERROR;
+ return OK;
}
};
diff --git a/libutils/include/utils/Functor.h b/libutils/include/utils/Functor.h
index c0c8d57..c458699 100644
--- a/libutils/include/utils/Functor.h
+++ b/libutils/include/utils/Functor.h
@@ -29,7 +29,7 @@
public:
Functor() {}
virtual ~Functor() {}
- virtual status_t operator ()(int /*what*/, void* /*data*/) { return NO_ERROR; }
+ virtual status_t operator()(int /*what*/, void* /*data*/) { return OK; }
};
} // namespace android
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index 3abce17..1571129 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -56,7 +56,7 @@
sp(T* other); // NOLINT(implicit)
sp(const sp<T>& other);
- sp(sp<T>&& other);
+ sp(sp<T>&& other) noexcept;
template<typename U> sp(U* other); // NOLINT(implicit)
template<typename U> sp(const sp<U>& other); // NOLINT(implicit)
template<typename U> sp(sp<U>&& other); // NOLINT(implicit)
@@ -67,7 +67,7 @@
sp& operator = (T* other);
sp& operator = (const sp<T>& other);
- sp& operator = (sp<T>&& other);
+ sp& operator=(sp<T>&& other) noexcept;
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (sp<U>&& other);
@@ -125,9 +125,8 @@
m_ptr->incStrong(this);
}
-template<typename T>
-sp<T>::sp(sp<T>&& other)
- : m_ptr(other.m_ptr) {
+template <typename T>
+sp<T>::sp(sp<T>&& other) noexcept : m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
@@ -169,8 +168,8 @@
return *this;
}
-template<typename T>
-sp<T>& sp<T>::operator =(sp<T>&& other) {
+template <typename T>
+sp<T>& sp<T>::operator=(sp<T>&& other) noexcept {
T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
if (oldPtr) oldPtr->decStrong(this);
if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
diff --git a/libutils/include/utils/Thread.h b/libutils/include/utils/Thread.h
index 3525138..fc67656 100644
--- a/libutils/include/utils/Thread.h
+++ b/libutils/include/utils/Thread.h
@@ -47,6 +47,7 @@
virtual ~Thread();
// Start the thread in threadLoop() which needs to be implemented.
+ // NOLINTNEXTLINE(google-default-arguments)
virtual status_t run( const char* name,
int32_t priority = PRIORITY_DEFAULT,
size_t stack = 0);
diff --git a/libutils/include/utils/Tokenizer.h b/libutils/include/utils/Tokenizer.h
index bb25f37..61c5ff7 100644
--- a/libutils/include/utils/Tokenizer.h
+++ b/libutils/include/utils/Tokenizer.h
@@ -37,7 +37,7 @@
/**
* Opens a file and maps it into memory.
*
- * Returns NO_ERROR and a tokenizer for the file, if successful.
+ * Returns OK and a tokenizer for the file, if successful.
* Otherwise returns an error and sets outTokenizer to NULL.
*/
static status_t open(const String8& filename, Tokenizer** outTokenizer);
@@ -45,7 +45,7 @@
/**
* Prepares to tokenize the contents of a string.
*
- * Returns NO_ERROR and a tokenizer for the string, if successful.
+ * Returns OK and a tokenizer for the string, if successful.
* Otherwise returns an error and sets outTokenizer to NULL.
*/
static status_t fromContents(const String8& filename,
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 2606aa9..9538bba 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -23,11 +23,21 @@
"-D_FILE_OFFSET_BITS=64",
],
cppflags: [
- "-Wold-style-cast",
// Incorrectly warns when C++11 empty brace {} initializer is used.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61489
"-Wno-missing-field-initializers",
],
+
+ // Enable -Wold-style-cast only for non-Windows targets. _islower_l,
+ // _isupper_l etc. in MinGW locale_win32.h (included from
+ // libcxx/include/__locale) has an old-style-cast.
+ target: {
+ not_windows: {
+ cppflags: [
+ "-Wold-style-cast",
+ ],
+ },
+ },
}
cc_defaults {
@@ -63,6 +73,7 @@
enabled: true,
},
double_loadable: true,
+ export_shared_lib_headers: ["libbase"],
defaults: [
"libziparchive_defaults",
@@ -74,14 +85,6 @@
"libz",
],
target: {
- android: {
- shared_libs: [
- "libutils",
- ],
- },
- host: {
- static_libs: ["libutils"],
- },
linux_bionic: {
enabled: true,
},
@@ -122,6 +125,7 @@
enabled: true,
},
},
+ test_suites: ["device-tests"],
}
// Performance benchmarks.
@@ -158,4 +162,5 @@
"libbase",
"libziparchive",
],
+ recovery_available: true,
}
diff --git a/libziparchive/include/ziparchive/zip_archive.h b/libziparchive/include/ziparchive/zip_archive.h
index 018b1a9..ab38dfd 100644
--- a/libziparchive/include/ziparchive/zip_archive.h
+++ b/libziparchive/include/ziparchive/zip_archive.h
@@ -14,17 +14,18 @@
* limitations under the License.
*/
+#pragma once
+
/*
* Read-only access to Zip archives, with minimal heap allocation.
*/
-#ifndef LIBZIPARCHIVE_ZIPARCHIVE_H_
-#define LIBZIPARCHIVE_ZIPARCHIVE_H_
#include <stdint.h>
#include <string.h>
#include <sys/cdefs.h>
#include <sys/types.h>
-#include <utils/Compat.h>
+
+#include "android-base/off64_t.h"
/* Zip compression methods we support */
enum {
@@ -103,7 +104,8 @@
off64_t offset;
};
-typedef void* ZipArchiveHandle;
+struct ZipArchive;
+typedef ZipArchive* ZipArchiveHandle;
/*
* Open a Zip archive, and sets handle to the value of the opaque
@@ -144,7 +146,7 @@
* this handle for any further operations without an intervening
* call to one of the OpenArchive variants.
*/
-void CloseArchive(ZipArchiveHandle handle);
+void CloseArchive(ZipArchiveHandle archive);
/*
* Find an entry in the Zip archive, by name. |entryName| must be a null
@@ -162,7 +164,7 @@
* On non-Windows platforms this method does not modify internal state and
* can be called concurrently.
*/
-int32_t FindEntry(const ZipArchiveHandle handle, const ZipString& entryName, ZipEntry* data);
+int32_t FindEntry(const ZipArchiveHandle archive, const ZipString& entryName, ZipEntry* data);
/*
* Start iterating over all entries of a zip file. The order of iteration
@@ -177,8 +179,8 @@
*
* Returns 0 on success and negative values on failure.
*/
-int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr, const ZipString* optional_prefix,
- const ZipString* optional_suffix);
+int32_t StartIteration(ZipArchiveHandle archive, void** cookie_ptr,
+ const ZipString* optional_prefix, const ZipString* optional_suffix);
/*
* Advance to the next element in the zipfile in iteration order.
@@ -203,7 +205,7 @@
*
* Returns 0 on success and negative values on failure.
*/
-int32_t ExtractEntryToFile(ZipArchiveHandle handle, ZipEntry* entry, int fd);
+int32_t ExtractEntryToFile(ZipArchiveHandle archive, ZipEntry* entry, int fd);
/**
* Uncompress a given zip entry to the memory region at |begin| and of
@@ -213,9 +215,9 @@
*
* Returns 0 on success and negative values on failure.
*/
-int32_t ExtractToMemory(ZipArchiveHandle handle, ZipEntry* entry, uint8_t* begin, uint32_t size);
+int32_t ExtractToMemory(ZipArchiveHandle archive, ZipEntry* entry, uint8_t* begin, uint32_t size);
-int GetFileDescriptor(const ZipArchiveHandle handle);
+int GetFileDescriptor(const ZipArchiveHandle archive);
const char* ErrorCodeString(int32_t error_code);
@@ -226,7 +228,7 @@
* Stream the uncompressed data through the supplied function,
* passing cookie to it each time it gets called.
*/
-int32_t ProcessZipEntryContents(ZipArchiveHandle handle, ZipEntry* entry,
+int32_t ProcessZipEntryContents(ZipArchiveHandle archive, ZipEntry* entry,
ProcessZipEntryFunction func, void* cookie);
#endif
@@ -272,5 +274,3 @@
int32_t Inflate(const Reader& reader, const uint32_t compressed_length,
const uint32_t uncompressed_length, Writer* writer, uint64_t* crc_out);
} // namespace zip_archive
-
-#endif // LIBZIPARCHIVE_ZIPARCHIVE_H_
diff --git a/libziparchive/include/ziparchive/zip_archive_stream_entry.h b/libziparchive/include/ziparchive/zip_archive_stream_entry.h
index b4766f8..8c6ca79 100644
--- a/libziparchive/include/ziparchive/zip_archive_stream_entry.h
+++ b/libziparchive/include/ziparchive/zip_archive_stream_entry.h
@@ -15,12 +15,13 @@
*/
// Read-only stream access to Zip archives entries.
-#ifndef LIBZIPARCHIVE_ZIPARCHIVESTREAMENTRY_H_
-#define LIBZIPARCHIVE_ZIPARCHIVESTREAMENTRY_H_
+#pragma once
+
+#include <ziparchive/zip_archive.h>
#include <vector>
-#include <ziparchive/zip_archive.h>
+#include "android-base/off64_t.h"
class ZipArchiveStreamEntry {
public:
@@ -43,5 +44,3 @@
off64_t offset_ = 0;
uint32_t crc32_ = 0u;
};
-
-#endif // LIBZIPARCHIVE_ZIPARCHIVESTREAMENTRY_H_
diff --git a/libziparchive/include/ziparchive/zip_writer.h b/libziparchive/include/ziparchive/zip_writer.h
index c350a27..f6c8427 100644
--- a/libziparchive/include/ziparchive/zip_writer.h
+++ b/libziparchive/include/ziparchive/zip_writer.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef LIBZIPARCHIVE_ZIPWRITER_H_
-#define LIBZIPARCHIVE_ZIPWRITER_H_
+#pragma once
#include <cstdio>
#include <ctime>
@@ -25,7 +24,7 @@
#include <vector>
#include "android-base/macros.h"
-#include "utils/Compat.h"
+#include "android-base/off64_t.h"
struct z_stream_s;
typedef struct z_stream_s z_stream;
@@ -91,10 +90,10 @@
explicit ZipWriter(FILE* f);
// Move constructor.
- ZipWriter(ZipWriter&& zipWriter);
+ ZipWriter(ZipWriter&& zipWriter) noexcept;
// Move assignment.
- ZipWriter& operator=(ZipWriter&& zipWriter);
+ ZipWriter& operator=(ZipWriter&& zipWriter) noexcept;
/**
* Starts a new zip entry with the given path and flags.
@@ -183,5 +182,3 @@
std::unique_ptr<z_stream, void (*)(z_stream*)> z_stream_;
std::vector<uint8_t> buffer_;
};
-
-#endif /* LIBZIPARCHIVE_ZIPWRITER_H_ */
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index add6e14..6b9f6e1 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -20,7 +20,8 @@
#define LOG_TAG "ziparchive"
-#include <assert.h>
+#include "ziparchive/zip_archive.h"
+
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -33,6 +34,10 @@
#include <memory>
#include <vector>
+#if defined(__APPLE__)
+#define lseek64 lseek
+#endif
+
#if defined(__BIONIC__)
#include <android/fdsan.h>
#endif
@@ -40,12 +45,10 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#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/utf8.h>
#include <log/log.h>
-#include <utils/Compat.h>
-#include <utils/FileMap.h>
-#include "ziparchive/zip_archive.h"
#include "zlib.h"
#include "entry_name_utils-inl.h"
@@ -58,12 +61,6 @@
// specified in the local file header and the central directory.
static const bool kCrcChecksEnabled = false;
-// This is for windows. If we don't open a file in binary mode, weird
-// things will happen.
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
// The maximum number of bytes to scan backwards for the EOCD start.
static const uint32_t kMaxEOCDSearch = kMaxCommentLen + sizeof(EocdRecord);
@@ -122,21 +119,36 @@
#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);
+}
+
/*
* Convert a ZipEntry to a hash table index, verifying that it's in a
* valid range.
*/
-static int64_t EntryToIndex(const ZipString* hash_table, const uint32_t hash_table_size,
- const ZipString& name) {
+static int64_t EntryToIndex(const ZipStringOffset* hash_table, const uint32_t hash_table_size,
+ const ZipString& 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 != NULL) {
- if (hash_table[ent] == name) {
+ while (hash_table[ent].name_offset != 0) {
+ if (isZipStringEqual(start, name, hash_table[ent])) {
return ent;
}
-
ent = (ent + 1) & (hash_table_size - 1);
}
@@ -147,8 +159,8 @@
/*
* Add a new entry to the hash table.
*/
-static int32_t AddToHash(ZipString* hash_table, const uint64_t hash_table_size,
- const ZipString& name) {
+static int32_t AddToHash(ZipStringOffset* hash_table, const uint64_t hash_table_size,
+ const ZipString& name, const uint8_t* start) {
const uint64_t hash = ComputeHash(name);
uint32_t ent = hash & (hash_table_size - 1);
@@ -156,32 +168,38 @@
* We over-allocated the table, so we're guaranteed to find an empty slot.
* Further, we guarantee that the hashtable size is not 0.
*/
- while (hash_table[ent].name != NULL) {
- if (hash_table[ent] == name) {
+ 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);
return kDuplicateEntry;
}
ent = (ent + 1) & (hash_table_size - 1);
}
-
- hash_table[ent].name = name.name;
+ hash_table[ent].name_offset = GetOffset(name.name, start);
hash_table[ent].name_length = name.name_length;
return 0;
}
+#if defined(__BIONIC__)
+uint64_t GetOwnerTag(const ZipArchive* archive) {
+ return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_ZIPARCHIVE,
+ reinterpret_cast<uint64_t>(archive));
+}
+#endif
+
ZipArchive::ZipArchive(const int fd, bool assume_ownership)
: mapped_zip(fd),
close_file(assume_ownership),
directory_offset(0),
central_directory(),
- directory_map(new android::FileMap()),
+ directory_map(),
num_entries(0),
hash_table_size(0),
hash_table(nullptr) {
#if defined(__BIONIC__)
if (assume_ownership) {
- android_fdsan_exchange_owner_tag(fd, 0, reinterpret_cast<uint64_t>(this));
+ android_fdsan_exchange_owner_tag(fd, 0, GetOwnerTag(this));
}
#endif
}
@@ -191,7 +209,7 @@
close_file(false),
directory_offset(0),
central_directory(),
- directory_map(new android::FileMap()),
+ directory_map(),
num_entries(0),
hash_table_size(0),
hash_table(nullptr) {}
@@ -199,7 +217,7 @@
ZipArchive::~ZipArchive() {
if (close_file && mapped_zip.GetFileDescriptor() >= 0) {
#if defined(__BIONIC__)
- android_fdsan_close_with_tag(mapped_zip.GetFileDescriptor(), reinterpret_cast<uint64_t>(this));
+ android_fdsan_close_with_tag(mapped_zip.GetFileDescriptor(), GetOwnerTag(this));
#else
close(mapped_zip.GetFileDescriptor());
#endif
@@ -209,7 +227,8 @@
}
static int32_t MapCentralDirectory0(const char* debug_file_name, ZipArchive* archive,
- off64_t file_length, off64_t read_amount, uint8_t* scan_buffer) {
+ off64_t file_length, off64_t read_amount,
+ uint8_t* scan_buffer) {
const off64_t search_start = file_length - read_amount;
if (!archive->mapped_zip.ReadAtOffset(scan_buffer, read_amount, search_start)) {
@@ -281,8 +300,7 @@
* in archive.
*/
- if (!archive->InitializeCentralDirectory(debug_file_name,
- static_cast<off64_t>(eocd->cd_start_offset),
+ 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;
@@ -362,7 +380,7 @@
*/
archive->hash_table_size = RoundUpPower2(1 + (num_entries * 4) / 3);
archive->hash_table =
- reinterpret_cast<ZipString*>(calloc(archive->hash_table_size, sizeof(ZipString)));
+ 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));
@@ -418,7 +436,8 @@
ZipString entry_name;
entry_name.name = file_name;
entry_name.name_length = file_name_length;
- const int add_result = AddToHash(archive->hash_table, archive->hash_table_size, entry_name);
+ const int add_result = AddToHash(archive->hash_table, archive->hash_table_size, entry_name,
+ archive->central_directory.GetBasePtr());
if (add_result != 0) {
ALOGW("Zip: Error adding entry to hash table %d", add_result);
return add_result;
@@ -472,7 +491,7 @@
}
int32_t OpenArchive(const char* fileName, ZipArchiveHandle* handle) {
- const int fd = ::android::base::utf8::open(fileName, O_RDONLY | O_BINARY, 0);
+ const int fd = ::android::base::utf8::open(fileName, O_RDONLY | O_BINARY | O_CLOEXEC, 0);
ZipArchive* archive = new ZipArchive(fd, true);
*handle = archive;
@@ -494,8 +513,7 @@
/*
* Close a ZipArchive, closing the file and freeing the contents.
*/
-void CloseArchive(ZipArchiveHandle handle) {
- ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
+void CloseArchive(ZipArchiveHandle archive) {
ALOGV("Closing archive %p", archive);
delete archive;
}
@@ -538,7 +556,9 @@
// 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 uint8_t* ptr = archive->hash_table[ent].name;
+ const ZipString from_offset =
+ archive->hash_table[ent].GetZipString(archive->central_directory.GetBasePtr());
+ const uint8_t* ptr = from_offset.name;
ptr -= sizeof(CentralDirectoryRecord);
// This is the base of our mmapped region, we have to sanity check that
@@ -648,8 +668,9 @@
ALOGW("Zip: failed reading lfh name from offset %" PRId64, static_cast<int64_t>(name_offset));
return kIoError;
}
-
- if (memcmp(archive->hash_table[ent].name, name_buf.data(), nameLen)) {
+ const ZipString from_offset =
+ archive->hash_table[ent].GetZipString(archive->central_directory.GetBasePtr());
+ if (memcmp(from_offset.name, name_buf.data(), nameLen)) {
return kInconsistentInformation;
}
@@ -719,10 +740,8 @@
}
};
-int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr, const ZipString* optional_prefix,
- const ZipString* optional_suffix) {
- ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
-
+int32_t StartIteration(ZipArchiveHandle archive, void** cookie_ptr,
+ const ZipString* optional_prefix, const ZipString* optional_suffix) {
if (archive == NULL || archive->hash_table == NULL) {
ALOGW("Zip: Invalid ZipArchiveHandle");
return kInvalidHandle;
@@ -740,26 +759,25 @@
delete reinterpret_cast<IterationHandle*>(cookie);
}
-int32_t FindEntry(const ZipArchiveHandle handle, const ZipString& entryName, ZipEntry* data) {
- const ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
+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);
return kInvalidEntryName;
}
- const int64_t ent = EntryToIndex(archive->hash_table, archive->hash_table_size, entryName);
-
+ 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;
}
-
return FindEntry(archive, ent, data);
}
int32_t Next(void* cookie, ZipEntry* data, ZipString* name) {
IterationHandle* handle = reinterpret_cast<IterationHandle*>(cookie);
if (handle == NULL) {
+ ALOGW("Zip: Null ZipArchiveHandle");
return kInvalidHandle;
}
@@ -771,19 +789,19 @@
const uint32_t currentOffset = handle->position;
const uint32_t hash_table_length = archive->hash_table_size;
- const ZipString* hash_table = archive->hash_table;
-
+ const ZipStringOffset* hash_table = archive->hash_table;
for (uint32_t i = currentOffset; i < hash_table_length; ++i) {
- if (hash_table[i].name != NULL &&
- (handle->prefix.name_length == 0 || hash_table[i].StartsWith(handle->prefix)) &&
- (handle->suffix.name_length == 0 || hash_table[i].EndsWith(handle->suffix))) {
+ 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))) {
handle->position = (i + 1);
const int error = FindEntry(archive, i, data);
if (!error) {
- name->name = hash_table[i].name;
+ name->name = from_offset.name;
name->name_length = hash_table[i].name_length;
}
-
return error;
}
}
@@ -801,7 +819,7 @@
virtual bool Append(uint8_t* buf, size_t buf_size) override {
if (bytes_written_ + buf_size > size_) {
- ALOGW("Zip: Unexpected size " ZD " (declared) vs " ZD " (actual)", size_,
+ ALOGW("Zip: Unexpected size %zu (declared) vs %zu (actual)", size_,
bytes_written_ + buf_size);
return false;
}
@@ -877,7 +895,7 @@
return FileWriter(fd, declared_length);
}
- FileWriter(FileWriter&& other)
+ FileWriter(FileWriter&& other) noexcept
: fd_(other.fd_),
declared_length_(other.declared_length_),
total_bytes_written_(other.total_bytes_written_) {
@@ -888,7 +906,7 @@
virtual bool Append(uint8_t* buf, size_t buf_size) override {
if (total_bytes_written_ + buf_size > declared_length_) {
- ALOGW("Zip: Unexpected size " ZD " (declared) vs " ZD " (actual)", declared_length_,
+ ALOGW("Zip: Unexpected size %zu (declared) vs %zu (actual)", declared_length_,
total_bytes_written_ + buf_size);
return false;
}
@@ -897,7 +915,7 @@
if (result) {
total_bytes_written_ += buf_size;
} else {
- ALOGW("Zip: unable to write " ZD " bytes to file; %s", buf_size, strerror(errno));
+ ALOGW("Zip: unable to write %zu bytes to file; %s", buf_size, strerror(errno));
}
return result;
@@ -1026,7 +1044,7 @@
}
} while (zerr == Z_OK);
- assert(zerr == Z_STREAM_END); /* other errors should've been caught */
+ CHECK_EQ(zerr, Z_STREAM_END); /* other errors should've been caught */
// NOTE: zstream.adler is always set to 0, because we're using the -MAX_WBITS
// "feature" of zlib to tell it there won't be a zlib file header. zlib
@@ -1090,8 +1108,7 @@
return 0;
}
-int32_t ExtractToWriter(ZipArchiveHandle handle, ZipEntry* entry, zip_archive::Writer* writer) {
- ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
+int32_t ExtractToWriter(ZipArchiveHandle archive, ZipEntry* entry, zip_archive::Writer* writer) {
const uint16_t method = entry->method;
// this should default to kUnknownCompressionMethod.
@@ -1119,18 +1136,18 @@
return return_value;
}
-int32_t ExtractToMemory(ZipArchiveHandle handle, ZipEntry* entry, uint8_t* begin, uint32_t size) {
+int32_t ExtractToMemory(ZipArchiveHandle archive, ZipEntry* entry, uint8_t* begin, uint32_t size) {
MemoryWriter writer(begin, size);
- return ExtractToWriter(handle, entry, &writer);
+ return ExtractToWriter(archive, entry, &writer);
}
-int32_t ExtractEntryToFile(ZipArchiveHandle handle, ZipEntry* entry, int fd) {
+int32_t ExtractEntryToFile(ZipArchiveHandle archive, ZipEntry* entry, int fd) {
auto writer = FileWriter::Create(fd, entry);
if (!writer.IsValid()) {
return kIoError;
}
- return ExtractToWriter(handle, entry, &writer);
+ return ExtractToWriter(archive, entry, &writer);
}
const char* ErrorCodeString(int32_t error_code) {
@@ -1147,8 +1164,8 @@
return "Unknown return code";
}
-int GetFileDescriptor(const ZipArchiveHandle handle) {
- return reinterpret_cast<ZipArchive*>(handle)->mapped_zip.GetFileDescriptor();
+int GetFileDescriptor(const ZipArchiveHandle archive) {
+ return archive->mapped_zip.GetFileDescriptor();
}
ZipString::ZipString(const char* entry_name) : name(reinterpret_cast<const uint8_t*>(entry_name)) {
@@ -1172,10 +1189,10 @@
void* cookie_;
};
-int32_t ProcessZipEntryContents(ZipArchiveHandle handle, ZipEntry* entry,
+int32_t ProcessZipEntryContents(ZipArchiveHandle archive, ZipEntry* entry,
ProcessZipEntryFunction func, void* cookie) {
ProcessWriter writer(func, cookie);
- return ExtractToWriter(handle, entry, &writer);
+ return ExtractToWriter(archive, entry, &writer);
}
#endif //! defined(_WIN32)
@@ -1234,16 +1251,14 @@
length_ = cd_size;
}
-bool ZipArchive::InitializeCentralDirectory(const char* debug_file_name, off64_t cd_start_offset,
- size_t cd_size) {
+bool ZipArchive::InitializeCentralDirectory(off64_t cd_start_offset, size_t cd_size) {
if (mapped_zip.HasFd()) {
- if (!directory_map->create(debug_file_name, mapped_zip.GetFileDescriptor(), cd_start_offset,
- cd_size, true /* read only */)) {
- return false;
- }
+ directory_map = android::base::MappedFile::FromFd(mapped_zip.GetFileDescriptor(),
+ cd_start_offset, cd_size, PROT_READ);
+ if (!directory_map) return false;
- CHECK_EQ(directory_map->getDataLength(), cd_size);
- central_directory.Initialize(directory_map->getDataPtr(), 0 /*offset*/, cd_size);
+ 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");
diff --git a/libziparchive/zip_archive_private.h b/libziparchive/zip_archive_private.h
index 0a73300..330a02a 100644
--- a/libziparchive/zip_archive_private.h
+++ b/libziparchive/zip_archive_private.h
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-#ifndef LIBZIPARCHIVE_ZIPARCHIVE_PRIVATE_H_
-#define LIBZIPARCHIVE_ZIPARCHIVE_PRIVATE_H_
+#pragma once
+
+#include <ziparchive/zip_archive.h>
#include <stdint.h>
#include <stdlib.h>
@@ -24,9 +25,8 @@
#include <memory>
#include <vector>
-#include <utils/FileMap.h>
-#include <ziparchive/zip_archive.h>
#include "android-base/macros.h"
+#include "android-base/mapped_file.h"
static const char* kErrorMessages[] = {
"Success",
@@ -136,6 +136,26 @@
size_t length_;
};
+/**
+ * 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.
+ */
+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;
+ }
+};
+
struct ZipArchive {
// open Zip archive
mutable MappedZipFile mapped_zip;
@@ -144,7 +164,7 @@
// mapped central directory area
off64_t directory_offset;
CentralDirectory central_directory;
- std::unique_ptr<android::FileMap> directory_map;
+ std::unique_ptr<android::base::MappedFile> directory_map;
// number of entries in the Zip archive
uint16_t num_entries;
@@ -154,14 +174,11 @@
// allocate so the maximum number entries can never be higher than
// ((4 * UINT16_MAX) / 3 + 1) which can safely fit into a uint32_t.
uint32_t hash_table_size;
- ZipString* hash_table;
+ ZipStringOffset* hash_table;
ZipArchive(const int fd, bool assume_ownership);
ZipArchive(void* address, size_t length);
~ZipArchive();
- bool InitializeCentralDirectory(const char* debug_file_name, off64_t cd_start_offset,
- size_t cd_size);
+ bool InitializeCentralDirectory(off64_t cd_start_offset, size_t cd_size);
};
-
-#endif // LIBZIPARCHIVE_ZIPARCHIVE_PRIVATE_H_
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 23dd5dc..cea42d4 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -27,10 +27,9 @@
#include <vector>
#include <android-base/file.h>
-#include <android-base/test_utils.h>
+#include <android-base/mapped_file.h>
#include <android-base/unique_fd.h>
#include <gtest/gtest.h>
-#include <utils/FileMap.h>
#include <ziparchive/zip_archive.h>
#include <ziparchive/zip_archive_stream_entry.h>
@@ -298,7 +297,7 @@
ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, kEmptyEntriesZip, sizeof(kEmptyEntriesZip)));
ZipArchiveHandle handle;
- ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "EmptyEntriesTest", &handle));
+ ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "EmptyEntriesTest", &handle, false));
ZipEntry entry;
ZipString empty_name;
@@ -323,7 +322,7 @@
ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, reinterpret_cast<const uint8_t*>(kAbZip),
sizeof(kAbZip) - 1));
ZipArchiveHandle handle;
- ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "EntryLargerThan32KTest", &handle));
+ ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "EntryLargerThan32KTest", &handle, false));
ZipEntry entry;
ZipString ab_name;
@@ -348,7 +347,7 @@
// Read the file back to a buffer and make sure the contents are
// the same as the memory buffer we extracted directly to.
std::vector<uint8_t> file_contents(kAbUncompressedSize);
- ASSERT_EQ(0, lseek64(tmp_output_file.fd, 0, SEEK_SET));
+ ASSERT_EQ(0, lseek(tmp_output_file.fd, 0, SEEK_SET));
ASSERT_TRUE(android::base::ReadFully(tmp_output_file.fd, &file_contents[0], file_contents.size()));
ASSERT_EQ(file_contents, buffer);
@@ -370,7 +369,7 @@
ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, trailer, sizeof(trailer)));
ZipArchiveHandle handle;
- ASSERT_GT(0, OpenArchiveFd(tmp_file.fd, "EmptyEntriesTest", &handle));
+ ASSERT_GT(0, OpenArchiveFd(tmp_file.fd, "EmptyEntriesTest", &handle, false));
}
TEST(ziparchive, ExtractToFile) {
@@ -392,7 +391,7 @@
// Assert that the first 8 bytes of the file haven't been clobbered.
uint8_t read_buffer[data_size];
- ASSERT_EQ(0, lseek64(tmp_file.fd, 0, SEEK_SET));
+ ASSERT_EQ(0, lseek(tmp_file.fd, 0, SEEK_SET));
ASSERT_TRUE(android::base::ReadFully(tmp_file.fd, read_buffer, data_size));
ASSERT_EQ(0, memcmp(read_buffer, data, data_size));
@@ -404,7 +403,7 @@
// Assert that the total length of the file is sane
ASSERT_EQ(static_cast<ssize_t>(data_size + kATxtContents.size()),
- lseek64(tmp_file.fd, 0, SEEK_END));
+ lseek(tmp_file.fd, 0, SEEK_END));
}
#if !defined(_WIN32)
@@ -416,11 +415,10 @@
ASSERT_EQ(0, fstat(fd, &sb));
// Memory map the file first and open the archive from the memory region.
- android::FileMap file_map;
- file_map.create(zip_path.c_str(), fd, 0 /*offset*/, sb.st_size, true);
+ auto file_map{android::base::MappedFile::FromFd(fd, 0, sb.st_size, PROT_READ)};
ZipArchiveHandle handle;
- ASSERT_EQ(0, OpenArchiveFromMemory(file_map.getDataPtr(), file_map.getDataLength(),
- zip_path.c_str(), &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");
@@ -581,7 +579,7 @@
ASSERT_NE(-1, tmp_file.fd);
ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, &zip_data[0], zip_data.size()));
ZipArchiveHandle handle;
- ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "ExtractEntryToMemory", &handle));
+ ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "ExtractEntryToMemory", &handle, false));
// This function expects a variant of kDataDescriptorZipFile, for look for
// an entry whose name is "name" and whose size is 12 (contents =
@@ -689,7 +687,7 @@
ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, &kZipFileWithBrokenLfhSignature[0],
kZipFileWithBrokenLfhSignature.size()));
ZipArchiveHandle handle;
- ASSERT_EQ(-1, OpenArchiveFd(tmp_file.fd, "LeadingNonZipBytes", &handle));
+ ASSERT_EQ(-1, OpenArchiveFd(tmp_file.fd, "LeadingNonZipBytes", &handle, false));
}
class VectorReader : public zip_archive::Reader {
diff --git a/libziparchive/zip_writer.cc b/libziparchive/zip_writer.cc
index 6ad3366..981df3a 100644
--- a/libziparchive/zip_writer.cc
+++ b/libziparchive/zip_writer.cc
@@ -26,8 +26,6 @@
#include <vector>
#include "android-base/logging.h"
-#include "utils/Compat.h"
-#include "utils/Log.h"
#include "entry_name_utils-inl.h"
#include "zip_archive_common.h"
@@ -97,7 +95,7 @@
}
}
-ZipWriter::ZipWriter(ZipWriter&& writer)
+ZipWriter::ZipWriter(ZipWriter&& writer) noexcept
: file_(writer.file_),
seekable_(writer.seekable_),
current_offset_(writer.current_offset_),
@@ -109,7 +107,7 @@
writer.state_ = State::kError;
}
-ZipWriter& ZipWriter::operator=(ZipWriter&& writer) {
+ZipWriter& ZipWriter::operator=(ZipWriter&& writer) noexcept {
file_ = writer.file_;
seekable_ = writer.seekable_;
current_offset_ = writer.current_offset_;
@@ -303,10 +301,10 @@
if (zerr != Z_OK) {
if (zerr == Z_VERSION_ERROR) {
- ALOGE("Installed zlib is not compatible with linked version (%s)", ZLIB_VERSION);
+ LOG(ERROR) << "Installed zlib is not compatible with linked version (" << ZLIB_VERSION << ")";
return HandleError(kZlibError);
} else {
- ALOGE("deflateInit2 failed (zerr=%d)", zerr);
+ LOG(ERROR) << "deflateInit2 failed (zerr=" << zerr << ")";
return HandleError(kZlibError);
}
}
diff --git a/llkd/Android.bp b/llkd/Android.bp
index a6edd26..62a637d 100644
--- a/llkd/Android.bp
+++ b/llkd/Android.bp
@@ -20,6 +20,12 @@
export_include_dirs: ["include"],
cflags: ["-Werror"],
+
+ product_variables: {
+ debuggable: {
+ cppflags: ["-D__PTRACE_ENABLED__"],
+ },
+ },
}
cc_binary {
@@ -39,4 +45,9 @@
cflags: ["-Werror"],
init_rc: ["llkd.rc"],
+ product_variables: {
+ debuggable: {
+ init_rc: ["llkd-debuggable.rc"],
+ },
+ },
}
diff --git a/llkd/README.md b/llkd/README.md
index 2314583..191f988 100644
--- a/llkd/README.md
+++ b/llkd/README.md
@@ -23,6 +23,9 @@
Operations
----------
+There are two detection scenarios. Persistent D or Z state, and persistent
+stack signature.
+
If a thread is in D or Z state with no forward progress for longer than
ro.llk.timeout_ms, or ro.llk.[D|Z].timeout_ms, kill the process or parent
process respectively. If another scan shows the same process continues to
@@ -32,6 +35,27 @@
double the expected time to flow through the mainloop. Sampling is every
ro.llk_sample_ms.
+For usedebug releases only, persistent stack signature checking is enabled.
+If a thread in any state but Z, has a persistent listed ro.llk.stack kernel
+symbol always being reported, even if there is forward scheduling progress, for
+longer than ro.llk.timeout_ms, or ro.llk.stack.timeout_ms, then issue a kill
+to the process. If another scan shows the same process continues to exist,
+then have a confirmed live-lock condition and need to panic. There is no
+ABA detection since forward scheduling progress is allowed, thus the condition
+for the symbols are:
+
+- Check is looking for " __symbol__+0x" or " __symbol__.cfi+0x" in
+ /proc/__pid__/stack.
+- The __symbol__ should be rare and short lived enough that on a typical
+ system the function is seen at most only once in a sample over the timeout
+ period of ro.llk.stack.timeout_ms, samples occur every ro.llk.check_ms. This
+ can be the only way to prevent a false trigger as there is no ABA protection.
+- Persistent continuously when the live lock condition exists.
+- Should be just below the function that is calling the lock that could
+ contend, because if the lock is below or in the symbol function, the
+ symbol will show in all affected processes, not just the one that
+ caused the lockup.
+
Default will not monitor init, or [kthreadd] and all that [kthreadd] spawns.
This reduces the effectiveness of llkd by limiting its coverage. If there is
value in covering [kthreadd] spawned threads, the requirement will be that
@@ -40,7 +64,9 @@
coding hygiene, a common request to add such to publicly reviewed kernel.org
maintained drivers). For instance use wait_event_interruptible() instead of
wait_event(). The blacklists can be adjusted accordingly if these
-conditions are met to cover kernel components.
+conditions are met to cover kernel components. For the stack symbol checking,
+there is an additional process blacklist so that we do not incide sepolicy
+violations on services that block ptrace operations.
An accompanying gTest set have been added, and will setup a persistent D or Z
process, with and without forward progress, but not in a live-lock state
@@ -60,10 +86,23 @@
Android Properties
------------------
-Android Properties llkd respond to (*prop*_ms parms are in milliseconds):
+The following are the Android Properties llkd respond to.
+*prop*_ms named properties are in milliseconds.
+Properties that use comma (*,*) separator for lists, use a leading separator to
+preserve default and add or subtract entries with (*optional*) plus (*+*) and
+minus (*-*) prefixes respectively.
+For these lists, the string "*false*" is synonymous with an *empty* list,
+and *blank* or *missing* resorts to the specified *default* value.
#### ro.config.low_ram
-default false, if true do not sysrq t (dump all threads).
+device is configured with limited memory.
+
+#### ro.debuggable
+device is configured for userdebug or eng build.
+
+#### ro.llk.sysrq_t
+default not ro.config.low_ram, or ro.debuggable if property is "eng".
+if true do sysrq t (dump all threads).
#### ro.llk.enable
default false, allow live-lock daemon to be enabled.
@@ -93,30 +132,59 @@
#### ro.llk.Z.timeout_ms
default ro.llk.timeout_ms, Z maximum timelimit.
+#### ro.llk.stack.timeout_ms
+default ro.llk.timeout_ms,
+checking for persistent stack symbols maximum timelimit.
+Only active on userdebug or eng builds.
+
#### ro.llk.check_ms
default 2 minutes samples of threads for D or Z.
+#### ro.llk.stack
+default cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
+comma separated list of kernel symbols.
+Look for kernel stack symbols that if ever persistently present can
+indicate a subsystem is locked up.
+Beware, check does not on purpose do forward scheduling ABA except by polling
+every ro.llk_check_ms over the period ro.llk.stack.timeout_ms, so stack symbol
+should be exceptionally rare and fleeting.
+One must be convinced that it is virtually *impossible* for symbol to show up
+persistently in all samples of the stack.
+Again, looks for a match for either " **symbol**+0x" or " **symbol**.cfi+0x"
+in stack expansion.
+Only available on userdebug or eng builds, limited privileges due to security
+concerns on user builds prevents this checking.
+
#### ro.llk.blacklist.process
default 0,1,2 (kernel, init and [kthreadd]) plus process names
-init,[kthreadd],[khungtaskd],lmkd,lmkd.llkd,llkd,watchdogd,
+init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd,
[watchdogd],[watchdogd/0],...,[watchdogd/***get_nprocs**-1*].
-The string false is the equivalent to an empty list.
Do not watch these processes. A process can be comm, cmdline or pid reference.
NB: automated default here can be larger than the current maximum property
size of 92.
NB: false is a very very very unlikely process to want to blacklist.
#### ro.llk.blacklist.parent
-default 0,2 (kernel and [kthreadd]).
-The string false is the equivalent to an empty list.
+default 0,2,adbd&[setsid] (kernel, [kthreadd] and adbd *only for zombie setsid*).
Do not watch processes that have this parent.
-A parent process can be comm, cmdline or pid reference.
+An ampersand (*&*) separator is used to specify that the parent is ignored
+only in combination with the target child process.
+Ampersand was selected because it is never part of a process name,
+however a setprop in the shell requires it to be escaped or quoted;
+init rc file where this is normally specified does not have this issue.
+A parent or target processes can be specified as comm, cmdline or pid reference.
#### ro.llk.blacklist.uid
default *empty* or false, comma separated list of uid numbers or names.
-The string false is the equivalent to an empty list.
Do not watch processes that match this uid.
+#### ro.llk.blacklist.process.stack
+default process names init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd.
+This subset of processes are not monitored for live lock stack signatures.
+Also prevents the sepolicy violation associated with processes that block
+ptrace, as these can not be checked anyways.
+Only active on userdebug and eng builds.
+
Architectural Concerns
----------------------
diff --git a/llkd/include/llkd.h b/llkd/include/llkd.h
index e3ae4bb..3586ca1 100644
--- a/llkd/include/llkd.h
+++ b/llkd/include/llkd.h
@@ -35,6 +35,8 @@
#define LLK_ENABLE_DEFAULT false /* "eng" and userdebug true */
#define KHT_ENABLE_WRITEABLE_PROPERTY "khungtask.enable"
#define KHT_ENABLE_PROPERTY "ro." KHT_ENABLE_WRITEABLE_PROPERTY
+#define LLK_ENABLE_SYSRQ_T_PROPERTY "ro.llk.sysrq_t"
+#define LLK_ENABLE_SYSRQ_T_DEFAULT true
#define LLK_MLOCKALL_PROPERTY "ro.llk.mlockall"
#define LLK_MLOCKALL_DEFAULT true
#define LLK_KILLTEST_PROPERTY "ro.llk.killtest"
@@ -43,16 +45,22 @@
#define KHT_TIMEOUT_PROPERTY "ro.khungtask.timeout"
#define LLK_D_TIMEOUT_MS_PROPERTY "ro.llk.D.timeout_ms"
#define LLK_Z_TIMEOUT_MS_PROPERTY "ro.llk.Z.timeout_ms"
+#define LLK_STACK_TIMEOUT_MS_PROPERTY "ro.llk.stack.timeout_ms"
#define LLK_CHECK_MS_PROPERTY "ro.llk.check_ms"
/* LLK_CHECK_MS_DEFAULT = actual timeout_ms / LLK_CHECKS_PER_TIMEOUT_DEFAULT */
#define LLK_CHECKS_PER_TIMEOUT_DEFAULT 5
+#define LLK_CHECK_STACK_PROPERTY "ro.llk.stack"
+#define LLK_CHECK_STACK_DEFAULT \
+ "cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable"
#define LLK_BLACKLIST_PROCESS_PROPERTY "ro.llk.blacklist.process"
#define LLK_BLACKLIST_PROCESS_DEFAULT \
- "0,1,2,init,[kthreadd],[khungtaskd],lmkd,lmkd.llkd,llkd,watchdogd,[watchdogd],[watchdogd/0]"
+ "0,1,2,init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd,[watchdogd],[watchdogd/0]"
#define LLK_BLACKLIST_PARENT_PROPERTY "ro.llk.blacklist.parent"
-#define LLK_BLACKLIST_PARENT_DEFAULT "0,2,[kthreadd]"
+#define LLK_BLACKLIST_PARENT_DEFAULT "0,2,[kthreadd],adbd&[setsid]"
#define LLK_BLACKLIST_UID_PROPERTY "ro.llk.blacklist.uid"
#define LLK_BLACKLIST_UID_DEFAULT ""
+#define LLK_BLACKLIST_STACK_PROPERTY "ro.llk.blacklist.process.stack"
+#define LLK_BLACKLIST_STACK_DEFAULT "init,lmkd.llkd,llkd,keystore,ueventd,apexd"
/* clang-format on */
__END_DECLS
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index bb55d1f..b26ad4d 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -24,6 +24,7 @@
#include <pwd.h> // getpwuid()
#include <signal.h>
#include <stdint.h>
+#include <string.h>
#include <sys/cdefs.h> // ___STRING, __predict_true() and _predict_false()
#include <sys/mman.h> // mlockall()
#include <sys/prctl.h>
@@ -73,16 +74,28 @@
bool llkMlockall = LLK_MLOCKALL_DEFAULT; // run mlocked
bool llkTestWithKill = LLK_KILLTEST_DEFAULT; // issue test kills
milliseconds llkTimeoutMs = LLK_TIMEOUT_MS_DEFAULT; // default timeout
-enum { llkStateD, llkStateZ, llkNumStates }; // state indexes
+enum { // enum of state indexes
+ llkStateD, // Persistent 'D' state
+ llkStateZ, // Persistent 'Z' state
+#ifdef __PTRACE_ENABLED__ // Extra privileged states
+ llkStateStack, // stack signature
+#endif // End of extra privilege
+ llkNumStates, // Maxumum number of states
+}; // state indexes
milliseconds llkStateTimeoutMs[llkNumStates]; // timeout override for each detection state
milliseconds llkCheckMs; // checking interval to inspect any
// persistent live-locked states
bool llkLowRam; // ro.config.low_ram
+bool llkEnableSysrqT = LLK_ENABLE_SYSRQ_T_DEFAULT; // sysrq stack trace dump
bool khtEnable = LLK_ENABLE_DEFAULT; // [khungtaskd] panic
// [khungtaskd] should have a timeout beyond the granularity of llkTimeoutMs.
// Provides a wide angle of margin b/c khtTimeout is also its granularity.
seconds khtTimeout = duration_cast<seconds>(llkTimeoutMs * (1 + LLK_CHECKS_PER_TIMEOUT_DEFAULT) /
LLK_CHECKS_PER_TIMEOUT_DEFAULT);
+#ifdef __PTRACE_ENABLED__
+// list of stack symbols to search for persistence.
+std::unordered_set<std::string> llkCheckStackSymbols;
+#endif
// Blacklist variables, initialized with comma separated lists of high false
// positive and/or dangerous references, e.g. without self restart, for pid,
@@ -95,8 +108,16 @@
// list of parent pids, comm or cmdline names to skip. default:
// kernel pid (0), [kthreadd] (2), or ourselves, enforced and implied
std::unordered_set<std::string> llkBlacklistParent;
+// list of parent and target processes to skip. default:
+// adbd *and* [setsid]
+std::unordered_map<std::string, std::unordered_set<std::string>> llkBlacklistParentAndChild;
// list of uids, and uid names, to skip, default nothing
std::unordered_set<std::string> llkBlacklistUid;
+#ifdef __PTRACE_ENABLED__
+// list of names to skip stack checking. "init", "lmkd", "llkd", "keystore" or
+// "logd" (if not userdebug).
+std::unordered_set<std::string> llkBlacklistStack;
+#endif
class dir {
public:
@@ -249,7 +270,7 @@
}
content.erase(pos);
uid_t ret;
- if (!android::base::ParseInt(content, &ret, uid_t(0))) {
+ if (!android::base::ParseUint(content, &ret, uid_t(0))) {
return -1;
}
return ret;
@@ -263,6 +284,9 @@
// forward scheduling progress.
milliseconds update; // llkUpdate millisecond signature of last.
milliseconds count; // duration in state.
+#ifdef __PTRACE_ENABLED__ // Privileged state checking
+ milliseconds count_stack; // duration where stack is stagnant.
+#endif // End privilege
pid_t pid; // /proc/<pid> before iterating through
// /proc/<pid>/task/<tid> for threads.
pid_t ppid; // /proc/<tid>/stat field 4 parent pid.
@@ -272,6 +296,9 @@
std::string cmdline; // cached /cmdline content
char state; // /proc/<tid>/stat field 3: Z or D
// (others we do not monitor: S, R, T or ?)
+#ifdef __PTRACE_ENABLED__ // Privileged state checking
+ char stack; // index in llkCheckStackSymbols for matches
+#endif // and with maximum index PROP_VALUE_MAX/2.
char comm[TASK_COMM_LEN + 3]; // space for adding '[' and ']'
bool exeMissingValid; // exeMissing has been cached
bool cmdlineValid; // cmdline has been cached
@@ -286,11 +313,17 @@
nrSwitches(0),
update(llkUpdate),
count(0ms),
+#ifdef __PTRACE_ENABLED__
+ count_stack(0ms),
+#endif
pid(pid),
ppid(ppid),
uid(-1),
time(time),
state(state),
+#ifdef __PTRACE_ENABLED__
+ stack(-1),
+#endif
exeMissingValid(false),
cmdlineValid(false),
updated(true),
@@ -343,6 +376,10 @@
void reset(void) { // reset cache, if we detected pid rollover
uid = -1;
state = '?';
+#ifdef __PTRACE_ENABLED__
+ count_stack = 0ms;
+ stack = -1;
+#endif
cmdline = "";
comm[0] = '\0';
exeMissingValid = false;
@@ -477,8 +514,8 @@
return android::base::Trim(content) == string;
}
-void llkPanicKernel(bool dump, pid_t tid, const char* state) __noreturn;
-void llkPanicKernel(bool dump, pid_t tid, const char* state) {
+void llkPanicKernel(bool dump, pid_t tid, const char* state, const std::string& message = "") {
+ if (!message.empty()) LOG(ERROR) << message;
auto sysrqTriggerFd = llkFileToWriteFd("/proc/sysrq-trigger");
if (sysrqTriggerFd < 0) {
// DYB
@@ -486,19 +523,37 @@
// The answer to life, the universe and everything
::exit(42);
// NOTREACHED
+ return;
}
- ::sync();
+ // Wish could ::sync() here, if storage is locked up, we will not continue.
if (dump) {
// Show all locks that are held
android::base::WriteStringToFd("d", sysrqTriggerFd);
+ // Show all waiting tasks
+ android::base::WriteStringToFd("w", sysrqTriggerFd);
// This can trigger hardware watchdog, that is somewhat _ok_.
// But useless if pstore configured for <256KB, low ram devices ...
- if (!llkLowRam) {
+ if (llkEnableSysrqT) {
android::base::WriteStringToFd("t", sysrqTriggerFd);
+ // Show all locks that are held (in case 't' overflows ramoops)
+ android::base::WriteStringToFd("d", sysrqTriggerFd);
+ // Show all waiting tasks (in case 't' overflows ramoops)
+ android::base::WriteStringToFd("w", sysrqTriggerFd);
}
::usleep(200000); // let everything settle
}
- llkWriteStringToFile("SysRq : Trigger a crash : 'livelock,"s + state + "'\n", "/dev/kmsg");
+ // SysRq message matches kernel format, and propagates through bootstat
+ // ultimately to the boot reason into panic,livelock,<state>.
+ llkWriteStringToFile(message + (message.empty() ? "" : "\n") +
+ "SysRq : Trigger a crash : 'livelock,"s + state + "'\n",
+ "/dev/kmsg");
+ // Because panic is such a serious thing to do, let us
+ // make sure that the tid being inspected still exists!
+ auto piddir = procdir + std::to_string(tid) + "/stat";
+ if (access(piddir.c_str(), F_OK) != 0) {
+ PLOG(WARNING) << piddir;
+ return;
+ }
android::base::WriteStringToFd("c", sysrqTriggerFd);
// NOTREACHED
// DYB
@@ -510,7 +565,9 @@
}
void llkAlarmHandler(int) {
- llkPanicKernel(false, ::getpid(), "alarm");
+ LOG(FATAL) << "alarm";
+ // NOTREACHED
+ llkPanicKernel(true, ::getpid(), "alarm");
}
milliseconds GetUintProperty(const std::string& key, milliseconds def) {
@@ -563,18 +620,38 @@
std::string llkFormat(const std::unordered_set<std::string>& blacklist) {
std::string ret;
- for (auto entry : blacklist) {
- if (ret.size()) {
- ret += ",";
- }
+ for (const auto& entry : blacklist) {
+ if (!ret.empty()) ret += ",";
ret += entry;
}
return ret;
}
+std::string llkFormat(
+ const std::unordered_map<std::string, std::unordered_set<std::string>>& blacklist,
+ bool leading_comma = false) {
+ std::string ret;
+ for (const auto& entry : blacklist) {
+ for (const auto& target : entry.second) {
+ if (leading_comma || !ret.empty()) ret += ",";
+ ret += entry.first + "&" + target;
+ }
+ }
+ return ret;
+}
+
+// This function parses the properties as a list, incorporating the supplied
+// default. A leading comma separator means preserve the defaults and add
+// entries (with an optional leading + sign), or removes entries with a leading
+// - sign.
+//
// We only officially support comma separators, but wetware being what they
// are will take some liberty and I do not believe they should be punished.
-std::unordered_set<std::string> llkSplit(const std::string& s) {
+std::unordered_set<std::string> llkSplit(const std::string& prop, const std::string& def) {
+ auto s = android::base::GetProperty(prop, def);
+ constexpr char separators[] = ", \t:;";
+ if (!s.empty() && (s != def) && strchr(separators, s[0])) s = def + s;
+
std::unordered_set<std::string> result;
// Special case, allow boolean false to empty the list, otherwise expected
@@ -584,9 +661,29 @@
size_t base = 0;
while (s.size() > base) {
- auto found = s.find_first_of(", \t:", base);
- // Only emplace content, empty entries are not an option
- if (found != base) result.emplace(s.substr(base, found - base));
+ auto found = s.find_first_of(separators, base);
+ // Only emplace unique content, empty entries are not an option
+ if (found != base) {
+ switch (s[base]) {
+ case '-':
+ ++base;
+ if (base >= s.size()) break;
+ if (base != found) {
+ auto have = result.find(s.substr(base, found - base));
+ if (have != result.end()) result.erase(have);
+ }
+ break;
+ case '+':
+ ++base;
+ if (base >= s.size()) break;
+ if (base == found) break;
+ // FALLTHRU (for gcc, lint, pcc, etc; following for clang)
+ FALLTHROUGH_INTENDED;
+ default:
+ result.emplace(s.substr(base, found - base));
+ break;
+ }
+ }
if (found == s.npos) break;
base = found + 1;
}
@@ -595,13 +692,42 @@
bool llkSkipName(const std::string& name,
const std::unordered_set<std::string>& blacklist = llkBlacklistProcess) {
- if ((name.size() == 0) || (blacklist.size() == 0)) {
- return false;
- }
+ if (name.empty() || blacklist.empty()) return false;
return blacklist.find(name) != blacklist.end();
}
+bool llkSkipProc(proc* procp,
+ const std::unordered_set<std::string>& blacklist = llkBlacklistProcess) {
+ if (!procp) return false;
+ if (llkSkipName(std::to_string(procp->pid), blacklist)) return true;
+ if (llkSkipName(procp->getComm(), blacklist)) return true;
+ if (llkSkipName(procp->getCmdline(), blacklist)) return true;
+ if (llkSkipName(android::base::Basename(procp->getCmdline()), blacklist)) return true;
+ return false;
+}
+
+const std::unordered_set<std::string>& llkSkipName(
+ const std::string& name,
+ const std::unordered_map<std::string, std::unordered_set<std::string>>& blacklist) {
+ static const std::unordered_set<std::string> empty;
+ if (name.empty() || blacklist.empty()) return empty;
+ auto found = blacklist.find(name);
+ if (found == blacklist.end()) return empty;
+ return found->second;
+}
+
+bool llkSkipPproc(proc* pprocp, proc* procp,
+ const std::unordered_map<std::string, std::unordered_set<std::string>>&
+ blacklist = llkBlacklistParentAndChild) {
+ if (!pprocp || !procp || blacklist.empty()) return false;
+ if (llkSkipProc(procp, llkSkipName(std::to_string(pprocp->pid), blacklist))) return true;
+ if (llkSkipProc(procp, llkSkipName(pprocp->getComm(), blacklist))) return true;
+ if (llkSkipProc(procp, llkSkipName(pprocp->getCmdline(), blacklist))) return true;
+ return llkSkipProc(procp,
+ llkSkipName(android::base::Basename(pprocp->getCmdline()), blacklist));
+}
+
bool llkSkipPid(pid_t pid) {
return llkSkipName(std::to_string(pid), llkBlacklistProcess);
}
@@ -667,6 +793,50 @@
return ret;
}
+#ifdef __PTRACE_ENABLED__
+bool llkCheckStack(proc* procp, const std::string& piddir) {
+ if (llkCheckStackSymbols.empty()) return false;
+ if (procp->state == 'Z') { // No brains for Zombies
+ procp->stack = -1;
+ procp->count_stack = 0ms;
+ return false;
+ }
+
+ // Don't check process that are known to block ptrace, save sepolicy noise.
+ if (llkSkipProc(procp, llkBlacklistStack)) return false;
+ auto kernel_stack = ReadFile(piddir + "/stack");
+ if (kernel_stack.empty()) {
+ LOG(VERBOSE) << piddir << "/stack empty comm=" << procp->getComm()
+ << " cmdline=" << procp->getCmdline();
+ return false;
+ }
+ // A scheduling incident that should not reset count_stack
+ if (kernel_stack.find(" cpu_worker_pools+0x") != std::string::npos) return false;
+ char idx = -1;
+ char match = -1;
+ std::string matched_stack_symbol = "<unknown>";
+ for (const auto& stack : llkCheckStackSymbols) {
+ if (++idx < 0) break;
+ if ((kernel_stack.find(" "s + stack + "+0x") != std::string::npos) ||
+ (kernel_stack.find(" "s + stack + ".cfi+0x") != std::string::npos)) {
+ match = idx;
+ matched_stack_symbol = stack;
+ break;
+ }
+ }
+ if (procp->stack != match) {
+ procp->stack = match;
+ procp->count_stack = 0ms;
+ return false;
+ }
+ if (match == char(-1)) return false;
+ procp->count_stack += llkCycle;
+ if (procp->count_stack < llkStateTimeoutMs[llkStateStack]) return false;
+ LOG(WARNING) << "Found " << matched_stack_symbol << " in stack for pid " << procp->pid;
+ return true;
+}
+#endif
+
// Primary ABA mitigation watching last time schedule activity happened
void llkCheckSchedUpdate(proc* procp, const std::string& piddir) {
// Audit finds /proc/<tid>/sched is just over 1K, and
@@ -679,12 +849,12 @@
// but if there are problems we assume at least a few
// samples of reads occur before we take any real action.
std::string schedString = ReadFile(piddir + "/sched");
- if (schedString.size() == 0) {
+ if (schedString.empty()) {
// /schedstat is not as standardized, but in 3.1+
// Android devices, the third field is nr_switches
// from /sched:
schedString = ReadFile(piddir + "/schedstat");
- if (schedString.size() == 0) {
+ if (schedString.empty()) {
return;
}
auto val = static_cast<unsigned long long>(-1);
@@ -723,6 +893,7 @@
void llkLogConfig(void) {
LOG(INFO) << "ro.config.low_ram=" << llkFormat(llkLowRam) << "\n"
+ << LLK_ENABLE_SYSRQ_T_PROPERTY "=" << llkFormat(llkEnableSysrqT) << "\n"
<< LLK_ENABLE_PROPERTY "=" << llkFormat(llkEnable) << "\n"
<< KHT_ENABLE_PROPERTY "=" << llkFormat(khtEnable) << "\n"
<< LLK_MLOCKALL_PROPERTY "=" << llkFormat(llkMlockall) << "\n"
@@ -731,9 +902,18 @@
<< LLK_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkTimeoutMs) << "\n"
<< LLK_D_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkStateTimeoutMs[llkStateD]) << "\n"
<< LLK_Z_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkStateTimeoutMs[llkStateZ]) << "\n"
+#ifdef __PTRACE_ENABLED__
+ << LLK_STACK_TIMEOUT_MS_PROPERTY "=" << llkFormat(llkStateTimeoutMs[llkStateStack])
+ << "\n"
+#endif
<< LLK_CHECK_MS_PROPERTY "=" << llkFormat(llkCheckMs) << "\n"
+#ifdef __PTRACE_ENABLED__
+ << LLK_CHECK_STACK_PROPERTY "=" << llkFormat(llkCheckStackSymbols) << "\n"
+ << LLK_BLACKLIST_STACK_PROPERTY "=" << llkFormat(llkBlacklistStack) << "\n"
+#endif
<< LLK_BLACKLIST_PROCESS_PROPERTY "=" << llkFormat(llkBlacklistProcess) << "\n"
- << LLK_BLACKLIST_PARENT_PROPERTY "=" << llkFormat(llkBlacklistParent) << "\n"
+ << LLK_BLACKLIST_PARENT_PROPERTY "=" << llkFormat(llkBlacklistParent)
+ << llkFormat(llkBlacklistParentAndChild, true) << "\n"
<< LLK_BLACKLIST_UID_PROPERTY "=" << llkFormat(llkBlacklistUid);
}
@@ -809,6 +989,7 @@
ms -= llkCycle;
auto myPid = ::getpid();
auto myTid = ::gettid();
+ auto dump = true;
for (auto dp = llkTopDirectory.read(); dp != nullptr; dp = llkTopDirectory.read()) {
std::string piddir;
@@ -832,7 +1013,7 @@
// Get the process stat
std::string stat = ReadFile(piddir + "/stat");
- if (stat.size() == 0) {
+ if (stat.empty()) {
continue;
}
unsigned tid = -1;
@@ -892,9 +1073,14 @@
if (pid == myPid) {
break;
}
- if (!llkIsMonitorState(state)) {
+#ifdef __PTRACE_ENABLED__
+ // if no stack monitoring, we can quickly exit here
+ if (!llkIsMonitorState(state) && llkCheckStackSymbols.empty()) {
continue;
}
+#else
+ if (!llkIsMonitorState(state)) continue;
+#endif
if ((tid == myTid) || llkSkipPid(tid)) {
continue;
}
@@ -902,20 +1088,26 @@
break;
}
- if (llkSkipName(procp->getComm())) {
+ auto process_comm = procp->getComm();
+ if (llkSkipName(process_comm)) {
continue;
}
if (llkSkipName(procp->getCmdline())) {
break;
}
+ if (llkSkipName(android::base::Basename(procp->getCmdline()))) {
+ break;
+ }
auto pprocp = llkTidLookup(ppid);
if (pprocp == nullptr) {
pprocp = llkTidAlloc(ppid, ppid, 0, "", 0, '?');
}
- if ((pprocp != nullptr) && (llkSkipName(pprocp->getComm(), llkBlacklistParent) ||
- llkSkipName(pprocp->getCmdline(), llkBlacklistParent))) {
- break;
+ if (pprocp) {
+ if (llkSkipPproc(pprocp, procp)) break;
+ if (llkSkipProc(pprocp, llkBlacklistParent)) break;
+ } else {
+ if (llkSkipName(std::to_string(ppid), llkBlacklistParent)) break;
}
if ((llkBlacklistUid.size() != 0) && llkSkipUid(procp->getUid())) {
@@ -925,12 +1117,26 @@
// ABA mitigation watching last time schedule activity happened
llkCheckSchedUpdate(procp, piddir);
- // Can only fall through to here if registered D or Z state !!!
- if (procp->count < llkStateTimeoutMs[(state == 'Z') ? llkStateZ : llkStateD]) {
- LOG(VERBOSE) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->"
- << pid << "->" << tid << ' ' << procp->getComm();
+#ifdef __PTRACE_ENABLED__
+ auto stuck = llkCheckStack(procp, piddir);
+ if (llkIsMonitorState(state)) {
+ if (procp->count >= llkStateTimeoutMs[(state == 'Z') ? llkStateZ : llkStateD]) {
+ stuck = true;
+ } else if (procp->count != 0ms) {
+ LOG(VERBOSE) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->"
+ << pid << "->" << tid << ' ' << process_comm;
+ }
+ }
+ if (!stuck) continue;
+#else
+ if (procp->count >= llkStateTimeoutMs[(state == 'Z') ? llkStateZ : llkStateD]) {
+ if (procp->count != 0ms) {
+ LOG(VERBOSE) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->"
+ << pid << "->" << tid << ' ' << process_comm;
+ }
continue;
}
+#endif
// We have to kill it to determine difference between live lock
// and persistent state blocked on a resource. Is there something
@@ -954,7 +1160,7 @@
break;
}
LOG(WARNING) << "Z " << llkFormat(procp->count) << ' ' << ppid << "->"
- << pid << "->" << tid << ' ' << procp->getComm() << " [kill]";
+ << pid << "->" << tid << ' ' << process_comm << " [kill]";
if ((llkKillOneProcess(pprocp, procp) >= 0) ||
(llkKillOneProcess(ppid, procp) >= 0)) {
continue;
@@ -969,21 +1175,26 @@
// not working is we kill a process that likes to
// stay in 'D' state, instead of panicing the
// kernel (worse).
- LOG(WARNING) << "D " << llkFormat(procp->count) << ' ' << pid << "->" << tid
- << ' ' << procp->getComm() << " [kill]";
+ default:
+ LOG(WARNING) << state << ' ' << llkFormat(procp->count) << ' ' << pid
+ << "->" << tid << ' ' << process_comm << " [kill]";
if ((llkKillOneProcess(llkTidLookup(pid), procp) >= 0) ||
- (llkKillOneProcess(pid, 'D', tid) >= 0) ||
+ (llkKillOneProcess(pid, state, tid) >= 0) ||
(llkKillOneProcess(procp, procp) >= 0) ||
- (llkKillOneProcess(tid, 'D', tid) >= 0)) {
+ (llkKillOneProcess(tid, state, tid) >= 0)) {
continue;
}
break;
}
}
// We are here because we have confirmed kernel live-lock
- LOG(ERROR) << state << ' ' << llkFormat(procp->count) << ' ' << ppid << "->" << pid
- << "->" << tid << ' ' << procp->getComm() << " [panic]";
- llkPanicKernel(true, tid, (state == 'Z') ? "zombie" : "driver");
+ const auto message = state + " "s + llkFormat(procp->count) + " " +
+ std::to_string(ppid) + "->" + std::to_string(pid) + "->" +
+ std::to_string(tid) + " " + process_comm + " [panic]";
+ llkPanicKernel(dump, tid,
+ (state == 'Z') ? "zombie" : (state == 'D') ? "driver" : "sleeping",
+ message);
+ dump = false;
}
LOG(VERBOSE) << "+closedir()";
}
@@ -995,21 +1206,15 @@
if (!p->second.updated) {
IF_ALOG(LOG_VERBOSE, LOG_TAG) {
std::string ppidCmdline = llkProcGetName(p->second.ppid, nullptr, nullptr);
- if (ppidCmdline.size()) {
- ppidCmdline = "(" + ppidCmdline + ")";
- }
+ if (!ppidCmdline.empty()) ppidCmdline = "(" + ppidCmdline + ")";
std::string pidCmdline;
if (p->second.pid != p->second.tid) {
pidCmdline = llkProcGetName(p->second.pid, nullptr, p->second.getCmdline());
- if (pidCmdline.size()) {
- pidCmdline = "(" + pidCmdline + ")";
- }
+ if (!pidCmdline.empty()) pidCmdline = "(" + pidCmdline + ")";
}
std::string tidCmdline =
llkProcGetName(p->second.tid, p->second.getComm(), p->second.getCmdline());
- if (tidCmdline.size()) {
- tidCmdline = "(" + tidCmdline + ")";
- }
+ if (!tidCmdline.empty()) tidCmdline = "(" + tidCmdline + ")";
LOG(VERBOSE) << "thread " << p->second.ppid << ppidCmdline << "->" << p->second.pid
<< pidCmdline << "->" << p->second.tid << tidCmdline << " removed";
}
@@ -1040,12 +1245,22 @@
return duration_cast<milliseconds>(llkCheck()).count();
}
+bool llkCheckEng(const std::string& property) {
+ return android::base::GetProperty(property, "eng") == "eng";
+}
+
bool llkInit(const char* threadname) {
+ auto debuggable = android::base::GetBoolProperty("ro.debuggable", false);
llkLowRam = android::base::GetBoolProperty("ro.config.low_ram", false);
- if (!LLK_ENABLE_DEFAULT && android::base::GetBoolProperty("ro.debuggable", false)) {
- llkEnable = android::base::GetProperty(LLK_ENABLE_PROPERTY, "eng") == "eng";
- khtEnable = android::base::GetProperty(KHT_ENABLE_PROPERTY, "eng") == "eng";
+ llkEnableSysrqT &= !llkLowRam;
+ if (debuggable) {
+ llkEnableSysrqT |= llkCheckEng(LLK_ENABLE_SYSRQ_T_PROPERTY);
+ if (!LLK_ENABLE_DEFAULT) { // NB: default is currently true ...
+ llkEnable |= llkCheckEng(LLK_ENABLE_PROPERTY);
+ khtEnable |= llkCheckEng(KHT_ENABLE_PROPERTY);
+ }
}
+ llkEnableSysrqT = android::base::GetBoolProperty(LLK_ENABLE_SYSRQ_T_PROPERTY, llkEnableSysrqT);
llkEnable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, llkEnable);
if (llkEnable && !llkTopDirectory.reset(procdir)) {
// Most likely reason we could be here is llkd was started
@@ -1069,8 +1284,19 @@
llkValidate(); // validate llkTimeoutMs, llkCheckMs and llkCycle
llkStateTimeoutMs[llkStateD] = GetUintProperty(LLK_D_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
llkStateTimeoutMs[llkStateZ] = GetUintProperty(LLK_Z_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+#ifdef __PTRACE_ENABLED__
+ llkStateTimeoutMs[llkStateStack] = GetUintProperty(LLK_STACK_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+#endif
llkCheckMs = GetUintProperty(LLK_CHECK_MS_PROPERTY, llkCheckMs);
llkValidate(); // validate all (effectively minus llkTimeoutMs)
+#ifdef __PTRACE_ENABLED__
+ if (debuggable) {
+ llkCheckStackSymbols = llkSplit(LLK_CHECK_STACK_PROPERTY, LLK_CHECK_STACK_DEFAULT);
+ }
+ std::string defaultBlacklistStack(LLK_BLACKLIST_STACK_DEFAULT);
+ if (!debuggable) defaultBlacklistStack += ",logd,/system/bin/logd";
+ llkBlacklistStack = llkSplit(LLK_BLACKLIST_STACK_PROPERTY, defaultBlacklistStack);
+#endif
std::string defaultBlacklistProcess(
std::to_string(kernelPid) + "," + std::to_string(initPid) + "," +
std::to_string(kthreaddPid) + "," + std::to_string(::getpid()) + "," +
@@ -1081,17 +1307,34 @@
for (int cpu = 1; cpu < get_nprocs_conf(); ++cpu) {
defaultBlacklistProcess += ",[watchdog/" + std::to_string(cpu) + "]";
}
- defaultBlacklistProcess =
- android::base::GetProperty(LLK_BLACKLIST_PROCESS_PROPERTY, defaultBlacklistProcess);
- llkBlacklistProcess = llkSplit(defaultBlacklistProcess);
+ llkBlacklistProcess = llkSplit(LLK_BLACKLIST_PROCESS_PROPERTY, defaultBlacklistProcess);
if (!llkSkipName("[khungtaskd]")) { // ALWAYS ignore as special
llkBlacklistProcess.emplace("[khungtaskd]");
}
- llkBlacklistParent = llkSplit(android::base::GetProperty(
- LLK_BLACKLIST_PARENT_PROPERTY, std::to_string(kernelPid) + "," + std::to_string(kthreaddPid) +
- "," LLK_BLACKLIST_PARENT_DEFAULT));
- llkBlacklistUid =
- llkSplit(android::base::GetProperty(LLK_BLACKLIST_UID_PROPERTY, LLK_BLACKLIST_UID_DEFAULT));
+ llkBlacklistParent = llkSplit(LLK_BLACKLIST_PARENT_PROPERTY,
+ std::to_string(kernelPid) + "," + std::to_string(kthreaddPid) +
+ "," LLK_BLACKLIST_PARENT_DEFAULT);
+ // derive llkBlacklistParentAndChild by moving entries with '&' from above
+ for (auto it = llkBlacklistParent.begin(); it != llkBlacklistParent.end();) {
+ auto pos = it->find('&');
+ if (pos == std::string::npos) {
+ ++it;
+ continue;
+ }
+ auto parent = it->substr(0, pos);
+ auto child = it->substr(pos + 1);
+ it = llkBlacklistParent.erase(it);
+
+ auto found = llkBlacklistParentAndChild.find(parent);
+ if (found == llkBlacklistParentAndChild.end()) {
+ llkBlacklistParentAndChild.emplace(std::make_pair(
+ std::move(parent), std::unordered_set<std::string>({std::move(child)})));
+ } else {
+ found->second.emplace(std::move(child));
+ }
+ }
+
+ llkBlacklistUid = llkSplit(LLK_BLACKLIST_UID_PROPERTY, LLK_BLACKLIST_UID_DEFAULT);
// internal watchdog
::signal(SIGALRM, llkAlarmHandler);
diff --git a/llkd/llkd-debuggable.rc b/llkd/llkd-debuggable.rc
new file mode 100644
index 0000000..724cb5e
--- /dev/null
+++ b/llkd/llkd-debuggable.rc
@@ -0,0 +1,19 @@
+on property:ro.debuggable=1
+ setprop llk.enable ${ro.llk.enable:-1}
+ setprop khungtask.enable ${ro.khungtask.enable:-1}
+
+on property:ro.llk.enable=eng
+ setprop llk.enable ${ro.debuggable:-0}
+
+on property:ro.khungtask.enable=eng
+ setprop khungtask.enable ${ro.debuggable:-0}
+
+service llkd-1 /system/bin/llkd
+ class late_start
+ disabled
+ user llkd
+ group llkd readproc
+ capabilities KILL IPC_LOCK SYS_PTRACE DAC_OVERRIDE
+ file /dev/kmsg w
+ file /proc/sysrq-trigger w
+ writepid /dev/cpuset/system-background/tasks
diff --git a/llkd/llkd.rc b/llkd/llkd.rc
index e538cdb..b1f96a8 100644
--- a/llkd/llkd.rc
+++ b/llkd/llkd.rc
@@ -3,15 +3,8 @@
setprop llk.enable ${ro.llk.enable:-0}
setprop khungtask.enable ${ro.khungtask.enable:-0}
-on property:ro.debuggable=1
- setprop llk.enable ${ro.llk.enable:-1}
- setprop khungtask.enable ${ro.khungtask.enable:-1}
-
-on property:ro.llk.enable=eng
- setprop llk.enable ${ro.debuggable:-0}
-
-on property:ro.khungtask.enable=eng
- setprop khungtask.enable ${ro.debuggable:-0}
+on property:ro.llk.enable=true
+ setprop llk.enable true
on property:llk.enable=1
setprop llk.enable true
@@ -19,6 +12,9 @@
on property:llk.enable=0
setprop llk.enable false
+on property:ro.khungtask.enable=true
+ setprop khungtask.enable true
+
on property:khungtask.enable=1
setprop khungtask.enable true
@@ -36,9 +32,9 @@
write /proc/sys/kernel/hung_task_panic 0
on property:llk.enable=true
- start llkd
+ start llkd-${ro.debuggable:-0}
-service llkd /system/bin/llkd
+service llkd-0 /system/bin/llkd
class late_start
disabled
user llkd
diff --git a/llkd/tests/llkd_test.cpp b/llkd/tests/llkd_test.cpp
index 3a15ff1..96079cc 100644
--- a/llkd/tests/llkd_test.cpp
+++ b/llkd/tests/llkd_test.cpp
@@ -14,8 +14,11 @@
* limitations under the License.
*/
+#include <fcntl.h>
#include <signal.h>
#include <stdint.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -81,9 +84,13 @@
(GetUintProperty(LLK_CHECK_MS_PROPERTY,
LLK_TIMEOUT_MS_DEFAULT / LLK_CHECKS_PER_TIMEOUT_DEFAULT) !=
duration_cast<milliseconds>(10s))) {
- execute("stop llkd");
+ execute("stop llkd-0");
+ execute("stop llkd-1");
rest();
std::string setprop("setprop ");
+ // Manually check that SyS_openat is _added_ to the list when restarted
+ execute((setprop + LLK_CHECK_STACK_PROPERTY + " ,SyS_openat").c_str());
+ rest();
execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " false").c_str());
rest();
execute((setprop + LLK_TIMEOUT_MS_PROPERTY + " 120000").c_str());
@@ -92,8 +99,10 @@
rest();
execute((setprop + LLK_CHECK_MS_PROPERTY + " 10000").c_str());
rest();
- execute((setprop + LLK_ENABLE_PROPERTY + " true").c_str());
- rest();
+ if (!default_enable) {
+ execute((setprop + LLK_ENABLE_PROPERTY + " true").c_str());
+ rest();
+ }
execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " true").c_str());
rest();
}
@@ -104,7 +113,7 @@
}
default_enable = android::base::GetBoolProperty(LLK_ENABLE_PROPERTY, default_enable);
if (default_enable) {
- execute("start llkd");
+ execute("start llkd-1");
rest();
GTEST_LOG_INFO << "llkd enabled\n";
} else {
@@ -123,8 +132,10 @@
llkTimeoutMs = LLK_TIMEOUT_MS_MINIMUM;
}
milliseconds llkCheckMs = llkTimeoutMs / LLK_CHECKS_PER_TIMEOUT_DEFAULT;
- auto timeout = GetUintProperty(
- (state == 'Z') ? LLK_Z_TIMEOUT_MS_PROPERTY : LLK_D_TIMEOUT_MS_PROPERTY, llkTimeoutMs);
+ auto timeout = GetUintProperty((state == 'Z') ? LLK_Z_TIMEOUT_MS_PROPERTY
+ : (state == 'S') ? LLK_STACK_TIMEOUT_MS_PROPERTY
+ : LLK_D_TIMEOUT_MS_PROPERTY,
+ llkTimeoutMs);
if (timeout < LLK_TIMEOUT_MS_MINIMUM) {
timeout = LLK_TIMEOUT_MS_MINIMUM;
}
@@ -285,3 +296,75 @@
waitForPid(child_pid);
}
+
+TEST(llkd, sleep) {
+ if (checkKill("kernel_panic,sysrq,livelock,sleeping")) {
+ return;
+ }
+ if (!android::base::GetBoolProperty("ro.debuggable", false)) {
+ GTEST_LOG_WARNING << "Features not available on user builds\n";
+ }
+
+ const auto period = llkdSleepPeriod('S');
+
+ /* Create a Persistent SyS_openat for single-ended pipe */
+ static constexpr char stack_pipe_file[] = "/dev/stack_pipe_file";
+ unlink(stack_pipe_file);
+ auto pipe_ret = mknod(stack_pipe_file, S_IFIFO | 0666, 0);
+ ASSERT_LE(0, pipe_ret);
+
+ auto child_pid = fork();
+ ASSERT_LE(0, child_pid);
+ if (!child_pid) {
+ child_pid = fork();
+ ASSERT_LE(0, child_pid);
+ if (!child_pid) {
+ sleep(period.count());
+ auto fd = open(stack_pipe_file, O_RDONLY | O_CLOEXEC);
+ close(fd);
+ exit(0);
+ } else {
+ auto fd = open(stack_pipe_file, O_WRONLY | O_CLOEXEC);
+ close(fd);
+ exit(42);
+ }
+ }
+
+ waitForPid(child_pid);
+
+ unlink(stack_pipe_file);
+}
+
+// b/120983740
+TEST(llkd, adbd_and_setsid) {
+ if (checkKill("kernel_panic,sysrq,livelock,zombie")) {
+ return;
+ }
+ const auto period = llkdSleepPeriod('S');
+
+ // expect llkd.zombie to trigger, but not for adbd&[setsid]
+ // Create a Persistent Zombie setsid Process
+ pid_t child_pid = fork();
+ ASSERT_LE(0, child_pid);
+ if (!child_pid) {
+ prctl(PR_SET_NAME, "adbd");
+ auto zombie_pid = fork();
+ ASSERT_LE(0, zombie_pid);
+ if (!zombie_pid) {
+ prctl(PR_SET_NAME, "setsid");
+ sleep(1);
+ exit(0);
+ }
+ sleep(period.count());
+ exit(42);
+ }
+
+ // Reverse of waitForPid, do _not_ expect kill
+ int wstatus;
+ ASSERT_LE(0, waitpid(child_pid, &wstatus, 0));
+ EXPECT_TRUE(WIFEXITED(wstatus));
+ if (WIFEXITED(wstatus)) {
+ EXPECT_EQ(42, WEXITSTATUS(wstatus));
+ }
+ ASSERT_FALSE(WIFSIGNALED(wstatus)) << "[ INFO ] signo=" << WTERMSIG(wstatus);
+}
diff --git a/lmkd/Android.bp b/lmkd/Android.bp
index 903d0e2..f9ed57c 100644
--- a/lmkd/Android.bp
+++ b/lmkd/Android.bp
@@ -5,6 +5,7 @@
shared_libs: [
"libcutils",
"liblog",
+ "libprocessgroup",
],
static_libs: [
"libstatslogc",
diff --git a/lmkd/include/lmkd.h b/lmkd/include/lmkd.h
index fe6364d..e72d159 100644
--- a/lmkd/include/lmkd.h
+++ b/lmkd/include/lmkd.h
@@ -30,6 +30,8 @@
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 */
};
/*
@@ -142,6 +144,53 @@
return 2 * sizeof(int);
}
+/*
+ * Prepare LMK_PROCPURGE packet and return packet size in bytes.
+ * Warning: no checks performed, caller should ensure valid parameters.
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+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/lmkd.c b/lmkd/lmkd.c
index 02534f2..ca78c38 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -16,6 +16,7 @@
#define LOG_TAG "lowmemorykiller"
+#include <dirent.h>
#include <errno.h>
#include <inttypes.h>
#include <pwd.h>
@@ -28,16 +29,22 @@
#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 <system/thread_defs.h>
#ifdef LMKD_LOG_STATS
#include "statslog.h"
@@ -83,6 +90,10 @@
#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)
+
/* Defined as ProcessList.SYSTEM_ADJ in ProcessList.java */
#define SYSTEM_ADJ (-900)
@@ -91,6 +102,8 @@
#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;
@@ -305,7 +318,20 @@
#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
#define ADJTOSLOT(adj) ((adj) + -OOM_SCORE_ADJ_MIN)
-static struct adjslot_list procadjslot_list[ADJTOSLOT(OOM_SCORE_ADJ_MAX) + 1];
+#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;
@@ -494,6 +520,12 @@
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 void cmd_procprio(LMKD_CTRL_PACKET packet) {
struct proc *procp;
char path[80];
@@ -545,7 +577,7 @@
} else if (params.oomadj >= 300) {
soft_limit_mult = 1;
} else if (params.oomadj >= 200) {
- soft_limit_mult = 2;
+ soft_limit_mult = 8;
} else if (params.oomadj >= 100) {
soft_limit_mult = 10;
} else if (params.oomadj >= 0) {
@@ -598,24 +630,148 @@
}
lmkd_pack_get_procremove(packet, ¶ms);
+ /*
+ * 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, ¶ms);
+
+ 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 > (int)ARRAY_SIZE(lowmem_adj))
+ 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];
@@ -671,12 +827,28 @@
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)
@@ -709,6 +881,19 @@
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;
@@ -774,7 +959,7 @@
}
#ifdef LMKD_LOG_STATS
-static void memory_stat_parse_line(char *line, struct memory_stat *mem_st) {
+static void memory_stat_parse_line(char* line, struct memory_stat* mem_st) {
char key[LINE_MAX + 1];
int64_t value;
@@ -796,17 +981,10 @@
mem_st->swap_in_bytes = value;
}
-static int memory_stat_parse(struct memory_stat *mem_st, int pid, uid_t uid) {
+static int memory_stat_from_cgroup(struct memory_stat* mem_st, int pid, uid_t uid) {
FILE *fp;
char buf[PATH_MAX];
- /*
- * Per-application memory.stat files are available only when
- * per-application memcgs are enabled.
- */
- if (!per_app_memcg)
- return -1;
-
snprintf(buf, sizeof(buf), MEMCG_PROCESS_MEMORY_STAT_PATH, uid, pid);
fp = fopen(buf, "r");
@@ -816,13 +994,51 @@
return -1;
}
- while (fgets(buf, PAGE_SIZE, fp) != NULL ) {
+ 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 */
@@ -1050,14 +1266,51 @@
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_score_adj,
- enum vmpressure_level level) {
+static int kill_one_process(struct proc* procp) {
int pid = procp->pid;
uid_t uid = procp->uid;
char *taskname;
int tasksize;
int r;
+ int result = -1;
#ifdef LMKD_LOG_STATS
struct memory_stat mem_st = {};
@@ -1066,19 +1319,21 @@
taskname = proc_get_name(pid);
if (!taskname) {
- pid_remove(pid);
- return -1;
+ goto out;
}
tasksize = proc_get_size(pid);
if (tasksize <= 0) {
- pid_remove(pid);
- return -1;
+ goto out;
}
#ifdef LMKD_LOG_STATS
if (enable_stats_log) {
- memory_stat_parse_result = memory_stat_parse(&mem_st, pid, uid);
+ 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
@@ -1086,42 +1341,50 @@
/* CAP_KILL required */
r = kill(pid, SIGKILL);
- ALOGI(
- "Killing '%s' (%d), uid %d, adj %d\n"
- " to free %ldkB because system is under %s memory pressure (min_oom_adj=%d)\n",
- taskname, pid, uid, procp->oomadj, tasksize * page_k,
- level_name[level], min_score_adj);
- pid_remove(pid);
+
+ set_process_group_and_prio(pid, SP_FOREGROUND, ANDROID_PRIORITY_HIGHEST);
+
+ inc_killcnt(procp->oomadj);
+ ALOGI("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);
- return -1;
+ 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.cache_in_bytes, mem_st.swap_in_bytes, mem_st.process_start_time_ns);
+ } 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);
}
#endif
- return tasksize;
+ result = tasksize;
}
- return 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 processes to kill to free required number of pages.
- * If pages_to_free is set to 0 only one process will be killed.
- * Returns the size of the killed processes.
+ * Find one process to kill at or above the given oom_adj level.
+ * Returns size of the killed process.
*/
-static int find_and_kill_processes(enum vmpressure_level level,
- int min_score_adj, int pages_to_free) {
+static int find_and_kill_process(int min_score_adj) {
int i;
- int killed_size;
- int pages_freed = 0;
+ int killed_size = 0;
#ifdef LMKD_LOG_STATS
bool lmk_state_change_start = false;
@@ -1137,7 +1400,7 @@
if (!procp)
break;
- killed_size = kill_one_process(procp, min_score_adj, level);
+ killed_size = kill_one_process(procp);
if (killed_size >= 0) {
#ifdef LMKD_LOG_STATS
if (enable_stats_log && !lmk_state_change_start) {
@@ -1146,20 +1409,12 @@
LMK_STATE_CHANGE_START);
}
#endif
-
- pages_freed += killed_size;
- if (pages_freed >= pages_to_free) {
-
-#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 pages_freed;
- }
+ break;
}
}
+ if (killed_size) {
+ break;
+ }
}
#ifdef LMKD_LOG_STATS
@@ -1168,7 +1423,7 @@
}
#endif
- return pages_freed;
+ return killed_size;
}
static int64_t get_memory_usage(struct reread_data *file_data) {
@@ -1228,10 +1483,21 @@
level - 1 : level);
}
-static inline unsigned long get_time_diff_ms(struct timeval *from,
- struct timeval *to) {
- return (to->tv_sec - from->tv_sec) * 1000 +
- (to->tv_usec - from->tv_usec) / 1000;
+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) {
@@ -1242,12 +1508,12 @@
enum vmpressure_level lvl;
union meminfo mi;
union zoneinfo zi;
- static struct timeval last_report_tm;
- static unsigned long skip_count = 0;
+ 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 pages_to_free = 0;
int minfree = 0;
static struct reread_data mem_usage_file_data = {
.filename = MEMCG_MEMORY_USAGE,
@@ -1272,19 +1538,26 @@
}
}
+ if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
+ ALOGE("Failed to get current time");
+ return;
+ }
+
if (kill_timeout_ms) {
- struct timeval curr_tm;
- gettimeofday(&curr_tm, NULL);
- if (get_time_diff_ms(&last_report_tm, &curr_tm) < kill_timeout_ms) {
- skip_count++;
+ // 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 (skip_count > 0) {
+ if (kill_skip_count > 0) {
ALOGI("%lu memory pressure events were skipped after a kill!",
- skip_count);
- skip_count = 0;
+ kill_skip_count);
+ kill_skip_count = 0;
}
if (meminfo_parse(&mi) < 0 || zoneinfo_parse(&zi) < 0) {
@@ -1322,9 +1595,6 @@
return;
}
- /* Free up enough pages to push over the highest minfree level */
- pages_to_free = lowmem_minfree[lowmem_targets_size - 1] -
- ((other_free < other_file) ? other_free : other_file);
goto do_kill;
}
@@ -1380,7 +1650,7 @@
do_kill:
if (low_ram_device) {
/* For Go devices kill only one task */
- if (find_and_kill_processes(level, level_oomadj[level], 0) == 0) {
+ if (find_and_kill_process(level_oomadj[level]) == 0) {
if (debug_process_killing) {
ALOGI("Nothing to kill");
}
@@ -1389,6 +1659,8 @@
}
} else {
int pages_freed;
+ static struct timespec last_report_tm;
+ static unsigned long report_skip_count = 0;
if (!use_minfree_levels) {
/* If pressure level is less than critical and enough free swap then ignore */
@@ -1402,10 +1674,7 @@
return;
}
/* 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) {
- pages_to_free = low_pressure_mem.max_nr_free_pages -
- mi.field.nr_free_pages;
- } else {
+ 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 ")",
@@ -1416,27 +1685,40 @@
min_score_adj = level_oomadj[level];
}
- pages_freed = find_and_kill_processes(level, min_score_adj, pages_to_free);
+ 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("Killing because cache %ldkB is below "
- "limit %ldkB for oom_adj %d\n"
- " Free memory is %ldkB %s reserved",
- other_file * page_k, minfree * page_k, min_score_adj,
- other_free * page_k, other_free >= 0 ? "above" : "below");
+ 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 (pages_freed < pages_to_free) {
- ALOGI("Unable to free enough memory (pages to free=%d, pages freed=%d)",
- pages_to_free, pages_freed);
- } else {
- ALOGI("Reclaimed enough memory (pages to free=%d, pages freed=%d)",
- pages_to_free, pages_freed);
- gettimeofday(&last_report_tm, NULL);
+ if (report_skip_count > 0) {
+ ALOGI("Suppressed %lu failed kill reports", report_skip_count);
+ report_skip_count = 0;
}
- if (pages_freed > 0) {
- meminfo_log(&mi);
- }
+
+ last_report_tm = curr_tm;
}
}
@@ -1568,6 +1850,8 @@
procadjslot_list[i].prev = &procadjslot_list[i];
}
+ memset(killcnt_idx, KILLCNT_INVALID_IDX, sizeof(killcnt_idx));
+
return 0;
}
diff --git a/lmkd/statslog.c b/lmkd/statslog.c
index 66d1164..689e8ae 100644
--- a/lmkd/statslog.c
+++ b/lmkd/statslog.c
@@ -65,7 +65,7 @@
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 swap_in_bytes, int64_t process_start_time_ns) {
assert(ctx != NULL);
int ret = -EINVAL;
if (!ctx) {
@@ -113,5 +113,9 @@
return ret;
}
+ if ((ret = android_log_write_int64(ctx, process_start_time_ns)) < 0) {
+ return ret;
+ }
+
return write_to_logger(ctx, LOG_ID_STATS);
}
diff --git a/lmkd/statslog.h b/lmkd/statslog.h
index edebb19..f3abe11 100644
--- a/lmkd/statslog.h
+++ b/lmkd/statslog.h
@@ -64,9 +64,13 @@
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
@@ -84,7 +88,7 @@
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 swap_in_bytes, int64_t process_start_time_ns);
__END_DECLS
diff --git a/lmkd/tests/Android.bp b/lmkd/tests/Android.bp
index cbf44e9..4e845fd 100644
--- a/lmkd/tests/Android.bp
+++ b/lmkd/tests/Android.bp
@@ -18,6 +18,7 @@
shared_libs: [
"libbase",
"liblog",
+ "libcutils",
],
static_libs: [
diff --git a/lmkd/tests/lmkd_test.cpp b/lmkd/tests/lmkd_test.cpp
index 1996bae..f54b25c 100644
--- a/lmkd/tests/lmkd_test.cpp
+++ b/lmkd/tests/lmkd_test.cpp
@@ -39,7 +39,7 @@
#define LMKDTEST_RESPAWN_FLAG "LMKDTEST_RESPAWN"
#define LMKD_LOGCAT_MARKER "lowmemorykiller"
-#define LMKD_KILL_MARKER_TEMPLATE LMKD_LOGCAT_MARKER ": Killing '%s'"
+#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
diff --git a/logcat/Android.bp b/logcat/Android.bp
index b0563a6..5030b15 100644
--- a/logcat/Android.bp
+++ b/logcat/Android.bp
@@ -24,10 +24,10 @@
],
shared_libs: [
"libbase",
- "libcutils",
- "liblog",
"libpcrecpp",
+ "libprocessgroup",
],
+ static_libs: ["liblog"],
logtags: ["event.logtags"],
}
diff --git a/logcat/Android.mk b/logcat/Android.mk
deleted file mode 100644
index a716993..0000000
--- a/logcat/Android.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2006-2014 The Android Open Source Project
-
-LOCAL_PATH := $(call my-dir)
-
-include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 0f56337..15e07fe 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -16,6 +16,7 @@
#include "logcat.h"
+#include <android-base/macros.h>
#include <arpa/inet.h>
#include <assert.h>
#include <ctype.h>
@@ -41,17 +42,18 @@
#include <atomic>
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include <android-base/file.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
#include <log/event_tag_map.h>
#include <log/logprint.h>
#include <private/android_logger.h>
+#include <processgroup/sched_policy.h>
#include <system/thread_defs.h>
#include <pcrecpp.h>
@@ -476,10 +478,10 @@
" -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"
- // Leave security (Device Owner only installations) and
- // kernel (userdebug and eng) buffers undocumented.
" -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"
@@ -565,23 +567,14 @@
return android_log_setPrintFormat(context->logformat, format);
}
-static const char multipliers[][2] = { { "" }, { "K" }, { "M" }, { "G" } };
-
-static unsigned long value_of_size(unsigned long value) {
- for (unsigned i = 0;
- (i < sizeof(multipliers) / sizeof(multipliers[0])) && (value >= 1024);
- value /= 1024, ++i)
- ;
- return value;
-}
-
-static const char* multiplier_of_size(unsigned long value) {
- unsigned i;
+static std::pair<unsigned long, const char*> format_of_size(unsigned long value) {
+ static const char multipliers[][3] = {{""}, {"Ki"}, {"Mi"}, {"Gi"}};
+ size_t i;
for (i = 0;
(i < sizeof(multipliers) / sizeof(multipliers[0])) && (value >= 1024);
value /= 1024, ++i)
;
- return multipliers[i];
+ return std::make_pair(value, multipliers[i]);
}
// String to unsigned int, returns -1 if it fails
@@ -967,7 +960,7 @@
case 't':
got_t = true;
mode |= ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK;
- // FALLTHRU
+ FALLTHROUGH_INTENDED;
case 'T':
if (strspn(optarg, "0123456789") != strlen(optarg)) {
char* cp = parseTime(tail_time, optarg);
@@ -1017,7 +1010,7 @@
getLogSize = true;
break;
}
- // FALLTHRU
+ FALLTHROUGH_INTENDED;
case 'G': {
char* cp;
@@ -1031,15 +1024,15 @@
case 'g':
case 'G':
setLogSize *= 1024;
- // FALLTHRU
+ FALLTHROUGH_INTENDED;
case 'm':
case 'M':
setLogSize *= 1024;
- // FALLTHRU
+ FALLTHROUGH_INTENDED;
case 'k':
case 'K':
setLogSize *= 1024;
- // FALLTHRU
+ FALLTHROUGH_INTENDED;
case '\0':
break;
@@ -1059,7 +1052,7 @@
getPruneList = true;
break;
}
- // FALLTHRU
+ FALLTHROUGH_INTENDED;
case 'P':
setPruneList = optarg;
@@ -1472,12 +1465,14 @@
if ((size < 0) || (readable < 0)) {
reportErrorName(&getSizeFail, dev->device, allSelected);
} 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 %ld%sb (%ld%sb consumed),"
- " max entry is %db, max payload is %db\n",
+ "%s: ring buffer is %lu %sB (%lu %sB consumed),"
+ " max entry is %d B, max payload is %d B\n",
dev->device,
- value_of_size(size), multiplier_of_size(size),
- value_of_size(readable), multiplier_of_size(readable),
+ 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,
diff --git a/logcat/tests/Android.bp b/logcat/tests/Android.bp
new file mode 100644
index 0000000..ab84150
--- /dev/null
+++ b/logcat/tests/Android.bp
@@ -0,0 +1,57 @@
+//
+// Copyright (C) 2013-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.
+//
+
+cc_defaults {
+ name: "logcat-tests-defaults",
+ cflags: [
+ "-fstack-protector-all",
+ "-g",
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-fno-builtin",
+ ],
+}
+
+// -----------------------------------------------------------------------------
+// Benchmarks
+// ----------------------------------------------------------------------------
+
+// Build benchmarks for the device. Run with:
+// adb shell /data/nativetest/logcat-benchmarks/logcat-benchmarks
+cc_benchmark {
+ name: "logcat-benchmarks",
+ defaults: ["logcat-tests-defaults"],
+ srcs: ["logcat_benchmark.cpp"],
+ shared_libs: ["libbase"],
+}
+
+// -----------------------------------------------------------------------------
+// Unit tests.
+// -----------------------------------------------------------------------------
+
+// Build tests for the device (with .so). Run with:
+// adb shell /data/nativetest/logcat-unit-tests/logcat-unit-tests
+cc_test {
+ name: "logcat-unit-tests",
+ defaults: ["logcat-tests-defaults"],
+ shared_libs: ["libbase"],
+ static_libs: ["liblog"],
+ srcs: [
+ "logcat_test.cpp",
+ "logcatd_test.cpp",
+ ],
+}
diff --git a/logcat/tests/Android.mk b/logcat/tests/Android.mk
deleted file mode 100644
index 66f6724..0000000
--- a/logcat/tests/Android.mk
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-# Copyright (C) 2013-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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-test_module_prefix := logcat-
-test_tags := tests
-
-test_c_flags := \
- -fstack-protector-all \
- -g \
- -Wall -Wextra \
- -Werror \
- -fno-builtin \
-
-# -----------------------------------------------------------------------------
-# Benchmarks
-# ----------------------------------------------------------------------------
-
-benchmark_src_files := \
- logcat_benchmark.cpp \
-
-# Build benchmarks for the device. Run with:
-# adb shell /data/nativetest/logcat-benchmarks/logcat-benchmarks
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(test_module_prefix)benchmarks
-LOCAL_MODULE_TAGS := $(test_tags)
-LOCAL_CFLAGS += $(test_c_flags)
-LOCAL_SRC_FILES := $(benchmark_src_files)
-LOCAL_SHARED_LIBRARIES := libbase
-include $(BUILD_NATIVE_BENCHMARK)
-
-# -----------------------------------------------------------------------------
-# Unit tests.
-# -----------------------------------------------------------------------------
-
-test_src_files := \
- logcat_test.cpp \
- logcatd_test.cpp \
-
-# Build tests for the device (with .so). Run with:
-# adb shell /data/nativetest/logcat-unit-tests/logcat-unit-tests
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(test_module_prefix)unit-tests
-LOCAL_MODULE_TAGS := $(test_tags)
-LOCAL_CFLAGS += $(test_c_flags)
-LOCAL_SHARED_LIBRARIES := liblog libbase
-LOCAL_SRC_FILES := $(test_src_files)
-include $(BUILD_NATIVE_TEST)
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index cc1632a..d5c40be 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -31,6 +31,7 @@
#include <string>
#include <android-base/file.h>
+#include <android-base/macros.h>
#include <android-base/stringprintf.h>
#include <gtest/gtest.h>
#include <log/event_tag_map.h>
@@ -557,47 +558,48 @@
while (fgets(buffer, sizeof(buffer), fp)) {
int size, consumed, max, payload;
- char size_mult[3], consumed_mult[3];
+ char size_mult[4], consumed_mult[4];
long full_size, full_consumed;
size = consumed = max = payload = 0;
// NB: crash log can be very small, not hit a Kb of consumed space
// doubly lucky we are not including it.
- if (6 != sscanf(buffer,
- "%*s ring buffer is %d%2s (%d%2s consumed),"
- " max entry is %db, max payload is %db",
- &size, size_mult, &consumed, consumed_mult, &max,
- &payload)) {
- fprintf(stderr, "WARNING: Parse error: %s", buffer);
- continue;
- }
+ EXPECT_EQ(6, sscanf(buffer,
+ "%*s ring buffer is %d %3s (%d %3s consumed),"
+ " max entry is %d B, max payload is %d B",
+ &size, size_mult, &consumed, consumed_mult, &max, &payload))
+ << "Parse error on: " << buffer;
full_size = size;
switch (size_mult[0]) {
case 'G':
full_size *= 1024;
- /* FALLTHRU */
+ FALLTHROUGH_INTENDED;
case 'M':
full_size *= 1024;
- /* FALLTHRU */
+ FALLTHROUGH_INTENDED;
case 'K':
full_size *= 1024;
- /* FALLTHRU */
- case 'b':
+ FALLTHROUGH_INTENDED;
+ case 'B':
break;
+ default:
+ ADD_FAILURE() << "Parse error on multiplier: " << size_mult;
}
full_consumed = consumed;
switch (consumed_mult[0]) {
case 'G':
full_consumed *= 1024;
- /* FALLTHRU */
+ FALLTHROUGH_INTENDED;
case 'M':
full_consumed *= 1024;
- /* FALLTHRU */
+ FALLTHROUGH_INTENDED;
case 'K':
full_consumed *= 1024;
- /* FALLTHRU */
- case 'b':
+ FALLTHROUGH_INTENDED;
+ case 'B':
break;
+ default:
+ ADD_FAILURE() << "Parse error on multiplier: " << consumed_mult;
}
EXPECT_GT((full_size * 9) / 4, full_consumed);
EXPECT_GT(full_size, max);
@@ -1229,39 +1231,38 @@
}
int size, consumed, max, payload;
- char size_mult[3], consumed_mult[3];
+ char size_mult[4], consumed_mult[4];
size = consumed = max = payload = 0;
if (6 == sscanf(buffer,
- "events: ring buffer is %d%2s (%d%2s consumed),"
- " max entry is %db, max payload is %db",
- &size, size_mult, &consumed, consumed_mult, &max,
- &payload)) {
+ "events: ring buffer is %d %3s (%d %3s consumed),"
+ " max entry is %d B, max payload is %d B",
+ &size, size_mult, &consumed, consumed_mult, &max, &payload)) {
long full_size = size, full_consumed = consumed;
switch (size_mult[0]) {
case 'G':
full_size *= 1024;
- /* FALLTHRU */
+ FALLTHROUGH_INTENDED;
case 'M':
full_size *= 1024;
- /* FALLTHRU */
+ FALLTHROUGH_INTENDED;
case 'K':
full_size *= 1024;
- /* FALLTHRU */
- case 'b':
+ FALLTHROUGH_INTENDED;
+ case 'B':
break;
}
switch (consumed_mult[0]) {
case 'G':
full_consumed *= 1024;
- /* FALLTHRU */
+ FALLTHROUGH_INTENDED;
case 'M':
full_consumed *= 1024;
- /* FALLTHRU */
+ FALLTHROUGH_INTENDED;
case 'K':
full_consumed *= 1024;
- /* FALLTHRU */
- case 'b':
+ FALLTHROUGH_INTENDED;
+ case 'B':
break;
}
EXPECT_GT(full_size, full_consumed);
@@ -1403,7 +1404,7 @@
int count = 0;
char buffer[BIG_BUFFER];
-#define logcat_regex_prefix ___STRING(logcat) "_test"
+#define logcat_regex_prefix logcat_executable "_test"
snprintf(buffer, sizeof(buffer),
logcat_executable " --pid %d -d -e " logcat_regex_prefix "_a+b",
@@ -1549,7 +1550,7 @@
{
static const struct tag sync = { 2720, "sync" };
- static const char id[] = ___STRING(logcat) ".descriptive-sync";
+ static const char id[] = logcat_executable ".descriptive-sync";
{
android_log_event_list ctx(sync.tagNo);
ctx << id << (int32_t)42 << (int32_t)-1 << (int32_t)0;
@@ -1664,7 +1665,7 @@
// Invent new entries because existing can not serve
EventTagMap* map = android_openEventTagMap(nullptr);
ASSERT_TRUE(nullptr != map);
- static const char name[] = ___STRING(logcat) ".descriptive-monotonic";
+ static const char name[] = logcat_executable ".descriptive-monotonic";
int myTag = android_lookupEventTagNum(map, name, "(new|1|s)",
ANDROID_LOG_UNKNOWN);
android_closeEventTagMap(map);
diff --git a/logd/.clang-format b/logd/.clang-format
deleted file mode 100644
index 393c309..0000000
--- a/logd/.clang-format
+++ /dev/null
@@ -1,11 +0,0 @@
-BasedOnStyle: Google
-AllowShortFunctionsOnASingleLine: false
-
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-IndentWidth: 4
-PointerAlignment: Left
-TabWidth: 4
-PenaltyExcessCharacter: 32
-
-Cpp11BracedListStyle: false
diff --git a/logd/.clang-format b/logd/.clang-format
new file mode 120000
index 0000000..1af4f51
--- /dev/null
+++ b/logd/.clang-format
@@ -0,0 +1 @@
+../.clang-format-4
\ No newline at end of file
diff --git a/logd/Android.bp b/logd/Android.bp
index 5c79976..bdbdf12 100644
--- a/logd/Android.bp
+++ b/logd/Android.bp
@@ -63,14 +63,17 @@
srcs: ["main.cpp"],
- static_libs: ["liblogd"],
+ static_libs: [
+ "liblog",
+ "liblogd",
+ ],
shared_libs: [
"libsysutils",
- "liblog",
"libcutils",
"libbase",
"libpackagelistparser",
+ "libprocessgroup",
"libcap",
],
diff --git a/logd/Android.mk b/logd/Android.mk
index 1bca891..aafa28d 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -5,9 +5,6 @@
LOCAL_MODULE := logtagd.rc
LOCAL_SRC_FILES := $(LOCAL_MODULE)
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := debug
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/init
include $(BUILD_PREBUILT)
-
-include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index 658e079..bd17555 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -42,7 +42,7 @@
LogTimeEntry::wrlock();
LastLogTimes::iterator it = times.begin();
while (it != times.end()) {
- entry = (*it);
+ entry = it->get();
if (entry->mClient == client) {
if (!entry->isWatchingMultiple(mLogMask)) {
LogTimeEntry::unlock();
@@ -63,31 +63,12 @@
}
}
entry->triggerReader_Locked();
- if (entry->runningReader_Locked()) {
- LogTimeEntry::unlock();
- return;
- }
- entry->incRef_Locked();
- break;
+ LogTimeEntry::unlock();
+ return;
}
it++;
}
- if (it == times.end()) {
- // Create LogTimeEntry in notifyNewLog() ?
- if (mTail == (unsigned long)-1) {
- LogTimeEntry::unlock();
- return;
- }
- entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask,
- mPid, mStart, mTimeout);
- times.push_front(entry);
- }
-
- client->incRef();
-
- // release client and entry reference counts once done
- entry->startReader_Locked();
LogTimeEntry::unlock();
}
diff --git a/logd/FlushCommand.h b/logd/FlushCommand.h
index 543dfc3..ceaf393 100644
--- a/logd/FlushCommand.h
+++ b/logd/FlushCommand.h
@@ -27,36 +27,11 @@
class FlushCommand : public SocketClientCommand {
LogReader& mReader;
- bool mNonBlock;
- unsigned long mTail;
log_mask_t mLogMask;
- pid_t mPid;
- log_time mStart;
- uint64_t mTimeout;
public:
- // for opening a reader
- explicit FlushCommand(LogReader& reader, bool nonBlock, unsigned long tail,
- log_mask_t logMask, pid_t pid, log_time start,
- uint64_t timeout)
- : mReader(reader),
- mNonBlock(nonBlock),
- mTail(tail),
- mLogMask(logMask),
- mPid(pid),
- mStart(start),
- mTimeout((start != log_time::EPOCH) ? timeout : 0) {
- }
-
- // for notification of an update
explicit FlushCommand(LogReader& reader, log_mask_t logMask)
- : mReader(reader),
- mNonBlock(false),
- mTail(-1),
- mLogMask(logMask),
- mPid(0),
- mStart(log_time::EPOCH),
- mTimeout(0) {
+ : mReader(reader), mLogMask(logMask) {
}
virtual void runSocketCommand(SocketClient* client);
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index fc8c960..470ffed 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -165,9 +165,14 @@
bug_num->assign("");
}
+ // Ensure the uid name is not null before passing it to the bug string.
if (uid >= AID_APP_START && uid <= AID_APP_END) {
- bug_num->append(" app=");
- bug_num->append(android::uidToName(uid));
+ char* uidname = android::uidToName(uid);
+ if (uidname) {
+ bug_num->append(" app=");
+ bug_num->append(uidname);
+ free(uidname);
+ }
}
}
@@ -295,7 +300,7 @@
return 0;
}
- log_time now;
+ log_time now(log_time::EPOCH);
static const char audit_str[] = " audit(";
char* timeptr = strstr(str, audit_str);
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index fd1b8b2..9cbc7c4 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -105,10 +105,8 @@
LastLogTimes::iterator times = mTimes.begin();
while (times != mTimes.end()) {
- LogTimeEntry* entry = (*times);
- if (entry->owned_Locked()) {
- entry->triggerReader_Locked();
- }
+ LogTimeEntry* entry = times->get();
+ entry->triggerReader_Locked();
times++;
}
@@ -401,7 +399,7 @@
((*it)->getLogId() != LOG_ID_KERNEL))) {
mLogElements.push_back(elem);
} else {
- log_time end = log_time::EPOCH;
+ log_time end(log_time::EPOCH);
bool end_set = false;
bool end_always = false;
@@ -409,17 +407,15 @@
LastLogTimes::iterator times = mTimes.begin();
while (times != mTimes.end()) {
- LogTimeEntry* entry = (*times);
- if (entry->owned_Locked()) {
- if (!entry->mNonBlock) {
- end_always = true;
- break;
- }
- // it passing mEnd is blocked by the following checks.
- if (!end_set || (end <= entry->mEnd)) {
- end = entry->mEnd;
- end_set = true;
- }
+ LogTimeEntry* entry = times->get();
+ if (!entry->mNonBlock) {
+ end_always = true;
+ break;
+ }
+ // it passing mEnd is blocked by the following checks.
+ if (!end_set || (end <= entry->mEnd)) {
+ end = entry->mEnd;
+ end_set = true;
}
times++;
}
@@ -710,8 +706,8 @@
// Region locked?
LastLogTimes::iterator times = mTimes.begin();
while (times != mTimes.end()) {
- LogTimeEntry* entry = (*times);
- if (entry->owned_Locked() && entry->isWatching(id) &&
+ LogTimeEntry* entry = times->get();
+ if (entry->isWatching(id) &&
(!oldest || (oldest->mStart > entry->mStart) ||
((oldest->mStart == entry->mStart) &&
(entry->mTimeout.tv_sec || entry->mTimeout.tv_nsec)))) {
@@ -1052,9 +1048,9 @@
LogTimeEntry::wrlock();
LastLogTimes::iterator times = mTimes.begin();
while (times != mTimes.end()) {
- LogTimeEntry* entry = (*times);
+ LogTimeEntry* entry = times->get();
// Killer punch
- if (entry->owned_Locked() && entry->isWatching(id)) {
+ if (entry->isWatching(id)) {
entry->release_Locked();
}
times++;
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 19e6d68..2fd9f95 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -55,8 +55,19 @@
mMsgLen(elem.mMsgLen),
mLogId(elem.mLogId),
mDropped(elem.mDropped) {
- mMsg = new char[mMsgLen];
- memcpy(mMsg, elem.mMsg, mMsgLen);
+ 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;
+ }
+ } else {
+ mMsg = new char[mMsgLen];
+ memcpy(mMsg, elem.mMsg, mMsgLen);
+ }
}
LogBufferElement::~LogBufferElement() {
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index e4393a3..edd326a 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -197,10 +197,9 @@
// NOTREACHED
}
-log_time LogKlog::correction =
- (log_time(CLOCK_REALTIME) < log_time(CLOCK_MONOTONIC))
- ? log_time::EPOCH
- : (log_time(CLOCK_REALTIME) - log_time(CLOCK_MONOTONIC));
+log_time LogKlog::correction = (log_time(CLOCK_REALTIME) < log_time(CLOCK_MONOTONIC))
+ ? log_time(log_time::EPOCH)
+ : (log_time(CLOCK_REALTIME) - log_time(CLOCK_MONOTONIC));
LogKlog::LogKlog(LogBuffer* buf, LogReader* reader, int fdWrite, int fdRead,
bool auditd)
@@ -268,7 +267,7 @@
static const char real_format[] = "%Y-%m-%d %H:%M:%S.%09q UTC";
if (len < (ssize_t)(strlen(real_format) + 5)) return;
- log_time real;
+ log_time real(log_time::EPOCH);
const char* ep = real.strptime(real_string, real_format);
if (!ep || (ep > &real_string[len]) || (real > log_time(CLOCK_REALTIME))) {
return;
@@ -282,20 +281,20 @@
tm.tm_isdst = -1;
localtime_r(&now, &tm);
if ((tm.tm_gmtoff < 0) && ((-tm.tm_gmtoff) > (long)real.tv_sec)) {
- real = log_time::EPOCH;
+ real = log_time(log_time::EPOCH);
} else {
real.tv_sec += tm.tm_gmtoff;
}
if (monotonic > real) {
- correction = log_time::EPOCH;
+ correction = log_time(log_time::EPOCH);
} else {
correction = real - monotonic;
}
}
-void LogKlog::sniffTime(log_time& now, const char*& buf, ssize_t len,
- bool reverse) {
- if (len <= 0) return;
+log_time LogKlog::sniffTime(const char*& buf, ssize_t len, bool reverse) {
+ log_time now(log_time::EPOCH);
+ if (len <= 0) return now;
const char* cp = nullptr;
if ((len > 10) && (*buf == '[')) {
@@ -310,7 +309,7 @@
}
buf = cp;
- if (isMonotonic()) return;
+ if (isMonotonic()) return now;
const char* b;
if (((b = android::strnstr(cp, len, suspendStr))) &&
@@ -329,11 +328,11 @@
// trigger a check for ntp-induced or hardware clock drift.
log_time real(CLOCK_REALTIME);
log_time mono(CLOCK_MONOTONIC);
- correction = (real < mono) ? log_time::EPOCH : (real - mono);
+ correction = (real < mono) ? log_time(log_time::EPOCH) : (real - mono);
} else if (((b = android::strnstr(cp, len, suspendedStr))) &&
(((b += strlen(suspendStr)) - cp) < len)) {
len -= b - cp;
- log_time real;
+ log_time real(log_time::EPOCH);
char* endp;
real.tv_sec = strtol(b, &endp, 10);
if ((*endp == '.') && ((endp - b) < len)) {
@@ -345,7 +344,7 @@
}
if (reverse) {
if (real > correction) {
- correction = log_time::EPOCH;
+ correction = log_time(log_time::EPOCH);
} else {
correction -= real;
}
@@ -363,6 +362,7 @@
now = log_time(CLOCK_REALTIME);
}
}
+ return now;
}
pid_t LogKlog::sniffPid(const char*& buf, ssize_t len) {
@@ -451,8 +451,7 @@
}
parseKernelPrio(cp, len - (cp - buf));
- log_time now;
- sniffTime(now, cp, len - (cp - buf), true);
+ log_time now = sniffTime(cp, len - (cp - buf), true);
const char* suspended = android::strnstr(buf, len, suspendedStr);
if (!suspended || (suspended > cp)) {
@@ -468,16 +467,14 @@
}
parseKernelPrio(cp, len - (cp - buf));
- sniffTime(now, cp, len - (cp - buf), true);
+ sniffTime(cp, len - (cp - buf), true);
}
// Convert kernel log priority number into an Android Logger priority number
static int convertKernelPrioToAndroidPrio(int pri) {
switch (pri & LOG_PRIMASK) {
case LOG_EMERG:
- // FALLTHRU
case LOG_ALERT:
- // FALLTHRU
case LOG_CRIT:
return ANDROID_LOG_FATAL;
@@ -488,9 +485,7 @@
return ANDROID_LOG_WARN;
default:
- // FALLTHRU
case LOG_NOTICE:
- // FALLTHRU
case LOG_INFO:
break;
@@ -552,8 +547,7 @@
const char* p = buf;
int pri = parseKernelPrio(p, len);
- log_time now;
- sniffTime(now, p, len - (p - buf), false);
+ log_time now = sniffTime(p, len - (p - buf), false);
// sniff for start marker
const char* start = android::strnstr(p, len - (p - buf), klogdStr);
diff --git a/logd/LogKlog.h b/logd/LogKlog.h
index bb92dd2..6bfd6a8 100644
--- a/logd/LogKlog.h
+++ b/logd/LogKlog.h
@@ -55,11 +55,10 @@
}
protected:
- void sniffTime(log_time& now, const char*& buf, ssize_t len, bool reverse);
- pid_t sniffPid(const char*& buf, ssize_t len);
- void calculateCorrection(const log_time& monotonic, const char* real_string,
- ssize_t len);
- virtual bool onDataAvailable(SocketClient* cli);
+ log_time sniffTime(const char*& buf, ssize_t len, bool reverse);
+ pid_t sniffPid(const char*& buf, ssize_t len);
+ void calculateCorrection(const log_time& monotonic, const char* real_string, ssize_t len);
+ virtual bool onDataAvailable(SocketClient* cli);
};
#endif
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 2b6556d..9db8c00 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -41,6 +41,7 @@
runOnEachSocket(&command);
}
+// Note returning false will release the SocketClient instance.
bool LogReader::onDataAvailable(SocketClient* cli) {
static bool name_set;
if (!name_set) {
@@ -57,6 +58,18 @@
}
buffer[len] = '\0';
+ // Clients are only allowed to send one command, disconnect them if they
+ // send another.
+ LogTimeEntry::wrlock();
+ for (const auto& entry : mLogbuf.mTimes) {
+ if (entry->mClient == cli) {
+ entry->release_Locked();
+ LogTimeEntry::unlock();
+ return false;
+ }
+ }
+ LogTimeEntry::unlock();
+
unsigned long tail = 0;
static const char _tail[] = " tail=";
char* cp = strstr(buffer, _tail);
@@ -199,14 +212,29 @@
cli->getUid(), cli->getGid(), cli->getPid(), nonBlock ? 'n' : 'b', tail,
logMask, (int)pid, sequence.nsec(), timeout);
- FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence, timeout);
+ if (sequence == log_time::EPOCH) {
+ timeout = 0;
+ }
+
+ LogTimeEntry::wrlock();
+ auto entry = std::make_unique<LogTimeEntry>(
+ *this, cli, nonBlock, tail, logMask, pid, sequence, timeout);
+ if (!entry->startReader_Locked()) {
+ LogTimeEntry::unlock();
+ return false;
+ }
+
+ // release client and entry reference counts once done
+ cli->incRef();
+ mLogbuf.mTimes.emplace_front(std::move(entry));
// Set acceptable upper limit to wait for slow reader processing b/27242723
struct timeval t = { LOGD_SNDTIMEO, 0 };
setsockopt(cli->getSocket(), SOL_SOCKET, SO_SNDTIMEO, (const char*)&t,
sizeof(t));
- command.runSocketCommand(cli);
+ LogTimeEntry::unlock();
+
return true;
}
@@ -215,9 +243,8 @@
LogTimeEntry::wrlock();
LastLogTimes::iterator it = times.begin();
while (it != times.end()) {
- LogTimeEntry* entry = (*it);
+ LogTimeEntry* entry = it->get();
if (entry->mClient == cli) {
- times.erase(it);
entry->release_Locked();
break;
}
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index d6b8ab3..469f6dc 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -531,7 +531,7 @@
name = std::string_view(alloc->c_str(), alloc->size());
}
- explicit TagNameKey(TagNameKey&& rval)
+ explicit TagNameKey(TagNameKey&& rval) noexcept
: alloc(rval.alloc), name(rval.name.data(), rval.name.length()) {
rval.alloc = nullptr;
}
diff --git a/logd/LogTags.cpp b/logd/LogTags.cpp
index 1ab9dd1..f19e7b0 100644
--- a/logd/LogTags.cpp
+++ b/logd/LogTags.cpp
@@ -30,6 +30,7 @@
#include <android-base/file.h>
#include <android-base/macros.h>
+#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
#include <log/log_event_list.h>
#include <log/log_properties.h>
@@ -38,6 +39,8 @@
#include "LogTags.h"
#include "LogUtils.h"
+using android::base::make_scope_guard;
+
static LogTags* logtags;
const char LogTags::system_event_log_tags[] = "/system/etc/event-log-tags";
@@ -316,27 +319,29 @@
std::string Format;
android_log_list_element elem;
{
- android_log_event_list ctx(log_msg);
- elem = ctx.read();
+ auto ctx = create_android_log_parser(log_msg.msg() + sizeof(uint32_t),
+ log_msg.entry.len - sizeof(uint32_t));
+ auto guard = make_scope_guard([&ctx]() { android_log_destroy(&ctx); });
+ elem = android_log_read_next(ctx);
if (elem.type != EVENT_TYPE_LIST) {
continue;
}
- elem = ctx.read();
+ elem = android_log_read_next(ctx);
if (elem.type != EVENT_TYPE_INT) {
continue;
}
Tag = elem.data.int32;
- elem = ctx.read();
+ elem = android_log_read_next(ctx);
if (elem.type != EVENT_TYPE_STRING) {
continue;
}
Name = std::string(elem.data.string, elem.len);
- elem = ctx.read();
+ elem = android_log_read_next(ctx);
if (elem.type != EVENT_TYPE_STRING) {
continue;
}
Format = std::string(elem.data.string, elem.len);
- elem = ctx.read();
+ elem = android_log_read_next(ctx);
}
if ((elem.type != EVENT_TYPE_LIST_STOP) || !elem.complete) continue;
@@ -524,10 +529,22 @@
tag2format_const_iterator iform = tag2format.find(tag);
std::string Format = (iform != tag2format.end()) ? iform->second : "";
- __android_log_event_list ctx(TAG_DEF_LOG_TAG);
- ctx << tag << Name << Format;
- std::string buffer(ctx);
- if (buffer.length() <= 0) return; // unlikely
+ auto ctx = create_android_logger(TAG_DEF_LOG_TAG);
+ auto guard = make_scope_guard([&ctx]() { android_log_destroy(&ctx); });
+ if (android_log_write_int32(ctx, static_cast<int32_t>(tag) < 0) ||
+ android_log_write_string8_len(ctx, Name.c_str(), Name.size()) < 0 ||
+ android_log_write_string8_len(ctx, Format.c_str(), Format.size()) < 0) {
+ return;
+ }
+
+ const char* cp = nullptr;
+ ssize_t len = android_log_write_list_buffer(ctx, &cp);
+
+ if (len <= 0 || cp == nullptr) {
+ return;
+ }
+
+ std::string buffer(cp, len);
/*
* struct {
diff --git a/logd/LogTimes.cpp b/logd/LogTimes.cpp
index 7a6f84b..208d67f 100644
--- a/logd/LogTimes.cpp
+++ b/logd/LogTimes.cpp
@@ -30,11 +30,7 @@
LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client,
bool nonBlock, unsigned long tail, log_mask_t logMask,
pid_t pid, log_time start, uint64_t timeout)
- : mRefCount(1),
- mRelease(false),
- mError(false),
- threadRunning(false),
- leadingDropped(false),
+ : leadingDropped(false),
mReader(reader),
mLogMask(logMask),
mPid(pid),
@@ -52,65 +48,21 @@
cleanSkip_Locked();
}
-void LogTimeEntry::startReader_Locked(void) {
+bool LogTimeEntry::startReader_Locked() {
pthread_attr_t attr;
- threadRunning = true;
-
if (!pthread_attr_init(&attr)) {
if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
if (!pthread_create(&mThread, &attr, LogTimeEntry::threadStart,
this)) {
pthread_attr_destroy(&attr);
- return;
+ return true;
}
}
pthread_attr_destroy(&attr);
}
- threadRunning = false;
- if (mClient) {
- mClient->decRef();
- }
- decRef_Locked();
-}
-void LogTimeEntry::threadStop(void* obj) {
- LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
-
- wrlock();
-
- if (me->mNonBlock) {
- me->error_Locked();
- }
-
- SocketClient* client = me->mClient;
-
- if (me->isError_Locked()) {
- LogReader& reader = me->mReader;
- LastLogTimes& times = reader.logbuf().mTimes;
-
- LastLogTimes::iterator it = times.begin();
- while (it != times.end()) {
- if (*it == me) {
- times.erase(it);
- me->release_nodelete_Locked();
- break;
- }
- it++;
- }
-
- me->mClient = nullptr;
- reader.release(client);
- }
-
- if (client) {
- client->decRef();
- }
-
- me->threadRunning = false;
- me->decRef_Locked();
-
- unlock();
+ return false;
}
void* LogTimeEntry::threadStart(void* obj) {
@@ -118,13 +70,7 @@
LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
- pthread_cleanup_push(threadStop, obj);
-
SocketClient* client = me->mClient;
- if (!client) {
- me->error();
- return nullptr;
- }
LogBuffer& logbuf = me->mReader.logbuf();
@@ -137,14 +83,14 @@
log_time start = me->mStart;
- while (me->threadRunning && !me->isError_Locked()) {
+ while (!me->mRelease) {
if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
if (pthread_cond_timedwait(&me->threadTriggeredCondition,
×Lock, &me->mTimeout) == ETIMEDOUT) {
me->mTimeout.tv_sec = 0;
me->mTimeout.tv_nsec = 0;
}
- if (!me->threadRunning || me->isError_Locked()) {
+ if (me->mRelease) {
break;
}
}
@@ -162,13 +108,12 @@
wrlock();
if (start == LogBufferElement::FLUSH_ERROR) {
- me->error_Locked();
break;
}
me->mStart = start + log_time(0, 1);
- if (me->mNonBlock || !me->threadRunning || me->isError_Locked()) {
+ if (me->mNonBlock || me->mRelease) {
break;
}
@@ -179,9 +124,21 @@
}
}
- unlock();
+ LogReader& reader = me->mReader;
+ reader.release(client);
- pthread_cleanup_pop(true);
+ client->decRef();
+
+ LastLogTimes& times = reader.logbuf().mTimes;
+ auto it =
+ std::find_if(times.begin(), times.end(),
+ [&me](const auto& other) { return other.get() == me; });
+
+ if (it != times.end()) {
+ times.erase(it);
+ }
+
+ unlock();
return nullptr;
}
@@ -247,7 +204,7 @@
goto skip;
}
- if (me->isError_Locked()) {
+ if (me->mRelease) {
goto stop;
}
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index 76d016c..9f6f203 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -18,10 +18,12 @@
#define _LOGD_LOG_TIMES_H__
#include <pthread.h>
+#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <list>
+#include <memory>
#include <log/log.h>
#include <sysutils/SocketClient.h>
@@ -33,16 +35,12 @@
class LogTimeEntry {
static pthread_mutex_t timesLock;
- unsigned int mRefCount;
- bool mRelease;
- bool mError;
- bool threadRunning;
+ bool mRelease = false;
bool leadingDropped;
pthread_cond_t threadTriggeredCondition;
pthread_t mThread;
LogReader& mReader;
static void* threadStart(void* me);
- static void threadStop(void* me);
const log_mask_t mLogMask;
const pid_t mPid;
unsigned int skipAhead[LOG_ID_MAX];
@@ -73,11 +71,8 @@
pthread_mutex_unlock(×Lock);
}
- void startReader_Locked(void);
+ bool startReader_Locked();
- bool runningReader_Locked(void) const {
- return threadRunning || mRelease || mError || mNonBlock;
- }
void triggerReader_Locked(void) {
pthread_cond_signal(&threadTriggeredCondition);
}
@@ -87,54 +82,13 @@
}
void cleanSkip_Locked(void);
- // These called after LogTimeEntry removed from list, lock implicitly held
- void release_nodelete_Locked(void) {
- mRelease = true;
- pthread_cond_signal(&threadTriggeredCondition);
- // assumes caller code path will call decRef_Locked()
- }
-
void release_Locked(void) {
+ // gracefully shut down the socket.
+ shutdown(mClient->getSocket(), SHUT_RDWR);
mRelease = true;
pthread_cond_signal(&threadTriggeredCondition);
- if (mRefCount || threadRunning) {
- return;
- }
- // No one else is holding a reference to this
- delete this;
}
- // Called to mark socket in jeopardy
- void error_Locked(void) {
- mError = true;
- }
- void error(void) {
- wrlock();
- error_Locked();
- unlock();
- }
-
- bool isError_Locked(void) const {
- return mRelease || mError;
- }
-
- // Mark Used
- // Locking implied, grabbed when protection around loop iteration
- void incRef_Locked(void) {
- ++mRefCount;
- }
-
- bool owned_Locked(void) const {
- return mRefCount != 0;
- }
-
- void decRef_Locked(void) {
- if ((mRefCount && --mRefCount) || !mRelease || threadRunning) {
- return;
- }
- // No one else is holding a reference to this
- delete this;
- }
bool isWatching(log_id_t id) const {
return mLogMask & (1 << id);
}
@@ -146,6 +100,6 @@
static int FilterSecondPass(const LogBufferElement* element, void* me);
};
-typedef std::list<LogTimeEntry*> LastLogTimes;
+typedef std::list<std::unique_ptr<LogTimeEntry>> LastLogTimes;
#endif // _LOGD_LOG_TIMES_H__
diff --git a/logd/main.cpp b/logd/main.cpp
index 8c38d9a..fd3cdf8 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -38,12 +38,12 @@
#include <android-base/macros.h>
#include <cutils/android_get_control_file.h>
#include <cutils/properties.h>
-#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
#include <log/event_tag_map.h>
#include <packagelistparser/packagelistparser.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
+#include <processgroup/sched_policy.h>
#include <utils/threads.h>
#include "CommandListener.h"
diff --git a/logd/tests/Android.bp b/logd/tests/Android.bp
new file mode 100644
index 0000000..83a194f
--- /dev/null
+++ b/logd/tests/Android.bp
@@ -0,0 +1,68 @@
+//
+// 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.
+//
+
+// -----------------------------------------------------------------------------
+// Unit tests.
+// -----------------------------------------------------------------------------
+
+cc_defaults {
+ name: "logd-unit-test-defaults",
+
+ cflags: [
+ "-fstack-protector-all",
+ "-g",
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-fno-builtin",
+
+ "-DAUDITD_LOG_TAG=1003",
+ "-DCHATTY_LOG_TAG=1004",
+ ],
+
+ srcs: ["logd_test.cpp"],
+
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libselinux",
+ ],
+ static_libs: ["liblog"],
+}
+
+// Build tests for the logger. Run with:
+// adb shell /data/nativetest/logd-unit-tests/logd-unit-tests
+cc_test {
+ name: "logd-unit-tests",
+ defaults: ["logd-unit-test-defaults"],
+}
+
+cc_test {
+ name: "CtsLogdTestCases",
+ defaults: ["logd-unit-test-defaults"],
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
+ test_suites: [
+ "cts",
+ "vts",
+ ],
+}
diff --git a/logd/tests/Android.mk b/logd/tests/Android.mk
deleted file mode 100644
index a0875ea..0000000
--- a/logd/tests/Android.mk
+++ /dev/null
@@ -1,86 +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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-# -----------------------------------------------------------------------------
-# Benchmarks. (see ../../liblog/tests)
-# -----------------------------------------------------------------------------
-
-test_module_prefix := logd-
-test_tags := tests
-
-# -----------------------------------------------------------------------------
-# Unit tests.
-# -----------------------------------------------------------------------------
-
-event_flag := -DAUDITD_LOG_TAG=1003 -DCHATTY_LOG_TAG=1004
-
-test_c_flags := \
- -fstack-protector-all \
- -g \
- -Wall -Wextra \
- -Werror \
- -fno-builtin \
- $(event_flag)
-
-test_src_files := \
- logd_test.cpp
-
-# Build tests for the logger. Run with:
-# adb shell /data/nativetest/logd-unit-tests/logd-unit-tests
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(test_module_prefix)unit-tests
-LOCAL_MODULE_TAGS := $(test_tags)
-LOCAL_CFLAGS += $(test_c_flags)
-LOCAL_SHARED_LIBRARIES := libbase libcutils liblog libselinux
-LOCAL_SRC_FILES := $(test_src_files)
-include $(BUILD_NATIVE_TEST)
-
-cts_executable := CtsLogdTestCases
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(cts_executable)
-LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS += $(test_c_flags)
-LOCAL_SRC_FILES := $(test_src_files)
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-LOCAL_SHARED_LIBRARIES := libbase libcutils liblog libselinux
-LOCAL_STATIC_LIBRARIES := libgtest libgtest_main
-LOCAL_COMPATIBILITY_SUITE := cts vts
-LOCAL_CTS_TEST_PACKAGE := android.core.logd
-include $(BUILD_CTS_EXECUTABLE)
-
-ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(cts_executable)_list
-LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS := $(test_c_flags) -DHOST
-LOCAL_C_INCLUDES := external/gtest/include
-LOCAL_SRC_FILES := $(test_src_files)
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)
-LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-LOCAL_CXX_STL := libc++
-LOCAL_SHARED_LIBRARIES := libbase libcutils liblog
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_HOST_NATIVE_TEST)
-
-endif # ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
diff --git a/mkbootimg/Android.bp b/mkbootimg/Android.bp
index 576a677..c3cf746 100644
--- a/mkbootimg/Android.bp
+++ b/mkbootimg/Android.bp
@@ -31,3 +31,34 @@
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/Android.mk b/mkbootimg/Android.mk
deleted file mode 100644
index 92e1e27..0000000
--- a/mkbootimg/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := mkbootimg
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_IS_HOST_MODULE := true
-
-LOCAL_MODULE := mkbootimg
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := unpack_bootimg
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_IS_HOST_MODULE := true
-
-LOCAL_MODULE := unpack_bootimg
-
-include $(BUILD_PREBUILT)
diff --git a/mkbootimg/include/bootimg/bootimg.h b/mkbootimg/include/bootimg/bootimg.h
index bce308b..4432f9e 100644
--- a/mkbootimg/include/bootimg/bootimg.h
+++ b/mkbootimg/include/bootimg/bootimg.h
@@ -110,25 +110,25 @@
*/
struct boot_img_hdr_v1 : public boot_img_hdr_v0 {
- uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO image */
- uint64_t recovery_dtbo_offset; /* offset to recovery dtbo in boot image */
+ 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 1, 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 | p pages
- * +-----------------+
+ * +---------------------+
+ * | boot header | 1 page
+ * +---------------------+
+ * | kernel | n pages
+ * +---------------------+
+ * | ramdisk | m pages
+ * +---------------------+
+ * | second stage | o pages
+ * +---------------------+
+ * | recovery dtbo/acpio | p 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
@@ -136,13 +136,14 @@
*
* 0. all entities are page_size aligned in flash
* 1. kernel and ramdisk are required (size != 0)
- * 2. recovery_dtbo is required for recovery.img in non-A/B devices(recovery_dtbo_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) at
* the specified physical address (kernel_addr, etc)
- * 5. If booting to recovery mode in a non-A/B device, extract recovery dtbo and
- * apply the correct set of overlays on the base device tree depending on the
- * hardware/product revision.
+ * 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
diff --git a/mkbootimg/mkbootimg b/mkbootimg/mkbootimg.py
old mode 100755
new mode 100644
similarity index 95%
rename from mkbootimg/mkbootimg
rename to mkbootimg/mkbootimg.py
index fda9af0..2eb2bab
--- a/mkbootimg/mkbootimg
+++ b/mkbootimg/mkbootimg.py
@@ -161,7 +161,10 @@
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('--recovery_dtbo', help='path to the recovery DTBO', 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)
diff --git a/mkbootimg/unpack_bootimg b/mkbootimg/unpack_bootimg.py
old mode 100755
new mode 100644
similarity index 100%
rename from mkbootimg/unpack_bootimg
rename to mkbootimg/unpack_bootimg.py
diff --git a/property_service/libpropertyinfoparser/Android.bp b/property_service/libpropertyinfoparser/Android.bp
index 70f6faa..5c57d69 100644
--- a/property_service/libpropertyinfoparser/Android.bp
+++ b/property_service/libpropertyinfoparser/Android.bp
@@ -12,5 +12,7 @@
"-Werror",
],
stl: "none",
+ system_shared_libs: [],
+ header_libs: ["libc_headers"],
export_include_dirs: ["include"],
}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 07f0797..85c7e9e 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -9,6 +9,10 @@
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
+# 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)
#######################################
@@ -18,7 +22,6 @@
LOCAL_MODULE := init-debug.rc
LOCAL_SRC_FILES := $(LOCAL_MODULE)
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := debug
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/init
include $(BUILD_PREBUILT)
@@ -67,6 +70,13 @@
LOCAL_REQUIRED_MODULES := asan.options $(ASAN_OPTIONS_FILES) $(ASAN_EXTRACT_FILES)
endif
+EXPORT_GLOBAL_HWASAN_OPTIONS :=
+ifneq ($(filter hwaddress,$(SANITIZE_TARGET)),)
+ ifneq ($(HWADDRESS_SANITIZER_GLOBAL_OPTIONS),)
+ EXPORT_GLOBAL_HWASAN_OPTIONS := export HWASAN_OPTIONS $(HWADDRESS_SANITIZER_GLOBAL_OPTIONS)
+ endif
+endif
+
EXPORT_GLOBAL_GCOV_OPTIONS :=
ifeq ($(NATIVE_COVERAGE),true)
EXPORT_GLOBAL_GCOV_OPTIONS := export GCOV_PREFIX /data/misc/gcov
@@ -77,7 +87,7 @@
#
# 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 $(BOARD_ROOT_EXTRA_FOLDERS)); \
+ sbin dev proc sys system data odm oem acct config storage mnt apex $(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; \
@@ -117,6 +127,7 @@
LOCAL_POST_INSTALL_CMD += ; ln -sf /vendor/odm/lib64 $(TARGET_ROOT_OUT)/odm/lib64
LOCAL_POST_INSTALL_CMD += ; ln -sf /vendor/odm/overlay $(TARGET_ROOT_OUT)/odm/overlay
LOCAL_POST_INSTALL_CMD += ; ln -sf /vendor/odm/priv-app $(TARGET_ROOT_OUT)/odm/priv-app
+LOCAL_POST_INSTALL_CMD += ; ln -sf /vendor/odm/usr $(TARGET_ROOT_OUT)/odm/usr
ifdef BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/cache
@@ -138,22 +149,14 @@
include $(BUILD_SYSTEM)/base_rules.mk
-# Regenerate init.environ.rc if PRODUCT_BOOTCLASSPATH has changed.
-bcp_md5 := $(word 1, $(shell echo $(PRODUCT_BOOTCLASSPATH) $(PRODUCT_SYSTEM_SERVER_CLASSPATH) | $(MD5SUM)))
-bcp_dep := $(intermediates)/$(bcp_md5).bcp.dep
-$(bcp_dep) :
- $(hide) mkdir -p $(dir $@) && rm -rf $(dir $@)*.bcp.dep && touch $@
-
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/init.environ.rc.in $(bcp_dep)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/init.environ.rc.in
@echo "Generate: $< -> $@"
@mkdir -p $(dir $@)
$(hide) sed -e 's?%BOOTCLASSPATH%?$(PRODUCT_BOOTCLASSPATH)?g' $< >$@
$(hide) sed -i -e 's?%SYSTEMSERVERCLASSPATH%?$(PRODUCT_SYSTEM_SERVER_CLASSPATH)?g' $@
$(hide) sed -i -e 's?%EXPORT_GLOBAL_ASAN_OPTIONS%?$(EXPORT_GLOBAL_ASAN_OPTIONS)?g' $@
$(hide) sed -i -e 's?%EXPORT_GLOBAL_GCOV_OPTIONS%?$(EXPORT_GLOBAL_GCOV_OPTIONS)?g' $@
-
-bcp_md5 :=
-bcp_dep :=
+ $(hide) sed -i -e 's?%EXPORT_GLOBAL_HWASAN_OPTIONS%?$(EXPORT_GLOBAL_HWASAN_OPTIONS)?g' $@
# Append PLATFORM_VNDK_VERSION to base name.
define append_vndk_version
@@ -206,6 +209,7 @@
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
@@ -243,6 +247,7 @@
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
diff --git a/rootdir/OWNERS b/rootdir/OWNERS
index 6029ae7..ca22eb8 100644
--- a/rootdir/OWNERS
+++ b/rootdir/OWNERS
@@ -1,3 +1,4 @@
+ccross@google.com
jeffv@google.com
jiyong@google.com
smoreland@google.com
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index ca6aafe..461184a 100644
--- a/rootdir/etc/ld.config.legacy.txt
+++ b/rootdir/etc/ld.config.legacy.txt
@@ -6,35 +6,40 @@
# 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 is searched
+# Except for /postinstall, where only /system and /product are searched
dir.postinstall = /postinstall
[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/odm/${LIB}
-namespace.default.asan.search.paths += /odm/${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}
###############################################################################
# Namespace config for binaries under /postinstall.
# Only one default namespace is defined and it 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 poinstall binaries. There is no reason to allow the
-# binaries to access the paths.
+# /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 = /system/${LIB}
+namespace.default.search.paths += /product/${LIB}
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index f2892f8..3804c86 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -8,7 +8,6 @@
dir.system = /system/bin/
dir.system = /system/xbin/
dir.system = /%PRODUCT%/bin/
-dir.system = /%PRODUCT_SERVICES%/bin/
dir.vendor = /odm/bin/
dir.vendor = /vendor/bin/
@@ -29,7 +28,7 @@
dir.postinstall = /postinstall
[system]
-additional.namespaces = sphal,vndk,rs
+additional.namespaces = runtime,conscrypt,media,sphal,vndk,rs
###############################################################################
# "default" namespace
@@ -74,13 +73,14 @@
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.resolv/${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 += /%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 += /%PRODUCT_SERVICES%/${LIB}
namespace.default.asan.permitted.paths = /data
namespace.default.asan.permitted.paths += /system/${LIB}/drm
@@ -105,6 +105,58 @@
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.resolv/${LIB}
+
+# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+namespace.default.links = runtime
+namespace.default.link.runtime.shared_libs = libart.so:libartd.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
+
+###############################################################################
+# "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.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.links = default
+namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
+namespace.media.link.default.shared_libs += libandroid.so
+namespace.media.link.default.shared_libs += libbinder_ndk.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
+
+namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
+namespace.conscrypt.links = default
+# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
+# when it exists.
+namespace.conscrypt.link.default.allow_all_shared_libs = true
###############################################################################
# "sphal" namespace
@@ -190,7 +242,7 @@
namespace.rs.links = default,vndk
-namespace.rs.link.default.shared_libs = %LLNDK_LIBRARIES%
+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.
@@ -250,6 +302,7 @@
# 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
@@ -325,6 +378,7 @@
# to the system namespace. This is possible since their ABI is stable across
# Android releases.
namespace.vndk.links = system,default
+
namespace.vndk.link.system.shared_libs = %LLNDK_LIBRARIES%
namespace.vndk.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
@@ -345,15 +399,17 @@
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 += /%PRODUCT%/${LIB}
+namespace.system.asan.search.paths += /data/asan/product_services/${LIB}
+namespace.system.asan.search.paths += /%PRODUCT_SERVICES%/${LIB}
###############################################################################
# Namespace config for binaries under /postinstall.
-# Only one default namespace is defined and it 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 poinstall binaries. There is no reason to allow the
-# binaries to access the paths.
+# 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
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index db65c14..2ce25b5 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -7,7 +7,7 @@
# absolute path of an executable is selected.
dir.system = /system/bin/
dir.system = /system/xbin/
-dir.system = /product/bin/
+dir.system = /%PRODUCT%/bin/
dir.vendor = /odm/bin/
dir.vendor = /vendor/bin/
@@ -28,7 +28,7 @@
dir.postinstall = /postinstall
[system]
-additional.namespaces = sphal,vndk,rs
+additional.namespaces = runtime,conscrypt,media,sphal,vndk,rs
###############################################################################
# "default" namespace
@@ -41,7 +41,8 @@
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%/${LIB}
+namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
namespace.default.asan.search.paths = /data/asan/system/${LIB}
namespace.default.asan.search.paths += /system/${LIB}
@@ -50,7 +51,59 @@
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 += /%PRODUCT%/${LIB}
+namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
+namespace.default.asan.search.paths += /%PRODUCT_SERVICES%/${LIB}
+
+# Keep in sync with ld.config.txt in the com.android.runtime APEX.
+namespace.default.links = runtime
+namespace.default.link.runtime.shared_libs = libart.so:libartd.so
+namespace.default.link.runtime.shared_libs += libnativehelper.so
+namespace.default.link.runtime.shared_libs += libnativeloader.so
+
+###############################################################################
+# "runtime" APEX namespace
+#
+# This namespace pulls in externally accessible libs 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.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.links = default
+namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
+namespace.media.link.default.shared_libs += libandroid.so
+namespace.media.link.default.shared_libs += libbinder_ndk.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
+
+namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
+namespace.conscrypt.links = default
+# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
+# when it exists.
+namespace.conscrypt.link.default.allow_all_shared_libs = true
###############################################################################
# "sphal" namespace
@@ -136,7 +189,7 @@
namespace.rs.links = default,vndk
-namespace.rs.link.default.shared_libs = %LLNDK_LIBRARIES%
+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.
@@ -186,9 +239,11 @@
# 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
@@ -205,11 +260,12 @@
namespace.default.search.paths += /vendor/${LIB}/vndk
namespace.default.search.paths += /vendor/${LIB}/vndk-sp
-# Access to system libraries are allowed
+# Access to system libraries is allowed
namespace.default.search.paths += /system/${LIB}/vndk%VNDK_VER%
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%/${LIB}
+namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
namespace.default.asan.search.paths = /data/asan/odm/${LIB}
namespace.default.asan.search.paths += /odm/${LIB}
@@ -230,17 +286,20 @@
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 += /%PRODUCT%/${LIB}
+namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
+namespace.default.asan.search.paths += /%PRODUCT_SERVICES%/${LIB}
###############################################################################
# Namespace config for binaries under /postinstall.
-# Only one default namespace is defined and it 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 poinstall binaries. There is no reason to allow the
-# binaries to access the paths.
+# 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%/${LIB}
+namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
diff --git a/rootdir/etc/public.libraries.android.txt b/rootdir/etc/public.libraries.android.txt
index e20b95d..d8f6095 100644
--- a/rootdir/etc/public.libraries.android.txt
+++ b/rootdir/etc/public.libraries.android.txt
@@ -1,6 +1,7 @@
# See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
libandroid.so
libaaudio.so
+libbinder_ndk.so
libc.so
libcamera2ndk.so
libdl.so
diff --git a/rootdir/etc/public.libraries.iot.txt b/rootdir/etc/public.libraries.iot.txt
index ff0813d..20905bf 100644
--- a/rootdir/etc/public.libraries.iot.txt
+++ b/rootdir/etc/public.libraries.iot.txt
@@ -2,6 +2,7 @@
libandroid.so
libandroidthings.so
libaaudio.so
+libbinder_ndk.so
libc.so
libcamera2ndk.so
libdl.so
diff --git a/rootdir/etc/public.libraries.wear.txt b/rootdir/etc/public.libraries.wear.txt
index 3c46094..4ece5b5 100644
--- a/rootdir/etc/public.libraries.wear.txt
+++ b/rootdir/etc/public.libraries.wear.txt
@@ -1,6 +1,7 @@
# See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
libandroid.so
libaaudio.so
+libbinder_ndk.so
libc.so
libcamera2ndk.so
libdl.so
diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in
index 2e2ab74..d10f7c1 100644
--- a/rootdir/init.environ.rc.in
+++ b/rootdir/init.environ.rc.in
@@ -5,9 +5,11 @@
export ANDROID_ASSETS /system/app
export ANDROID_DATA /data
export ANDROID_STORAGE /storage
+ export ANDROID_RUNTIME_ROOT /apex/com.android.runtime
export EXTERNAL_STORAGE /sdcard
export ASEC_MOUNTPOINT /mnt/asec
export BOOTCLASSPATH %BOOTCLASSPATH%
export SYSTEMSERVERCLASSPATH %SYSTEMSERVERCLASSPATH%
%EXPORT_GLOBAL_ASAN_OPTIONS%
%EXPORT_GLOBAL_GCOV_OPTIONS%
+ %EXPORT_GLOBAL_HWASAN_OPTIONS%
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 1c2ef64..537bf86 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -109,6 +109,8 @@
mkdir /mnt/runtime/read/self 0755 root root
mkdir /mnt/runtime/write 0755 root root
mkdir /mnt/runtime/write/self 0755 root root
+ mkdir /mnt/runtime/full 0755 root root
+ mkdir /mnt/runtime/full/self 0755 root root
# Symlink to keep legacy apps working in multi-user world
symlink /storage/self/primary /sdcard
@@ -269,6 +271,25 @@
# that they can be chown'd to system:system later on boot
write /sys/class/leds/vibrator/trigger "transient"
+ # This is used by Bionic to select optimized routines.
+ write /dev/cpu_variant:${ro.bionic.arch} ${ro.bionic.cpu_variant}
+ chmod 0444 /dev/cpu_variant:${ro.bionic.arch}
+ write /dev/cpu_variant:${ro.bionic.2nd_arch} ${ro.bionic.2nd_cpu_variant}
+ chmod 0444 /dev/cpu_variant:${ro.bionic.2nd_arch}
+
+ # Setup APEX mount point and its security context
+ mount tmpfs tmpfs /apex nodev noexec nosuid
+ chmod 0755 /apex
+ chown root root /apex
+ restorecon /apex
+
+ # Start logd before any other services run to ensure we capture all of their logs.
+ start logd
+ # Start essential services.
+ start servicemanager
+ start hwservicemanager
+ start vndservicemanager
+
# Healthd can trigger a full boot from charger mode by signaling this
# property when the power button is held.
on property:sys.boot_from_charger_mode=1
@@ -306,12 +327,12 @@
# /data, which in turn can only be loaded when system properties are present.
trigger post-fs-data
- # Now we can start zygote for devices with file based encryption
- trigger zygote-start
-
# Load persist properties and override properties (if enabled) from /data.
trigger load_persist_props_action
+ # Now we can start zygote for devices with file based encryption
+ trigger zygote-start
+
# Remove a file to wake up anything waiting for firmware.
trigger firmware_mounts_complete
@@ -319,17 +340,8 @@
trigger boot
on post-fs
- # Load properties from
- # /system/build.prop,
- # /odm/build.prop,
- # /vendor/build.prop and
- # /factory/factory.prop
- load_system_props
- # start essential services
- start logd
- start servicemanager
- start hwservicemanager
- start vndservicemanager
+ start vold
+ exec - system system -- /system/bin/vdc checkpoint markBootAttempt
# Once everything is setup, no need to modify /.
# The bind+remount combination allows this to work in containers.
@@ -392,6 +404,10 @@
class_start early_hal
on post-fs-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
chown system system /data
chmod 0771 /data
@@ -399,7 +415,6 @@
restorecon /data
# Make sure we have the device encryption key.
- start vold
installkey /data
# Start bootcharting as soon as possible after the data partition is
@@ -407,6 +422,9 @@
mkdir /data/bootchart 0755 shell shell
bootchart start
+ # Start apexd as soon as we can
+ start apexd
+
# Avoid predictable entropy pool. Carry over entropy from previous boot.
copy /data/system/entropy.dat /dev/urandom
@@ -473,6 +491,8 @@
mkdir /data/misc/profman 0770 system shell
mkdir /data/misc/gcov 0770 root root
+ mkdir /data/preloads 0775 system system
+
mkdir /data/vendor 0771 root root
mkdir /data/vendor_ce 0771 root root
mkdir /data/vendor_de 0771 root root
@@ -520,6 +540,9 @@
mkdir /data/anr 0775 system system
+ mkdir /data/apex 0750 root system
+ mkdir /data/staging 0750 system system
+
# NFC: create data/nfc for nv storage
mkdir /data/nfc 0770 nfc nfc
mkdir /data/nfc/param 0770 nfc nfc
@@ -557,8 +580,8 @@
# 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 /system, delete if not.
- exec - system system -- /system/bin/tzdatacheck /system/usr/share/zoneinfo /data/misc/zoneinfo
+ # 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
# If there is no post-fs-data action in the init.<device>.rc file, you
# must uncomment this line, otherwise encrypted filesystems
@@ -781,3 +804,6 @@
service flash_recovery /system/bin/install-recovery.sh
class main
oneshot
+
+on property:apexd.status=ready
+ parse_apex_configs
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index ac87979..2e95687 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -4,6 +4,7 @@
user root
group root readproc reserved_disk
socket zygote stream 660 root system
+ updatable
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index a535846..1cfc3d6 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -4,6 +4,7 @@
user root
group root readproc reserved_disk
socket zygote stream 660 root system
+ updatable
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
@@ -19,5 +20,6 @@
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
+ updatable
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 6fc810b..8ab012d 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -4,6 +4,7 @@
user root
group root readproc reserved_disk
socket zygote stream 660 root system
+ updatable
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index 7ddd52e..5abf149 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -4,6 +4,7 @@
user root
group root readproc reserved_disk
socket zygote stream 660 root system
+ updatable
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
@@ -19,5 +20,6 @@
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
+ updatable
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/ld_config_backward_compatibility_check.py b/rootdir/ld_config_backward_compatibility_check.py
new file mode 100755
index 0000000..1a27578
--- /dev/null
+++ b/rootdir/ld_config_backward_compatibility_check.py
@@ -0,0 +1,177 @@
+#!/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 2f85dec..451f5ad 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -1,7 +1,5 @@
firmware_directories /etc/firmware/ /odm/firmware/ /vendor/firmware/ /firmware/image/
-
-subsystem adf
- devname uevent_devname
+uevent_socket_rcvbuf_size 16M
subsystem graphics
devname uevent_devpath
@@ -11,26 +9,10 @@
devname uevent_devpath
dirname /dev/dri
-subsystem oncrpc
- devname uevent_devpath
- dirname /dev/oncrpc
-
-subsystem adsp
- devname uevent_devpath
- dirname /dev/adsp
-
-subsystem msm_camera
- devname uevent_devpath
- dirname /dev/msm_camera
-
subsystem input
devname uevent_devpath
dirname /dev/input
-subsystem mtd
- devname uevent_devpath
- dirname /dev/mtd
-
subsystem sound
devname uevent_devpath
dirname /dev/snd
@@ -58,73 +40,24 @@
/dev/pmsg0 0222 root log
-# the msm hw3d client device node is world writable/readable.
-/dev/msm_hw3dc 0666 root root
-
-# gpu driver for adreno200 is globally accessible
-/dev/kgsl 0666 root root
-
# kms driver for drm based gpu
/dev/dri/* 0666 root graphics
# these should not be world writable
-/dev/diag 0660 radio radio
-/dev/diag_arm9 0660 radio radio
-/dev/ttyMSM0 0600 bluetooth bluetooth
/dev/uhid 0660 uhid uhid
-/dev/uinput 0660 system bluetooth
-/dev/alarm 0664 system radio
+/dev/uinput 0660 uhid uhid
/dev/rtc0 0640 system system
/dev/tty0 0660 root system
/dev/graphics/* 0660 root graphics
-/dev/msm_hw3dm 0660 system graphics
/dev/input/* 0660 root input
/dev/v4l-touch* 0660 root input
-/dev/eac 0660 root audio
-/dev/cam 0660 root camera
-/dev/pmem 0660 system graphics
-/dev/pmem_adsp* 0660 system audio
-/dev/pmem_camera* 0660 system camera
-/dev/oncrpc/* 0660 root system
-/dev/adsp/* 0660 system audio
/dev/snd/* 0660 system audio
-/dev/mt9t013 0660 system system
-/dev/msm_camera/* 0660 system system
-/dev/akm8976_daemon 0640 compass system
-/dev/akm8976_aot 0640 compass system
-/dev/akm8973_daemon 0640 compass system
-/dev/akm8973_aot 0640 compass system
-/dev/bma150 0640 compass system
-/dev/cm3602 0640 compass system
-/dev/akm8976_pffd 0640 compass system
-/dev/lightsensor 0640 system system
-/dev/msm_pcm_out* 0660 system audio
-/dev/msm_pcm_in* 0660 system audio
-/dev/msm_pcm_ctl* 0660 system audio
-/dev/msm_snd* 0660 system audio
-/dev/msm_mp3* 0660 system audio
-/dev/audience_a1026* 0660 system audio
-/dev/tpa2018d1* 0660 system audio
-/dev/msm_audpre 0660 system audio
-/dev/msm_audio_ctl 0660 system audio
-/dev/htc-acoustic 0660 system audio
-/dev/vdec 0660 system audio
-/dev/q6venc 0660 system audio
-/dev/snd/dsp 0660 system audio
-/dev/snd/dsp1 0660 system audio
-/dev/snd/mixer 0660 system audio
-/dev/smd0 0640 radio radio
-/dev/qmi 0640 radio radio
-/dev/qmi0 0640 radio radio
-/dev/qmi1 0640 radio radio
-/dev/qmi2 0640 radio radio
/dev/bus/usb/* 0660 root usb
/dev/mtp_usb 0660 root mtp
/dev/usb_accessory 0660 root usb
/dev/tun 0660 system vpn
# CDMA radio interface MUX
-/dev/ts0710mux* 0640 radio radio
/dev/ppp 0660 radio vpn
# sysfs properties
@@ -134,6 +67,3 @@
/sys/devices/virtual/usb_composite/* enable 0664 root system
/sys/devices/system/cpu/cpu* cpufreq/scaling_max_freq 0664 system system
/sys/devices/system/cpu/cpu* cpufreq/scaling_min_freq 0664 system system
-
-# DVB API device nodes
-/dev/dvb* 0660 root system
diff --git a/rootdir/update_and_install_ld_config.mk b/rootdir/update_and_install_ld_config.mk
index 4d6df77..79bed7b 100644
--- a/rootdir/update_and_install_ld_config.mk
+++ b/rootdir/update_and_install_ld_config.mk
@@ -18,10 +18,13 @@
# 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))
+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)
@@ -35,9 +38,11 @@
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.
@@ -82,11 +87,19 @@
$(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)
deps := $(llndk_libraries_file) $(vndksp_libraries_file) $(vndkcore_libraries_file) \
$(vndkprivate_libraries_file)
+ifeq ($(check_backward_compatibility),true)
+deps += $(compatibility_check_script)
+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" $< >$@
@@ -108,9 +121,11 @@
$(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 :=
diff --git a/run-as/.clang-format b/run-as/.clang-format
new file mode 120000
index 0000000..fd0645f
--- /dev/null
+++ b/run-as/.clang-format
@@ -0,0 +1 @@
+../.clang-format-2
\ No newline at end of file
diff --git a/run-as/run-as.cpp b/run-as/run-as.cpp
index d005ecf..8752eef 100644
--- a/run-as/run-as.cpp
+++ b/run-as/run-as.cpp
@@ -25,6 +25,9 @@
#include <sys/types.h>
#include <unistd.h>
+#include <string>
+#include <vector>
+
#include <libminijail.h>
#include <scoped_minijail.h>
@@ -129,6 +132,25 @@
return check_directory(data_path, uid);
}
+std::vector<gid_t> get_supplementary_gids(uid_t userAppId) {
+ std::vector<gid_t> gids;
+ int size = getgroups(0, &gids[0]);
+ if (size < 0) {
+ error(1, errno, "getgroups failed");
+ }
+ gids.resize(size);
+ size = getgroups(size, &gids[0]);
+ if (size != static_cast<int>(gids.size())) {
+ error(1, errno, "getgroups failed");
+ }
+ // Profile guide compiled oat files (like /data/app/xxx/oat/arm64/base.odex) are not readable
+ // worldwide (DEXOPT_PUBLIC flag isn't set). To support reading them (needed by simpleperf for
+ // profiling), add shared app gid to supplementary groups.
+ gid_t shared_app_gid = userAppId % AID_USER_OFFSET - AID_APP_START + AID_SHARED_GID_START;
+ gids.push_back(shared_app_gid);
+ return gids;
+}
+
int main(int argc, char* argv[]) {
// Check arguments.
if (argc < 2) {
@@ -144,7 +166,7 @@
// Some devices can disable running run-as, such as Chrome OS when running in
// non-developer mode.
if (android::base::GetBoolProperty("ro.boot.disable_runas", false)) {
- error(1, 0, "run-as is disabled from the kernel commandline");
+ error(1, 0, "run-as is disabled from the kernel commandline");
}
char* pkgname = argv[1];
@@ -167,6 +189,15 @@
if (!packagelist_parse(packagelist_parse_callback, &info)) {
error(1, errno, "packagelist_parse failed");
}
+
+ // Handle a multi-user data path
+ if (userId > 0) {
+ free(info.data_dir);
+ if (asprintf(&info.data_dir, "/data/user/%d/%s", userId, pkgname) == -1) {
+ error(1, errno, "asprintf failed");
+ }
+ }
+
if (info.uid == 0) {
error(1, 0, "unknown package: %s", pkgname);
}
@@ -199,13 +230,15 @@
// same time to avoid nasty surprises.
uid_t uid = userAppId;
uid_t gid = userAppId;
+ std::vector<gid_t> supplementary_gids = get_supplementary_gids(userAppId);
ScopedMinijail j(minijail_new());
minijail_change_uid(j.get(), uid);
minijail_change_gid(j.get(), gid);
- minijail_keep_supplementary_gids(j.get());
+ minijail_set_supplementary_gids(j.get(), supplementary_gids.size(), supplementary_gids.data());
minijail_enter(j.get());
- if (selinux_android_setcontext(uid, 0, info.seinfo, pkgname) < 0) {
+ std::string seinfo = std::string(info.seinfo) + ":fromRunAs";
+ if (selinux_android_setcontext(uid, 0, seinfo.c_str(), pkgname) < 0) {
error(1, errno, "couldn't set SELinux security context");
}
diff --git a/sdcard/sdcard.cpp b/sdcard/sdcard.cpp
index dc36596..e1de130 100644
--- a/sdcard/sdcard.cpp
+++ b/sdcard/sdcard.cpp
@@ -160,6 +160,7 @@
std::string dest_path_default = "/mnt/runtime/default/" + label;
std::string dest_path_read = "/mnt/runtime/read/" + label;
std::string dest_path_write = "/mnt/runtime/write/" + label;
+ std::string dest_path_full = "/mnt/runtime/full/" + label;
umask(0);
if (multi_user) {
@@ -172,7 +173,10 @@
default_normal, use_esdfs) ||
!sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_write, uid, gid,
multi_user, userid, AID_EVERYBODY, full_write ? 0007 : 0027,
- derive_gid, default_normal, use_esdfs)) {
+ derive_gid, default_normal, use_esdfs) ||
+ !sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_full, uid, gid,
+ multi_user, userid, AID_EVERYBODY, 0007, derive_gid,
+ default_normal, use_esdfs)) {
LOG(FATAL) << "failed to sdcardfs_setup";
}
} else {
@@ -186,7 +190,10 @@
derive_gid, default_normal, use_esdfs) ||
!sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_write, uid, gid,
multi_user, userid, AID_EVERYBODY, full_write ? 0007 : 0022,
- derive_gid, default_normal, use_esdfs)) {
+ derive_gid, default_normal, use_esdfs) ||
+ !sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_full, uid, gid,
+ multi_user, userid, AID_EVERYBODY, 0007, derive_gid,
+ default_normal, use_esdfs)) {
LOG(FATAL) << "failed to sdcardfs_setup";
}
}
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 3d7521c..cb5c5cb 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -18,9 +18,11 @@
"newfs_msdos",
"reboot",
"sh",
+ "simpleperf",
"tcpdump",
"toolbox",
"toybox",
+ "unzip",
],
}
@@ -31,6 +33,7 @@
"sh.recovery",
"toolbox.recovery",
"toybox.recovery",
+ "unzip.recovery",
],
}
diff --git a/shell_and_utilities/README.md b/shell_and_utilities/README.md
index d8cf867..ffda3a5 100644
--- a/shell_and_utilities/README.md
+++ b/shell_and_utilities/README.md
@@ -1,5 +1,4 @@
-Android's shell and utilities
-=============================
+# Android's shell and utilities
Since IceCreamSandwich Android has used
[mksh](https://www.mirbsd.org/mksh.htm) as its shell. Before then it used
@@ -34,8 +33,7 @@
full list for a release by running `toybox` directly.
-Android 2.3 (Gingerbread)
--------------------------
+## Android 2.3 (Gingerbread)
BSD: cat dd newfs\_msdos
@@ -46,8 +44,7 @@
umount uptime vmstat watchprops wipe
-Android 4.0 (IceCreamSandwich)
-------------------------------
+## Android 4.0 (IceCreamSandwich)
BSD: cat dd newfs\_msdos
@@ -58,8 +55,7 @@
touch umount uptime vmstat watchprops wipe
-Android 4.1-4.3 (JellyBean)
----------------------------
+## Android 4.1-4.3 (JellyBean)
BSD: cat cp dd du grep newfs\_msdos
@@ -71,8 +67,7 @@
sync top touch umount uptime vmstat watchprops wipe
-Android 4.4 (KitKat)
---------------------
+## Android 4.4 (KitKat)
BSD: cat cp dd du grep newfs\_msdos
@@ -84,8 +79,7 @@
stop swapoff swapon sync top touch umount uptime vmstat watchprops wipe
-Android 5.0 (Lollipop)
-----------------------
+## Android 5.0 (Lollipop)
BSD: cat chown cp dd du grep kill ln mv printenv rm rmdir sleep sync
@@ -97,8 +91,7 @@
top touch umount uptime vmstat watchprops wipe
-Android 6.0 (Marshmallow)
--------------------------
+## Android 6.0 (Marshmallow)
BSD: dd du grep
@@ -118,8 +111,7 @@
vmstat wc which whoami xargs yes
-Android 7.0 (Nougat)
---------------------
+## Android 7.0 (Nougat)
BSD: dd grep
@@ -140,8 +132,7 @@
uptime usleep vmstat wc which whoami xargs xxd yes
-Android 8.0 (Oreo)
-------------------
+## Android 8.0 (Oreo)
BSD: dd grep
@@ -164,8 +155,8 @@
tty ulimit umount uname uniq unix2dos uptime usleep uudecode uuencode
vmstat wc which whoami xargs xxd yes zcat
-Android P
----------
+
+## Android 9.0 (Pie)
BSD: dd grep
@@ -190,8 +181,8 @@
umount uname uniq unix2dos uptime usleep uudecode uuencode vmstat wc
which whoami xargs xxd yes zcat
-Android Q
----------
+
+## Android Q
BSD: grep fsck\_msdos newfs\_msdos
@@ -201,17 +192,22 @@
toolbox: getevent getprop
-toybox: acpi base64 basename blockdev cal cat chcon chgrp chmod chown
-chroot chrt cksum clear cmp comm cp cpio cut date dd df diff dirname
-dmesg dos2unix du echo env expand expr fallocate false file find flock
-fmt free getenforce groups gunzip gzip head hostname hwclock id ifconfig
-inotifyd insmod ionice iorenice kill killall ln load\_policy log logname
-losetup ls lsmod lsof lspci lsusb md5sum microcom mkdir mkfifo mknod
-mkswap mktemp modinfo modprobe more mount mountpoint mv nc netcat netstat
-nice nl nohup nsenter od paste patch pgrep pidof pkill pmap printenv
-printf ps pwd readlink realpath renice restorecon rm rmdir rmmod runcon
-sed sendevent seq setenforce setprop setsid sha1sum sha224sum sha256sum
-sha384sum sha512sum sleep sort split start stat stop strings stty swapoff
-swapon sync sysctl tac tail tar taskset tee time timeout top touch tr
-true truncate tty ulimit umount uname uniq unix2dos unshare uptime usleep
-uudecode uuencode vmstat wc which whoami xargs xxd yes zcat
+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
+setprop setsid sha1sum sha224sum sha256sum sha384sum sha512sum sleep
+sort split start stat stop 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 7466728..733b60f 100644
--- a/storaged/Android.bp
+++ b/storaged/Android.bp
@@ -62,7 +62,7 @@
"uid_info.cpp",
"storaged.proto",
":storaged_aidl",
- "binder/android/os/storaged/IStoragedPrivate.aidl",
+ ":storaged_aidl_private",
],
static_libs: ["libhealthhalutils"],
@@ -116,4 +116,13 @@
srcs: [
"binder/android/os/IStoraged.aidl",
],
+ path: "binder",
+}
+
+filegroup {
+ name: "storaged_aidl_private",
+ srcs: [
+ "binder/android/os/storaged/IStoragedPrivate.aidl",
+ ],
+ path: "binder",
}
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index 77c6167..6897663 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -341,20 +341,14 @@
if (mConfig.event_time_check_usec &&
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_ts) < 0) {
check_time = false;
- static time_t state_a;
- IF_ALOG_RATELIMIT_LOCAL(300, &state_a) {
- PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
- }
+ PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
}
event();
if (mConfig.event_time_check_usec && check_time) {
if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_ts) < 0) {
- static time_t state_b;
- IF_ALOG_RATELIMIT_LOCAL(300, &state_b) {
- PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
- }
+ PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
return;
}
int64_t cost = (end_ts.tv_sec - start_ts.tv_sec) * SEC_TO_USEC +
diff --git a/storaged/storaged_diskstats.cpp b/storaged/storaged_diskstats.cpp
index 1050033..8b5001d 100644
--- a/storaged/storaged_diskstats.cpp
+++ b/storaged/storaged_diskstats.cpp
@@ -129,6 +129,10 @@
bool success = false;
auto ret = service->getDiskStats([&success, stats](auto result, const auto& halStats) {
+ if (result == Result::NOT_SUPPORTED) {
+ LOG_TO(SYSTEM, DEBUG) << "getDiskStats is not supported on health HAL.";
+ return;
+ }
if (result != Result::SUCCESS || halStats.size() == 0) {
LOG_TO(SYSTEM, ERROR) << "getDiskStats failed with result " << toString(result)
<< " and size " << halStats.size();
diff --git a/storaged/storaged_info.cpp b/storaged/storaged_info.cpp
index 5605f66..ca2421b 100644
--- a/storaged/storaged_info.cpp
+++ b/storaged/storaged_info.cpp
@@ -87,12 +87,21 @@
day_start_tp += chrono::seconds(perf_history.day_start_sec());
nr_samples = perf_history.nr_samples();
+ if (nr_samples < recent_perf.size()) {
+ recent_perf.erase(recent_perf.begin() + nr_samples, recent_perf.end());
+ }
+ size_t i = 0;
for (auto bw : perf_history.recent_perf()) {
- recent_perf.push_back(bw);
+ if (i < recent_perf.size()) {
+ recent_perf[i] = bw;
+ } else {
+ recent_perf.push_back(bw);
+ }
+ ++i;
}
nr_days = perf_history.nr_days();
- int i = 0;
+ i = 0;
for (auto bw : perf_history.daily_perf()) {
daily_perf[i++] = bw;
}
@@ -370,8 +379,12 @@
void health_storage_info_t::report() {
auto ret = mHealth->getStorageInfo([this](auto result, const auto& halInfos) {
+ if (result == Result::NOT_SUPPORTED) {
+ LOG_TO(SYSTEM, DEBUG) << "getStorageInfo is not supported on health HAL.";
+ return;
+ }
if (result != Result::SUCCESS || halInfos.size() == 0) {
- LOG_TO(SYSTEM, DEBUG) << "getStorageInfo failed with result " << toString(result)
+ LOG_TO(SYSTEM, ERROR) << "getStorageInfo failed with result " << toString(result)
<< " and size " << halInfos.size();
return;
}
@@ -380,7 +393,7 @@
});
if (!ret.isOk()) {
- LOG_TO(SYSTEM, DEBUG) << "getStorageInfo failed with " << ret.description();
+ LOG_TO(SYSTEM, ERROR) << "getStorageInfo failed with " << ret.description();
}
}
diff --git a/storaged/storaged_service.cpp b/storaged/storaged_service.cpp
index 17ea25b..45f1d4d 100644
--- a/storaged/storaged_service.cpp
+++ b/storaged/storaged_service.cpp
@@ -161,7 +161,7 @@
storaged_sp->update_uid_io_interval(time_window);
}
- return NO_ERROR;
+ return OK;
}
binder::Status StoragedService::onUserStarted(int32_t userId) {
diff --git a/storaged/uid_info.cpp b/storaged/uid_info.cpp
index 58e3fd2..0f718de 100644
--- a/storaged/uid_info.cpp
+++ b/storaged/uid_info.cpp
@@ -32,7 +32,7 @@
parcel->writeCString(task_it.second.comm.c_str());
parcel->write(&task_it.second.io, sizeof(task_it.second.io));
}
- return NO_ERROR;
+ return OK;
}
status_t UidInfo::readFromParcel(const Parcel* parcel) {
@@ -48,5 +48,5 @@
parcel->read(&task.io, sizeof(task.io));
tasks[task.pid] = task;
}
- return NO_ERROR;
+ return OK;
}
diff --git a/toolbox/getevent.c b/toolbox/getevent.c
index 39033ad..e2c77c3 100644
--- a/toolbox/getevent.c
+++ b/toolbox/getevent.c
@@ -530,6 +530,9 @@
const char *device = NULL;
const char *device_path = "/dev/input";
+ /* disable buffering on stdout */
+ setbuf(stdout, NULL);
+
opterr = 0;
do {
c = getopt(argc, argv, "tns:Sv::dpilqc:rh");
diff --git a/trusty/keymaster/3.0/TrustyKeymaster3Device.cpp b/trusty/keymaster/3.0/TrustyKeymaster3Device.cpp
index 8e3b3b1..98cbcc3 100644
--- a/trusty/keymaster/3.0/TrustyKeymaster3Device.cpp
+++ b/trusty/keymaster/3.0/TrustyKeymaster3Device.cpp
@@ -21,6 +21,7 @@
#include <cutils/log.h>
#include <keymaster/android_keymaster_messages.h>
#include <trusty_keymaster/TrustyKeymaster3Device.h>
+#include <trusty_keymaster/ipc/trusty_keymaster_ipc.h>
using ::keymaster::AbortOperationRequest;
using ::keymaster::AbortOperationResponse;
@@ -111,7 +112,8 @@
}
}
}
- KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} {
+ KmParamSet(KmParamSet&& other) noexcept
+ : keymaster_key_param_set_t{other.params, other.length} {
other.length = 0;
other.params = nullptr;
}
@@ -393,20 +395,32 @@
const hidl_vec<KeyParameter>& inParams,
const hidl_vec<uint8_t>& input, update_cb _hidl_cb) {
UpdateOperationRequest request;
- request.op_handle = operationHandle;
- request.input.Reinitialize(input.data(), input.size());
- request.additional_params.Reinitialize(KmParamSet(inParams));
-
UpdateOperationResponse response;
- impl_->UpdateOperation(request, &response);
-
- uint32_t resultConsumed = 0;
hidl_vec<KeyParameter> resultParams;
hidl_vec<uint8_t> resultBlob;
- if (response.error == KM_ERROR_OK) {
- resultConsumed = response.input_consumed;
- resultParams = kmParamSet2Hidl(response.output_params);
- resultBlob = kmBuffer2hidlVec(response.output);
+ uint32_t resultConsumed = 0;
+
+ request.op_handle = operationHandle;
+ request.additional_params.Reinitialize(KmParamSet(inParams));
+
+ 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();
diff --git a/trusty/keymaster/3.0/android.hardware.keymaster@3.0-service.trusty.rc b/trusty/keymaster/3.0/android.hardware.keymaster@3.0-service.trusty.rc
index e9d3054..503f3de 100644
--- a/trusty/keymaster/3.0/android.hardware.keymaster@3.0-service.trusty.rc
+++ b/trusty/keymaster/3.0/android.hardware.keymaster@3.0-service.trusty.rc
@@ -1,4 +1,4 @@
service vendor.keymaster-3-0 /vendor/bin/hw/android.hardware.keymaster@3.0-service.trusty
class early_hal
user nobody
- group system drmrpc
+ group drmrpc
diff --git a/trusty/keymaster/include/trusty_keymaster/legacy/trusty_keymaster_device.h b/trusty/keymaster/include/trusty_keymaster/legacy/trusty_keymaster_device.h
index 5a80795..a483c0d 100644
--- a/trusty/keymaster/include/trusty_keymaster/legacy/trusty_keymaster_device.h
+++ b/trusty/keymaster/include/trusty_keymaster/legacy/trusty_keymaster_device.h
@@ -80,6 +80,8 @@
const keymaster_blob_t* input, const keymaster_blob_t* signature,
keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
keymaster_error_t abort(keymaster_operation_handle_t operation_handle);
+ keymaster_error_t delete_key(const keymaster_key_blob_t* key);
+ keymaster_error_t delete_all_keys();
private:
keymaster_error_t Send(uint32_t command, const Serializable& request,
diff --git a/trusty/keymaster/legacy/trusty_keymaster_device.cpp b/trusty/keymaster/legacy/trusty_keymaster_device.cpp
index ea00a92..88c3e7b 100644
--- a/trusty/keymaster/legacy/trusty_keymaster_device.cpp
+++ b/trusty/keymaster/legacy/trusty_keymaster_device.cpp
@@ -70,8 +70,8 @@
device_.export_key = export_key;
device_.attest_key = attest_key;
device_.upgrade_key = upgrade_key;
- device_.delete_key = nullptr;
- device_.delete_all_keys = nullptr;
+ device_.delete_key = delete_key;
+ device_.delete_all_keys = delete_all_keys;
device_.begin = begin;
device_.update = update;
device_.finish = finish;
@@ -122,10 +122,10 @@
void AddClientAndAppData(const keymaster_blob_t* client_id, const keymaster_blob_t* app_data,
RequestType* request) {
request->additional_params.Clear();
- if (client_id) {
+ if (client_id && client_id->data_length > 0) {
request->additional_params.push_back(TAG_APPLICATION_ID, *client_id);
}
- if (app_data) {
+ if (app_data && app_data->data_length > 0) {
request->additional_params.push_back(TAG_APPLICATION_DATA, *app_data);
}
}
@@ -606,6 +606,34 @@
return trusty_keymaster_send(KM_ABORT_OPERATION, request, &response);
}
+keymaster_error_t TrustyKeymasterDevice::delete_key(const keymaster_key_blob_t* key) {
+ ALOGD("Device received delete_key");
+
+ if (error_ != KM_ERROR_OK) {
+ return error_;
+ }
+
+ if (!key || !key->key_material)
+ return KM_ERROR_UNEXPECTED_NULL_POINTER;
+
+ DeleteKeyRequest request(message_version_);
+ request.SetKeyMaterial(*key);
+ DeleteKeyResponse response(message_version_);
+ return trusty_keymaster_send(KM_DELETE_KEY, request, &response);
+}
+
+keymaster_error_t TrustyKeymasterDevice::delete_all_keys() {
+ ALOGD("Device received delete_all_key");
+
+ if (error_ != KM_ERROR_OK) {
+ return error_;
+ }
+
+ DeleteAllKeysRequest request(message_version_);
+ DeleteAllKeysResponse response(message_version_);
+ return trusty_keymaster_send(KM_DELETE_ALL_KEYS, request, &response);
+}
+
hw_device_t* TrustyKeymasterDevice::hw_device() {
return &device_.common;
}
@@ -719,4 +747,15 @@
return convert_device(dev)->abort(operation_handle);
}
+/* static */
+keymaster_error_t TrustyKeymasterDevice::delete_key(const keymaster2_device_t* dev,
+ const keymaster_key_blob_t* key) {
+ return convert_device(dev)->delete_key(key);
+}
+
+/* static */
+keymaster_error_t TrustyKeymasterDevice::delete_all_keys(const keymaster2_device_t* dev) {
+ return convert_device(dev)->delete_all_keys();
+}
+
} // namespace keymaster
diff --git a/trusty/libtrusty/tipc-test/Android.bp b/trusty/libtrusty/tipc-test/Android.bp
index 32499e3..9676b79 100644
--- a/trusty/libtrusty/tipc-test/Android.bp
+++ b/trusty/libtrusty/tipc-test/Android.bp
@@ -17,12 +17,10 @@
vendor: true,
srcs: ["tipc_test.c"],
- static_libs: [
- "libtrusty",
- ],
shared_libs: [
"libc",
"liblog",
+ "libtrusty",
],
gtest: false,
cflags: [
diff --git a/trusty/utils/trusty-ut-ctrl/Android.bp b/trusty/utils/trusty-ut-ctrl/Android.bp
new file mode 100644
index 0000000..77d1f70
--- /dev/null
+++ b/trusty/utils/trusty-ut-ctrl/Android.bp
@@ -0,0 +1,30 @@
+// 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: "trusty-ut-ctrl",
+ vendor: true,
+
+ srcs: ["ut-ctrl.c"],
+ shared_libs: [
+ "libc",
+ "liblog",
+ "libtrusty",
+ ],
+ gtest: false,
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/trusty/utils/trusty-ut-ctrl/ut-ctrl.c b/trusty/utils/trusty-ut-ctrl/ut-ctrl.c
new file mode 100644
index 0000000..9e72af3
--- /dev/null
+++ b/trusty/utils/trusty-ut-ctrl/ut-ctrl.c
@@ -0,0 +1,159 @@
+/*
+ * 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 <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#include <trusty/tipc.h>
+
+#define TIPC_DEFAULT_DEVNAME "/dev/trusty-ipc-dev0"
+
+static const char* dev_name = NULL;
+static const char* ut_app = NULL;
+
+static const char* _sopts = "hD:";
+static const struct option _lopts[] = {
+ {"help", no_argument, 0, 'h'},
+ {"dev", required_argument, 0, 'D'},
+ {0, 0, 0, 0},
+};
+
+static const char* usage =
+ "Usage: %s [options] unittest-app\n"
+ "\n"
+ "options:\n"
+ " -h, --help prints this message and exit\n"
+ " -D, --dev name Trusty device name\n"
+ "\n";
+
+static const char* usage_long = "\n";
+
+static bool opt_silent = false;
+
+static void print_usage_and_exit(const char* prog, int code, bool verbose) {
+ fprintf(stderr, usage, prog);
+ if (verbose) {
+ fprintf(stderr, "%s", usage_long);
+ }
+ exit(code);
+}
+
+static void parse_options(int argc, char** argv) {
+ int c;
+ int oidx = 0;
+
+ while (1) {
+ c = getopt_long(argc, argv, _sopts, _lopts, &oidx);
+ if (c == -1) {
+ break; /* done */
+ }
+
+ switch (c) {
+ case 'D':
+ dev_name = strdup(optarg);
+ break;
+
+ case 's':
+ opt_silent = true;
+ break;
+
+ case 'h':
+ print_usage_and_exit(argv[0], EXIT_SUCCESS, true);
+ break;
+
+ default:
+ print_usage_and_exit(argv[0], EXIT_FAILURE, false);
+ }
+ }
+
+ if (optind < argc) {
+ ut_app = strdup(argv[optind]);
+ }
+}
+
+enum test_message_header {
+ TEST_PASSED = 0,
+ TEST_FAILED = 1,
+ TEST_MESSAGE = 2,
+};
+
+static int run_trusty_unitest(const char* utapp) {
+ int fd;
+ int rc;
+ char rx_buf[1024];
+
+ /* connect to unitest app */
+ fd = tipc_connect(dev_name, utapp);
+ if (fd < 0) {
+ fprintf(stderr, "failed to connect to '%s' app: %s\n", utapp, strerror(-fd));
+ return fd;
+ }
+
+ /* wait for test to complete */
+ for (;;) {
+ rc = read(fd, rx_buf, sizeof(rx_buf));
+ if (rc <= 0 || rc >= (int)sizeof(rx_buf)) {
+ fprintf(stderr, "%s: Read failed: %d\n", __func__, rc);
+ tipc_close(fd);
+ return -1;
+ }
+
+ if (rx_buf[0] == TEST_PASSED) {
+ break;
+ } else if (rx_buf[0] == TEST_FAILED) {
+ break;
+ } else if (rx_buf[0] == TEST_MESSAGE) {
+ write(STDOUT_FILENO, rx_buf + 1, rc - 1);
+ } else {
+ fprintf(stderr, "%s: Bad message header: %d\n", __func__, rx_buf[0]);
+ break;
+ }
+ }
+
+ /* close connection to unitest app */
+ tipc_close(fd);
+
+ return rx_buf[0] == TEST_PASSED ? 0 : -1;
+}
+
+int main(int argc, char** argv) {
+ int rc = 0;
+
+ if (argc <= 1) {
+ print_usage_and_exit(argv[0], EXIT_FAILURE, false);
+ }
+
+ parse_options(argc, argv);
+
+ if (!dev_name) {
+ dev_name = TIPC_DEFAULT_DEVNAME;
+ }
+
+ if (!ut_app) {
+ fprintf(stderr, "Unittest app must be specified\n");
+ print_usage_and_exit(argv[0], EXIT_FAILURE, false);
+ }
+
+ rc = run_trusty_unitest(ut_app);
+
+ return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}