Merge branch 'security-aosp-qt-release' into int/10/fp2

* security-aosp-qt-release:
  Backport of Win-specific suppression of potentially rogue construct that can engage in directory traversal on the host.

Change-Id: I14d4f0e33fd28c4f1aa7449c154634232db1e915
diff --git a/adb/Android.bp b/adb/Android.bp
index 01e00dd..8cc47b1 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -410,6 +410,11 @@
                 "remount",
             ],
         },
+        fp2_use_appops_su: {
+            cflags: [
+                "-DFP2_USE_APPOPS_SU",
+            ],
+        },
     },
 
     target: {
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index e2a17c5..8dd85d7 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -1668,17 +1668,29 @@
             return 0;
         }
     } else if (!strcmp(argv[0], "rescue")) {
+        // adb rescue getprop
         // adb rescue getprop <prop>
         // adb rescue install <filename>
         // adb rescue wipe userdata
-        if (argc != 3) error_exit("rescue requires two arguments");
+        if (argc < 2) error_exit("rescue requires at least one argument");
         if (!strcmp(argv[1], "getprop")) {
-            return adb_connect_command(android::base::StringPrintf("rescue-getprop:%s", argv[2]));
+            if (argc == 2) {
+                return adb_connect_command("rescue-getprop:");
+            }
+            if (argc == 3) {
+                return adb_connect_command(
+                        android::base::StringPrintf("rescue-getprop:%s", argv[2]));
+            }
+            error_exit("invalid rescue getprop arguments");
         } else if (!strcmp(argv[1], "install")) {
+            if (argc != 3) error_exit("rescue install requires two arguments");
             if (adb_sideload_install(argv[2], true /* rescue_mode */) != 0) {
                 return 1;
             }
-        } else if (!strcmp(argv[1], "wipe") && !strcmp(argv[2], "userdata")) {
+        } else if (!strcmp(argv[1], "wipe")) {
+            if (argc != 3 || strcmp(argv[2], "userdata") != 0) {
+                error_exit("invalid rescue wipe arguments");
+            }
             return adb_wipe_devices();
         } else {
             error_exit("invalid rescue argument");
diff --git a/adb/daemon/restart_service.cpp b/adb/daemon/restart_service.cpp
index 16d2627..be72824 100644
--- a/adb/daemon/restart_service.cpp
+++ b/adb/daemon/restart_service.cpp
@@ -28,6 +28,11 @@
 #include "adb_io.h"
 #include "adb_unique_fd.h"
 
+#ifdef FP2_USE_APPOPS_SU
+#include "adb.h"
+#include "adb_utils.h"
+#endif
+
 void restart_root_service(unique_fd fd) {
     if (getuid() == 0) {
         WriteFdExactly(fd.get(), "adbd is already running as root\n");
@@ -37,6 +42,16 @@
         WriteFdExactly(fd.get(), "adbd cannot run as root in production builds\n");
         return;
     }
+#ifdef FP2_USE_APPOPS_SU
+    int root_access = android::base::GetIntProperty("persist.sys.root_access", 0);
+    std::string build_type = android::base::GetProperty("ro.build.type", "");
+
+    if (build_type != "eng" && (root_access & 2) != 2) {
+        WriteFdExactly(fd, "root access is disabled by system setting - "
+                "enable in Settings -> System -> Developer options\n");
+        return;
+    }
+#endif
 
     LOG(INFO) << "adbd restarting as root";
     android::base::SetProperty("service.adb.root", "1");
diff --git a/code_coverage/Android.mk b/code_coverage/Android.mk
new file mode 100644
index 0000000..80ab36b
--- /dev/null
+++ b/code_coverage/Android.mk
@@ -0,0 +1,37 @@
+# policies to allow processes inside minijail to dump code coverage information
+#
+
+LOCAL_PATH := $(call my-dir)
+
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := code_coverage.policy
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MULTILIB := both
+
+ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm arm64))
+LOCAL_MODULE_STEM_32 := code_coverage.arm.policy
+LOCAL_MODULE_STEM_64 := code_coverage.arm64.policy
+endif
+
+ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), x86 x86_64))
+LOCAL_MODULE_STEM_32 := code_coverage.x86.policy
+LOCAL_MODULE_STEM_64 := code_coverage.x86_64.policy
+endif
+
+# different files for different configurations
+ifeq ($(NATIVE_COVERAGE),true)
+LOCAL_SRC_FILES_arm := seccomp_policy/code_coverage.arm.policy
+LOCAL_SRC_FILES_arm64 := seccomp_policy/code_coverage.arm64.policy
+LOCAL_SRC_FILES_x86 := seccomp_policy/code_coverage.x86.policy
+LOCAL_SRC_FILES_x86_64 := seccomp_policy/code_coverage.x86_64.policy
+else
+LOCAL_SRC_FILES_arm := empty_policy/code_coverage.arm.policy
+LOCAL_SRC_FILES_arm64 := empty_policy/code_coverage.arm64.policy
+LOCAL_SRC_FILES_x86 := empty_policy/code_coverage.x86.policy
+LOCAL_SRC_FILES_x86_64 := empty_policy/code_coverage.x86_64.policy
+endif
+
+LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/seccomp_policy
+include $(BUILD_PREBUILT)
diff --git a/code_coverage/empty_policy/code_coverage.arm.policy b/code_coverage/empty_policy/code_coverage.arm.policy
new file mode 100644
index 0000000..4c9132b
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.arm.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.arm.policy
diff --git a/code_coverage/empty_policy/code_coverage.arm64.policy b/code_coverage/empty_policy/code_coverage.arm64.policy
new file mode 100644
index 0000000..dc5c35a
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.arm64.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.arm64.policy
diff --git a/code_coverage/empty_policy/code_coverage.x86.policy b/code_coverage/empty_policy/code_coverage.x86.policy
new file mode 100644
index 0000000..044f34c
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.x86.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.x86.policy
diff --git a/code_coverage/empty_policy/code_coverage.x86_64.policy b/code_coverage/empty_policy/code_coverage.x86_64.policy
new file mode 100644
index 0000000..6dcd22d
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.x86_64.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.x86_64.policy
diff --git a/code_coverage/seccomp_policy/code_coverage.arm.policy b/code_coverage/seccomp_policy/code_coverage.arm.policy
new file mode 100644
index 0000000..d6784e3
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.arm.policy
@@ -0,0 +1,14 @@
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl64: 1
+fstat64: 1
+geteuid32: 1
+_llseek: 1
+mmap2: 1
+sigreturn: 1
+gettimeofday: 1
+prctl: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.arm64.policy b/code_coverage/seccomp_policy/code_coverage.arm64.policy
new file mode 100644
index 0000000..4c3dd26
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.arm64.policy
@@ -0,0 +1,13 @@
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl: 1
+fstat: 1
+geteuid: 1
+lseek: 1
+mmap: 1
+rt_sigreturn: 1
+prctl: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.policy.def b/code_coverage/seccomp_policy/code_coverage.policy.def
new file mode 100644
index 0000000..f136084
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.policy.def
@@ -0,0 +1,51 @@
+// SECCOMP_MODE_STRICT
+//
+// minijail allowances for code coverage
+// this is processed with generate.sh, so we can use appropriate directives
+// size specific: __LP64__ for 64 bit, else 32 bit
+// arch specific: __arm__, __aarch64__, __i386__, __x86_64__
+
+// includes *all* syscalls used during the coverage dumping
+// no skipping just because they might have been in another policy file.
+
+// coverage tool uses different operations on different passes
+// 1st: uses write() to fill the file
+// 2nd-Nth: uses mmap() to update in place
+
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+
+#if     defined(__LP64__)
+fcntl: 1
+fstat: 1
+geteuid: 1
+lseek: 1
+mmap: 1
+rt_sigreturn: 1
+#else
+fcntl64: 1
+fstat64: 1
+geteuid32: 1
+_llseek: 1
+mmap2: 1
+sigreturn: 1
+#endif
+
+#if     defined(__arm__)
+gettimeofday: 1
+#endif
+
+#if     defined(__i386__)
+madvise: 1
+#endif
+
+#if     defined(__arm__)
+prctl: 1
+#elif   defined(__aarch64__)
+prctl: 1
+#endif
+
diff --git a/code_coverage/seccomp_policy/code_coverage.x86.policy b/code_coverage/seccomp_policy/code_coverage.x86.policy
new file mode 100644
index 0000000..24ff8b9
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.x86.policy
@@ -0,0 +1,13 @@
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl64: 1
+fstat64: 1
+geteuid32: 1
+_llseek: 1
+mmap2: 1
+sigreturn: 1
+madvise: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.x86_64.policy b/code_coverage/seccomp_policy/code_coverage.x86_64.policy
new file mode 100644
index 0000000..3081036
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.x86_64.policy
@@ -0,0 +1,12 @@
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl: 1
+fstat: 1
+geteuid: 1
+lseek: 1
+mmap: 1
+rt_sigreturn: 1
diff --git a/code_coverage/seccomp_policy/generate.sh b/code_coverage/seccomp_policy/generate.sh
new file mode 100755
index 0000000..ae582c6
--- /dev/null
+++ b/code_coverage/seccomp_policy/generate.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# generate the arch-specific files from the generic one
+
+set -ex
+
+cd "$(dirname "$0")"
+CPP='cpp -undef -E -P code_coverage.policy.def'
+$CPP -D__arm__ -o code_coverage.arm.policy
+$CPP -D__aarch64__ -D__LP64__ -o code_coverage.arm64.policy
+$CPP -D__i386__ -o code_coverage.x86.policy
+$CPP -D__x86_64__ -D__LP64__ -o code_coverage.x86_64.policy
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 64df53e..1f249c5 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -176,7 +176,7 @@
   if (crasher_pid != -1) {
     kill(crasher_pid, SIGKILL);
     int status;
-    waitpid(crasher_pid, &status, WUNTRACED);
+    TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED));
   }
 
   android::base::SetProperty(kWaitForGdbKey, previous_wait_for_gdb ? "1" : "0");
