Merge "libsnapshot: Remove GetSnapshotSize"
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index 449a170..dd95a5e 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -55,13 +55,7 @@
 
 cc_defaults {
     name: "libdm_defaults",
-    sanitize: {
-        misc_undefined: ["integer"],
-    },
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
+    defaults: ["fs_mgr_defaults"],
     static_libs: [
         "libdm",
         "libbase",
@@ -76,3 +70,12 @@
     name: "libdm_test",
     defaults: ["libdm_defaults"],
 }
+
+cc_test {
+    name: "vts_libdm_test",
+    defaults: ["libdm_defaults"],
+    test_suites: ["vts-core"],
+    auto_gen_config: true,
+    require_root: true,
+    test_min_api_level: 29,
+}
diff --git a/fs_mgr/libdm/vts_core/Android.bp b/fs_mgr/libdm/vts_core/Android.bp
deleted file mode 100644
index 2eceb28..0000000
--- a/fs_mgr/libdm/vts_core/Android.bp
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-cc_test {
-    name: "vts_libdm_test",
-    defaults: ["libdm_defaults"],
-    test_suites: ["vts-core"],
-    require_root: true,
-    test_min_api_level: 29,
-}
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index 178b343..a7c77b8 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -69,13 +69,7 @@
 
 cc_defaults {
     name: "liblp_test_defaults",
-    sanitize: {
-        misc_undefined: ["integer"],
-    },
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
+    defaults: ["fs_mgr_defaults"],
     cppflags: [
         "-Wno-unused-parameter",
     ],
@@ -101,6 +95,14 @@
 }
 
 cc_test {
+    name: "vts_core_liblp_test",
+    defaults: ["liblp_test_defaults"],
+    test_suites: ["vts-core"],
+    auto_gen_config: true,
+    test_min_api_level: 29,
+}
+
+cc_test {
     name: "vts_kernel_liblp_test",
     defaults: ["liblp_test_defaults"],
 }
diff --git a/fs_mgr/liblp/vts_core/Android.bp b/fs_mgr/liblp/vts_core/Android.bp
deleted file mode 100644
index 7af0b9e..0000000
--- a/fs_mgr/liblp/vts_core/Android.bp
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-cc_test {
-    name: "vts_core_liblp_test",
-    defaults: ["liblp_test_defaults"],
-    test_suites: ["vts-core"],
-    test_min_api_level: 29,
-}
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 4852cd0..a15d136 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -36,16 +36,18 @@
 // The split SEPolicy is loaded as described below:
 // 1) There is a precompiled SEPolicy located at either /vendor/etc/selinux/precompiled_sepolicy or
 //    /odm/etc/selinux/precompiled_sepolicy if odm parition is present.  Stored along with this file
-//    are the sha256 hashes of the parts of the SEPolicy on /system and /product that were used to
-//    compile this precompiled policy.  The system partition contains a similar sha256 of the parts
-//    of the SEPolicy that it currently contains.  Symmetrically, product paritition contains a
-//    sha256 of its SEPolicy.  System loads this precompiled_sepolicy directly if and only if hashes
-//    for system policy match and hashes for product policy match.
-// 2) If these hashes do not match, then either /system or /product (or both) have been updated out
-//    of sync with /vendor and the init needs to compile the SEPolicy.  /system contains the
-//    SEPolicy compiler, secilc, and it is used by the LoadSplitPolicy() function below to compile
-//    the SEPolicy to a temp directory and load it.  That function contains even more documentation
-//    with the specific implementation details of how the SEPolicy is compiled if needed.
+//    are the sha256 hashes of the parts of the SEPolicy on /system, /system_ext and /product that
+//    were used to compile this precompiled policy.  The system partition contains a similar sha256
+//    of the parts of the SEPolicy that it currently contains.  Symmetrically, system_ext and
+//    product paritition contain sha256 hashes of their SEPolicy.  The init loads this
+//    precompiled_sepolicy directly if and only if the hashes along with the precompiled SEPolicy on
+//    /vendor or /odm match the hashes for system, system_ext and product SEPolicy, respectively.
+// 2) If these hashes do not match, then either /system or /system_ext or /product (or some of them)
+//    have been updated out of sync with /vendor (or /odm if it is present) and the init needs to
+//    compile the SEPolicy.  /system contains the SEPolicy compiler, secilc, and it is used by the
+//    LoadSplitPolicy() function below to compile the SEPolicy to a temp directory and load it.
+//    That function contains even more documentation with the specific implementation details of how
+//    the SEPolicy is compiled if needed.
 
 #include "selinux.h"
 
@@ -228,6 +230,13 @@
                       "/system/etc/selinux/plat_sepolicy_and_mapping.sha256";
         return false;
     }
+    std::string actual_system_ext_id;
+    if (!ReadFirstLine("/system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256",
+                       &actual_system_ext_id)) {
+        PLOG(INFO) << "Failed to read "
+                      "/system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256";
+        return false;
+    }
     std::string actual_product_id;
     if (!ReadFirstLine("/product/etc/selinux/product_sepolicy_and_mapping.sha256",
                        &actual_product_id)) {
@@ -243,6 +252,13 @@
         file->clear();
         return false;
     }
+    std::string precompiled_system_ext_id;
+    std::string precompiled_system_ext_sha256 = *file + ".system_ext_sepolicy_and_mapping.sha256";
+    if (!ReadFirstLine(precompiled_system_ext_sha256.c_str(), &precompiled_system_ext_id)) {
+        PLOG(INFO) << "Failed to read " << precompiled_system_ext_sha256;
+        file->clear();
+        return false;
+    }
     std::string precompiled_product_id;
     std::string precompiled_product_sha256 = *file + ".product_sepolicy_and_mapping.sha256";
     if (!ReadFirstLine(precompiled_product_sha256.c_str(), &precompiled_product_id)) {
@@ -251,6 +267,7 @@
         return false;
     }
     if (actual_plat_id.empty() || actual_plat_id != precompiled_plat_id ||
+        actual_system_ext_id.empty() || actual_system_ext_id != precompiled_system_ext_id ||
         actual_product_id.empty() || actual_product_id != precompiled_product_id) {
         file->clear();
         return false;
@@ -336,6 +353,17 @@
         plat_compat_cil_file.clear();
     }
 
+    std::string system_ext_policy_cil_file("/system_ext/etc/selinux/system_ext_sepolicy.cil");
+    if (access(system_ext_policy_cil_file.c_str(), F_OK) == -1) {
+        system_ext_policy_cil_file.clear();
+    }
+
+    std::string system_ext_mapping_file("/system_ext/etc/selinux/mapping/" + vend_plat_vers +
+                                        ".cil");
+    if (access(system_ext_mapping_file.c_str(), F_OK) == -1) {
+        system_ext_mapping_file.clear();
+    }
+
     std::string product_policy_cil_file("/product/etc/selinux/product_sepolicy.cil");
     if (access(product_policy_cil_file.c_str(), F_OK) == -1) {
         product_policy_cil_file.clear();
@@ -384,6 +412,12 @@
     if (!plat_compat_cil_file.empty()) {
         compile_args.push_back(plat_compat_cil_file.c_str());
     }
+    if (!system_ext_policy_cil_file.empty()) {
+        compile_args.push_back(system_ext_policy_cil_file.c_str());
+    }
+    if (!system_ext_mapping_file.empty()) {
+        compile_args.push_back(system_ext_mapping_file.c_str());
+    }
     if (!product_policy_cil_file.empty()) {
         compile_args.push_back(product_policy_cil_file.c_str());
     }
diff --git a/liblog/Android.bp b/liblog/Android.bp
index c38d8cd..8a63007 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -23,7 +23,6 @@
     "logger_read.cpp",
     "logger_write.cpp",
     "logprint.cpp",
-    "stderr_write.cpp",
 ]
 liblog_host_sources = [
     "fake_log_device.cpp",
@@ -108,7 +107,9 @@
     },
 
     cflags: [
+        "-Wall",
         "-Werror",
+        "-Wextra",
         // This is what we want to do:
         //  liblog_cflags := $(shell \
         //   sed -n \
diff --git a/liblog/config_write.cpp b/liblog/config_write.cpp
index d454379..6ed893d 100644
--- a/liblog/config_write.cpp
+++ b/liblog/config_write.cpp
@@ -66,27 +66,6 @@
     __android_log_add_transport(&__android_log_transport_write, &fakeLoggerWrite);
 #endif
   }
-
-  if (__android_log_transport & LOGGER_STDERR) {
-    extern struct android_log_transport_write stderrLoggerWrite;
-
-    /*
-     * stderr logger should be primary if we can be the only one, or if
-     * already in the primary list.  Otherwise land in the persist list.
-     * Remember we can be called here if we are already initialized.
-     */
-    if (list_empty(&__android_log_transport_write)) {
-      __android_log_add_transport(&__android_log_transport_write, &stderrLoggerWrite);
-    } else {
-      struct android_log_transport_write* transp;
-      write_transport_for_each(transp, &__android_log_transport_write) {
-        if (transp == &stderrLoggerWrite) {
-          return;
-        }
-      }
-      __android_log_add_transport(&__android_log_persist_write, &stderrLoggerWrite);
-    }
-  }
 }
 
 void __android_log_config_write_close() {
diff --git a/liblog/include/log/log_transport.h b/liblog/include/log/log_transport.h
index b48761a..bda7c25 100644
--- a/liblog/include/log/log_transport.h
+++ b/liblog/include/log/log_transport.h
@@ -22,7 +22,7 @@
 #define LOGGER_KERNEL  0x02 /* Reserved/Deprecated */
 #define LOGGER_NULL    0x04 /* Does not release resources of other selections */
 #define LOGGER_RESERVED 0x08 /* Reserved, previously for logging to local memory */
-#define LOGGER_STDERR  0x10 /* logs sent to stderr */
+#define LOGGER_RESERVED2  0x10 /* Reserved, previously for logs sent to stderr */
 /* clang-format on */
 
 /* Both return the selected transport flag mask, or negative errno */
diff --git a/liblog/log_event_list.cpp b/liblog/log_event_list.cpp
index b1b527c..f148ef3 100644
--- a/liblog/log_event_list.cpp
+++ b/liblog/log_event_list.cpp
@@ -88,7 +88,6 @@
 
 android_log_context create_android_log_parser(const char* msg, size_t len) {
   android_log_context_internal* context;
-  size_t i;
 
   context =
       static_cast<android_log_context_internal*>(calloc(1, sizeof(android_log_context_internal)));
@@ -401,22 +400,6 @@
 }
 
 /*
- * Extract a 4-byte value from a byte stream.
- */
-static inline uint32_t get4LE(const uint8_t* src) {
-  return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-}
-
-/*
- * Extract an 8-byte value from a byte stream.
- */
-static inline uint64_t get8LE(const uint8_t* src) {
-  uint32_t low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-  uint32_t high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
-  return ((uint64_t)high << 32) | (uint64_t)low;
-}
-
-/*
  * Gets the next element. Parsing errors result in an EVENT_TYPE_UNKNOWN type.
  * If there is nothing to process, the complete field is set to non-zero. If
  * an EVENT_TYPE_UNKNOWN type is returned once, and the caller does not check
@@ -489,7 +472,7 @@
         elem.type = EVENT_TYPE_UNKNOWN;
         return elem;
       }
-      elem.data.int32 = get4LE(&context->storage[pos]);
+      elem.data.int32 = *reinterpret_cast<int32_t*>(&context->storage[pos]);
       /* common tangeable object suffix */
       pos += elem.len;
       elem.complete = !context->list_nest_depth && !context->count[0];
@@ -508,7 +491,7 @@
         elem.type = EVENT_TYPE_UNKNOWN;
         return elem;
       }
-      elem.data.int64 = get8LE(&context->storage[pos]);
+      elem.data.int64 = *reinterpret_cast<int64_t*>(&context->storage[pos]);
       /* common tangeable object suffix */
       pos += elem.len;
       elem.complete = !context->list_nest_depth && !context->count[0];
@@ -527,7 +510,7 @@
         elem.complete = true;
         return elem;
       }
-      elem.len = get4LE(&context->storage[pos]);
+      elem.len = *reinterpret_cast<int32_t*>(&context->storage[pos]);
       pos += sizeof(int32_t);
       if ((pos + elem.len) > context->len) {
         elem.len = context->len - pos; /* truncate string */
diff --git a/liblog/logd_reader.cpp b/liblog/logd_reader.cpp
index eba305f..d5bf844 100644
--- a/liblog/logd_reader.cpp
+++ b/liblog/logd_reader.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <endian.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
diff --git a/liblog/logd_writer.cpp b/liblog/logd_writer.cpp
index c3f72f4..2c64b0b 100644
--- a/liblog/logd_writer.cpp
+++ b/liblog/logd_writer.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <endian.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -184,9 +183,9 @@
       android_log_event_int_t buffer;
 
       header.id = LOG_ID_SECURITY;
-      buffer.header.tag = htole32(LIBLOG_LOG_TAG);
+      buffer.header.tag = LIBLOG_LOG_TAG;
       buffer.payload.type = EVENT_TYPE_INT;
-      buffer.payload.data = htole32(snapshot);
+      buffer.payload.data = snapshot;
 
       newVec[headerLength].iov_base = &buffer;
       newVec[headerLength].iov_len = sizeof(buffer);
@@ -202,9 +201,9 @@
       android_log_event_int_t buffer;
 
       header.id = LOG_ID_EVENTS;
-      buffer.header.tag = htole32(LIBLOG_LOG_TAG);
+      buffer.header.tag = LIBLOG_LOG_TAG;
       buffer.payload.type = EVENT_TYPE_INT;
-      buffer.payload.data = htole32(snapshot);
+      buffer.payload.data = snapshot;
 
       newVec[headerLength].iov_base = &buffer;
       newVec[headerLength].iov_len = sizeof(buffer);
diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp
index 4fbab4b..7fc8747 100644
--- a/liblog/logger_write.cpp
+++ b/liblog/logger_write.cpp
@@ -39,13 +39,6 @@
 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;
 
-/*
- * 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 int check_log_uid_permissions() {
 #if defined(__ANDROID__)
   uid_t uid = __android_log_uid();
@@ -104,22 +97,6 @@
   }
 }
 
-extern "C" int __android_log_dev_available() {
-  struct android_log_transport_write* node;
-
-  if (list_empty(&__android_log_transport_write)) {
-    return kLogUninitialized;
-  }
-
-  write_transport_for_each(node, &__android_log_transport_write) {
-    __android_log_cache_available(node);
-    if (node->logMask) {
-      return kLogAvailable;
-    }
-  }
-  return kLogNotAvailable;
-}
-
 #if defined(__ANDROID__)
 static atomic_uintptr_t tagMap;
 #endif
@@ -228,13 +205,6 @@
   return ret;
 }
 
-/*
- * Extract a 4-byte value from a byte stream. le32toh open coded
- */
-static inline uint32_t get4LE(const uint8_t* src) {
-  return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-}
-
 static int __write_to_log_daemon(log_id_t log_id, struct iovec* vec, size_t nr) {
   struct android_log_transport_write* node;
   int ret, save_errno;
@@ -302,7 +272,7 @@
       }
     }
     if (m && (m != (EventTagMap*)(uintptr_t)-1LL)) {
-      tag = android_lookupEventTag_len(m, &len, get4LE(static_cast<uint8_t*>(vec[0].iov_base)));
+      tag = android_lookupEventTag_len(m, &len, *static_cast<uint32_t*>(vec[0].iov_base));
     }
     ret = __android_log_is_loggable_len(ANDROID_LOG_INFO, tag, len, ANDROID_LOG_VERBOSE);
     if (f) { /* local copy marked for close */
@@ -616,9 +586,9 @@
     return retval;
   }
 