@@ -195,8 +195,7 @@
 void CrasherTest::FinishIntercept(int* result) {
   InterceptResponse response;
 
-  // Timeout for tombstoned intercept is 10 seconds.
-  ssize_t rc = TIMEOUT(20, read(intercept_fd.get(), &response, sizeof(response)));
+  ssize_t rc = TIMEOUT(30, read(intercept_fd.get(), &response, sizeof(response)));
   if (rc == -1) {
     FAIL() << "failed to read response from tombstoned: " << strerror(errno);
   } else if (rc == 0) {
@@ -233,7 +232,7 @@
     FAIL() << "crasher pipe uninitialized";
   }
 
-  ssize_t rc = write(crasher_pipe.get(), "\n", 1);
+  ssize_t rc = TEMP_FAILURE_RETRY(write(crasher_pipe.get(), "\n", 1));
   if (rc == -1) {
     FAIL() << "failed to write to crasher pipe: " << strerror(errno);
   } else if (rc == 0) {
@@ -243,9 +242,10 @@
 
 void CrasherTest::AssertDeath(int signo) {
   int status;
-  pid_t pid = TIMEOUT(5, waitpid(crasher_pid, &status, 0));
+  pid_t pid = TIMEOUT(30, waitpid(crasher_pid, &status, 0));
   if (pid != crasher_pid) {
-    printf("failed to wait for crasher (pid %d)\n", crasher_pid);
+    printf("failed to wait for crasher (expected pid %d, return value %d): %s\n", crasher_pid, pid,
+           strerror(errno));
     sleep(100);
     FAIL() << "failed to wait for crasher: " << strerror(errno);
   }
@@ -440,7 +440,7 @@
   FinishCrasher();
 
   int status;
-  ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, WUNTRACED));
+  ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED)));
   ASSERT_TRUE(WIFSTOPPED(status));
   ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
 
@@ -608,7 +608,7 @@
     PLOG(FATAL) << "tmpfile failed";
   }
 
-  unique_fd tmp_fd(dup(fileno(tmp_file)));
+  unique_fd tmp_fd(TEMP_FAILURE_RETRY(dup(fileno(tmp_file))));
   if (!android::base::WriteStringToFd(policy, tmp_fd.get())) {
     PLOG(FATAL) << "failed to write policy to tmpfile";
   }
@@ -821,7 +821,7 @@
   FinishCrasher();
 
   int status;
-  ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, 0));
+  ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
   ASSERT_TRUE(WIFSTOPPED(status));
   ASSERT_EQ(SIGABRT, WSTOPSIG(status));
 
@@ -836,7 +836,7 @@
   regex += R"( \(.+debuggerd_test)";
   ASSERT_MATCH(result, regex.c_str());
 
-  ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, 0));
+  ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
   ASSERT_TRUE(WIFSTOPPED(status));
   ASSERT_EQ(SIGABRT, WSTOPSIG(status));
 
@@ -850,7 +850,7 @@
 
   StartProcess([]() {
     android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
-    unique_fd fd(open("/dev/null", O_RDONLY | O_CLOEXEC));
+    unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY | O_CLOEXEC)));
     if (fd == -1) {
       abort();
     }
@@ -885,13 +885,13 @@
     raise(DEBUGGER_SIGNAL);
 
     errno = 0;
-    rc = waitpid(-1, &status, __WALL | __WNOTHREAD);
+    rc = TEMP_FAILURE_RETRY(waitpid(-1, &status, __WALL | __WNOTHREAD));
     if (rc != -1 || errno != ECHILD) {
       errx(2, "second waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
     }
     _exit(0);
   } else {
-    rc = waitpid(forkpid, &status, 0);
+    rc = TEMP_FAILURE_RETRY(waitpid(forkpid, &status, 0));
     ASSERT_EQ(forkpid, rc);
     ASSERT_TRUE(WIFEXITED(status));
     ASSERT_EQ(0, WEXITSTATUS(status));
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index c8caa67..f3a5074 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -141,7 +141,6 @@
     { nullptr,    "boot_other.img",   "boot.sig",     "boot",     true,  ImageType::Normal },
     { "cache",    "cache.img",        "cache.sig",    "cache",    true,  ImageType::Extra },
     { "dtbo",     "dtbo.img",         "dtbo.sig",     "dtbo",     true,  ImageType::BootCritical },
-    { "dts",      "dt.img",           "dt.sig",       "dts",      true,  ImageType::BootCritical },
     { "odm",      "odm.img",          "odm.sig",      "odm",      true,  ImageType::Normal },
     { "product",  "product.img",      "product.sig",  "product",  true,  ImageType::Normal },
     { "product_services",
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index f1ce125..f753f54 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -245,11 +245,11 @@
             if (should_force_check(*fs_stat)) {
                 ret = android_fork_execvp_ext(
                     ARRAY_SIZE(e2fsck_forced_argv), const_cast<char**>(e2fsck_forced_argv), &status,
-                    true, LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), NULL, 0);
+                    true, LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), nullptr, 0);
             } else {
                 ret = android_fork_execvp_ext(
                     ARRAY_SIZE(e2fsck_argv), const_cast<char**>(e2fsck_argv), &status, true,
-                    LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), NULL, 0);
+                    LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), nullptr, 0);
             }
 
             if (ret < 0) {
@@ -263,13 +263,19 @@
         }
     } 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);
+        const char* f2fs_fsck_forced_argv[] = {F2FS_FSCK_BIN, "-f", blk_device.c_str()};
 
-        ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv),
-                                      const_cast<char **>(f2fs_fsck_argv),
-                                      &status, true, LOG_KLOG | LOG_FILE,
-                                      true, const_cast<char *>(FSCK_LOG_FILE),
-                                      NULL, 0);
+        if (should_force_check(*fs_stat)) {
+            LINFO << "Running " << F2FS_FSCK_BIN << " -f " << realpath(blk_device);
+            ret = android_fork_execvp_ext(
+                ARRAY_SIZE(f2fs_fsck_forced_argv), const_cast<char**>(f2fs_fsck_forced_argv), &status,
+                true, LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), nullptr, 0);
+        } else {
+            LINFO << "Running " << F2FS_FSCK_BIN << " -a " << realpath(blk_device);
+            ret = android_fork_execvp_ext(
+                ARRAY_SIZE(f2fs_fsck_argv), const_cast<char**>(f2fs_fsck_argv), &status, true,
+                LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), nullptr, 0);
+        }
         if (ret < 0) {
             /* No need to check for error in fork, we can't really handle it now */
             LERROR << "Failed trying to run " << F2FS_FSCK_BIN;
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 7df7cfd..22b0585 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -790,15 +790,16 @@
 
 FstabEntry BuildGsiSystemFstabEntry() {
     // .logical_partition_name is required to look up AVB Hashtree descriptors.
-    FstabEntry system = {
-            .blk_device = "system_gsi",
-            .mount_point = "/system",
-            .fs_type = "ext4",
-            .flags = MS_RDONLY,
-            .fs_options = "barrier=1",
-            // could add more keys separated by ':'.
-            .avb_keys = "/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey",
-            .logical_partition_name = "system"};
+    FstabEntry system = {.blk_device = "system_gsi",
+                         .mount_point = "/system",
+                         .fs_type = "ext4",
+                         .flags = MS_RDONLY,
+                         .fs_options = "barrier=1",
+                         // could add more keys separated by ':'.
+                         .avb_keys =
+                                 "/avb/q-gsi.avbpubkey:/avb/q-developer-gsi.avbpubkey:"
+                                 "/avb/r-developer-gsi.avbpubkey:/avb/s-developer-gsi.avbpubkey",
+                         .logical_partition_name = "system"};
     system.fs_mgr_flags.wait = true;
     system.fs_mgr_flags.logical = true;
     system.fs_mgr_flags.first_stage_mount = true;
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 0a6014d..f21d529 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -32,7 +32,6 @@
 #include <unistd.h>
 
 #include <algorithm>
-#include <map>
 #include <memory>
 #include <string>
 #include <vector>
@@ -517,10 +516,166 @@
     return ret;
 }
 
+bool fs_mgr_overlayfs_set_shared_mount(const std::string& mount_point, bool shared_flag) {
+    auto ret = mount(nullptr, mount_point.c_str(), nullptr, shared_flag ? MS_SHARED : MS_PRIVATE,
+                     nullptr);
+    if (ret) {
+        PERROR << "__mount(target=" << mount_point
+               << ",flag=" << (shared_flag ? "MS_SHARED" : "MS_PRIVATE") << ")=" << ret;
+        return false;
+    }
+    return true;
+}
+
+bool fs_mgr_overlayfs_move_mount(const std::string& source, const std::string& target) {
+    auto ret = mount(source.c_str(), target.c_str(), nullptr, MS_MOVE, nullptr);
+    if (ret) {
+        PERROR << "__mount(source=" << source << ",target=" << target << ",flag=MS_MOVE)=" << ret;
+        return false;
+    }
+    return true;
+}
+
+struct mount_info {
+    std::string mount_point;
+    bool shared_flag;
+};
+
+std::vector<mount_info> ReadMountinfoFromFile(const std::string& path) {
+    std::vector<mount_info> info;
+
+    auto file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
+    if (!file) {
+        PERROR << __FUNCTION__ << "(): cannot open file: '" << path << "'";
+        return info;
+    }
+
+    ssize_t len;
+    size_t alloc_len = 0;
+    char* line = nullptr;
+    while ((len = getline(&line, &alloc_len, file.get())) != -1) {
+        /* if the last character is a newline, shorten the string by 1 byte */
+        if (line[len - 1] == '\n') {
+            line[len - 1] = '\0';
+        }
+
+        static constexpr char delim[] = " \t";
+        char* save_ptr;
+        if (!strtok_r(line, delim, &save_ptr)) {
+            LERROR << "Error parsing mount ID";
+            break;
+        }
+        if (!strtok_r(nullptr, delim, &save_ptr)) {
+            LERROR << "Error parsing parent ID";
+            break;
+        }
+        if (!strtok_r(nullptr, delim, &save_ptr)) {
+            LERROR << "Error parsing mount source";
+            break;
+        }
+        if (!strtok_r(nullptr, delim, &save_ptr)) {
+            LERROR << "Error parsing root";
+            break;
+        }
+
+        char* p;
+        if (!(p = strtok_r(nullptr, delim, &save_ptr))) {
+            LERROR << "Error parsing mount_point";
+            break;
+        }
+        mount_info entry = {p, false};
+
+        if (!strtok_r(nullptr, delim, &save_ptr)) {
+            LERROR << "Error parsing mount_flags";
+            break;
+        }
+
+        while ((p = strtok_r(nullptr, delim, &save_ptr))) {
+            if ((p[0] == '-') && (p[1] == '\0')) break;
+            if (android::base::StartsWith(p, "shared:")) entry.shared_flag = true;
+        }
+        if (!p) {
+            LERROR << "Error parsing fields";
+            break;
+        }
+        info.emplace_back(std::move(entry));
+    }
+
+    free(line);
+    if (info.empty()) {
+        LERROR << __FUNCTION__ << "(): failed to load mountinfo from : '" << path << "'";
+    }
+    return info;
+}
+
 bool fs_mgr_overlayfs_mount(const std::string& mount_point) {
     auto options = fs_mgr_get_overlayfs_options(mount_point);
     if (options.empty()) return false;
 
+    auto retval = true;
+    auto save_errno = errno;
+
+    struct move_entry {
+        std::string mount_point;
+        std::string dir;
+        bool shared_flag;
+    };
+    std::vector<move_entry> move;
+    auto parent_private = false;
+    auto parent_made_private = false;
+    auto dev_private = false;
+    auto dev_made_private = false;
+    for (auto& entry : ReadMountinfoFromFile("/proc/self/mountinfo")) {
+        if ((entry.mount_point == mount_point) && !entry.shared_flag) {
+            parent_private = true;
+        }
+        if ((entry.mount_point == "/dev") && !entry.shared_flag) {
+            dev_private = true;
+        }
+
+        if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) {
+            continue;
+        }
+        if (std::find_if(move.begin(), move.end(), [&entry](const auto& it) {
+                return android::base::StartsWith(entry.mount_point, it.mount_point + "/");
+            }) != move.end()) {
+            continue;
+        }
+
+        // use as the bound directory in /dev.
+        auto new_context = fs_mgr_get_context(entry.mount_point);
+        if (!new_context.empty() && setfscreatecon(new_context.c_str())) {
+            PERROR << "setfscreatecon " << new_context;
+        }
+        move_entry new_entry = {std::move(entry.mount_point), "/dev/TemporaryDir-XXXXXX",
+                                entry.shared_flag};
+        const auto target = mkdtemp(new_entry.dir.data());
+        if (!target) {
+            retval = false;
+            save_errno = errno;
+            PERROR << "temporary directory for MS_BIND";
+            setfscreatecon(nullptr);
+            continue;
+        }
+        setfscreatecon(nullptr);
+
+        if (!parent_private && !parent_made_private) {
+            parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false);
+        }
+        if (new_entry.shared_flag) {
+            new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false);
+        }
+        if (!fs_mgr_overlayfs_move_mount(new_entry.mount_point, new_entry.dir)) {
+            retval = false;
+            save_errno = errno;
+            if (new_entry.shared_flag) {
+                fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true);
+            }
+            continue;
+        }
+        move.emplace_back(std::move(new_entry));
+    }
+
     // 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, ",");
@@ -535,12 +690,38 @@
     auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_RELATIME,
                      options.c_str());
     if (ret) {
+        retval = false;
+        save_errno = errno;
         PERROR << report << ret;
-        return false;
     } else {
         LINFO << report << ret;
-        return true;
     }
+
+    // Move submounts back.
+    for (const auto& entry : move) {
+        if (!dev_private && !dev_made_private) {
+            dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false);
+        }
+
+        if (!fs_mgr_overlayfs_move_mount(entry.dir, entry.mount_point)) {
+            retval = false;
+            save_errno = errno;
+        } else if (entry.shared_flag &&
+                   !fs_mgr_overlayfs_set_shared_mount(entry.mount_point, true)) {
+            retval = false;
+            save_errno = errno;
+        }
+        rmdir(entry.dir.c_str());
+    }
+    if (dev_made_private) {
+        fs_mgr_overlayfs_set_shared_mount("/dev", true);
+    }
+    if (parent_made_private) {
+        fs_mgr_overlayfs_set_shared_mount(mount_point, true);
+    }
+
+    errno = save_errno;
+    return retval;
 }
 
 // Mount kScratchMountPoint
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 06c8176..f6e5830 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -583,6 +583,20 @@
                                       POWER_SUPPLY_SYSFS_PATH, name);
                     if (access(path, R_OK) == 0)
                         mHealthdConfig->batteryChargeCounterPath = path;
+                    else if (strcmp(name, "battery") == 0) {
+                        // On Qualcomm chipsets, the value might come from the
+                        // "QPNP PMIC Battery Management System driver", which
+                        // creates sysfs entries separate from the "battery"
+                        // node.
+                        path.clear();
+                        path.appendFormat("%s/bms/charge_counter",
+                            POWER_SUPPLY_SYSFS_PATH);
+                        if (access(path, R_OK) == 0) {
+                            KLOG_INFO(LOG_TAG, "Reading charge_counter from "
+                                "bms instead of the battery driver.");
+                            mHealthdConfig->batteryChargeCounterPath = path;
+                        }
+                    }
                 }
 
                 if (mHealthdConfig->batteryTemperaturePath.isEmpty()) {
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 0e5aa4f..5345caf 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -37,6 +37,7 @@
 #include <sys/socket.h>
 
 #include <cutils/android_get_control_file.h>
+#include <cutils/android_reboot.h>
 #include <cutils/klog.h>
 #include <cutils/misc.h>
 #include <cutils/properties.h>
@@ -155,39 +156,63 @@
 
 static animation::frame default_animation_frames[] = {
     {
-        .disp_time = 750,
+        .disp_time = 500,
+        .min_level = 0,
+        .max_level = 9,
+        .surface = NULL,
+    },
+    {
+        .disp_time = 500,
         .min_level = 0,
         .max_level = 19,
         .surface = NULL,
     },
     {
-        .disp_time = 750,
+        .disp_time = 500,
+        .min_level = 0,
+        .max_level = 29,
+        .surface = NULL,
+    },
+    {
+        .disp_time = 500,
         .min_level = 0,
         .max_level = 39,
         .surface = NULL,
     },
     {
-        .disp_time = 750,
+        .disp_time = 500,
+        .min_level = 0,
+        .max_level = 49,
+        .surface = NULL,
+    },
+    {
+        .disp_time = 500,
         .min_level = 0,
         .max_level = 59,
         .surface = NULL,
     },
     {
-        .disp_time = 750,
+        .disp_time = 500,
+        .min_level = 0,
+        .max_level = 69,
+        .surface = NULL,
+    },
+    {
+        .disp_time = 500,
         .min_level = 0,
         .max_level = 79,
         .surface = NULL,
     },
     {
-        .disp_time = 750,
-        .min_level = 80,
-        .max_level = 95,
+        .disp_time = 500,
+        .min_level = 0,
+        .max_level = 89,
         .surface = NULL,
     },
     {
-        .disp_time = 750,
+        .disp_time = 500,
         .min_level = 0,
-        .max_level = 100,
+        .max_level = 97,
         .surface = NULL,
     },
 };
@@ -515,6 +540,8 @@
 static void handle_power_supply_state(charger* charger, int64_t now) {
     if (!charger->have_battery_state) return;
 
+    healthd_board_mode_charger_battery_update(batt_prop);
+
     if (!charger->charger_connected) {
         request_suspend(false);
         if (charger->next_pwr_check == -1) {
@@ -681,6 +708,11 @@
 
     LOGW("--------------- STARTING CHARGER MODE ---------------\n");
 
+    if (!healthd_board_mode_charger_init()) {
+        LOGE("healthd_mode_charger_init failed restarting\n");
+        android_reboot(ANDROID_RB_RESTART2, 0, 0);
+    }
+
     ret = ev_init(std::bind(&input_callback, charger, std::placeholders::_1, std::placeholders::_2));
     if (!ret) {
         epollfd = ev_get_epollfd();
diff --git a/healthd/images/battery_scale.png b/healthd/images/battery_scale.png
index 2ae8f0f..231f627 100644
--- a/healthd/images/battery_scale.png
+++ b/healthd/images/battery_scale.png
Binary files differ
diff --git a/healthd/include/healthd/healthd.h b/healthd/include/healthd/healthd.h
index a900071..f992a1d 100644
--- a/healthd/include/healthd/healthd.h
+++ b/healthd/include/healthd/healthd.h
@@ -127,4 +127,12 @@
 
 int healthd_board_battery_update(struct android::BatteryProperties *props);
 
+// This API is called to update the battery/charging status by using the user
+// noticeable method other then the animation, such as: LEDs
+void healthd_board_mode_charger_battery_update(struct android::BatteryProperties *batt_prop);
+
+// This API is used to handle some board specific charger mode initialization,
+// such as: checking the charging is enabled or not.
+int healthd_board_mode_charger_init(void);
+
 #endif /* _HEALTHD_H_ */
diff --git a/init/Android.bp b/init/Android.bp
index 6be7290..4893484 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -136,6 +136,7 @@
         "ueventd.cpp",
         "ueventd_parser.cpp",
         "util.cpp",
+        "vendor_init.cpp",
     ],
     whole_static_libs: ["libcap", "com.android.sysprop.apex"],
     header_libs: ["bootimg_headers"],
@@ -150,6 +151,12 @@
             exclude_shared_libs: ["libbinder", "libutils"],
         },
     },
+
+    product_variables: {
+        target_init_vendor_lib: {
+            whole_static_libs: ["%s"],
+        },
+    },
 }
 
 cc_binary {
diff --git a/init/NOTICE b/init/NOTICE
index c5b1efa..383d0f5 100644
--- a/init/NOTICE
+++ b/init/NOTICE
@@ -188,3 +188,29 @@
 
    END OF TERMS AND CONDITIONS
 
+Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
diff --git a/init/property_service.cpp b/init/property_service.cpp
index f2c7462..421ffd8 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -64,6 +64,7 @@
 #include "selinux.h"
 #include "subcontext.h"
 #include "util.h"
+#include "vendor_init.h"
 
 using namespace std::literals;
 
@@ -765,6 +766,10 @@
     for (const auto& persistent_property_record : persistent_properties.properties()) {
         property_set(persistent_property_record.name(), persistent_property_record.value());
     }
+
+    // Load vendor persistent properties
+    vendor_load_persist_properties();
+
     persistent_properties_loaded = true;
     property_set("ro.persistent_properties.ready", "true");
 }
@@ -912,10 +917,15 @@
         }
     }
 