-  __android_log_transport &= LOGGER_LOGD | LOGGER_STDERR;
+  __android_log_transport &= LOGGER_LOGD;
 
-  transport_flag &= LOGGER_LOGD | LOGGER_STDERR;
+  transport_flag &= LOGGER_LOGD;
 
   if (__android_log_transport != transport_flag) {
     __android_log_transport = transport_flag;
@@ -644,7 +614,7 @@
   if (write_to_log == __write_to_log_null) {
     ret = LOGGER_NULL;
   } else {
-    __android_log_transport &= LOGGER_LOGD | LOGGER_STDERR;
+    __android_log_transport &= LOGGER_LOGD;
     ret = __android_log_transport;
     if ((write_to_log != __write_to_log_init) && (write_to_log != __write_to_log_daemon)) {
       ret = -EINVAL;
diff --git a/liblog/logprint.cpp b/liblog/logprint.cpp
index 3a54445..dd2c797 100644
--- a/liblog/logprint.cpp
+++ b/liblog/logprint.cpp
@@ -291,8 +291,10 @@
   return 1;
 }
 
+#ifndef __MINGW32__
 static const char tz[] = "TZ";
 static const char utc[] = "UTC";
+#endif
 
 /**
  * Returns FORMAT_OFF on invalid string
@@ -580,24 +582,6 @@
   return 0;
 }
 
-/*
- * Extract a 4-byte value from a byte stream.
- */
-static inline uint32_t get4LE(const uint8_t* src) {
-  return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-}
-
-/*
- * Extract an 8-byte value from a byte stream.
- */
-static inline uint64_t get8LE(const uint8_t* src) {
-  uint32_t low, high;
-
-  low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-  high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
-  return ((uint64_t)high << 32) | (uint64_t)low;
-}
-
 static bool findChar(const char** cp, size_t* len, int c) {
   while ((*len) && isspace(*(*cp))) {
     ++(*cp);
@@ -744,7 +728,7 @@
         int32_t ival;
 
         if (eventDataLen < 4) return -1;
-        ival = get4LE(eventData);
+        ival = *reinterpret_cast<const int32_t*>(eventData);
         eventData += 4;
         eventDataLen -= 4;
 
@@ -754,7 +738,7 @@
     case EVENT_TYPE_LONG:
       /* 64-bit signed long */
       if (eventDataLen < 8) return -1;
-      lval = get8LE(eventData);
+      lval = *reinterpret_cast<const int64_t*>(eventData);
       eventData += 8;
       eventDataLen -= 8;
     pr_lval:
@@ -774,7 +758,7 @@
         float fval;
 
         if (eventDataLen < 4) return -1;
-        ival = get4LE(eventData);
+        ival = *reinterpret_cast<const uint32_t*>(eventData);
         fval = *(float*)&ival;
         eventData += 4;
         eventDataLen -= 4;
@@ -795,7 +779,7 @@
         unsigned int strLen;
 
         if (eventDataLen < 4) return -1;
-        strLen = get4LE(eventData);
+        strLen = *reinterpret_cast<const uint32_t*>(eventData);
         eventData += 4;
         eventDataLen -= 4;
 
@@ -1034,7 +1018,7 @@
   }
   inCount = buf->len;
   if (inCount < 4) return -1;
-  tagIndex = get4LE(eventData);
+  tagIndex = *reinterpret_cast<const uint32_t*>(eventData);
   eventData += 4;
   inCount -= 4;
 
@@ -1189,6 +1173,7 @@
   return p - begin;
 }
 
+#ifdef __ANDROID__
 static char* readSeconds(char* e, struct timespec* t) {
   unsigned long multiplier;
   char* p;
@@ -1229,7 +1214,6 @@
   return (long long)now->tv_sec * NS_PER_SEC + now->tv_nsec;
 }
 
-#ifdef __ANDROID__
 static void convertMonotonic(struct timespec* result, const AndroidLogEntry* entry) {
   struct listnode* node;
   struct conversionList {
diff --git a/liblog/pmsg_reader.cpp b/liblog/pmsg_reader.cpp
index 81563bc..005fec8 100644
--- a/liblog/pmsg_reader.cpp
+++ b/liblog/pmsg_reader.cpp
@@ -130,7 +130,6 @@
   ssize_t ret;
   off_t current, next;
   uid_t uid;
-  struct android_log_logger* logger;
   struct __attribute__((__packed__)) {
     android_pmsg_log_header_t p;
     android_log_header_t l;
diff --git a/liblog/pmsg_writer.cpp b/liblog/pmsg_writer.cpp
index 4632b32..69720ed 100644
--- a/liblog/pmsg_writer.cpp
+++ b/liblog/pmsg_writer.cpp
@@ -87,13 +87,6 @@
   return 1;
 }
 
-/*
- * Extract a 4-byte value from a byte stream.
- */
-static inline uint32_t get4LE(const uint8_t* src) {
-  return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-}
-
 static int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
   static const unsigned headerLength = 2;
   struct iovec newVec[nr + headerLength];
@@ -107,7 +100,7 @@
       return -EINVAL;
     }
 
-    if (SNET_EVENT_LOG_TAG != get4LE(static_cast<uint8_t*>(vec[0].iov_base))) {
+    if (SNET_EVENT_LOG_TAG != *static_cast<uint8_t*>(vec[0].iov_base)) {
       return -EPERM;
     }
   }
diff --git a/liblog/stderr_write.cpp b/liblog/stderr_write.cpp
deleted file mode 100644
index e76673f..0000000
--- a/liblog/stderr_write.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * stderr write handler.  Output is logcat-like, and responds to
- * logcat's environment variables ANDROID_PRINTF_LOG and
- * ANDROID_LOG_TAGS to filter output.
- *
- * This transport only provides a writer, that means that it does not
- * provide an End-To-End capability as the logs are effectively _lost_
- * to the stderr file stream.  The purpose of this transport is to
- * supply a means for command line tools to report their logging
- * to the stderr stream, in line with all other activities.
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <log/event_tag_map.h>
-#include <log/log.h>
-#include <log/logprint.h>
-
-#include "log_portability.h"
-#include "logger.h"
-#include "uio.h"
-
-static int stderrOpen();
-static void stderrClose();
-static int stderrAvailable(log_id_t logId);
-static int stderrWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
-
-struct stderrContext {
-  AndroidLogFormat* logformat;
-#if defined(__ANDROID__)
-  EventTagMap* eventTagMap;
-#endif
-};
-
-struct android_log_transport_write stderrLoggerWrite = {
-    .node = {&stderrLoggerWrite.node, &stderrLoggerWrite.node},
-    .context.priv = NULL,
-    .name = "stderr",
-    .available = stderrAvailable,
-    .open = stderrOpen,
-    .close = stderrClose,
-    .write = stderrWrite,
-};
-
-static int stderrOpen() {
-  struct stderrContext* ctx;
-  const char* envStr;
-  bool setFormat;
-
-  if (!stderr || (fileno(stderr) < 0)) {
-    return -EBADF;
-  }
-
-  if (stderrLoggerWrite.context.priv) {
-    return fileno(stderr);
-  }
-
-  ctx = static_cast<stderrContext*>(calloc(1, sizeof(stderrContext)));
-  if (!ctx) {
-    return -ENOMEM;
-  }
-
-  ctx->logformat = android_log_format_new();
-  if (!ctx->logformat) {
-    free(ctx);
-    return -ENOMEM;
-  }
-
-  envStr = getenv("ANDROID_PRINTF_LOG");
-  setFormat = false;
-
-  if (envStr) {
-    char* formats = strdup(envStr);
-    char* sv = NULL;
-    char* arg = formats;
-    while (!!(arg = strtok_r(arg, ",:; \t\n\r\f", &sv))) {
-      AndroidLogPrintFormat format = android_log_formatFromString(arg);
-      arg = NULL;
-      if (format == FORMAT_OFF) {
-        continue;
-      }
-      if (android_log_setPrintFormat(ctx->logformat, format) <= 0) {
-        continue;
-      }
-      setFormat = true;
-    }
-    free(formats);
-  }
-  if (!setFormat) {
-    AndroidLogPrintFormat format = android_log_formatFromString("threadtime");
-    android_log_setPrintFormat(ctx->logformat, format);
-  }
-  envStr = getenv("ANDROID_LOG_TAGS");
-  if (envStr) {
-    android_log_addFilterString(ctx->logformat, envStr);
-  }
-  stderrLoggerWrite.context.priv = ctx;
-
-  return fileno(stderr);
-}
-
-static void stderrClose() {
-  stderrContext* ctx = static_cast<stderrContext*>(stderrLoggerWrite.context.priv);
-
-  if (ctx) {
-    stderrLoggerWrite.context.priv = NULL;
-    if (ctx->logformat) {
-      android_log_format_free(ctx->logformat);
-      ctx->logformat = NULL;
-    }
-#if defined(__ANDROID__)
-    if (ctx->eventTagMap) {
-      android_closeEventTagMap(ctx->eventTagMap);
-      ctx->eventTagMap = NULL;
-    }
-#endif
-  }
-}
-
-static int stderrAvailable(log_id_t logId) {
-  if ((logId >= LOG_ID_MAX) || (logId == LOG_ID_KERNEL)) {
-    return -EINVAL;
-  }
-  return 1;
-}
-
-static int stderrWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
-  struct log_msg log_msg;
-  AndroidLogEntry entry;
-  char binaryMsgBuf[1024];
-  int err;
-  size_t i;
-  stderrContext* ctx = static_cast<stderrContext*>(stderrLoggerWrite.context.priv);
-
-  if (!ctx) return -EBADF;
-  if (!vec || !nr) return -EINVAL;
-
-  log_msg.entry.len = 0;
-  log_msg.entry.hdr_size = sizeof(log_msg.entry);
-  log_msg.entry.pid = getpid();
-#ifdef __BIONIC__
-  log_msg.entry.tid = gettid();
-#else
-  log_msg.entry.tid = getpid();
-#endif
-  log_msg.entry.sec = ts->tv_sec;
-  log_msg.entry.nsec = ts->tv_nsec;
-  log_msg.entry.lid = logId;
-  log_msg.entry.uid = __android_log_uid();
-
-  for (i = 0; i < nr; ++i) {
-    size_t len = vec[i].iov_len;
-    if ((log_msg.entry.len + len) > LOGGER_ENTRY_MAX_PAYLOAD) {
-      len = LOGGER_ENTRY_MAX_PAYLOAD - log_msg.entry.len;
-    }
-    if (!len) continue;
-    memcpy(log_msg.entry.msg + log_msg.entry.len, vec[i].iov_base, len);
-    log_msg.entry.len += len;
-  }
-
-  if ((logId == LOG_ID_EVENTS) || (logId == LOG_ID_SECURITY)) {
-#if defined(__ANDROID__)
-    if (!ctx->eventTagMap) {
-      ctx->eventTagMap = android_openEventTagMap(NULL);
-    }
-#endif
-    err = android_log_processBinaryLogBuffer(&log_msg.entry_v1, &entry,
-#if defined(__ANDROID__)
-                                             ctx->eventTagMap,
-#else
-                                             NULL,
-#endif
-                                             binaryMsgBuf, sizeof(binaryMsgBuf));
-  } else {
-    err = android_log_processLogBuffer(&log_msg.entry_v1, &entry);
-  }
-
-  /* print known truncated data, in essence logcat --debug */
-  if ((err < 0) && !entry.message) return -EINVAL;
-
-  if (!android_log_shouldPrintLine(ctx->logformat, entry.tag, entry.priority)) {
-    return log_msg.entry.len;
-  }
-
-  err = android_log_printLogLine(ctx->logformat, fileno(stderr), &entry);
-  if (err < 0) return errno ? -errno : -EINVAL;
-  return log_msg.entry.len;
-}
diff --git a/liblog/tests/Android.bp b/liblog/tests/Android.bp
index d9d1a21..45f09f2 100644
--- a/liblog/tests/Android.bp
+++ b/liblog/tests/Android.bp
@@ -54,8 +54,7 @@
     ],
     srcs: [
         "libc_test.cpp",
-        "liblog_test_default.cpp",
-        "liblog_test_stderr.cpp",
+        "liblog_test.cpp",
         "log_id_test.cpp",
         "log_radio_test.cpp",
         "log_read_test.cpp",
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 21d12a1..7163743 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -17,7 +17,6 @@
 #include <fcntl.h>
 #include <inttypes.h>
 #include <poll.h>
-#include <sys/endian.h>
 #include <sys/socket.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
@@ -227,14 +226,14 @@
   buffer.header.tag = 0;
   buffer.payload.type = EVENT_TYPE_INT;
   uint32_t snapshot = 0;
-  buffer.payload.data = htole32(snapshot);
+  buffer.payload.data = snapshot;
 
   newVec[2].iov_base = &buffer;
   newVec[2].iov_len = sizeof(buffer);
 
   while (state.KeepRunning()) {
     ++snapshot;
-    buffer.payload.data = htole32(snapshot);
+    buffer.payload.data = snapshot;
     writev(pstore_fd, newVec, nr);
   }
   state.PauseTiming();
@@ -303,11 +302,11 @@
   buffer->payload.header.tag = 0;
   buffer->payload.payload.type = EVENT_TYPE_INT;
   uint32_t snapshot = 0;
-  buffer->payload.payload.data = htole32(snapshot);
+  buffer->payload.payload.data = snapshot;
 
   while (state.KeepRunning()) {
     ++snapshot;
-    buffer->payload.payload.data = htole32(snapshot);
+    buffer->payload.payload.data = snapshot;
     write(pstore_fd, &buffer->pmsg_header,
           sizeof(android_pmsg_log_header_t) + sizeof(android_log_header_t) +
               sizeof(android_log_event_int_t));
@@ -378,11 +377,11 @@
   buffer->payload.header.tag = 0;
   buffer->payload.payload.type = EVENT_TYPE_INT;
   uint32_t snapshot = 0;
-  buffer->payload.payload.data = htole32(snapshot);
+  buffer->payload.payload.data = snapshot;
 
   while (state.KeepRunning()) {
     ++snapshot;
-    buffer->payload.payload.data = htole32(snapshot);
+    buffer->payload.payload.data = snapshot;
     write(pstore_fd, &buffer->pmsg_header,
           sizeof(android_pmsg_log_header_t) + sizeof(android_log_header_t) +
               sizeof(android_log_event_int_t));
@@ -453,11 +452,11 @@
   buffer->payload.header.tag = 0;
   buffer->payload.payload.type = EVENT_TYPE_INT;
   uint32_t snapshot = 0;
-  buffer->payload.payload.data = htole32(snapshot);
+  buffer->payload.payload.data = snapshot;
 
   while (state.KeepRunning()) {
     ++snapshot;
-    buffer->payload.payload.data = htole32(snapshot);
+    buffer->payload.payload.data = snapshot;
     write(pstore_fd, &buffer->pmsg_header, LOGGER_ENTRY_MAX_PAYLOAD);
   }
   state.PauseTiming();
@@ -526,11 +525,11 @@
   buffer->payload.header.tag = 0;
   buffer->payload.payload.type = EVENT_TYPE_INT;
   uint32_t snapshot = 0;
-  buffer->payload.payload.data = htole32(snapshot);
+  buffer->payload.payload.data = snapshot;
 
   while (state.KeepRunning()) {
     ++snapshot;
-    buffer->payload.payload.data = htole32(snapshot);
+    buffer->payload.payload.data = snapshot;
     write(pstore_fd, &buffer->pmsg_header, LOGGER_ENTRY_MAX_PAYLOAD);
   }
   state.PauseTiming();
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 5a73dc0..34fb909 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -38,26 +38,10 @@
 #include <gtest/gtest.h>
 #include <log/log_event_list.h>
 #include <log/log_properties.h>
-#include <log/log_transport.h>
 #include <log/logprint.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
-#ifndef TEST_PREFIX
-#ifdef TEST_LOGGER
-#define TEST_PREFIX android_set_log_transport(TEST_LOGGER);
-// make sure we always run code despite overrides if compiled for android
-#elif defined(__ANDROID__)
-#define TEST_PREFIX
-#endif
-#endif
-
-#ifdef USING_LOGGER_STDERR
-#define SUPPORTS_END_TO_END 0
-#else
-#define SUPPORTS_END_TO_END 1
-#endif
-
 // enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
 // non-syscall libs. Since we are only using this in the emergency of
 // a signal to stuff a terminating code into the logs, we will spin rather
@@ -73,9 +57,6 @@
   })
 
 TEST(liblog, __android_log_btwrite) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
-#endif
   int intBuf = 0xDEADBEEF;
   EXPECT_LT(0,
             __android_log_btwrite(0, EVENT_TYPE_INT, &intBuf, sizeof(intBuf)));
@@ -89,7 +70,7 @@
   usleep(1000);
 }
 
-#if (defined(__ANDROID__) && defined(USING_LOGGER_DEFAULT))
+#if defined(__ANDROID__)
 static std::string popenToString(const std::string& command) {
   std::string ret;
 
@@ -160,9 +141,6 @@
 
 TEST(liblog, __android_log_btwrite__android_logger_list_read) {
 #ifdef __ANDROID__
-#ifdef TEST_PREFIX
-  TEST_PREFIX
-#endif
   struct logger_list* logger_list;
 
   pid_t pid = getpid();
@@ -174,7 +152,6 @@
 
   log_time ts(CLOCK_MONOTONIC);
   EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
-#ifdef USING_LOGGER_DEFAULT
   // Check that we can close and reopen the logger
   bool logdwActiveAfter__android_log_btwrite;
   if (getuid() == AID_ROOT) {
@@ -197,11 +174,9 @@
     bool logdwActiveAfter__android_log_close = isLogdwActive();
     EXPECT_FALSE(logdwActiveAfter__android_log_close);
   }
-#endif
 
   log_time ts1(CLOCK_MONOTONIC);
   EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
-#ifdef USING_LOGGER_DEFAULT
   if (getuid() == AID_ROOT) {
 #ifndef NO_PSTORE
     bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
@@ -210,7 +185,6 @@
     logdwActiveAfter__android_log_btwrite = isLogdwActive();
     EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
   }
-#endif
   usleep(1000000);
 
   int count = 0;
@@ -244,8 +218,8 @@
     }
   }
 
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
-  EXPECT_EQ(SUPPORTS_END_TO_END, second_count);
+  EXPECT_EQ(1, count);
+  EXPECT_EQ(1, second_count);
 
   android_logger_list_close(logger_list);
 #else
@@ -253,144 +227,8 @@
 #endif
 }
 
-#ifdef __ANDROID__
-static void print_transport(const char* prefix, int logger) {
-  static const char orstr[] = " | ";
-
-  if (!prefix) {
-    prefix = "";
-  }
-  if (logger < 0) {
-    fprintf(stderr, "%s%s\n", prefix, strerror(-logger));
-    return;
-  }
-
-  if (logger == LOGGER_DEFAULT) {
-    fprintf(stderr, "%sLOGGER_DEFAULT", prefix);
-    prefix = orstr;
-  }
-  if (logger & LOGGER_LOGD) {
-    fprintf(stderr, "%sLOGGER_LOGD", prefix);
-    prefix = orstr;
-  }
-  if (logger & LOGGER_KERNEL) {
-    fprintf(stderr, "%sLOGGER_KERNEL", prefix);
-    prefix = orstr;
-  }
-  if (logger & LOGGER_NULL) {
-    fprintf(stderr, "%sLOGGER_NULL", prefix);
-    prefix = orstr;
-  }
-  if (logger & LOGGER_STDERR) {
-    fprintf(stderr, "%sLOGGER_STDERR", prefix);
-    prefix = orstr;
-  }
-  logger &= ~(LOGGER_LOGD | LOGGER_KERNEL | LOGGER_NULL | LOGGER_STDERR);
-  if (logger) {
-    fprintf(stderr, "%s0x%x", prefix, logger);
-    prefix = orstr;
-  }
-  if (prefix == orstr) {
-    fprintf(stderr, "\n");
-  }
-}
-#endif
-
-// This test makes little sense standalone, and requires the tests ahead
-// and behind us, to make us whole.  We could incorporate a prefix and
-// suffix test to make this standalone, but opted to not complicate this.
-TEST(liblog, android_set_log_transport) {
-#ifdef __ANDROID__
-#ifdef TEST_PREFIX
-  TEST_PREFIX
-#endif
-
-  int logger = android_get_log_transport();
-  print_transport("android_get_log_transport = ", logger);
-  EXPECT_NE(LOGGER_NULL, logger);
-
-  int ret;
-  EXPECT_EQ(LOGGER_NULL, ret = android_set_log_transport(LOGGER_NULL));
-  print_transport("android_set_log_transport = ", ret);
-  EXPECT_EQ(LOGGER_NULL, ret = android_get_log_transport());
-  print_transport("android_get_log_transport = ", ret);
-
-  pid_t pid = getpid();
-
-  struct logger_list* logger_list;
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
-  log_time ts(CLOCK_MONOTONIC);
-  EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
-
-  usleep(1000000);
-
-  int count = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    EXPECT_EQ(log_msg.entry.pid, pid);
-
-    if ((log_msg.entry.len != sizeof(android_log_event_long_t)) ||
-        (log_msg.id() != LOG_ID_EVENTS)) {
-      continue;
-    }
-
-    android_log_event_long_t* eventData;
-    eventData = reinterpret_cast<android_log_event_long_t*>(log_msg.msg());
-
-    if (!eventData || (eventData->payload.type != EVENT_TYPE_LONG)) {
-      continue;
-    }
-
-    log_time tx(reinterpret_cast<char*>(&eventData->payload.data));
-    if (ts == tx) {
-      ++count;
-    }
-  }
-
-  android_logger_list_close(logger_list);
-
-  EXPECT_EQ(logger, ret = android_set_log_transport(logger));
-  print_transport("android_set_log_transport = ", ret);
-  EXPECT_EQ(logger, ret = android_get_log_transport());
-  print_transport("android_get_log_transport = ", ret);
-
-  // False negative if liblog.__android_log_btwrite__android_logger_list_read
-  // fails above, so we will likely succeed. But we will have so many
-  // failures elsewhere that it is probably not worthwhile for us to
-  // highlight yet another disappointment.
-  //
-  // We also expect failures in the following tests if the set does not
-  // react in an appropriate manner internally, yet passes, so we depend
-  // on this test being in the middle of a series of tests performed in
-  // the same process.
-  EXPECT_EQ(0, count);
-#else
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
-
-#ifdef TEST_PREFIX
-static inline uint32_t get4LE(const uint8_t* src) {
-  return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-}
-
-static inline uint32_t get4LE(const char* src) {
-  return get4LE(reinterpret_cast<const uint8_t*>(src));
-}
-#endif
-
 static void bswrite_test(const char* message) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
   struct logger_list* logger_list;
 
   pid_t pid = getpid();
@@ -400,11 +238,7 @@
                    LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
                    1000, pid)));
 
-#ifdef __ANDROID__
   log_time ts(android_log_clockid());
-#else
-  log_time ts(CLOCK_REALTIME);
-#endif
 
   EXPECT_LT(0, __android_log_bswrite(0, message));
   size_t num_lines = 1, size = 0, length = 0, total = 0;
@@ -455,7 +289,7 @@
       continue;
     }
 
-    size_t len = get4LE(reinterpret_cast<char*>(&eventData->length));
+    size_t len = eventData->length;
     if (len == total) {
       ++count;
 
@@ -486,7 +320,7 @@
     }
   }
 
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+  EXPECT_EQ(1, count);
 
   android_logger_list_close(logger_list);
 #else
@@ -516,8 +350,7 @@
 }
 
 static void buf_write_test(const char* message) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
   struct logger_list* logger_list;
 
   pid_t pid = getpid();
@@ -528,11 +361,7 @@
            LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
 
   static const char tag[] = "TEST__android_log_buf_write";
-#ifdef __ANDROID__
   log_time ts(android_log_clockid());
-#else
-  log_time ts(CLOCK_REALTIME);
-#endif
 
   EXPECT_LT(
       0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO, tag, message));
@@ -590,7 +419,7 @@
     android_log_format_free(logformat);
   }
 
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+  EXPECT_EQ(1, count);
 
   android_logger_list_close(logger_list);
 #else
@@ -611,8 +440,7 @@
   buf_write_test("\n Hello World \n");
 }
 
-#ifdef USING_LOGGER_DEFAULT  // requires blocking reader functionality
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
 static unsigned signaled;
 static log_time signal_time;
 
@@ -673,8 +501,7 @@
 #endif
 
 TEST(liblog, android_logger_list_read__cpu_signal) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
   struct logger_list* logger_list;
   unsigned long long v = 0xDEADBEEFA55A0000ULL;
 