+    // Update with vendor-specific property runtime overrides
+    vendor_load_properties();
+
     property_initialize_ro_product_props();
     property_derive_build_fingerprint();
 
-    update_sys_usb_config();
+    if (android::base::GetBoolProperty("ro.persistent_properties.ready", false)) {
+        update_sys_usb_config();
+    }
 }
 
 static int SelinuxAuditCallback(void* data, security_class_t /*cls*/, char* buf, size_t len) {
diff --git a/init/reboot_utils.cpp b/init/reboot_utils.cpp
index d1a712f..de085cc 100644
--- a/init/reboot_utils.cpp
+++ b/init/reboot_utils.cpp
@@ -21,11 +21,12 @@
 
 #include <string>
 
-#include "android-base/file.h"
-#include "android-base/logging.h"
-#include "android-base/strings.h"
-#include "backtrace/Backtrace.h"
-#include "cutils/android_reboot.h"
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <backtrace/Backtrace.h>
+#include <cutils/android_reboot.h>
 
 #include "capabilities.h"
 
@@ -93,7 +94,14 @@
             break;
 
         case ANDROID_RB_THERMOFF:
-            reboot(RB_POWER_OFF);
+            if (android::base::GetBoolProperty("ro.thermal_warmreset", false)) {
+                LOG(INFO) << "Try to trigger a warm reset for thermal shutdown";
+                static constexpr const char kThermalShutdownTarget[] = "shutdown,thermal";
+                syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+                        LINUX_REBOOT_CMD_RESTART2, kThermalShutdownTarget);
+            } else {
+                reboot(RB_POWER_OFF);
+            }
             break;
     }
     // In normal case, reboot should not return.
diff --git a/init/service.cpp b/init/service.cpp
index ccc37b7..2db548e 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -387,6 +387,7 @@
                     LOG(ERROR) << "updatable process '" << name_ << "' exited 4 times "
                                << (boot_completed ? "in 4 minutes" : "before boot completed");
                     // Notifies update_verifier and apexd
+                    property_set("ro.init.updatable_crashing_process_name", name_);
                     property_set("ro.init.updatable_crashing", "1");
                 }
             }