@@ -766,7 +593,7 @@
 #endif
 }
 
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
 /*
  *  Strictly, we are not allowed to log messages in a signal context, the
  * correct way to handle this is to ensure the messages are constructed in
@@ -830,8 +657,7 @@
 #endif
 
 TEST(liblog, android_logger_list_read__cpu_thread) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
   struct logger_list* logger_list;
   unsigned long long v = 0xDEADBEAFA55A0000ULL;
 
@@ -923,9 +749,8 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // USING_LOGGER_DEFAULT
 
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
 static const char max_payload_tag[] = "TEST_max_payload_and_longish_tag_XXXX";
 #define SIZEOF_MAX_PAYLOAD_BUF \
   (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(max_payload_tag) - 1)
@@ -1062,10 +887,8 @@
 when you depart from me, sorrow abides and happiness\n\
 takes his leave.";
 
-#ifdef USING_LOGGER_DEFAULT
 TEST(liblog, max_payload) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
   pid_t pid = getpid();
   char tag[sizeof(max_payload_tag)];
   memcpy(tag, max_payload_tag, sizeof(tag));
@@ -1120,22 +943,16 @@
 
   android_logger_list_close(logger_list);
 
-#if SUPPORTS_END_TO_END
   EXPECT_EQ(true, matches);
 
   EXPECT_LE(SIZEOF_MAX_PAYLOAD_BUF, static_cast<size_t>(max_len));
 #else
-  EXPECT_EQ(false, matches);
-#endif
-#else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif
 
 TEST(liblog, __android_log_buf_print__maxtag) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
   struct logger_list* logger_list;
 
   pid_t pid = getpid();
@@ -1145,11 +962,7 @@
       (logger_list = android_logger_list_open(
            LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
 
-#ifdef __ANDROID__
   log_time ts(android_log_clockid());
-#else
-  log_time ts(CLOCK_REALTIME);
-#endif
 
   EXPECT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO,
                                        max_payload_buf, max_payload_buf));
@@ -1192,7 +1005,7 @@
     android_log_format_free(logformat);
   }
 
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+  EXPECT_EQ(1, count);
 
   android_logger_list_close(logger_list);
 #else
@@ -1201,8 +1014,7 @@
 }
 
 TEST(liblog, too_big_payload) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
   pid_t pid = getpid();
   static const char big_payload_tag[] = "TEST_big_payload_XXXX";
   char tag[sizeof(big_payload_tag)];
@@ -1254,10 +1066,6 @@
 
   android_logger_list_close(logger_list);
 
-#if !SUPPORTS_END_TO_END
-  max_len =
-      max_len ? max_len : LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag);
-#endif
   EXPECT_LE(LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag),
             static_cast<size_t>(max_len));
 
@@ -1273,10 +1081,8 @@
 #endif
 }
 
-#ifdef USING_LOGGER_DEFAULT
 TEST(liblog, dual_reader) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
 
   static const int num = 25;
 
@@ -1331,15 +1137,13 @@
   android_logger_list_close(logger_list1);
   android_logger_list_close(logger_list2);
 
-  EXPECT_EQ(num * SUPPORTS_END_TO_END, count1);
-  EXPECT_EQ((num - 10) * SUPPORTS_END_TO_END, count2);
+  EXPECT_EQ(num, count1);
+  EXPECT_EQ(num - 10, count2);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif
 
-#ifdef USING_LOGGER_DEFAULT  // Do not retest logprint
 static bool checkPriForTag(AndroidLogFormat* p_format, const char* tag,
                            android_LogPriority pri) {
   return android_log_shouldPrintLine(p_format, tag, pri) &&
@@ -1415,9 +1219,7 @@
 
   android_log_format_free(p_format);
 }
-#endif  // USING_LOGGER_DEFAULT
 
-#ifdef USING_LOGGER_DEFAULT  // Do not retest property handling
 TEST(liblog, is_loggable) {
 #ifdef __ANDROID__
   static const char tag[] = "is_loggable";
@@ -1705,14 +1507,11 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // USING_LOGGER_DEFAULT
 
 // Following tests the specific issues surrounding error handling wrt logd.
 // Kills logd and toss all collected data, equivalent to logcat -b all -c,
 // except we also return errors to the logging callers.
-#ifdef USING_LOGGER_DEFAULT
 #ifdef __ANDROID__
-#ifdef TEST_PREFIX
 // helper to liblog.enoent to count end-to-end matching logging messages.
 static int count_matching_ts(log_time ts) {
   usleep(1000000);
@@ -1747,19 +1546,17 @@
 
   return count;
 }
-#endif  // TEST_PREFIX
 
 TEST(liblog, enoent) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   if (getuid() != 0) {
     GTEST_SKIP() << "Skipping test, must be run as root.";
     return;
   }
 
-  TEST_PREFIX
   log_time ts(CLOCK_MONOTONIC);
   EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
-  EXPECT_EQ(SUPPORTS_END_TO_END, count_matching_ts(ts));
+  EXPECT_EQ(1, count_matching_ts(ts));
 
   // This call will fail unless we are root, beware of any
   // test prior to this one playing with setuid and causing interference.
@@ -1800,19 +1597,17 @@
 
   ts = log_time(CLOCK_MONOTONIC);
   EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
-  EXPECT_EQ(SUPPORTS_END_TO_END, count_matching_ts(ts));
+  EXPECT_EQ(1, count_matching_ts(ts));
 
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 #endif  // __ANDROID__
-#endif  // USING_LOGGER_DEFAULT
 
 // Below this point we run risks of setuid(AID_SYSTEM) which may affect others.
 
 // Do not retest properties, and cannot log into LOG_ID_SECURITY
-#ifdef USING_LOGGER_DEFAULT
 TEST(liblog, __security) {
 #ifdef __ANDROID__
   static const char persist_key[] = "persist.logd.security";
@@ -2069,13 +1864,11 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // USING_LOGGER_DEFAULT
 
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
 static void android_errorWriteWithInfoLog_helper(int TAG, const char* SUBTAG,
                                                  int UID, const char* payload,
                                                  int DATA_LEN, int& count) {
-  TEST_PREFIX
   struct logger_list* logger_list;
 
   pid_t pid = getpid();
@@ -2111,7 +1904,7 @@
     char* original = eventData;
 
     // Tag
-    int tag = get4LE(eventData);
+    int tag = *reinterpret_cast<int32_t*>(eventData);
     eventData += 4;
 
     if (tag != TAG) {
@@ -2138,7 +1931,7 @@
 
     unsigned subtag_len = strlen(SUBTAG);
     if (subtag_len > 32) subtag_len = 32;
-    ASSERT_EQ(subtag_len, get4LE(eventData));
+    ASSERT_EQ(subtag_len, *reinterpret_cast<uint32_t*>(eventData));
     eventData += 4;
 
     if (memcmp(SUBTAG, eventData, subtag_len)) {
@@ -2150,14 +1943,14 @@
     ASSERT_EQ(EVENT_TYPE_INT, eventData[0]);
     eventData++;
 
-    ASSERT_EQ(UID, (int)get4LE(eventData));
+    ASSERT_EQ(UID, *reinterpret_cast<int32_t*>(eventData));
     eventData += 4;
 
     // Element #3: string type for data
     ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
     eventData++;
 
-    size_t dataLen = get4LE(eventData);
+    size_t dataLen = *reinterpret_cast<int32_t*>(eventData);
     eventData += 4;
     if (DATA_LEN < 512) ASSERT_EQ(DATA_LEN, (int)dataLen);
 
@@ -2189,11 +1982,11 @@
 #endif
 
 TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__typical) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   int count;
   android_errorWriteWithInfoLog_helper(UNIQUE_TAG(1), "test-subtag", -1,
                                        max_payload_buf, 200, count);
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+  EXPECT_EQ(1, count);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2201,12 +1994,12 @@
 
 TEST(liblog,
      android_errorWriteWithInfoLog__android_logger_list_read__data_too_large) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   int count;
   android_errorWriteWithInfoLog_helper(UNIQUE_TAG(2), "test-subtag", -1,
                                        max_payload_buf, sizeof(max_payload_buf),
                                        count);
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+  EXPECT_EQ(1, count);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2214,7 +2007,7 @@
 
 TEST(liblog,
      android_errorWriteWithInfoLog__android_logger_list_read__null_data) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   int count;
   android_errorWriteWithInfoLog_helper(UNIQUE_TAG(3), "test-subtag", -1, NULL,
                                        200, count);
@@ -2226,12 +2019,12 @@
 
 TEST(liblog,
      android_errorWriteWithInfoLog__android_logger_list_read__subtag_too_long) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   int count;
   android_errorWriteWithInfoLog_helper(
       UNIQUE_TAG(4), "abcdefghijklmnopqrstuvwxyz now i know my abc", -1,
       max_payload_buf, 200, count);
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+  EXPECT_EQ(1, count);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2245,10 +2038,9 @@
   buf_write_test(max_payload_buf);
 }
 
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
 static void android_errorWriteLog_helper(int TAG, const char* SUBTAG,
                                          int& count) {
-  TEST_PREFIX
   struct logger_list* logger_list;
 
   pid_t pid = getpid();
@@ -2270,7 +2062,7 @@
     if (!eventData) continue;
 
     // Tag
-    int tag = get4LE(eventData);
+    int tag = *reinterpret_cast<int32_t*>(eventData);
     eventData += 4;
 
     if (tag != TAG) continue;
@@ -2323,7 +2115,7 @@
     }
 
     // Tag
-    int tag = get4LE(eventData);
+    int tag = *reinterpret_cast<int32_t*>(eventData);
     eventData += 4;
 
     if (tag != TAG) {
@@ -2348,7 +2140,7 @@
     ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
     eventData++;
 
-    ASSERT_EQ(strlen(SUBTAG), get4LE(eventData));
+    ASSERT_EQ(strlen(SUBTAG), *reinterpret_cast<uint32_t*>(eventData));
     eventData += 4;
 
     if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) {
@@ -2362,17 +2154,17 @@
 #endif
 
 TEST(liblog, android_errorWriteLog__android_logger_list_read__success) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   int count;
   android_errorWriteLog_helper(UNIQUE_TAG(5), "test-subtag", count);
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+  EXPECT_EQ(1, count);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
 TEST(liblog, android_errorWriteLog__android_logger_list_read__null_subtag) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   int count;
   android_errorWriteLog_helper(UNIQUE_TAG(6), NULL, count);
   EXPECT_EQ(0, count);
@@ -2382,7 +2174,7 @@
 }
 
 // Do not retest logger list handling
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
 static int is_real_element(int type) {
   return ((type == EVENT_TYPE_INT) || (type == EVENT_TYPE_LONG) ||
           (type == EVENT_TYPE_STRING) || (type == EVENT_TYPE_FLOAT));
@@ -2537,9 +2329,9 @@
 
   return 0;
 }
-#endif  // TEST_PREFIX
+#endif  // __ANDROID__
 
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
 static const char* event_test_int32(uint32_t tag, size_t& expected_len) {
   android_log_context ctx;
 
@@ -2793,7 +2585,6 @@
 
 static void create_android_logger(const char* (*fn)(uint32_t tag,
                                                     size_t& expected_len)) {
-  TEST_PREFIX
   struct logger_list* logger_list;
 
   pid_t pid = getpid();
@@ -2862,7 +2653,7 @@
     // test buffer reading API
     int buffer_to_string = -1;
     if (eventData) {
-      snprintf(msgBuf, sizeof(msgBuf), "I/[%" PRIu32 "]", get4LE(eventData));
+      snprintf(msgBuf, sizeof(msgBuf), "I/[%" PRIu32 "]", *reinterpret_cast<uint32_t*>(eventData));
       print_barrier();
       fprintf(stderr, "%-10s(%5u): ", msgBuf, pid);
       memset(msgBuf, 0, sizeof(msgBuf));
@@ -2877,14 +2668,14 @@
     EXPECT_EQ(0, strcmp(expected_string, msgBuf));
   }
 
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+  EXPECT_EQ(1, count);
 
   android_logger_list_close(logger_list);
 }
 #endif
 
 TEST(liblog, create_android_logger_int32) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_int32);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2892,7 +2683,7 @@
 }
 
 TEST(liblog, create_android_logger_int64) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_int64);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2900,7 +2691,7 @@
 }
 
 TEST(liblog, create_android_logger_list_int64) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_list_int64);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2908,7 +2699,7 @@
 }
 
 TEST(liblog, create_android_logger_simple_automagic_list) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_simple_automagic_list);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2916,7 +2707,7 @@
 }
 
 TEST(liblog, create_android_logger_list_empty) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_list_empty);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2924,7 +2715,7 @@
 }
 
 TEST(liblog, create_android_logger_complex_nested_list) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_complex_nested_list);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2932,7 +2723,7 @@
 }
 
 TEST(liblog, create_android_logger_7_level_prefix) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_7_level_prefix);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2940,7 +2731,7 @@
 }
 
 TEST(liblog, create_android_logger_7_level_suffix) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_7_level_suffix);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2948,7 +2739,7 @@
 }
 
 TEST(liblog, create_android_logger_android_log_error_write) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_android_log_error_write);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2956,14 +2747,13 @@
 }
 
 TEST(liblog, create_android_logger_android_log_error_write_null) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_android_log_error_write_null);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
-#ifdef USING_LOGGER_DEFAULT  // Do not retest logger list handling
 TEST(liblog, create_android_logger_overflow) {
   android_log_context ctx;
 
@@ -2990,9 +2780,7 @@
   EXPECT_LE(0, android_log_destroy(&ctx));
   ASSERT_TRUE(NULL == ctx);
 }
-#endif  // USING_LOGGER_DEFAULT
 
-#ifdef USING_LOGGER_DEFAULT  // Do not retest pmsg functionality
 #ifdef __ANDROID__
 #ifndef NO_PSTORE
 static const char __pmsg_file[] =
@@ -3129,9 +2917,7 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // USING_LOGGER_DEFAULT
 
-#ifdef USING_LOGGER_DEFAULT  // Do not retest event mapping functionality
 TEST(liblog, android_lookupEventTagNum) {
 #ifdef __ANDROID__
   EventTagMap* map = android_openEventTagMap(NULL);
@@ -3148,4 +2934,3 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // USING_LOGGER_DEFAULT
diff --git a/liblog/tests/liblog_test_default.cpp b/liblog/tests/liblog_test_default.cpp
deleted file mode 100644
index 2edea27..0000000
--- a/liblog/tests/liblog_test_default.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifdef __ANDROID__
-#include <log/log_transport.h>
-#define TEST_LOGGER LOGGER_DEFAULT
-#endif
-#define USING_LOGGER_DEFAULT
-#include "liblog_test.cpp"
diff --git a/liblog/tests/liblog_test_stderr.cpp b/liblog/tests/liblog_test_stderr.cpp
deleted file mode 100644
index abc1b9c..0000000
--- a/liblog/tests/liblog_test_stderr.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <log/log_transport.h>
-#define liblog liblog_stderr
-#define TEST_LOGGER LOGGER_STDERR
-#define USING_LOGGER_STDERR
-#include "liblog_test.cpp"
diff --git a/libmeminfo/tools/procmem.cpp b/libmeminfo/tools/procmem.cpp
index 47881ed..b245f2a 100644
--- a/libmeminfo/tools/procmem.cpp
+++ b/libmeminfo/tools/procmem.cpp
@@ -17,6 +17,7 @@
 #include <errno.h>
 #include <inttypes.h>
 #include <stdlib.h>
+#include <sys/mman.h>
 #include <unistd.h>
 
 #include <iostream>
@@ -59,25 +60,25 @@
 
 static void print_separator(std::stringstream& ss) {
     if (show_wss) {
-        ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n", "-------",
+        ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n",
                                             "-------", "-------", "-------", "-------", "-------",
-                                            "-------", "");
+                                            "-------", "-------", "-------", "");
         return;
     }
-    ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n", "-------",
+    ss << ::android::base::StringPrintf("%7s  %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",
+        ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n", "WRss",
                                             "WPss", "WUss", "WShCl", "WShDi", "WPrCl", "WPrDi",
-                                            "Name");
+                                            "Flags", "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");
+        ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n",
+                                            "Vss", "Rss", "Pss", "Uss", "ShCl", "ShDi", "PrCl",
+                                            "PrDi", "Flags", "Name");
     }
     print_separator(ss);
 }
@@ -103,7 +104,15 @@
             continue;
         }
         print_stats(ss, vma_stats);
-        ss << vma.name << std::endl;
+
+        // TODO: b/141711064 fix libprocinfo to record (p)rivate or (s)hared flag
+        // for now always report as private
+        std::string flags_str("---p");
+        if (vma.flags & PROT_READ) flags_str[0] = 'r';
+        if (vma.flags & PROT_WRITE) flags_str[1] = 'w';
+        if (vma.flags & PROT_EXEC) flags_str[2] = 'x';
+
+        ss << ::android::base::StringPrintf("%7s  ", flags_str.c_str()) << vma.name << std::endl;
     }
     print_separator(ss);
     print_stats(ss, proc_stats);
diff --git a/libnativebridge/CPPLINT.cfg b/libnativebridge/CPPLINT.cfg
new file mode 100644
index 0000000..578047b
--- /dev/null
+++ b/libnativebridge/CPPLINT.cfg
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+filter=-build/header_guard
+filter=-whitespace/comments
+filter=-whitespace/parens
diff --git a/libnativeloader/CPPLINT.cfg b/libnativeloader/CPPLINT.cfg
new file mode 100644
index 0000000..db98533
--- /dev/null
+++ b/libnativeloader/CPPLINT.cfg
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+filter=-build/header_guard
+filter=-readability/check
+filter=-build/namespaces
diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h
index 13ce10f..6c5cfc4 100644
--- a/libunwindstack/include/unwindstack/MapInfo.h
+++ b/libunwindstack/include/unwindstack/MapInfo.h
@@ -59,11 +59,14 @@
   uint16_t flags = 0;
   std::string name;
   std::shared_ptr<Elf> elf;
+  // The offset of the beginning of this mapping to the beginning of the
+  // ELF file.
+  // elf_offset == offset - elf_start_offset.
   // This value is only non-zero if the offset is non-zero but there is
   // no elf signature found at that offset.
   uint64_t elf_offset = 0;
-  // This value is the offset from the map in memory that is the start
-  // of the elf. This is not equal to offset when the linker splits
+  // This value is the offset into the file of the map in memory that is the
+  // start of the elf. This is not equal to offset when the linker splits
   // shared libraries into a read-only and read-execute map.
   uint64_t elf_start_offset = 0;
 
diff --git a/lmkd/README.md b/lmkd/README.md
index 656a6ea..8a73692 100644
--- a/lmkd/README.md
+++ b/lmkd/README.md
@@ -60,6 +60,31 @@
                              any eligible task (fast decision). Default = false
 
   ro.lmk.kill_timeout_ms:    duration in ms after a kill when no additional
-                             kill will be done, Default = 0 (disabled)
+                             kill will be done. Default = 0 (disabled)
 
   ro.lmk.debug:              enable lmkd debug logs, Default = false
+
+  ro.lmk.swap_free_low_percentage: level of free swap as a percentage of the
+                             total swap space used as a threshold to consider
+                             the system as swap space starved. Default for
+                             low-RAM devices = 10, for high-end devices = 20
+
+  ro.lmk.thrashing_limit:    number of workingset refaults as a percentage of
+                             the file-backed pagecache size used as a threshold
+                             to consider system thrashing its pagecache.
+                             Default for low-RAM devices = 30, for high-end
+                             devices = 100
+
+  ro.lmk.thrashing_limit_decay: thrashing threshold decay expressed as a
+                             percentage of the original threshold used to lower
+                             the threshold when system does not recover even
+                             after a kill. Default for low-RAM devices = 50,
+                             for high-end devices = 10
+
+  ro.lmk.psi_partial_stall_ms: partial PSI stall threshold in milliseconds for
+                             triggering low memory notification. Default for
+                             low-RAM devices = 200, for high-end devices = 70
+
+  ro.lmk.psi_complete_stall_ms: complete PSI stall threshold in milliseconds for
+                             triggering critical memory notification. Default =
+                             700
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index f06717d..2ba3f44 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -79,9 +79,12 @@
 #define MEMCG_MEMORYSW_USAGE "/dev/memcg/memory.memsw.usage_in_bytes"
 #define ZONEINFO_PATH "/proc/zoneinfo"
 #define MEMINFO_PATH "/proc/meminfo"
+#define VMSTAT_PATH "/proc/vmstat"
 #define PROC_STATUS_TGID_FIELD "Tgid:"
 #define LINE_MAX 128
 
+#define PERCEPTIBLE_APP_ADJ 200
+
 /* Android Logger event logtags (see event.logtags) */
 #define MEMINFO_LOG_TAG 10195355
 
@@ -110,15 +113,34 @@
  * PSI_WINDOW_SIZE_MS after the event happens.
  */
 #define PSI_WINDOW_SIZE_MS 1000
-/* Polling period after initial PSI signal */
-#define PSI_POLL_PERIOD_MS 10
-/* Poll for the duration of one window after initial PSI signal */
-#define PSI_POLL_COUNT (PSI_WINDOW_SIZE_MS / PSI_POLL_PERIOD_MS)
+/* Polling period after PSI signal when pressure is high */
+#define PSI_POLL_PERIOD_SHORT_MS 10
+/* Polling period after PSI signal when pressure is low */
+#define PSI_POLL_PERIOD_LONG_MS 100
 
 #define min(a, b) (((a) < (b)) ? (a) : (b))
+#define max(a, b) (((a) > (b)) ? (a) : (b))
 
 #define FAIL_REPORT_RLIMIT_MS 1000
 
+/*
+ * System property defaults
+ */
+/* ro.lmk.swap_free_low_percentage property defaults */
+#define DEF_LOW_SWAP_LOWRAM 10
+#define DEF_LOW_SWAP 20
+/* ro.lmk.thrashing_limit property defaults */
+#define DEF_THRASHING_LOWRAM 30
+#define DEF_THRASHING 100
+/* ro.lmk.thrashing_limit_decay property defaults */
+#define DEF_THRASHING_DECAY_LOWRAM 50
+#define DEF_THRASHING_DECAY 10
+/* ro.lmk.psi_partial_stall_ms property defaults */
+#define DEF_PARTIAL_STALL_LOWRAM 200
+#define DEF_PARTIAL_STALL 70
+/* ro.lmk.psi_complete_stall_ms property defaults */
+#define DEF_COMPLETE_STALL 700
+
 /* default to old in-kernel interface if no memory pressure events */
 static bool use_inkernel_interface = true;
 static bool has_inkernel_module;
@@ -159,6 +181,10 @@
 static bool use_minfree_levels;
 static bool per_app_memcg;
 static int swap_free_low_percentage;