diff --git a/init/vendor_init.cpp b/init/vendor_init.cpp
new file mode 100644
index 0000000..9848f2e
--- /dev/null
+++ b/init/vendor_init.cpp
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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 "vendor_init.h"
+
+/* init vendor override stubs */
+
+__attribute__ ((weak))
+void vendor_load_properties()
+{
+}
+
+__attribute__ ((weak))
+void vendor_load_persist_properties()
+{
+}
diff --git a/init/vendor_init.h b/init/vendor_init.h
new file mode 100644
index 0000000..5523f92
--- /dev/null
+++ b/init/vendor_init.h
@@ -0,0 +1,34 @@
+/*
+Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+ */
+
+#ifndef __INIT_VENDOR__H__
+#define __INIT_VENDOR__H__
+extern void vendor_load_properties(void);
+extern void vendor_load_persist_properties(void);
+#endif /* __INIT_VENDOR__H__ */
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index a5f4f0e..a1f4319 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -197,7 +197,7 @@
     // the following two files are INTENTIONALLY set-uid, but they
     // are NOT included on user builds.
     { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/procmem" },
-    { 04750, AID_ROOT,      AID_SHELL,     0, "system/xbin/su" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/su" },
 
     // the following files have enhanced capabilities and ARE included
     // in user builds.
diff --git a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
index a16c3fd..a6e7f69 100644
--- a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
+++ b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
@@ -19,6 +19,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <set>
 #include <string>
 #include <vector>
 #include <unordered_map>
@@ -33,6 +34,7 @@
         : inode_(inode), size_(size), count_(count), exporter_(exporter), name_(name) {
         total_refs_ = 0;
     }
+    DmaBuffer() = default;
     ~DmaBuffer() = default;
 
     // Adds one file descriptor reference for the given pid
@@ -54,11 +56,13 @@
     ino_t inode() const { return inode_; }
     uint64_t total_refs() const { return total_refs_; }
     uint64_t count() const { return count_; };
+    const std::set<pid_t>& pids() const { return pids_; }
     const std::string& name() const { return name_; }
     const std::string& exporter() const { return exporter_; }
     void SetName(const std::string& name) { name_ = name; }
     void SetExporter(const std::string& exporter) { exporter_ = exporter; }
     void SetCount(uint64_t count) { count_ = count; }
+    uint64_t Pss() const { return size_ / pids_.size(); }
 
     bool operator==(const DmaBuffer& rhs) {
         return (inode_ == rhs.inode()) && (size_ == rhs.size()) && (name_ == rhs.name()) &&
@@ -70,6 +74,7 @@
     uint64_t size_;
     uint64_t count_;
     uint64_t total_refs_;
+    std::set<pid_t> pids_;
     std::string exporter_;
     std::string name_;
     std::unordered_map<pid_t, int> fdrefs_;
@@ -80,6 +85,7 @@
         auto [it, inserted] = map->insert(std::make_pair(pid, 1));
         if (!inserted)
             it->second++;
+        pids_.insert(pid);
     }
 };
 
diff --git a/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp b/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp
index 0851fb3..48901b1 100644
--- a/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp
+++ b/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp
@@ -16,17 +16,19 @@
 
 #include <dirent.h>
 #include <errno.h>
+#include <getopt.h>
 #include <inttypes.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
-#include <iostream>
 #include <fstream>
+#include <iostream>
+#include <map>
+#include <set>
 #include <sstream>
 #include <string>
 #include <vector>
-#include <map>
-#include <set>
 
 #include <android-base/stringprintf.h>
 #include <dmabufinfo/dmabufinfo.h>
@@ -35,15 +37,16 @@
 
 [[noreturn]] static void usage(int exit_status) {
     fprintf(stderr,
-            "Usage: %s [PID] \n"
-            "\t If PID is supplied, the dmabuf information for this process is shown.\n"
-            "\t Otherwise, shows the information for all processes.\n",
+            "Usage: %s [-ah] [PID] \n"
+            "-a\t show all dma buffers (ion) in big table, [buffer x process] grid \n"
+            "-h\t show this help\n"
+            "  \t If PID is supplied, the dmabuf information for that process is shown.\n",
             getprogname());
 
     exit(exit_status);
 }
 
-static std::string GetProcessBaseName(pid_t pid) {
+static std::string GetProcessComm(const pid_t pid) {
     std::string pid_path = android::base::StringPrintf("/proc/%d/comm", pid);
     std::ifstream in{pid_path};
     if (!in) return std::string("N/A");
@@ -53,133 +56,211 @@
     return line;
 }
 
-static void AddPidsToSet(const std::unordered_map<pid_t, int>& map, std::set<pid_t>* set)
-{
-    for (auto it = map.begin(); it != map.end(); ++it)
-        set->insert(it->first);
-}
-
-static void PrintDmaBufInfo(const std::vector<DmaBuffer>& bufs) {
-    std::set<pid_t> pid_set;
-    std::map<pid_t, int> pid_column;
-
+static void PrintDmaBufTable(const std::vector<DmaBuffer>& bufs) {
     if (bufs.empty()) {
-        std::cout << "dmabuf info not found ¯\\_(ツ)_/¯" << std::endl;
+        printf("dmabuf info not found ¯\\_(ツ)_/¯\n");
         return;
     }
 
     // Find all unique pids in the input vector, create a set
-    for (int i = 0; i < bufs.size(); i++) {
-        AddPidsToSet(bufs[i].fdrefs(), &pid_set);
-        AddPidsToSet(bufs[i].maprefs(), &pid_set);
+    std::set<pid_t> pid_set;
+    for (auto& buf : bufs) {
+        pid_set.insert(buf.pids().begin(), buf.pids().end());
     }
 
-    int pid_count = 0;
+    // Format the header string spaced and separated with '|'
+    printf("    Dmabuf Inode |            Size |      Ref Counts |");
+    for (auto pid : pid_set) {
+        printf("%16s:%-5d |", GetProcessComm(pid).c_str(), pid);
+    }
+    printf("\n");
 
-    std::cout << "\t\t\t\t\t\t";
+    // holds per-process dmabuf size in kB
+    std::map<pid_t, uint64_t> per_pid_size = {};
+    uint64_t dmabuf_total_size = 0;
 
-    // Create a map to convert each unique pid into a column number
-    for (auto it = pid_set.begin(); it != pid_set.end(); ++it, ++pid_count) {
-        pid_column.insert(std::make_pair(*it, pid_count));
-        std::cout << ::android::base::StringPrintf("[pid: % 4d]\t", *it);
+    // Iterate through all dmabufs and collect per-process sizes, refs
+    for (auto& buf : bufs) {
+        printf("%16ju |%13" PRIu64 " kB |%16" PRIu64 " |", static_cast<uintmax_t>(buf.inode()),
+               buf.size() / 1024, buf.total_refs());
+        // Iterate through each process to find out per-process references for each buffer,
+        // gather total size used by each process etc.
+        for (pid_t pid : pid_set) {
+            int pid_refs = 0;
+            if (buf.fdrefs().count(pid) == 1) {
+                // Get the total number of ref counts the process is holding
+                // on this buffer. We don't differentiate between mmap or fd.
+                pid_refs += buf.fdrefs().at(pid);
+                if (buf.maprefs().count(pid) == 1) {
+                    pid_refs += buf.maprefs().at(pid);
+                }
+            }
+
+            if (pid_refs) {
+                // Add up the per-pid total size. Note that if a buffer is mapped
+                // in 2 different processes, the size will be shown as mapped or opened
+                // in both processes. This is intended for visibility.
+                //
+                // If one wants to get the total *unique* dma buffers, they can simply
+                // sum the size of all dma bufs shown by the tool
+                per_pid_size[pid] += buf.size() / 1024;
+                printf("%17d refs |", pid_refs);
+            } else {
+                printf("%22s |", "--");
+            }
+        }
+        dmabuf_total_size += buf.size() / 1024;
+        printf("\n");
     }
 
-    std::cout << std::endl << "\t\t\t\t\t\t";
+    printf("------------------------------------\n");
+    printf("%-16s  %13" PRIu64 " kB |%16s |", "TOTALS", dmabuf_total_size, "n/a");
+    for (auto pid : pid_set) {
+        printf("%19" PRIu64 " kB |", per_pid_size[pid]);
+    }
+    printf("\n");
 
-    for (auto it = pid_set.begin(); it != pid_set.end(); ++it) {
-        std::cout << ::android::base::StringPrintf("%16s",
-            GetProcessBaseName(*it).c_str());
+    return;
+}
+
+static void PrintDmaBufPerProcess(const std::vector<DmaBuffer>& bufs) {
+    if (bufs.empty()) {
+        printf("dmabuf info not found ¯\\_(ツ)_/¯\n");
+        return;
     }
 
-    std::cout << std::endl << "\tinode\t\tsize\t\tcount\t";
-    for (int i = 0; i < pid_count; i++) {
-        std::cout << "fd\tmap\t";
+    // Create a reverse map from pid to dmabufs
+    std::unordered_map<pid_t, std::set<ino_t>> pid_to_inodes = {};
+    uint64_t total_size = 0;  // Total size of dmabufs in the system
+    uint64_t kernel_rss = 0;  // Total size of dmabufs NOT mapped or opened by a process
+    for (auto& buf : bufs) {
+        for (auto pid : buf.pids()) {
+            pid_to_inodes[pid].insert(buf.inode());
+        }
+        total_size += buf.size();
+        if (buf.fdrefs().empty() && buf.maprefs().empty()) {
+            kernel_rss += buf.size();
+        }
     }
-    std::cout << std::endl;
+    // Create an inode to dmabuf map. We know inodes are unique..
+    std::unordered_map<ino_t, DmaBuffer> inode_to_dmabuf;
+    for (auto buf : bufs) {
+        inode_to_dmabuf[buf.inode()] = buf;
+    }
 
-    auto fds = std::make_unique<int[]>(pid_count);
-    auto maps = std::make_unique<int[]>(pid_count);
-    auto pss = std::make_unique<long[]>(pid_count);
+    uint64_t total_rss = 0, total_pss = 0;
+    for (auto& [pid, inodes] : pid_to_inodes) {
+        uint64_t pss = 0;
+        uint64_t rss = 0;
 
-    memset(pss.get(), 0, sizeof(long) * pid_count);
+        printf("%16s:%-5d\n", GetProcessComm(pid).c_str(), pid);
+        printf("%22s %16s %16s %16s %16s\n", "Name", "Rss", "Pss", "nr_procs", "Inode");
+        for (auto& inode : inodes) {
+            DmaBuffer& buf = inode_to_dmabuf[inode];
+            printf("%22s %13" PRIu64 " kB %13" PRIu64 " kB %16zu %16" PRIuMAX "\n",
+                   buf.name().empty() ? "<unknown>" : buf.name().c_str(), buf.size() / 1024,
+                   buf.Pss() / 1024, buf.pids().size(), static_cast<uintmax_t>(buf.inode()));
+            rss += buf.size();
+            pss += buf.Pss();
+        }
+        printf("%22s %13" PRIu64 " kB %13" PRIu64 " kB %16s\n", "PROCESS TOTAL", rss / 1024,
+               pss / 1024, "");
+        printf("----------------------\n");
+        total_rss += rss;
+        total_pss += pss;
+    }
+    printf("dmabuf total: %" PRIu64 " kB kernel_rss: %" PRIu64 " kB userspace_rss: %" PRIu64
+           " kB userspace_pss: %" PRIu64 " kB\n ",
+           total_size / 1024, kernel_rss / 1024, total_rss / 1024, total_pss / 1024);
+}
 
-    for (auto buf = bufs.begin(); buf != bufs.end(); ++buf) {
+static bool ReadDmaBufs(std::vector<DmaBuffer>* bufs) {
+    bufs->clear();
 
-        std::cout << ::android::base::StringPrintf("%16lu\t%10" PRIu64 "\t%" PRIu64 "\t",
-            buf->inode(),buf->size(), buf->count());
+    if (!ReadDmaBufInfo(bufs)) {
+        fprintf(stderr, "debugfs entry for dmabuf not available, skipping\n");
+        return false;
+    }
 
-        memset(fds.get(), 0, sizeof(int) * pid_count);
-        memset(maps.get(), 0, sizeof(int) * pid_count);
+    std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir);
+    if (!dir) {
+        fprintf(stderr, "Failed to open /proc directory\n");
+        bufs->clear();
+        return false;
+    }
 
-        for (auto it = buf->fdrefs().begin(); it != buf->fdrefs().end(); ++it) {
-            fds[pid_column[it->first]] = it->second;
-            pss[pid_column[it->first]] += buf->size() * it->second / buf->count();
+    struct dirent* dent;
+    while ((dent = readdir(dir.get()))) {
+        if (dent->d_type != DT_DIR) continue;
+
+        int pid = atoi(dent->d_name);
+        if (pid == 0) {
+            continue;
         }
 
-        for (auto it = buf->maprefs().begin(); it != buf->maprefs().end(); ++it) {
-            maps[pid_column[it->first]] = it->second;
-            pss[pid_column[it->first]] += buf->size() * it->second / buf->count();
+        if (!AppendDmaBufInfo(pid, bufs)) {
+            fprintf(stderr, "Unable to read dmabuf info for pid %d\n", pid);
+            bufs->clear();
+            return false;
         }
+    }
 
-        for (int i = 0; i < pid_count; i++) {
-            std::cout << ::android::base::StringPrintf("%d\t%d\t", fds[i], maps[i]);
-        }
-        std::cout << std::endl;
-    }
-    std::cout << "-----------------------------------------" << std::endl;
-    std::cout << "PSS                                      ";
-    for (int i = 0; i < pid_count; i++) {
-        std::cout << ::android::base::StringPrintf("%15ldK", pss[i] / 1024);
-    }
-    std::cout << std::endl;
+    return true;
 }
 
 int main(int argc, char* argv[]) {
-    pid_t pid = -1;
-    std::vector<DmaBuffer> bufs;
-    bool show_all = true;
+    struct option longopts[] = {{"all", no_argument, nullptr, 'a'},
+                                {"help", no_argument, nullptr, 'h'},
+                                {0, 0, nullptr, 0}};
 
-    if (argc > 1) {
-        if (sscanf(argv[1], "%d", &pid) == 1) {
-            show_all = false;
+    int opt;
+    bool show_table = false;
+    while ((opt = getopt_long(argc, argv, "ah", longopts, nullptr)) != -1) {
+        switch (opt) {
+            case 'a':
+                show_table = true;
+                break;
+            case 'h':
+                usage(EXIT_SUCCESS);
+            default:
+                usage(EXIT_FAILURE);
         }
-        else {
+    }
+
+    pid_t pid = -1;
+    if (optind < argc) {
+        if (show_table) {
+            fprintf(stderr, "Invalid arguments: -a does not need arguments\n");
+            usage(EXIT_FAILURE);
+        }
+        if (optind != (argc - 1)) {
+            fprintf(stderr, "Invalid arguments - only one [PID] argument is allowed\n");
+            usage(EXIT_FAILURE);
+        }
+        pid = atoi(argv[optind]);
+        if (pid == 0) {
+            fprintf(stderr, "Invalid process id %s\n", argv[optind]);
             usage(EXIT_FAILURE);
         }
     }
 
-    if (show_all) {
-        if (!ReadDmaBufInfo(&bufs)) {
-            std::cerr << "debugfs entry for dmabuf not available, skipping" << std::endl;
-            bufs.clear();
-        }
-        std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir);
-        if (!dir) {
-            std::cerr << "Failed to open /proc directory" << std::endl;
+    std::vector<DmaBuffer> bufs;
+    if (pid != -1) {
+        if (!ReadDmaBufInfo(pid, &bufs)) {
+            fprintf(stderr, "Unable to read dmabuf info for %d\n", pid);
             exit(EXIT_FAILURE);
         }
-        struct dirent* dent;
-        while ((dent = readdir(dir.get()))) {
-            if (dent->d_type != DT_DIR) continue;
-
-            int matched = sscanf(dent->d_name, "%d", &pid);
-            if (matched != 1) {
-                continue;
-            }
-
-            if (!AppendDmaBufInfo(pid, &bufs)) {
-                std::cerr << "Unable to read dmabuf info for pid " << pid << std::endl;
-                exit(EXIT_FAILURE);
-            }
-        }
     } else {
-        if (!ReadDmaBufInfo(pid, &bufs)) {
-            std::cerr << "Unable to read dmabuf info" << std::endl;
-            exit(EXIT_FAILURE);
-        }
+        if (!ReadDmaBufs(&bufs)) exit(EXIT_FAILURE);
     }
-    PrintDmaBufInfo(bufs);
+
+    // Show the old dmabuf table, inode x process
+    if (show_table) {
+        PrintDmaBufTable(bufs);
+        return 0;
+    }
+
+    PrintDmaBufPerProcess(bufs);
+
     return 0;
 }
-
-
diff --git a/libmeminfo/pageacct.cpp b/libmeminfo/pageacct.cpp
index 0a26c08..cb17af8 100644
--- a/libmeminfo/pageacct.cpp
+++ b/libmeminfo/pageacct.cpp
@@ -81,7 +81,8 @@
         if (!InitPageAcct()) return false;
     }
 
-    if (pread64(kpageflags_fd_, flags, sizeof(uint64_t), pfn * sizeof(uint64_t)) < 0) {
+    if (pread64(kpageflags_fd_, flags, sizeof(uint64_t), pfn * sizeof(uint64_t)) !=
+        sizeof(uint64_t)) {
         PLOG(ERROR) << "Failed to read page flags for page " << pfn;
         return false;
     }
@@ -95,7 +96,8 @@
         if (!InitPageAcct()) return false;
     }
 
-    if (pread64(kpagecount_fd_, mapcount, sizeof(uint64_t), pfn * sizeof(uint64_t)) < 0) {
+    if (pread64(kpagecount_fd_, mapcount, sizeof(uint64_t), pfn * sizeof(uint64_t)) !=
+        sizeof(uint64_t)) {
         PLOG(ERROR) << "Failed to read map count for page " << pfn;
         return false;
     }
@@ -130,7 +132,7 @@
     off64_t offset = pfn_to_idle_bitmap_offset(pfn);
     uint64_t idle_bits;
 
-    if (pread64(pageidle_fd_, &idle_bits, sizeof(uint64_t), offset) < 0) {
+    if (pread64(pageidle_fd_, &idle_bits, sizeof(uint64_t), offset) != sizeof(uint64_t)) {
         PLOG(ERROR) << "Failed to read page idle bitmap for page " << pfn;
         return -errno;
     }
diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp
index 934d65c..a8b43c1 100644
--- a/libmeminfo/procmeminfo.cpp
+++ b/libmeminfo/procmeminfo.cpp
@@ -27,6 +27,7 @@
 #include <memory>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
@@ -278,68 +279,89 @@
 
 bool ProcMemInfo::ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_pageidle) {
     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_;
+    if (get_wss && use_pageidle && !pinfo.InitPageAcct(true)) {
+        LOG(ERROR) << "Failed to init idle page accounting";
         return false;
     }
 
-    if (get_wss && use_pageidle) {
-        if (!pinfo.InitPageAcct(true)) {
-            LOG(ERROR) << "Failed to init idle page accounting";
-            return false;
-        }
-    }
+    uint64_t pagesz = getpagesize();
+    size_t num_pages = (vma.end - vma.start) / pagesz;
+    size_t first_page = vma.start / pagesz;
 
-    std::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) {
+    std::vector<uint64_t> page_cache;
+    size_t cur_page_cache_index = 0;
+    size_t num_in_page_cache = 0;
+    size_t num_leftover_pages = num_pages;
+    for (size_t cur_page = first_page; cur_page < first_page + num_pages; ++cur_page) {
         if (!get_wss) {
             vma.usage.vss += pagesz;
         }
-        uint64_t p = pg_frames[i];
-        if (!PAGE_PRESENT(p) && !PAGE_SWAPPED(p)) continue;
 
-        if (PAGE_SWAPPED(p)) {
+        // Cache page map data.
+        if (cur_page_cache_index == num_in_page_cache) {
+            static constexpr size_t kMaxPages = 2048;
+            num_leftover_pages -= num_in_page_cache;
+            if (num_leftover_pages > kMaxPages) {
+                num_in_page_cache = kMaxPages;
+            } else {
+                num_in_page_cache = num_leftover_pages;
+            }
+            page_cache.resize(num_in_page_cache);
+            size_t total_bytes = page_cache.size() * sizeof(uint64_t);
+            ssize_t bytes = pread64(pagemap_fd, page_cache.data(), total_bytes,
+                                    cur_page * sizeof(uint64_t));
+            if (bytes != total_bytes) {
+                if (bytes == -1) {
+                    PLOG(ERROR) << "Failed to read page data at offset 0x" << std::hex
+                                << cur_page * sizeof(uint64_t);
+                } else {
+                    LOG(ERROR) << "Failed to read page data at offset 0x" << std::hex
+                               << cur_page * sizeof(uint64_t) << std::dec << " read bytes " << bytes
+                               << " expected bytes " << total_bytes;
+                }
+                return false;
+            }
+            cur_page_cache_index = 0;
+        }
+
+        uint64_t page_info = page_cache[cur_page_cache_index++];
+        if (!PAGE_PRESENT(page_info) && !PAGE_SWAPPED(page_info)) continue;
+
+        if (PAGE_SWAPPED(page_info)) {
             vma.usage.swap += pagesz;
-            swap_offsets_.emplace_back(PAGE_SWAP_OFFSET(p));
+            swap_offsets_.emplace_back(PAGE_SWAP_OFFSET(page_info));
             continue;
         }
 
-        uint64_t page_frame = PAGE_PFN(p);
-        if (!pinfo.PageFlags(page_frame, &pg_flags[i])) {
+        uint64_t page_frame = PAGE_PFN(page_info);
+        uint64_t cur_page_flags;
+        if (!pinfo.PageFlags(page_frame, &cur_page_flags)) {
             LOG(ERROR) << "Failed to get page flags for " << page_frame << " in process " << pid_;
             swap_offsets_.clear();
             return false;
         }
 
         // skip unwanted pages from the count
-        if ((pg_flags[i] & pgflags_mask_) != pgflags_) continue;
+        if ((cur_page_flags & pgflags_mask_) != pgflags_) continue;
 
-        if (!pinfo.PageMapCount(page_frame, &pg_counts[i])) {
+        uint64_t cur_page_counts;
+        if (!pinfo.PageMapCount(page_frame, &cur_page_counts)) {
             LOG(ERROR) << "Failed to get page count for " << page_frame << " in process " << pid_;
             swap_offsets_.clear();
             return false;
         }
 
         // Page was unmapped between the presence check at the beginning of the loop and here.
-        if (pg_counts[i] == 0) {
-            pg_frames[i] = 0;
-            pg_flags[i] = 0;
+        if (cur_page_counts == 0) {
             continue;
         }
 
-        bool is_dirty = !!(pg_flags[i] & (1 << KPF_DIRTY));
-        bool is_private = (pg_counts[i] == 1);
+        bool is_dirty = !!(cur_page_flags & (1 << KPF_DIRTY));
+        bool is_private = (cur_page_counts == 1);
         // Working set
         if (get_wss) {
             bool is_referenced = use_pageidle ? (pinfo.IsPageIdle(page_frame) == 1)
-                                              : !!(pg_flags[i] & (1 << KPF_REFERENCED));
+                                              : !!(cur_page_flags & (1 << KPF_REFERENCED));
             if (!is_referenced) {
                 continue;
             }
@@ -351,7 +373,7 @@
 
         vma.usage.rss += pagesz;
         vma.usage.uss += is_private ? pagesz : 0;
-        vma.usage.pss += pagesz / pg_counts[i];
+        vma.usage.pss += pagesz / cur_page_counts;
         if (is_private) {
             vma.usage.private_dirty += is_dirty ? pagesz : 0;
             vma.usage.private_clean += is_dirty ? 0 : pagesz;
diff --git a/libmeminfo/tools/procrank.cpp b/libmeminfo/tools/procrank.cpp
index cb3757d..1e44ff9 100644
--- a/libmeminfo/tools/procrank.cpp
+++ b/libmeminfo/tools/procrank.cpp
@@ -348,7 +348,7 @@
     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;
+        return reverse_sort ? stats_a.rss < stats_b.rss : stats_a.rss > stats_b.rss;
     };
 
     auto vss_sort = [](ProcessRecord& a, ProcessRecord& b) {
diff --git a/libmeminfo/vts/AndroidTest.xml b/libmeminfo/vts/AndroidTest.xml
index 530d16e..9614025 100644
--- a/libmeminfo/vts/AndroidTest.xml
+++ b/libmeminfo/vts/AndroidTest.xml
@@ -24,6 +24,7 @@
         <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_meminfo_test/vts_meminfo_test" />
         <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_meminfo_test/vts_meminfo_test" />
         <option name="binary-test-type" value="gtest"/>
+        <option name="precondition-first-api-level" value="29" />
         <option name="test-timeout" value="10m"/>
     </test>
 </configuration>
diff --git a/libsystem/include/system/camera.h b/libsystem/include/system/camera.h
index 2ca90c3..990edcf 100644
--- a/libsystem/include/system/camera.h
+++ b/libsystem/include/system/camera.h
@@ -88,9 +88,20 @@
     // Notify on autofocus start and stop. This is useful in continuous
     // autofocus - FOCUS_MODE_CONTINUOUS_VIDEO and FOCUS_MODE_CONTINUOUS_PICTURE.
     CAMERA_MSG_FOCUS_MOVE = 0x0800,       // notifyCallback
+    CAMERA_MSG_VENDOR_START = 0x1000,
+    CAMERA_MSG_STATS_DATA = CAMERA_MSG_VENDOR_START,
+    CAMERA_MSG_META_DATA = 0x2000,
+    CAMERA_MSG_VENDOR_END = 0x8000,
     CAMERA_MSG_ALL_MSGS = 0xFFFF
 };
 
+/** meta data type in CameraMetaDataCallback */
+enum {
+    CAMERA_META_DATA_ASD = 0x001,    //ASD data
+    CAMERA_META_DATA_FD = 0x002,     //FD/FP data
+    CAMERA_META_DATA_HDR = 0x003,    //Auto HDR data
+};
+
 /** cmdType in sendCommand functions */
 enum {
     CAMERA_CMD_START_SMOOTH_ZOOM = 1,
@@ -189,7 +200,25 @@
      * IMPLEMENTATION_DEFINED, then HALv3 devices will use gralloc usage flags
      * of SW_READ_OFTEN.
      */
-    CAMERA_CMD_SET_VIDEO_FORMAT = 11
+    CAMERA_CMD_SET_VIDEO_FORMAT = 11,
+
+    CAMERA_CMD_VENDOR_START = 20,
+    /**
+     * Commands to enable/disable preview histogram
+     *
+     * Based on user's input to enable/disable histogram from the camera
+     * UI, send the appropriate command to the HAL to turn on/off the histogram
+     * stats and start sending the data to the application.
+     */
+    CAMERA_CMD_HISTOGRAM_ON = CAMERA_CMD_VENDOR_START,
+    CAMERA_CMD_HISTOGRAM_OFF = CAMERA_CMD_VENDOR_START + 1,
+    CAMERA_CMD_HISTOGRAM_SEND_DATA  = CAMERA_CMD_VENDOR_START + 2,
+    CAMERA_CMD_LONGSHOT_ON = CAMERA_CMD_VENDOR_START + 3,
+    CAMERA_CMD_LONGSHOT_OFF = CAMERA_CMD_VENDOR_START + 4,
+    CAMERA_CMD_STOP_LONGSHOT = CAMERA_CMD_VENDOR_START + 5,
+    CAMERA_CMD_METADATA_ON = CAMERA_CMD_VENDOR_START + 6,
+    CAMERA_CMD_METADATA_OFF = CAMERA_CMD_VENDOR_START + 7,
+    CAMERA_CMD_VENDOR_END = 200,
 };
 
 /** camera fatal errors */
@@ -284,10 +313,32 @@
      * -2000, -2000 if this is not supported.
      */
     int32_t mouth[2];
+    int32_t smile_degree;
+    int32_t smile_score;
+    int32_t blink_detected;
+    int32_t face_recognised;
+    int32_t gaze_angle;
+    int32_t updown_dir;
+    int32_t leftright_dir;
+    int32_t roll_dir;
+    int32_t left_right_gaze;
+    int32_t top_bottom_gaze;
+    int32_t leye_blink;
+    int32_t reye_blink;
 
 } camera_face_t;
 
 /**
+ * The information of a data type received in a camera frame.
+ */
+typedef enum {
+    /** Data buffer */
+    CAMERA_FRAME_DATA_BUF = 0x000,
+    /** File descriptor */
+    CAMERA_FRAME_DATA_FD = 0x100
+} camera_frame_data_type_t;
+
+/**
  * The metadata of the frame data.
  */
 typedef struct camera_frame_metadata {
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index c2ee061..7c5a466 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -79,6 +79,7 @@
 #define MEMCG_MEMORYSW_USAGE "/dev/memcg/memory.memsw.usage_in_bytes"
 #define ZONEINFO_PATH "/proc/zoneinfo"
 #define MEMINFO_PATH "/proc/meminfo"
+#define PROC_STATUS_TGID_FIELD "Tgid:"
 #define LINE_MAX 128
 
 /* Android Logger event logtags (see event.logtags) */
@@ -551,6 +552,49 @@
            (to->tv_nsec - from->tv_nsec) / (long)NS_PER_MS;
 }
 
+static int proc_get_tgid(int pid) {
+    char path[PATH_MAX];
+    char buf[PAGE_SIZE];
+    int fd;
+    ssize_t size;
+    char *pos;
+    int64_t tgid = -1;
+
+    snprintf(path, PATH_MAX, "/proc/%d/status", pid);
+    fd = open(path, O_RDONLY | O_CLOEXEC);
+    if (fd < 0) {
+        return -1;
+    }
+
+    size = read_all(fd, buf, sizeof(buf) - 1);
+    if (size < 0) {
+        goto out;
+    }
+    buf[size] = 0;
+
+    pos = buf;
+    while (true) {
+        pos = strstr(pos, PROC_STATUS_TGID_FIELD);
+        /* Stop if TGID tag not found or found at the line beginning */
+        if (pos == NULL || pos == buf || pos[-1] == '\n') {
+            break;
+        }
+        pos++;
+    }
+
+    if (pos == NULL) {
+        goto out;
+    }
+
+    pos += strlen(PROC_STATUS_TGID_FIELD);
+    while (*pos == ' ') pos++;
+    parse_int64(pos, &tgid);
+
+out:
+    close(fd);
+    return (int)tgid;
+}
+
 static void cmd_procprio(LMKD_CTRL_PACKET packet) {
     struct proc *procp;
     char path[80];
@@ -559,6 +603,7 @@
     struct lmk_procprio params;
     bool is_system_server;
     struct passwd *pwdrec;
+    int tgid;
 
     lmkd_pack_get_procprio(packet, &params);
 
@@ -568,6 +613,14 @@
         return;
     }
 
+    /* Check if registered process is a thread group leader */
+    tgid = proc_get_tgid(params.pid);
+    if (tgid >= 0 && tgid != params.pid) {
+        ALOGE("Attempt to register a task that is not a thread group leader (tid %d, tgid %d)",
+            params.pid, tgid);
+        return;
+    }
+
     /* gid containing AID_READPROC required */
     /* CAP_SYS_RESOURCE required */
     /* CAP_DAC_OVERRIDE required */
@@ -1332,6 +1385,7 @@
 static int kill_one_process(struct proc* procp, int min_oom_score) {
     int pid = procp->pid;
     uid_t uid = procp->uid;
+    int tgid;
     char *taskname;
     int tasksize;
     int r;
@@ -1345,6 +1399,12 @@
     (void)(min_oom_score);
 #endif
 
+    tgid = proc_get_tgid(pid);
+    if (tgid >= 0 && tgid != pid) {
+        ALOGE("Possible pid reuse detected (pid %d, tgid %d)!", pid, tgid);
+        goto out;
+    }
+
     taskname = proc_get_name(pid);
     if (!taskname) {
         goto out;
diff --git a/mkbootimg/mkbootimg.py b/mkbootimg/mkbootimg.py
index 92b11a5..f0c958b 100644
--- a/mkbootimg/mkbootimg.py
+++ b/mkbootimg/mkbootimg.py
@@ -79,7 +79,7 @@
         args.base + args.second_offset,                 # physical load addr
         args.base + args.tags_offset,                   # physical addr for kernel tags
         args.pagesize,                                  # flash page size we assume
-        args.header_version,                            # version of bootimage header
+        max(args.header_version, filesize(args.dt)),    # version of bootimage header or dt size in bytes
         (args.os_version << 11) | args.os_patch_level)) # os version and patch level
     args.output.write(pack('16s', args.board.encode())) # asciiz product name
     args.output.write(pack('512s', args.cmdline[:512].encode()))
@@ -88,6 +88,7 @@
     update_sha(sha, args.kernel)
     update_sha(sha, args.ramdisk)
     update_sha(sha, args.second)
+    update_sha(sha, args.dt)
 
     if args.header_version > 0:
         update_sha(sha, args.recovery_dtbo)
@@ -203,15 +204,22 @@
     parser.add_argument('--id', help='print the image ID on standard output',
                         action='store_true')
     parser.add_argument('--header_version', help='boot image header version', type=parse_int, default=0)
+    parser.add_argument('--dt', help='path to the device tree image', type=FileType('rb'))
     parser.add_argument('-o', '--output', help='output file name', type=FileType('wb'),
                         required=True)
-    return parser.parse_args()
+
+    args = parser.parse_args()
+    if args.header_version > 0 and args.dt != None:
+        raise ValueError('header_version and dt cannot be set at the same time')
+
+    return args
 
 
 def write_data(args):
     write_padded_file(args.output, args.kernel, args.pagesize)
     write_padded_file(args.output, args.ramdisk, args.pagesize)
     write_padded_file(args.output, args.second, args.pagesize)
+    write_padded_file(args.output, args.dt, args.pagesize)
 
     if args.header_version > 0:
         write_padded_file(args.output, args.recovery_dtbo, args.pagesize)
diff --git a/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp b/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
index f484550..6846a69 100644
--- a/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
+++ b/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
@@ -375,9 +375,11 @@
       {"audio_hal.period_size", "u:object_r:default_prop:s0"},
       {"bluetooth.enable_timeout_ms", "u:object_r:bluetooth_prop:s0"},
       {"dalvik.vm.appimageformat", "u:object_r:dalvik_prop:s0"},
+      {"dalvik.vm.boot-dex2oat-cpu-set", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.boot-dex2oat-threads", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.dex2oat-Xms", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.dex2oat-Xmx", "u:object_r:dalvik_prop:s0"},
+      {"dalvik.vm.dex2oat-cpu-set", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.dex2oat-threads", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.dexopt.secondary", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.heapgrowthlimit", "u:object_r:dalvik_prop:s0"},
@@ -388,6 +390,7 @@
       {"dalvik.vm.heaptargetutilization", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.image-dex2oat-Xms", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.image-dex2oat-Xmx", "u:object_r:dalvik_prop:s0"},
+      {"dalvik.vm.image-dex2oat-cpu-set", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.image-dex2oat-threads", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.isa.arm.features", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.isa.arm.variant", "u:object_r:dalvik_prop:s0"},
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 7ff1588..24b3999 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -89,7 +89,7 @@
 
 EXPORT_GLOBAL_GCOV_OPTIONS :=
 ifeq ($(NATIVE_COVERAGE),true)
-  EXPORT_GLOBAL_GCOV_OPTIONS := export GCOV_PREFIX /data/misc/gcov
+  EXPORT_GLOBAL_GCOV_OPTIONS := export GCOV_PREFIX /data/misc/trace
 endif
 
 # Put it here instead of in init.rc module definition,
diff --git a/rootdir/avb/Android.mk b/rootdir/avb/Android.mk
index 5dc019c..f96ffdd 100644
--- a/rootdir/avb/Android.mk
+++ b/rootdir/avb/Android.mk
@@ -16,6 +16,21 @@
 include $(BUILD_PREBUILT)
 
 #######################################
+# q-developer-gsi.avbpubkey
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := q-developer-gsi.avbpubkey
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
+else
+LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
+endif
+
+include $(BUILD_PREBUILT)
+
+#######################################
 # r-gsi.avbpubkey
 include $(CLEAR_VARS)
 
@@ -31,6 +46,21 @@
 include $(BUILD_PREBUILT)
 
 #######################################
+# r-developer-gsi.avbpubkey
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := r-developer-gsi.avbpubkey
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
+else
+LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
+endif
+
+include $(BUILD_PREBUILT)
+
+#######################################
 # s-gsi.avbpubkey
 include $(CLEAR_VARS)
 
@@ -44,3 +74,18 @@
 endif
 
 include $(BUILD_PREBUILT)
+
+#######################################
+# s-developer-gsi.avbpubkey
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := s-developer-gsi.avbpubkey
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
+else
+LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
+endif
+
+include $(BUILD_PREBUILT)
diff --git a/rootdir/avb/q-developer-gsi.avbpubkey b/rootdir/avb/q-developer-gsi.avbpubkey
new file mode 100644
index 0000000..0ace69d
--- /dev/null
+++ b/rootdir/avb/q-developer-gsi.avbpubkey
Binary files differ
diff --git a/rootdir/avb/r-developer-gsi.avbpubkey b/rootdir/avb/r-developer-gsi.avbpubkey
new file mode 100644
index 0000000..aac39cc
--- /dev/null
+++ b/rootdir/avb/r-developer-gsi.avbpubkey
Binary files differ
diff --git a/rootdir/avb/s-developer-gsi.avbpubkey b/rootdir/avb/s-developer-gsi.avbpubkey
new file mode 100644
index 0000000..f0a6c11
--- /dev/null
+++ b/rootdir/avb/s-developer-gsi.avbpubkey
Binary files differ
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 84b308d..c95f60f 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -143,6 +143,7 @@
 
 # TODO(b/122876336): Remove libpac.so once it's migrated to Webview
 namespace.default.link.runtime.shared_libs += libpac.so
+namespace.default.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
 
 # When libnetd_resolv.so can't be found in the default namespace, search for it
 # in the resolv namespace. Don't allow any other libraries from the resolv namespace
@@ -363,7 +364,7 @@
 # The "vndk" namespace links to "default" namespace for LLNDK libs and links to
 # "sphal" namespace for vendor libs.  The ordering matters.  The "default"
 # namespace has higher priority than the "sphal" namespace.
-namespace.vndk.links = default,sphal
+namespace.vndk.links = default,sphal,runtime
 
 # When these NDK libs are required inside this namespace, then it is redirected
 # to the default namespace. This is possible since their ABI is stable across
@@ -371,6 +372,8 @@
 namespace.vndk.link.default.shared_libs  = %LLNDK_LIBRARIES%
 namespace.vndk.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
 
+namespace.vndk.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES%
+
 # Allow VNDK-SP extensions to use vendor libraries
 namespace.vndk.link.sphal.allow_all_shared_libs = true
 
@@ -423,8 +426,10 @@
 namespace.default.asan.permitted.paths += /data/asan/vendor
 namespace.default.asan.permitted.paths +=           /vendor
 
-namespace.default.links = system,vndk%VNDK_IN_SYSTEM_NS%
-namespace.default.link.system.shared_libs = %LLNDK_LIBRARIES%
+namespace.default.links = system,vndk%VNDK_IN_SYSTEM_NS%,runtime
+namespace.default.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES%
+namespace.default.link.system.shared_libs  = %LLNDK_LIBRARIES%
+namespace.default.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
 namespace.default.link.vndk_in_system.shared_libs = %VNDK_USING_CORE_VARIANT_LIBRARIES%
 namespace.default.link.vndk.shared_libs  = %VNDK_SAMEPROCESS_LIBRARIES%
 namespace.default.link.vndk.shared_libs += %VNDK_CORE_LIBRARIES%
@@ -477,13 +482,15 @@
 # Android releases.  The links here should be identical to that of the
 # 'vndk_in_system' namespace, except for the link between 'vndk' and
 # 'vndk_in_system'.
-namespace.vndk.links = system,default%VNDK_IN_SYSTEM_NS%
+namespace.vndk.links = system,default%VNDK_IN_SYSTEM_NS%,runtime
 
 namespace.vndk.link.system.shared_libs  = %LLNDK_LIBRARIES%
 namespace.vndk.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
 
 namespace.vndk.link.default.allow_all_shared_libs = true
 
+namespace.vndk.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES%
+
 namespace.vndk.link.vndk_in_system.shared_libs = %VNDK_USING_CORE_VARIANT_LIBRARIES%
 
 ###############################################################################
@@ -515,6 +522,7 @@
 namespace.system.link.runtime.shared_libs += libnativeloader.so
 # Workaround for b/124772622
 namespace.system.link.runtime.shared_libs += libandroidicu.so
+namespace.system.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
 
 ###############################################################################
 # "vndk_in_system" namespace
@@ -553,7 +561,8 @@
 #   1. 'vndk_in_system' needs to be freely linked back to 'vndk'.
 #   2. 'vndk_in_system' does not need to link to 'default', as any library that
 #      requires anything vendor would not be a vndk_in_system library.
-namespace.vndk_in_system.links = vndk,system
+namespace.vndk_in_system.links = vndk,system,runtime
+namespace.vndk_in_system.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES%
 
 namespace.vndk_in_system.link.system.shared_libs  = %LLNDK_LIBRARIES%
 namespace.vndk_in_system.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
@@ -596,6 +605,7 @@
 
 # TODO(b/122876336): Remove libpac.so once it's migrated to Webview
 namespace.default.link.runtime.shared_libs += libpac.so
+namespace.default.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
 
 namespace.default.link.resolv.shared_libs = libnetd_resolv.so
 
@@ -684,3 +694,5 @@
 namespace.default.search.paths  = /system/${LIB}
 namespace.default.search.paths += /%PRODUCT%/${LIB}
 namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
+
+namespace.default.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES%
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 5db7698..5642559 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -417,6 +417,7 @@
 
 # TODO(b/122876336): Remove libpac.so once it's migrated to Webview
 namespace.default.link.runtime.shared_libs += libpac.so
+namespace.default.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
 
 namespace.default.link.resolv.shared_libs = libnetd_resolv.so
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 893998c..e898d4d 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -680,6 +680,12 @@
     # to make it too large, since it may bring userdata loss, if they
     # are not aware of using fsync()/sync() to prepare sudden power-cut.
     write /sys/fs/f2fs/${dev.mnt.blk.data}/cp_interval 200
+    write /sys/fs/f2fs/${dev.mnt.blk.data}/gc_urgent_sleep_time 50
+
+    # limit discard size to 128MB in order to avoid long IO latency
+    # for filesystem tuning first (dm or sda)
+    # Note that, if dm-<num> is used, sda/mmcblk0 should be tuned in vendor/init.rc
+    write /sys/devices/virtual/block/${dev.mnt.blk.data}/queue/discard_max_bytes 134217728
 
     # Permissions for System Server and daemons.
     chown radio system /sys/android_power/state
@@ -796,6 +802,9 @@
 
 on property:sys.boot_completed=1
     bootchart stop
+    # Setup per_boot directory so other .rc could start to use it on boot_completed
+    exec - system system -- /bin/rm -rf /data/per_boot
+    mkdir /data/per_boot 0700 system system
 
 # system server cannot write to /proc/sys files,
 # and chown/chmod does not work for /proc/sys/ entries.
diff --git a/rootdir/update_and_install_ld_config.mk b/rootdir/update_and_install_ld_config.mk
index f62c3df..1282868 100644
--- a/rootdir/update_and_install_ld_config.mk
+++ b/rootdir/update_and_install_ld_config.mk
@@ -88,7 +88,7 @@
 # $(2): output file with the filtered list of lib names
 $(LOCAL_BUILT_MODULE): private-filter-out-private-libs = \
   paste -sd ":" $(1) > $(2) && \
-  cat $(PRIVATE_VNDK_PRIVATE_LIBRARIES_FILE) | xargs -n 1 -I privatelib bash -c "sed -i.bak 's/privatelib//' $(2)" && \
+  while read -r privatelib; do sed -i.bak "s/$$privatelib//" $(2) ; done < $(PRIVATE_VNDK_PRIVATE_LIBRARIES_FILE) && \
   sed -i.bak -e 's/::\+/:/g ; s/^:\+// ; s/:\+$$//' $(2) && \
   rm -f $(2).bak
 $(LOCAL_BUILT_MODULE): PRIVATE_LLNDK_LIBRARIES_FILE := $(llndk_libraries_file)
@@ -139,8 +139,9 @@
 endif
 
 	$(hide) echo -n > $(PRIVATE_INTERMEDIATES_DIR)/private_llndk && \
-	cat $(PRIVATE_VNDK_PRIVATE_LIBRARIES_FILE) | \
-	xargs -n 1 -I privatelib bash -c "(grep privatelib $(PRIVATE_LLNDK_LIBRARIES_FILE) || true) >> $(PRIVATE_INTERMEDIATES_DIR)/private_llndk" && \
+	while read -r privatelib; \
+	do (grep $$privatelib $(PRIVATE_LLNDK_LIBRARIES_FILE) || true) >> $(PRIVATE_INTERMEDIATES_DIR)/private_llndk ; \
+	done < $(PRIVATE_VNDK_PRIVATE_LIBRARIES_FILE) && \
 	paste -sd ":" $(PRIVATE_INTERMEDIATES_DIR)/private_llndk | \
 	sed -i.bak -e "s?%PRIVATE_LLNDK_LIBRARIES%?$$(cat -)?g" $@
 
diff --git a/usbd/usbd.cpp b/usbd/usbd.cpp
index 191fb92..6e24d8e 100644
--- a/usbd/usbd.cpp
+++ b/usbd/usbd.cpp
@@ -24,8 +24,6 @@
 
 #include <hidl/HidlTransportSupport.h>
 
-#define PERSISTENT_USB_CONFIG "persist.sys.usb.config"
-
 using android::base::GetProperty;
 using android::base::SetProperty;
 using android::hardware::configureRpcThreadpool;
@@ -34,14 +32,15 @@
 using android::hardware::Return;
 
 int main(int /*argc*/, char** /*argv*/) {
-    configureRpcThreadpool(1, true /*callerWillJoin*/);
+    if (GetProperty("ro.bootmode", "") == "charger") exit(0);
 
+    configureRpcThreadpool(1, true /*callerWillJoin*/);
     android::sp<IUsbGadget> gadget = IUsbGadget::getService();
     Return<void> ret;
 
     if (gadget != nullptr) {
         LOG(INFO) << "Usb HAL found.";
-        std::string function = GetProperty(PERSISTENT_USB_CONFIG, "");
+        std::string function = GetProperty("persist.sys.usb.config", "");
         if (function == "adb") {
             LOG(INFO) << "peristent prop is adb";
             SetProperty("ctl.start", "adbd");