+static int psi_partial_stall_ms;
+static int psi_complete_stall_ms;
+static int thrashing_limit_pct;
+static int thrashing_limit_decay_pct;
 static bool use_psi_monitors = false;
 static struct psi_threshold psi_thresholds[VMPRESS_LEVEL_COUNT] = {
     { PSI_SOME, 70 },    /* 70ms out of 1sec for partial stall */
@@ -168,10 +194,30 @@
 
 static android_log_context ctx;
 
+enum polling_update {
+    POLLING_DO_NOT_CHANGE,
+    POLLING_START,
+    POLLING_STOP,
+};
+
+/*
+ * Data used for periodic polling for the memory state of the device.
+ * Note that when system is not polling poll_handler is set to NULL,
+ * when polling starts poll_handler gets set and is reset back to
+ * NULL when polling stops.
+ */
+struct polling_params {
+    struct event_handler_info* poll_handler;
+    struct timespec poll_start_tm;
+    struct timespec last_poll_tm;
+    int polling_interval_ms;
+    enum polling_update update;
+};
+
 /* data required to handle events */
 struct event_handler_info {
     int data;
-    void (*handler)(int data, uint32_t events);
+    void (*handler)(int data, uint32_t events, struct polling_params *poll_params);
 };
 
 /* data required to handle socket events */
@@ -204,37 +250,99 @@
 static int lowmem_targets_size;
 
 /* Fields to parse in /proc/zoneinfo */
-enum zoneinfo_field {
-    ZI_NR_FREE_PAGES = 0,
-    ZI_NR_FILE_PAGES,
-    ZI_NR_SHMEM,
-    ZI_NR_UNEVICTABLE,
-    ZI_WORKINGSET_REFAULT,
-    ZI_HIGH,
-    ZI_FIELD_COUNT
+/* zoneinfo per-zone fields */
+enum zoneinfo_zone_field {
+    ZI_ZONE_NR_FREE_PAGES = 0,
+    ZI_ZONE_MIN,
+    ZI_ZONE_LOW,
+    ZI_ZONE_HIGH,
+    ZI_ZONE_PRESENT,
+    ZI_ZONE_NR_FREE_CMA,
+    ZI_ZONE_FIELD_COUNT
 };
 
-static const char* const zoneinfo_field_names[ZI_FIELD_COUNT] = {
+static const char* const zoneinfo_zone_field_names[ZI_ZONE_FIELD_COUNT] = {
     "nr_free_pages",
-    "nr_file_pages",
-    "nr_shmem",
-    "nr_unevictable",
-    "workingset_refault",
+    "min",
+    "low",
     "high",
+    "present",
+    "nr_free_cma",
 };
 
-union zoneinfo {
+/* zoneinfo per-zone special fields */
+enum zoneinfo_zone_spec_field {
+    ZI_ZONE_SPEC_PROTECTION = 0,
+    ZI_ZONE_SPEC_PAGESETS,
+    ZI_ZONE_SPEC_FIELD_COUNT,
+};
+
+static const char* const zoneinfo_zone_spec_field_names[ZI_ZONE_SPEC_FIELD_COUNT] = {
+    "protection:",
+    "pagesets",
+};
+
+/* see __MAX_NR_ZONES definition in kernel mmzone.h */
+#define MAX_NR_ZONES 6
+
+union zoneinfo_zone_fields {
     struct {
         int64_t nr_free_pages;
-        int64_t nr_file_pages;
-        int64_t nr_shmem;
-        int64_t nr_unevictable;
-        int64_t workingset_refault;
+        int64_t min;
+        int64_t low;
         int64_t high;
-        /* fields below are calculated rather than read from the file */
-        int64_t totalreserve_pages;
+        int64_t present;
+        int64_t nr_free_cma;
     } field;
-    int64_t arr[ZI_FIELD_COUNT];
+    int64_t arr[ZI_ZONE_FIELD_COUNT];
+};
+
+struct zoneinfo_zone {
+    union zoneinfo_zone_fields fields;
+    int64_t protection[MAX_NR_ZONES];
+    int64_t max_protection;
+};
+
+/* zoneinfo per-node fields */
+enum zoneinfo_node_field {
+    ZI_NODE_NR_INACTIVE_FILE = 0,
+    ZI_NODE_NR_ACTIVE_FILE,
+    ZI_NODE_WORKINGSET_REFAULT,
+    ZI_NODE_FIELD_COUNT
+};
+
+static const char* const zoneinfo_node_field_names[ZI_NODE_FIELD_COUNT] = {
+    "nr_inactive_file",
+    "nr_active_file",
+    "workingset_refault",
+};
+
+union zoneinfo_node_fields {
+    struct {
+        int64_t nr_inactive_file;
+        int64_t nr_active_file;
+        int64_t workingset_refault;
+    } field;
+    int64_t arr[ZI_NODE_FIELD_COUNT];
+};
+
+struct zoneinfo_node {
+    int id;
+    int zone_count;
+    struct zoneinfo_zone zones[MAX_NR_ZONES];
+    union zoneinfo_node_fields fields;
+};
+
+/* for now two memory nodes is more than enough */
+#define MAX_NR_NODES 2
+
+struct zoneinfo {
+    int node_count;
+    struct zoneinfo_node nodes[MAX_NR_NODES];
+    int64_t totalreserve_pages;
+    int64_t total_inactive_file;
+    int64_t total_active_file;
+    int64_t total_workingset_refault;
 };
 
 /* Fields to parse in /proc/meminfo */
@@ -310,6 +418,41 @@
     int64_t arr[MI_FIELD_COUNT];
 };
 
+/* Fields to parse in /proc/vmstat */
+enum vmstat_field {
+    VS_FREE_PAGES,
+    VS_INACTIVE_FILE,
+    VS_ACTIVE_FILE,
+    VS_WORKINGSET_REFAULT,
+    VS_PGSCAN_KSWAPD,
+    VS_PGSCAN_DIRECT,
+    VS_PGSCAN_DIRECT_THROTTLE,
+    VS_FIELD_COUNT
+};
+
+static const char* const vmstat_field_names[MI_FIELD_COUNT] = {
+    "nr_free_pages",
+    "nr_inactive_file",
+    "nr_active_file",
+    "workingset_refault",
+    "pgscan_kswapd",
+    "pgscan_direct",
+    "pgscan_direct_throttle",
+};
+
+union vmstat {
+    struct {
+        int64_t nr_free_pages;
+        int64_t nr_inactive_file;
+        int64_t nr_active_file;
+        int64_t workingset_refault;
+        int64_t pgscan_kswapd;
+        int64_t pgscan_direct;
+        int64_t pgscan_direct_throttle;
+    } field;
+    int64_t arr[VS_FIELD_COUNT];
+};
+
 enum field_match_result {
     NO_MATCH,
     PARSE_FAIL,
@@ -365,6 +508,10 @@
 static char* proc_get_name(int pid);
 static void poll_kernel();
 
+static int clamp(int low, int high, int value) {
+    return max(min(value, high), low);
+}
+
 static bool parse_int64(const char* str, int64_t* ret) {
     char* endptr;
     long long val = strtoll(str, &endptr, 10);
@@ -375,20 +522,25 @@
     return true;
 }
 
+static int find_field(const char* name, const char* const field_names[], int field_count) {
+    for (int i = 0; i < field_count; i++) {
+        if (!strcmp(name, field_names[i])) {
+            return i;
+        }
+    }
+    return -1;
+}
+
 static enum field_match_result match_field(const char* cp, const char* ap,
                                    const char* const field_names[],
                                    int field_count, int64_t* field,
                                    int *field_idx) {
-    int64_t val;
-    int i;
-
-    for (i = 0; i < field_count; i++) {
-        if (!strcmp(cp, field_names[i])) {
-            *field_idx = i;
-            return parse_int64(ap, field) ? PARSE_SUCCESS : PARSE_FAIL;
-        }
+    int i = find_field(cp, field_names, field_count);
+    if (i < 0) {
+        return NO_MATCH;
     }
-    return NO_MATCH;
+    *field_idx = i;
+    return parse_int64(ap, field) ? PARSE_SUCCESS : PARSE_FAIL;
 }
 
 /*
@@ -424,28 +576,50 @@
  * memory pressure to minimize file opening which by itself requires kernel
  * memory allocation and might result in a stall on memory stressed system.
  */
-static int reread_file(struct reread_data *data, char *buf, size_t buf_size) {
+static char *reread_file(struct reread_data *data) {
+    /* start with page-size buffer and increase if needed */
+    static ssize_t buf_size = PAGE_SIZE;
+    static char *new_buf, *buf = NULL;
     ssize_t size;
 
     if (data->fd == -1) {
-        data->fd = open(data->filename, O_RDONLY | O_CLOEXEC);
-        if (data->fd == -1) {
+        /* First-time buffer initialization */
+        if (!buf && (buf = malloc(buf_size)) == NULL) {
+            return NULL;
+        }
+
+        data->fd = TEMP_FAILURE_RETRY(open(data->filename, O_RDONLY | O_CLOEXEC));
+        if (data->fd < 0) {
             ALOGE("%s open: %s", data->filename, strerror(errno));
-            return -1;
+            return NULL;
         }
     }
 
-    size = read_all(data->fd, buf, buf_size - 1);
-    if (size < 0) {
-        ALOGE("%s read: %s", data->filename, strerror(errno));
-        close(data->fd);
-        data->fd = -1;
-        return -1;
+    while (true) {
+        size = read_all(data->fd, buf, buf_size - 1);
+        if (size < 0) {
+            ALOGE("%s read: %s", data->filename, strerror(errno));
+            close(data->fd);
+            data->fd = -1;
+            return NULL;
+        }
+        if (size < buf_size - 1) {
+            break;
+        }
+        /*
+         * Since we are reading /proc files we can't use fstat to find out
+         * the real size of the file. Double the buffer size and keep retrying.
+         */
+        if ((new_buf = realloc(buf, buf_size * 2)) == NULL) {
+            errno = ENOMEM;
+            return NULL;
+        }
+        buf = new_buf;
+        buf_size *= 2;
     }
-    ALOG_ASSERT((size_t)size < buf_size - 1, "%s too large", data->filename);
     buf[size] = 0;
 
-    return 0;
+    return buf;
 }
 
 static struct proc *pid_lookup(int pid) {
@@ -1002,7 +1176,8 @@
     ALOGE("Wrong control socket read length cmd=%d len=%d", cmd, len);
 }
 
-static void ctrl_data_handler(int data, uint32_t events) {
+static void ctrl_data_handler(int data, uint32_t events,
+                              struct polling_params *poll_params __unused) {
     if (events & EPOLLIN) {
         ctrl_command_handler(data);
     }
@@ -1017,7 +1192,8 @@
     return -1;
 }
 
-static void ctrl_connect_handler(int data __unused, uint32_t events __unused) {
+static void ctrl_connect_handler(int data __unused, uint32_t events __unused,
+                                 struct polling_params *poll_params __unused) {
     struct epoll_event epev;
     int free_dscock_idx = get_free_dsock();
 
@@ -1138,91 +1314,202 @@
 }
 #endif
 
-/* /prop/zoneinfo parsing routines */
-static int64_t zoneinfo_parse_protection(char *cp) {
+/*
+ * /proc/zoneinfo parsing routines
+ * Expected file format is:
+ *
+ *   Node <node_id>, zone   <zone_name>
+ *   (
+ *    per-node stats
+ *       (<per-node field name> <value>)+
+ *   )?
+ *   (pages free     <value>
+ *       (<per-zone field name> <value>)+
+ *    pagesets
+ *       (<unused fields>)*
+ *   )+
+ *   ...
+ */
+static void zoneinfo_parse_protection(char *buf, struct zoneinfo_zone *zone) {
+    int zone_idx;
     int64_t max = 0;
-    long long zoneval;
     char *save_ptr;
 
-    for (cp = strtok_r(cp, "(), ", &save_ptr); cp;
-         cp = strtok_r(NULL, "), ", &save_ptr)) {
-        zoneval = strtoll(cp, &cp, 0);
+    for (buf = strtok_r(buf, "(), ", &save_ptr), zone_idx = 0;
+         buf && zone_idx < MAX_NR_ZONES;
+         buf = strtok_r(NULL, "), ", &save_ptr), zone_idx++) {
+        long long zoneval = strtoll(buf, &buf, 0);
         if (zoneval > max) {
             max = (zoneval > INT64_MAX) ? INT64_MAX : zoneval;
         }
+        zone->protection[zone_idx] = zoneval;
     }
-
-    return max;
+    zone->max_protection = max;
 }
 
-static bool zoneinfo_parse_line(char *line, union zoneinfo *zi) {
-    char *cp = line;
-    char *ap;
-    char *save_ptr;
-    int64_t val;
-    int field_idx;
+static int zoneinfo_parse_zone(char **buf, struct zoneinfo_zone *zone) {
+    for (char *line = strtok_r(NULL, "\n", buf); line;
+         line = strtok_r(NULL, "\n", buf)) {
+        char *cp;
+        char *ap;
+        char *save_ptr;
+        int64_t val;
+        int field_idx;
+        enum field_match_result match_res;
 
-    cp = strtok_r(line, " ", &save_ptr);
-    if (!cp) {
-        return true;
-    }
-
-    if (!strcmp(cp, "protection:")) {
-        ap = strtok_r(NULL, ")", &save_ptr);
-    } else {
-        ap = strtok_r(NULL, " ", &save_ptr);
-    }
-
-    if (!ap) {
-        return true;
-    }
-
-    switch (match_field(cp, ap, zoneinfo_field_names,
-                        ZI_FIELD_COUNT, &val, &field_idx)) {
-    case (PARSE_SUCCESS):
-        zi->arr[field_idx] += val;
-        break;
-    case (NO_MATCH):
-        if (!strcmp(cp, "protection:")) {
-            zi->field.totalreserve_pages +=
-                zoneinfo_parse_protection(ap);
+        cp = strtok_r(line, " ", &save_ptr);
+        if (!cp) {
+            return false;
         }
-        break;
-    case (PARSE_FAIL):
-    default:
-        return false;
+
+        field_idx = find_field(cp, zoneinfo_zone_spec_field_names, ZI_ZONE_SPEC_FIELD_COUNT);
+        if (field_idx >= 0) {
+            /* special field */
+            if (field_idx == ZI_ZONE_SPEC_PAGESETS) {
+                /* no mode fields we are interested in */
+                return true;
+            }
+
+            /* protection field */
+            ap = strtok_r(NULL, ")", &save_ptr);
+            if (ap) {
+                zoneinfo_parse_protection(ap, zone);
+            }
+            continue;
+        }
+
+        ap = strtok_r(NULL, " ", &save_ptr);
+        if (!ap) {
+            continue;
+        }
+
+        match_res = match_field(cp, ap, zoneinfo_zone_field_names, ZI_ZONE_FIELD_COUNT,
+            &val, &field_idx);
+        if (match_res == PARSE_FAIL) {
+            return false;
+        }
+        if (match_res == PARSE_SUCCESS) {
+            zone->fields.arr[field_idx] = val;
+        }
+        if (field_idx == ZI_ZONE_PRESENT && val == 0) {
+            /* zone is not populated, stop parsing it */
+            return true;
+        }
     }
-    return true;
+    return false;
 }
 
-static int zoneinfo_parse(union zoneinfo *zi) {
+static int zoneinfo_parse_node(char **buf, struct zoneinfo_node *node) {
+    int fields_to_match = ZI_NODE_FIELD_COUNT;
+
+    for (char *line = strtok_r(NULL, "\n", buf); line;
+         line = strtok_r(NULL, "\n", buf)) {
+        char *cp;
+        char *ap;
+        char *save_ptr;
+        int64_t val;
+        int field_idx;
+        enum field_match_result match_res;
+
+        cp = strtok_r(line, " ", &save_ptr);
+        if (!cp) {
+            return false;
+        }
+
+        ap = strtok_r(NULL, " ", &save_ptr);
+        if (!ap) {
+            return false;
+        }
+
+        match_res = match_field(cp, ap, zoneinfo_node_field_names, ZI_NODE_FIELD_COUNT,
+            &val, &field_idx);
+        if (match_res == PARSE_FAIL) {
+            return false;
+        }
+        if (match_res == PARSE_SUCCESS) {
+            node->fields.arr[field_idx] = val;
+            fields_to_match--;
+            if (!fields_to_match) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+static int zoneinfo_parse(struct zoneinfo *zi) {
     static struct reread_data file_data = {
         .filename = ZONEINFO_PATH,
         .fd = -1,
     };
-    char buf[PAGE_SIZE];
+    char *buf;
     char *save_ptr;
     char *line;
+    char zone_name[LINE_MAX];
+    struct zoneinfo_node *node = NULL;
+    int node_idx = 0;
+    int zone_idx = 0;
 
-    memset(zi, 0, sizeof(union zoneinfo));
+    memset(zi, 0, sizeof(struct zoneinfo));
 
-    if (reread_file(&file_data, buf, sizeof(buf)) < 0) {
+    if ((buf = reread_file(&file_data)) == NULL) {
         return -1;
     }
 
     for (line = strtok_r(buf, "\n", &save_ptr); line;
          line = strtok_r(NULL, "\n", &save_ptr)) {
-        if (!zoneinfo_parse_line(line, zi)) {
-            ALOGE("%s parse error", file_data.filename);
-            return -1;
+        int node_id;
+        if (sscanf(line, "Node %d, zone %" STRINGIFY(LINE_MAX) "s", &node_id, zone_name) == 2) {
+            if (!node || node->id != node_id) {
+                /* new node is found */
+                if (node) {
+                    node->zone_count = zone_idx + 1;
+                    node_idx++;
+                    if (node_idx == MAX_NR_NODES) {
+                        /* max node count exceeded */
+                        ALOGE("%s parse error", file_data.filename);
+                        return -1;
+                    }
+                }
+                node = &zi->nodes[node_idx];
+                node->id = node_id;
+                zone_idx = 0;
+                if (!zoneinfo_parse_node(&save_ptr, node)) {
+                    ALOGE("%s parse error", file_data.filename);
+                    return -1;
+                }
+            } else {
+                /* new zone is found */
+                zone_idx++;
+            }
+            if (!zoneinfo_parse_zone(&save_ptr, &node->zones[zone_idx])) {
+                ALOGE("%s parse error", file_data.filename);
+                return -1;
+            }
         }
     }
-    zi->field.totalreserve_pages += zi->field.high;
+    if (!node) {
+        ALOGE("%s parse error", file_data.filename);
+        return -1;
+    }
+    node->zone_count = zone_idx + 1;
+    zi->node_count = node_idx + 1;
 
+    /* calculate totals fields */
+    for (node_idx = 0; node_idx < zi->node_count; node_idx++) {
+        node = &zi->nodes[node_idx];
+        for (zone_idx = 0; zone_idx < node->zone_count; zone_idx++) {
+            struct zoneinfo_zone *zone = &zi->nodes[node_idx].zones[zone_idx];
+            zi->totalreserve_pages += zone->max_protection + zone->fields.field.high;
+        }
+        zi->total_inactive_file += node->fields.field.nr_inactive_file;
+        zi->total_active_file += node->fields.field.nr_active_file;
+        zi->total_workingset_refault += node->fields.field.workingset_refault;
+    }
     return 0;
 }
 
-/* /prop/meminfo parsing routines */
+/* /proc/meminfo parsing routines */
 static bool meminfo_parse_line(char *line, union meminfo *mi) {
     char *cp = line;
     char *ap;
@@ -1254,13 +1541,13 @@
         .filename = MEMINFO_PATH,
         .fd = -1,
     };
-    char buf[PAGE_SIZE];
+    char *buf;
     char *save_ptr;
     char *line;
 
     memset(mi, 0, sizeof(union meminfo));
 
-    if (reread_file(&file_data, buf, sizeof(buf)) < 0) {
+    if ((buf = reread_file(&file_data)) == NULL) {
         return -1;
     }
 
@@ -1277,6 +1564,59 @@
     return 0;
 }
 
+/* /proc/vmstat parsing routines */
+static bool vmstat_parse_line(char *line, union vmstat *vs) {
+    char *cp;
+    char *ap;
+    char *save_ptr;
+    int64_t val;
+    int field_idx;
+    enum field_match_result match_res;
+
+    cp = strtok_r(line, " ", &save_ptr);
+    if (!cp) {
+        return false;
+    }
+
+    ap = strtok_r(NULL, " ", &save_ptr);
+    if (!ap) {
+        return false;
+    }
+
+    match_res = match_field(cp, ap, vmstat_field_names, VS_FIELD_COUNT,
+        &val, &field_idx);
+    if (match_res == PARSE_SUCCESS) {
+        vs->arr[field_idx] = val;
+    }
+    return (match_res != PARSE_FAIL);
+}
+
+static int vmstat_parse(union vmstat *vs) {
+    static struct reread_data file_data = {
+        .filename = VMSTAT_PATH,
+        .fd = -1,
+    };
+    char *buf;
+    char *save_ptr;
+    char *line;
+
+    memset(vs, 0, sizeof(union vmstat));
+
+    if ((buf = reread_file(&file_data)) == NULL) {
+        return -1;
+    }
+
+    for (line = strtok_r(buf, "\n", &save_ptr); line;
+         line = strtok_r(NULL, "\n", &save_ptr)) {
+        if (!vmstat_parse_line(line, vs)) {
+            ALOGE("%s parse error", file_data.filename);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
 static void meminfo_log(union meminfo *mi) {
     for (int field_idx = 0; field_idx < MI_FIELD_COUNT; field_idx++) {
         android_log_write_int32(ctx, (int32_t)min(mi->arr[field_idx] * page_k, INT32_MAX));
@@ -1321,8 +1661,9 @@
     /* gid containing AID_READPROC required */
     snprintf(path, PATH_MAX, "/proc/%d/cmdline", pid);
     fd = open(path, O_RDONLY | O_CLOEXEC);
-    if (fd == -1)
+    if (fd == -1) {
         return NULL;
+    }
     ret = read_all(fd, line, sizeof(line) - 1);
     close(fd);
     if (ret < 0) {
@@ -1330,8 +1671,11 @@
     }
 
     cp = strchr(line, ' ');
-    if (cp)
+    if (cp) {
         *cp = '\0';
+    } else {
+        line[ret] = '\0';
+    }
 
     return line;
 }
@@ -1401,7 +1745,7 @@
 static int last_killed_pid = -1;
 
 /* Kill one process specified by procp.  Returns the size of the process killed */
-static int kill_one_process(struct proc* procp, int min_oom_score) {
+static int kill_one_process(struct proc* procp, int min_oom_score, const char *reason) {
     int pid = procp->pid;
     uid_t uid = procp->uid;
     int tgid;
@@ -1452,8 +1796,13 @@
     set_process_group_and_prio(pid, SP_FOREGROUND, ANDROID_PRIORITY_HIGHEST);
 
     inc_killcnt(procp->oomadj);
-    ALOGE("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB", taskname, pid, uid, procp->oomadj,
-          tasksize * page_k);
+    if (reason) {
+        ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB; reason: %s", taskname, pid,
+              uid, procp->oomadj, tasksize * page_k, reason);
+    } else {
+        ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB", taskname, pid,
+              uid, procp->oomadj, tasksize * page_k);
+    }
 
     TRACE_KILL_END();
 
@@ -1491,7 +1840,7 @@
  * Find one process to kill at or above the given oom_adj level.
  * Returns size of the killed process.
  */
-static int find_and_kill_process(int min_score_adj) {
+static int find_and_kill_process(int min_score_adj, const char *reason) {
     int i;
     int killed_size = 0;
 
@@ -1509,7 +1858,7 @@
             if (!procp)
                 break;
 
-            killed_size = kill_one_process(procp, min_score_adj);
+            killed_size = kill_one_process(procp, min_score_adj, reason);
             if (killed_size >= 0) {
 #ifdef LMKD_LOG_STATS
                 if (enable_stats_log && !lmk_state_change_start) {
@@ -1538,9 +1887,9 @@
 static int64_t get_memory_usage(struct reread_data *file_data) {
     int ret;
     int64_t mem_usage;
-    char buf[32];
+    char *buf;
 
-    if (reread_file(file_data, buf, sizeof(buf)) < 0) {
+    if ((buf = reread_file(file_data)) == NULL) {
         return -1;
     }
 
@@ -1609,14 +1958,277 @@
     return false;
 }
 
-static void mp_event_common(int data, uint32_t events __unused) {
+enum zone_watermark {
+    WMARK_MIN = 0,
+    WMARK_LOW,
+    WMARK_HIGH,
+    WMARK_NONE
+};
+
+struct zone_watermarks {
+    long high_wmark;
+    long low_wmark;
+    long min_wmark;
+};
+
+/*
+ * Returns lowest breached watermark or WMARK_NONE.
+ */
+static enum zone_watermark get_lowest_watermark(union meminfo *mi,
+                                                struct zone_watermarks *watermarks)
+{
+    int64_t nr_free_pages = mi->field.nr_free_pages - mi->field.cma_free;
+
+    if (nr_free_pages < watermarks->min_wmark) {
+        return WMARK_MIN;
+    }
+    if (nr_free_pages < watermarks->low_wmark) {
+        return WMARK_LOW;
+    }
+    if (nr_free_pages < watermarks->high_wmark) {
+        return WMARK_HIGH;
+    }
+    return WMARK_NONE;
+}
+
+void calc_zone_watermarks(struct zoneinfo *zi, struct zone_watermarks *watermarks) {
+    memset(watermarks, 0, sizeof(struct zone_watermarks));
+
+    for (int node_idx = 0; node_idx < zi->node_count; node_idx++) {
+        struct zoneinfo_node *node = &zi->nodes[node_idx];
+        for (int zone_idx = 0; zone_idx < node->zone_count; zone_idx++) {
+            struct zoneinfo_zone *zone = &node->zones[zone_idx];
+
+            if (!zone->fields.field.present) {
+                continue;
+            }
+
+            watermarks->high_wmark += zone->max_protection + zone->fields.field.high;
+            watermarks->low_wmark += zone->max_protection + zone->fields.field.low;
+            watermarks->min_wmark += zone->max_protection + zone->fields.field.min;
+        }
+    }
+}
+
+static void mp_event_psi(int data, uint32_t events, struct polling_params *poll_params) {
+    enum kill_reasons {
+        NONE = -1, /* To denote no kill condition */
+        PRESSURE_AFTER_KILL = 0,
+        NOT_RESPONDING,
+        LOW_SWAP_AND_THRASHING,
+        LOW_MEM_AND_SWAP,
+        LOW_MEM_AND_THRASHING,
+        DIRECT_RECL_AND_THRASHING,
+        KILL_REASON_COUNT
+    };
+    enum reclaim_state {
+        NO_RECLAIM = 0,
+        KSWAPD_RECLAIM,
+        DIRECT_RECLAIM,
+    };
+    static int64_t init_ws_refault;
+    static int64_t base_file_lru;
+    static int64_t init_pgscan_kswapd;
+    static int64_t init_pgscan_direct;
+    static int64_t swap_low_threshold;
+    static bool killing;
+    static int thrashing_limit;
+    static bool in_reclaim;
+    static struct zone_watermarks watermarks;
+    static struct timespec wmark_update_tm;
+
+    union meminfo mi;
+    union vmstat vs;
+    struct timespec curr_tm;
+    int64_t thrashing = 0;
+    bool swap_is_low = false;
+    enum vmpressure_level level = (enum vmpressure_level)data;
+    enum kill_reasons kill_reason = NONE;
+    bool cycle_after_kill = false;
+    enum reclaim_state reclaim = NO_RECLAIM;
+    enum zone_watermark wmark = WMARK_NONE;
+    char kill_desc[LINE_MAX];
+    bool cut_thrashing_limit = false;
+    int min_score_adj = 0;
+
+    /* Skip while still killing a process */
+    if (is_kill_pending()) {
+        /* TODO: replace this quick polling with pidfd polling if kernel supports */
+        goto no_kill;
+    }
+
+    if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
+        ALOGE("Failed to get current time");
+        return;
+    }
+
+    if (vmstat_parse(&vs) < 0) {
+        ALOGE("Failed to parse vmstat!");
+        return;
+    }
+
+    if (meminfo_parse(&mi) < 0) {
+        ALOGE("Failed to parse meminfo!");
+        return;
+    }
+
+    /* Reset states after process got killed */
+    if (killing) {
+        killing = false;
+        cycle_after_kill = true;
+        /* Reset file-backed pagecache size and refault amounts after a kill */
+        base_file_lru = vs.field.nr_inactive_file + vs.field.nr_active_file;
+        init_ws_refault = vs.field.workingset_refault;
+    }
+
+    /* Check free swap levels */
+    if (swap_free_low_percentage) {
+        if (!swap_low_threshold) {
+            swap_low_threshold = mi.field.total_swap * swap_free_low_percentage / 100;
+        }
+        swap_is_low = mi.field.free_swap < swap_low_threshold;
+    }
+
+    /* Identify reclaim state */
+    if (vs.field.pgscan_direct > init_pgscan_direct) {
+        init_pgscan_direct = vs.field.pgscan_direct;
+        init_pgscan_kswapd = vs.field.pgscan_kswapd;
+        reclaim = DIRECT_RECLAIM;
+    } else if (vs.field.pgscan_kswapd > init_pgscan_kswapd) {
+        init_pgscan_kswapd = vs.field.pgscan_kswapd;
+        reclaim = KSWAPD_RECLAIM;
+    } else {
+        in_reclaim = false;
+        /* Skip if system is not reclaiming */
+        goto no_kill;
+    }
+
+    if (!in_reclaim) {
+        /* Record file-backed pagecache size when entering reclaim cycle */
+        base_file_lru = vs.field.nr_inactive_file + vs.field.nr_active_file;
+        init_ws_refault = vs.field.workingset_refault;
+        thrashing_limit = thrashing_limit_pct;
+    } else {
+        /* Calculate what % of the file-backed pagecache refaulted so far */
+        thrashing = (vs.field.workingset_refault - init_ws_refault) * 100 / base_file_lru;
+    }
+    in_reclaim = true;
+
+    /*
+     * Refresh watermarks once per min in case user updated one of the margins.
+     * TODO: b/140521024 replace this periodic update with an API for AMS to notify LMKD
+     * that zone watermarks were changed by the system software.
+     */
+    if (watermarks.high_wmark == 0 || get_time_diff_ms(&wmark_update_tm, &curr_tm) > 60000) {
+        struct zoneinfo zi;
+
+        if (zoneinfo_parse(&zi) < 0) {
+            ALOGE("Failed to parse zoneinfo!");
+            return;
+        }
+
+        calc_zone_watermarks(&zi, &watermarks);
+        wmark_update_tm = curr_tm;
+     }
+
+    /* Find out which watermark is breached if any */
+    wmark = get_lowest_watermark(&mi, &watermarks);
+
+    /*
+     * TODO: move this logic into a separate function
+     * Decide if killing a process is necessary and record the reason
+     */
+    if (cycle_after_kill && wmark < WMARK_LOW) {
+        /*
+         * Prevent kills not freeing enough memory which might lead to OOM kill.
+         * This might happen when a process is consuming memory faster than reclaim can
+         * free even after a kill. Mostly happens when running memory stress tests.
+         */
+        kill_reason = PRESSURE_AFTER_KILL;
+        strncpy(kill_desc, "min watermark is breached even after kill", sizeof(kill_desc));
+    } else if (level == VMPRESS_LEVEL_CRITICAL && events != 0) {
+        /*
+         * Device is too busy reclaiming memory which might lead to ANR.
+         * Critical level is triggered when PSI complete stall (all tasks are blocked because
+         * of the memory congestion) breaches the configured threshold.
+         */
+        kill_reason = NOT_RESPONDING;
+        strncpy(kill_desc, "device is not responding", sizeof(kill_desc));
+    } else if (swap_is_low && thrashing > thrashing_limit_pct) {
+        /* Page cache is thrashing while swap is low */
+        kill_reason = LOW_SWAP_AND_THRASHING;
+        snprintf(kill_desc, sizeof(kill_desc), "device is low on swap (%" PRId64
+            "kB < %" PRId64 "kB) and thrashing (%" PRId64 "%%)",
+            mi.field.free_swap * page_k, swap_low_threshold * page_k, thrashing);
+    } else if (swap_is_low && wmark < WMARK_HIGH) {
+        /* Both free memory and swap are low */
+        kill_reason = LOW_MEM_AND_SWAP;
+        snprintf(kill_desc, sizeof(kill_desc), "%s watermark is breached and swap is low (%"
+            PRId64 "kB < %" PRId64 "kB)", wmark > WMARK_LOW ? "min" : "low",
+            mi.field.free_swap * page_k, swap_low_threshold * page_k);
+    } else if (wmark < WMARK_HIGH && thrashing > thrashing_limit) {
+        /* Page cache is thrashing while memory is low */
+        kill_reason = LOW_MEM_AND_THRASHING;
+        snprintf(kill_desc, sizeof(kill_desc), "%s watermark is breached and thrashing (%"
+            PRId64 "%%)", wmark > WMARK_LOW ? "min" : "low", thrashing);
+        cut_thrashing_limit = true;
+        /* Do not kill perceptible apps because of thrashing */
+        min_score_adj = PERCEPTIBLE_APP_ADJ;
+    } else if (reclaim == DIRECT_RECLAIM && thrashing > thrashing_limit) {
+        /* Page cache is thrashing while in direct reclaim (mostly happens on lowram devices) */
+        kill_reason = DIRECT_RECL_AND_THRASHING;
+        snprintf(kill_desc, sizeof(kill_desc), "device is in direct reclaim and thrashing (%"
+            PRId64 "%%)", thrashing);
+        cut_thrashing_limit = true;
+        /* Do not kill perceptible apps because of thrashing */
+        min_score_adj = PERCEPTIBLE_APP_ADJ;
+    }
+
+    /* Kill a process if necessary */
+    if (kill_reason != NONE) {
+        int pages_freed = find_and_kill_process(min_score_adj, kill_desc);
+        if (pages_freed > 0) {
+            killing = true;
+            if (cut_thrashing_limit) {
+                /*
+                 * Cut thrasing limit by thrashing_limit_decay_pct percentage of the current
+                 * thrashing limit until the system stops thrashing.
+                 */
+                thrashing_limit = (thrashing_limit * (100 - thrashing_limit_decay_pct)) / 100;
+            }
+        }
+        meminfo_log(&mi);
+    }
+
+no_kill:
+    /*
+     * Start polling after initial PSI event;
+     * extend polling while device is in direct reclaim or process is being killed;
+     * do not extend when kswapd reclaims because that might go on for a long time
+     * without causing memory pressure
+     */
+    if (events || killing || reclaim == DIRECT_RECLAIM) {
+        poll_params->update = POLLING_START;
+    }
+
+    /* Decide the polling interval */
+    if (swap_is_low || killing) {
+        /* Fast polling during and after a kill or when swap is low */
+        poll_params->polling_interval_ms = PSI_POLL_PERIOD_SHORT_MS;
+    } else {
+        /* By default use long intervals */
+        poll_params->polling_interval_ms = PSI_POLL_PERIOD_LONG_MS;
+    }
+}
+
+static void mp_event_common(int data, uint32_t events, struct polling_params *poll_params) {
     int ret;
     unsigned long long evcount;
     int64_t mem_usage, memsw_usage;
     int64_t mem_pressure;
     enum vmpressure_level lvl;
     union meminfo mi;
-    union zoneinfo zi;
+    struct zoneinfo zi;
     struct timespec curr_tm;
     static struct timespec last_kill_tm;
     static unsigned long kill_skip_count = 0;
@@ -1653,6 +2265,15 @@
         }
     }
 
+    /* Start polling after initial PSI event */
+    if (use_psi_monitors && events) {
+        /* Override polling params only if current event is more critical */
+        if (!poll_params->poll_handler || data > poll_params->poll_handler->data) {
+            poll_params->polling_interval_ms = PSI_POLL_PERIOD_SHORT_MS;
+            poll_params->update = POLLING_START;
+        }
+    }
+
     if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
         ALOGE("Failed to get current time");
         return;
@@ -1683,7 +2304,7 @@
     if (use_minfree_levels) {
         int i;
 
-        other_free = mi.field.nr_free_pages - zi.field.totalreserve_pages;
+        other_free = mi.field.nr_free_pages - zi.totalreserve_pages;
         if (mi.field.nr_file_pages > (mi.field.shmem + mi.field.unevictable + mi.field.swap_cached)) {
             other_file = (mi.field.nr_file_pages - mi.field.shmem -
                           mi.field.unevictable - mi.field.swap_cached);
@@ -1765,7 +2386,7 @@
 do_kill:
     if (low_ram_device) {
         /* For Go devices kill only one task */
-        if (find_and_kill_process(level_oomadj[level]) == 0) {
+        if (find_and_kill_process(level_oomadj[level], NULL) == 0) {
             if (debug_process_killing) {
                 ALOGI("Nothing to kill");
             }
@@ -1790,7 +2411,7 @@
             min_score_adj = level_oomadj[level];
         }
 
-        pages_freed = find_and_kill_process(min_score_adj);
+        pages_freed = find_and_kill_process(min_score_adj, NULL);
 
         if (pages_freed == 0) {
             /* Rate limit kill reports when nothing was reclaimed */
@@ -1811,7 +2432,7 @@
                 "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,
+                zi.totalreserve_pages * page_k,
                 minfree * page_k, min_score_adj);
         } else {
             ALOGI("Reclaimed %ldkB at oom_adj %d",
@@ -1827,8 +2448,15 @@
     }
 }
 
-static bool init_mp_psi(enum vmpressure_level level) {
-    int fd = init_psi_monitor(psi_thresholds[level].stall_type,
+static bool init_mp_psi(enum vmpressure_level level, bool use_new_strategy) {
+    int fd;
+
+    /* Do not register a handler if threshold_ms is not set */
+    if (!psi_thresholds[level].threshold_ms) {
+        return true;
+    }
+
+    fd = init_psi_monitor(psi_thresholds[level].stall_type,
         psi_thresholds[level].threshold_ms * US_PER_MS,
         PSI_WINDOW_SIZE_MS * US_PER_MS);
 
@@ -1836,7 +2464,7 @@
         return false;
     }
 
-    vmpressure_hinfo[level].handler = mp_event_common;
+    vmpressure_hinfo[level].handler = use_new_strategy ? mp_event_psi : mp_event_common;
     vmpressure_hinfo[level].data = level;
     if (register_psi_monitor(epollfd, fd, &vmpressure_hinfo[level]) < 0) {
         destroy_psi_monitor(fd);
@@ -1860,14 +2488,29 @@
 }
 
 static bool init_psi_monitors() {
-    if (!init_mp_psi(VMPRESS_LEVEL_LOW)) {
+    /*
+     * When PSI is used on low-ram devices or on high-end devices without memfree levels
+     * use new kill strategy based on zone watermarks, free swap and thrashing stats
+     */
+    bool use_new_strategy =
+        property_get_bool("ro.lmk.use_new_strategy", low_ram_device || !use_minfree_levels);
+
+    /* In default PSI mode override stall amounts using system properties */
+    if (use_new_strategy) {
+        /* Do not use low pressure level */
+        psi_thresholds[VMPRESS_LEVEL_LOW].threshold_ms = 0;
+        psi_thresholds[VMPRESS_LEVEL_MEDIUM].threshold_ms = psi_partial_stall_ms;
+        psi_thresholds[VMPRESS_LEVEL_CRITICAL].threshold_ms = psi_complete_stall_ms;
+    }
+
+    if (!init_mp_psi(VMPRESS_LEVEL_LOW, use_new_strategy)) {
         return false;
     }
-    if (!init_mp_psi(VMPRESS_LEVEL_MEDIUM)) {
+    if (!init_mp_psi(VMPRESS_LEVEL_MEDIUM, use_new_strategy)) {
         destroy_mp_psi(VMPRESS_LEVEL_LOW);
         return false;
     }
-    if (!init_mp_psi(VMPRESS_LEVEL_CRITICAL)) {
+    if (!init_mp_psi(VMPRESS_LEVEL_CRITICAL, use_new_strategy)) {
         destroy_mp_psi(VMPRESS_LEVEL_MEDIUM);
         destroy_mp_psi(VMPRESS_LEVEL_LOW);
         return false;
@@ -2010,6 +2653,10 @@
 #endif
 
 static int init(void) {
+    struct reread_data file_data = {
+        .filename = ZONEINFO_PATH,
+        .fd = -1,
+    };
     struct epoll_event epev;
     int i;
     int ret;
@@ -2087,37 +2734,68 @@
 
     memset(killcnt_idx, KILLCNT_INVALID_IDX, sizeof(killcnt_idx));
 
+    /*
+     * Read zoneinfo as the biggest file we read to create and size the initial
+     * read buffer and avoid memory re-allocations during memory pressure
+     */
+    if (reread_file(&file_data) == NULL) {
+        ALOGE("Failed to read %s: %s", file_data.filename, strerror(errno));
+    }
+
     return 0;
 }
 
 static void mainloop(void) {
     struct event_handler_info* handler_info;
-    struct event_handler_info* poll_handler = NULL;
-    struct timespec last_report_tm, curr_tm;
+    struct polling_params poll_params;
+    struct timespec curr_tm;
     struct epoll_event *evt;
     long delay = -1;
-    int polling = 0;
+
+    poll_params.poll_handler = NULL;
+    poll_params.update = POLLING_DO_NOT_CHANGE;
 
     while (1) {
         struct epoll_event events[maxevents];
         int nevents;
         int i;
 
-        if (polling) {
+        if (poll_params.poll_handler) {
             /* Calculate next timeout */
             clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm);
-            delay = get_time_diff_ms(&last_report_tm, &curr_tm);
-            delay = (delay < PSI_POLL_PERIOD_MS) ?
-                PSI_POLL_PERIOD_MS - delay : PSI_POLL_PERIOD_MS;
+            delay = get_time_diff_ms(&poll_params.last_poll_tm, &curr_tm);
+            delay = (delay < poll_params.polling_interval_ms) ?
+                poll_params.polling_interval_ms - delay : poll_params.polling_interval_ms;
 
             /* Wait for events until the next polling timeout */
             nevents = epoll_wait(epollfd, events, maxevents, delay);
 
             clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm);
-            if (get_time_diff_ms(&last_report_tm, &curr_tm) >= PSI_POLL_PERIOD_MS) {
-                polling--;
-                poll_handler->handler(poll_handler->data, 0);
-                last_report_tm = curr_tm;
+            if (get_time_diff_ms(&poll_params.last_poll_tm, &curr_tm) >=
+                poll_params.polling_interval_ms) {
+                /* Set input params for the call */
+                poll_params.poll_handler->handler(poll_params.poll_handler->data, 0, &poll_params);
+                poll_params.last_poll_tm = curr_tm;
+
+                if (poll_params.update != POLLING_DO_NOT_CHANGE) {
+                    switch (poll_params.update) {
+                    case POLLING_START:
+                        poll_params.poll_start_tm = curr_tm;
+                        break;
+                    case POLLING_STOP:
+                        poll_params.poll_handler = NULL;
+                        break;
+                    default:
+                        break;
+                    }
+                    poll_params.update = POLLING_DO_NOT_CHANGE;
+                } else {
+                    if (get_time_diff_ms(&poll_params.poll_start_tm, &curr_tm) >
+                        PSI_WINDOW_SIZE_MS) {
+                        /* Polled for the duration of PSI window, time to stop */
+                        poll_params.poll_handler = NULL;
+                    }
+                }
             }
         } else {
             /* Wait for events with no timeout */
@@ -2148,25 +2826,37 @@
 
         /* Second pass to handle all other events */
         for (i = 0, evt = &events[0]; i < nevents; ++i, evt++) {
-            if (evt->events & EPOLLERR)
+            if (evt->events & EPOLLERR) {
                 ALOGD("EPOLLERR on event #%d", i);
+            }
             if (evt->events & EPOLLHUP) {
                 /* This case was handled in the first pass */
                 continue;
             }
             if (evt->data.ptr) {
                 handler_info = (struct event_handler_info*)evt->data.ptr;
-                handler_info->handler(handler_info->data, evt->events);
+                /* Set input params for the call */
+                handler_info->handler(handler_info->data, evt->events, &poll_params);
 
-                if (use_psi_monitors && handler_info->handler == mp_event_common) {
-                    /*
-                     * Poll for the duration of PSI_WINDOW_SIZE_MS after the
-                     * initial PSI event because psi events are rate-limited
-                     * at one per sec.
-                     */
-                    polling = PSI_POLL_COUNT;
-                    poll_handler = handler_info;
-                    clock_gettime(CLOCK_MONOTONIC_COARSE, &last_report_tm);
+                if (poll_params.update != POLLING_DO_NOT_CHANGE) {
+                    switch (poll_params.update) {
+                    case POLLING_START:
+                        /*
+                         * Poll for the duration of PSI_WINDOW_SIZE_MS after the
+                         * initial PSI event because psi events are rate-limited
+                         * at one per sec.
+                         */
+                        clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm);
+                        poll_params.poll_start_tm = poll_params.last_poll_tm = curr_tm;
+                        poll_params.poll_handler = handler_info;
+                        break;
+                    case POLLING_STOP:
+                        poll_params.poll_handler = NULL;
+                        break;
+                    default:
+                        break;
+                    }
+                    poll_params.update = POLLING_DO_NOT_CHANGE;
                 }
             }
         }
@@ -2203,8 +2893,16 @@
         property_get_bool("ro.lmk.use_minfree_levels", false);
     per_app_memcg =
         property_get_bool("ro.config.per_app_memcg", low_ram_device);
-    swap_free_low_percentage =
-        property_get_int32("ro.lmk.swap_free_low_percentage", 10);
+    swap_free_low_percentage = clamp(0, 100, property_get_int32("ro.lmk.swap_free_low_percentage",
+        low_ram_device ? DEF_LOW_SWAP_LOWRAM : DEF_LOW_SWAP));
+    psi_partial_stall_ms = property_get_int32("ro.lmk.psi_partial_stall_ms",
+        low_ram_device ? DEF_PARTIAL_STALL_LOWRAM : DEF_PARTIAL_STALL);
+    psi_complete_stall_ms = property_get_int32("ro.lmk.psi_complete_stall_ms",
+        DEF_COMPLETE_STALL);
+    thrashing_limit_pct = max(0, property_get_int32("ro.lmk.thrashing_limit",
+        low_ram_device ? DEF_THRASHING_LOWRAM : DEF_THRASHING));
+    thrashing_limit_decay_pct = clamp(0, 100, property_get_int32("ro.lmk.thrashing_limit_decay",
+        low_ram_device ? DEF_THRASHING_DECAY_LOWRAM : DEF_THRASHING_DECAY));
 
     ctx = create_android_logger(MEMINFO_LOG_TAG);
 
diff --git a/logwrapper/Android.bp b/logwrapper/Android.bp
index e360a85..8851a47 100644
--- a/logwrapper/Android.bp
+++ b/logwrapper/Android.bp
@@ -56,10 +56,10 @@
 // ========================================================
 
 cc_benchmark {
-    name: "android_fork_execvp_ext_benchmark",
+    name: "logwrap_fork_execvp_benchmark",
     defaults: ["logwrapper_defaults"],
     srcs: [
-        "android_fork_execvp_ext_benchmark.cpp",
+        "logwrap_fork_execvp_benchmark.cpp",
     ],
     shared_libs: [
         "libbase",
diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h
index c329586..cb40ee2 100644
--- a/logwrapper/include/logwrap/logwrap.h
+++ b/logwrapper/include/logwrap/logwrap.h
@@ -59,24 +59,3 @@
 
 int logwrap_fork_execvp(int argc, const char* const* argv, int* status, bool forward_signals,
                         int log_target, bool abbreviated, const char* file_path);
-
-// TODO: Actually deprecate this and the below.
-static inline int android_fork_execvp_ext(int argc, char* argv[], int* status, bool ignore_int_quit,
-                                          int log_target, bool abbreviated, const char* file_path,
-                                          void* unused_opts, int unused_opts_len) {
-    (void)ignore_int_quit;
-    (void)unused_opts;
-    (void)unused_opts_len;
-    return logwrap_fork_execvp(argc, argv, status, false, log_target, abbreviated, file_path);
-}
-
-/* Similar to above, except abbreviated logging is not available, and if logwrap
- * is true, logging is to the Android system log, and if false, there is no
- * logging.
- */
-static inline int android_fork_execvp(int argc, char* argv[], int* status, bool ignore_int_quit,
-                                      bool logwrap) {
-    (void)ignore_int_quit;
-    return logwrap_fork_execvp(argc, argv, status, false, (logwrap ? LOG_ALOG : LOG_NONE), false,
-                               nullptr);
-}
diff --git a/logwrapper/android_fork_execvp_ext_benchmark.cpp b/logwrapper/logwrap_fork_execvp_benchmark.cpp
similarity index 81%
rename from logwrapper/android_fork_execvp_ext_benchmark.cpp
rename to logwrapper/logwrap_fork_execvp_benchmark.cpp
index 1abd932..b2d0c71 100644
--- a/logwrapper/android_fork_execvp_ext_benchmark.cpp
+++ b/logwrapper/logwrap_fork_execvp_benchmark.cpp
@@ -23,9 +23,7 @@
     const char* argv[] = {"/system/bin/echo", "hello", "world"};
     const int argc = 3;
     while (state.KeepRunning()) {
-        int rc = android_fork_execvp_ext(
-            argc, (char**)argv, NULL /* status */, false /* ignore_int_quit */, LOG_NONE,
-            false /* abbreviated */, NULL /* file_path */, NULL /* opts */, 0 /* opts_len */);
+        int rc = logwrap_fork_execvp(argc, argv, nullptr, false, LOG_NONE, false, nullptr);
         CHECK_EQ(0, rc);
     }
 }
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 7097a12..a0059db 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -432,6 +432,22 @@
 		echo $(lib) >> $@;)
 
 #######################################
+# vndkcorevariant.libraries.txt
+include $(CLEAR_VARS)
+LOCAL_MODULE := vndkcorevariant.libraries.txt
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
+LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
+include $(BUILD_SYSTEM)/base_rules.mk
+$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_CORE_VARIANT_LIBRARIES := $(call module-installed-files-or-guess,$(VNDK_USING_CORE_VARIANT_LIBRARIES),.vendor)
+$(LOCAL_BUILT_MODULE):
+	@echo "Generate: $@"
+	@mkdir -p $(dir $@)
+	$(hide) echo -n > $@
+	$(hide) $(foreach lib,$(PRIVATE_VNDK_CORE_VARIANT_LIBRARIES), \
+		echo $(lib) >> $@;)
+
+#######################################
 # adb_debug.prop in debug ramdisk
 include $(CLEAR_VARS)
 LOCAL_MODULE := adb_debug.prop