Merge "Move libnative{bridge,loader} to art/"
diff --git a/libcutils/trace-dev.cpp b/libcutils/trace-dev.cpp
index 4da8215..bff16c1 100644
--- a/libcutils/trace-dev.cpp
+++ b/libcutils/trace-dev.cpp
@@ -34,12 +34,9 @@
     if (atrace_marker_fd == -1) {
         ALOGE("Error opening trace file: %s (%d)", strerror(errno), errno);
         atrace_enabled_tags = 0;
-        goto done;
+    } else {
+      atrace_enabled_tags = atrace_get_property();
     }
-
-    atrace_enabled_tags = atrace_get_property();
-
-done:
     atomic_store_explicit(&atrace_is_ready, true, memory_order_release);
 }
 
diff --git a/libion/ion.c b/libion/ion.c
index 5141ea8..07b4caf 100644
--- a/libion/ion.c
+++ b/libion/ion.c
@@ -31,7 +31,7 @@
 #include <unistd.h>
 
 #include <ion/ion.h>
-#include "ion_4.19.h"
+#include <linux/ion_4.19.h>
 
 #include <log/log.h>
 
diff --git a/libion/ion_4.12.h b/libion/kernel-headers/linux/ion_4.12.h
similarity index 81%
rename from libion/ion_4.12.h
rename to libion/kernel-headers/linux/ion_4.12.h
index 614510c..1af8284 100644
--- a/libion/ion_4.12.h
+++ b/libion/kernel-headers/linux/ion_4.12.h
@@ -22,27 +22,27 @@
 #include <linux/types.h>
 #define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8)
 struct ion_new_allocation_data {
-  __u64 len;
-  __u32 heap_id_mask;
-  __u32 flags;
-  __u32 fd;
-  __u32 unused;
+    __u64 len;
+    __u32 heap_id_mask;
+    __u32 flags;
+    __u32 fd;
+    __u32 unused;
 };
 #define MAX_HEAP_NAME 32
 struct ion_heap_data {
-  char name[MAX_HEAP_NAME];
-  __u32 type;
-  __u32 heap_id;
-  __u32 reserved0;
-  __u32 reserved1;
-  __u32 reserved2;
+    char name[MAX_HEAP_NAME];
+    __u32 type;
+    __u32 heap_id;
+    __u32 reserved0;
+    __u32 reserved1;
+    __u32 reserved2;
 };
 struct ion_heap_query {
-  __u32 cnt;
-  __u32 reserved0;
-  __u64 heaps;
-  __u32 reserved1;
-  __u32 reserved2;
+    __u32 cnt;
+    __u32 reserved0;
+    __u64 heaps;
+    __u32 reserved1;
+    __u32 reserved2;
 };
 #define ION_IOC_MAGIC 'I'
 #define ION_IOC_NEW_ALLOC _IOWR(ION_IOC_MAGIC, 0, struct ion_new_allocation_data)
diff --git a/libion/ion_4.19.h b/libion/kernel-headers/linux/ion_4.19.h
similarity index 100%
rename from libion/ion_4.19.h
rename to libion/kernel-headers/linux/ion_4.19.h
diff --git a/libion/tests/ion_4.12.h b/libion/tests/ion_4.12.h
deleted file mode 100644
index 614510c..0000000
--- a/libion/tests/ion_4.12.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- ***   This header was automatically generated from a Linux kernel header
- ***   of the same name, to make information necessary for userspace to
- ***   call into the kernel available to libc.  It contains only constants,
- ***   structures, and macros generated from the original header, and thus,
- ***   contains no copyrightable information.
- ***
- ***   To edit the content of this header, modify the corresponding
- ***   source file (e.g. under external/kernel-headers/original/) then
- ***   run bionic/libc/kernel/tools/update_all.py
- ***
- ***   Any manual change here will be lost the next time this script will
- ***   be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _UAPI_LINUX_ION_NEW_H
-#define _UAPI_LINUX_ION_NEW_H
-#include <linux/ioctl.h>
-#include <linux/types.h>
-#define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8)
-struct ion_new_allocation_data {
-  __u64 len;
-  __u32 heap_id_mask;
-  __u32 flags;
-  __u32 fd;
-  __u32 unused;
-};
-#define MAX_HEAP_NAME 32
-struct ion_heap_data {
-  char name[MAX_HEAP_NAME];
-  __u32 type;
-  __u32 heap_id;
-  __u32 reserved0;
-  __u32 reserved1;
-  __u32 reserved2;
-};
-struct ion_heap_query {
-  __u32 cnt;
-  __u32 reserved0;
-  __u64 heaps;
-  __u32 reserved1;
-  __u32 reserved2;
-};
-#define ION_IOC_MAGIC 'I'
-#define ION_IOC_NEW_ALLOC _IOWR(ION_IOC_MAGIC, 0, struct ion_new_allocation_data)
-#define ION_IOC_HEAP_QUERY _IOWR(ION_IOC_MAGIC, 8, struct ion_heap_query)
-#endif
diff --git a/libion/tests/ion_test_fixture.h b/libion/tests/ion_test_fixture.h
index 4f254b8..c78fe41 100644
--- a/libion/tests/ion_test_fixture.h
+++ b/libion/tests/ion_test_fixture.h
@@ -18,8 +18,8 @@
 #define ION_TEST_FIXTURE_H_
 
 #include <gtest/gtest.h>
+#include <linux/ion_4.12.h>
 #include <vector>
-#include "ion_4.12.h"
 
 using ::testing::Test;
 
diff --git a/liblog/include/private/android_logger.h b/liblog/include/private/android_logger.h
index 5e04148..d3cb571 100644
--- a/liblog/include/private/android_logger.h
+++ b/liblog/include/private/android_logger.h
@@ -57,6 +57,18 @@
   int32_t tag;  // Little Endian Order
 } android_event_header_t;
 
+// Event payload EVENT_TYPE_LIST
+typedef struct __attribute__((__packed__)) {
+  int8_t type;  // EVENT_TYPE_LIST
+  int8_t element_count;
+} android_event_list_t;
+
+// Event payload EVENT_TYPE_FLOAT
+typedef struct __attribute__((__packed__)) {
+  int8_t type;  // EVENT_TYPE_FLOAT
+  float data;
+} android_event_float_t;
+
 /* Event payload EVENT_TYPE_INT */
 typedef struct __attribute__((__packed__)) {
   int8_t type;   // EVENT_TYPE_INT
diff --git a/liblog/log_event_list.cpp b/liblog/log_event_list.cpp
index 18ea930..7882c96 100644
--- a/liblog/log_event_list.cpp
+++ b/liblog/log_event_list.cpp
@@ -51,11 +51,9 @@
 typedef struct android_log_context_internal android_log_context_internal;
 
 static void init_context(android_log_context_internal* context, uint32_t tag) {
-  size_t needed;
-
   context->tag = tag;
   context->read_write_flag = kAndroidLoggerWrite;
-  needed = sizeof(uint8_t) + sizeof(uint8_t);
+  size_t needed = sizeof(android_event_list_t);
   if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
     context->overflow = true;
   }
@@ -143,7 +141,6 @@
 }
 
 int android_log_write_list_begin(android_log_context ctx) {
-  size_t needed;
   android_log_context_internal* context;
 
   context = (android_log_context_internal*)ctx;
@@ -154,7 +151,7 @@
     context->overflow = true;
     return -EOVERFLOW;
   }
-  needed = sizeof(uint8_t) + sizeof(uint8_t);
+  size_t needed = sizeof(android_event_list_t);
   if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
     context->overflow = true;
     return -EIO;
@@ -168,8 +165,9 @@
   if (context->overflow) {
     return -EIO;
   }
-  context->storage[context->pos + 0] = EVENT_TYPE_LIST;
-  context->storage[context->pos + 1] = 0;
+  auto* event_list = reinterpret_cast<android_event_list_t*>(&context->storage[context->pos]);
+  event_list->type = EVENT_TYPE_LIST;
+  event_list->element_count = 0;
   context->list[context->list_nest_depth] = context->pos + 1;
   context->count[context->list_nest_depth] = 0;
   context->pos += needed;
@@ -177,57 +175,49 @@
 }
 
 int android_log_write_int32(android_log_context ctx, int32_t value) {
-  size_t needed;
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
+  android_log_context_internal* context = (android_log_context_internal*)ctx;
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
   if (context->overflow) {
     return -EIO;
   }
-  needed = sizeof(uint8_t) + sizeof(value);
+  size_t needed = sizeof(android_event_int_t);
   if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
     context->overflow = true;
     return -EIO;
   }
   context->count[context->list_nest_depth]++;
-  context->storage[context->pos + 0] = EVENT_TYPE_INT;
-  *reinterpret_cast<int32_t*>(&context->storage[context->pos + 1]) = value;
+  auto* event_int = reinterpret_cast<android_event_int_t*>(&context->storage[context->pos]);
+  event_int->type = EVENT_TYPE_INT;
+  event_int->data = value;
   context->pos += needed;
   return 0;
 }
 
 int android_log_write_int64(android_log_context ctx, int64_t value) {
-  size_t needed;
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
+  android_log_context_internal* context = (android_log_context_internal*)ctx;
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
   if (context->overflow) {
     return -EIO;
   }
-  needed = sizeof(uint8_t) + sizeof(value);
+  size_t needed = sizeof(android_event_long_t);
   if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
     context->overflow = true;
     return -EIO;
   }
   context->count[context->list_nest_depth]++;
-  context->storage[context->pos + 0] = EVENT_TYPE_LONG;
-  *reinterpret_cast<int64_t*>(&context->storage[context->pos + 1]) = value;
+  auto* event_long = reinterpret_cast<android_event_long_t*>(&context->storage[context->pos]);
+  event_long->type = EVENT_TYPE_LONG;
+  event_long->data = value;
   context->pos += needed;
   return 0;
 }
 
 int android_log_write_string8_len(android_log_context ctx, const char* value, size_t maxlen) {
-  size_t needed;
-  ssize_t len;
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
+  android_log_context_internal* context = (android_log_context_internal*)ctx;
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
@@ -237,8 +227,8 @@
   if (!value) {
     value = "";
   }
-  len = strnlen(value, maxlen);
-  needed = sizeof(uint8_t) + sizeof(int32_t) + len;
+  int32_t len = strnlen(value, maxlen);
+  size_t needed = sizeof(android_event_string_t) + len;
   if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
     /* Truncate string for delivery */
     len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(int32_t);
@@ -248,10 +238,11 @@
     }
   }
   context->count[context->list_nest_depth]++;
-  context->storage[context->pos + 0] = EVENT_TYPE_STRING;
-  *reinterpret_cast<ssize_t*>(&context->storage[context->pos + 1]) = len;
+  auto* event_string = reinterpret_cast<android_event_string_t*>(&context->storage[context->pos]);
+  event_string->type = EVENT_TYPE_STRING;
+  event_string->length = len;
   if (len) {
-    memcpy(&context->storage[context->pos + 5], value, len);
+    memcpy(&event_string->data, value, len);
   }
   context->pos += needed;
   return len;
@@ -262,26 +253,22 @@
 }
 
 int android_log_write_float32(android_log_context ctx, float value) {
-  size_t needed;
-  uint32_t ivalue;
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
+  android_log_context_internal* context = (android_log_context_internal*)ctx;
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
   if (context->overflow) {
     return -EIO;
   }
-  needed = sizeof(uint8_t) + sizeof(ivalue);
+  size_t needed = sizeof(android_event_float_t);
   if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
     context->overflow = true;
     return -EIO;
   }
-  ivalue = *(uint32_t*)&value;
   context->count[context->list_nest_depth]++;
-  context->storage[context->pos + 0] = EVENT_TYPE_FLOAT;
-  *reinterpret_cast<uint32_t*>(&context->storage[context->pos + 1]) = ivalue;
+  auto* event_float = reinterpret_cast<android_event_float_t*>(&context->storage[context->pos]);
+  event_float->type = EVENT_TYPE_FLOAT;
+  event_float->data = value;
   context->pos += needed;
   return 0;
 }
@@ -443,20 +430,22 @@
     return elem;
   }
 
-  elem.type = static_cast<AndroidEventLogType>(context->storage[pos++]);
+  elem.type = static_cast<AndroidEventLogType>(context->storage[pos]);
   switch ((int)elem.type) {
     case EVENT_TYPE_FLOAT:
     /* Rely on union to translate elem.data.int32 into elem.data.float32 */
     /* FALLTHRU */
-    case EVENT_TYPE_INT:
+    case EVENT_TYPE_INT: {
       elem.len = sizeof(int32_t);
-      if ((pos + elem.len) > context->len) {
+      if ((pos + sizeof(android_event_int_t)) > context->len) {
         elem.type = EVENT_TYPE_UNKNOWN;
         return elem;
       }
-      elem.data.int32 = *reinterpret_cast<int32_t*>(&context->storage[pos]);
+
+      auto* event_int = reinterpret_cast<android_event_int_t*>(&context->storage[pos]);
+      pos += sizeof(android_event_int_t);
+      elem.data.int32 = event_int->data;
       /* common tangeable object suffix */
-      pos += elem.len;
       elem.complete = !context->list_nest_depth && !context->count[0];
       if (!peek) {
         if (!context->count[context->list_nest_depth] ||
@@ -466,16 +455,19 @@
         context->pos = pos;
       }
       return elem;
+    }
 
-    case EVENT_TYPE_LONG:
+    case EVENT_TYPE_LONG: {
       elem.len = sizeof(int64_t);
-      if ((pos + elem.len) > context->len) {
+      if ((pos + sizeof(android_event_long_t)) > context->len) {
         elem.type = EVENT_TYPE_UNKNOWN;
         return elem;
       }
-      elem.data.int64 = *reinterpret_cast<int64_t*>(&context->storage[pos]);
+
+      auto* event_long = reinterpret_cast<android_event_long_t*>(&context->storage[pos]);
+      pos += sizeof(android_event_long_t);
+      elem.data.int64 = event_long->data;
       /* common tangeable object suffix */
-      pos += elem.len;
       elem.complete = !context->list_nest_depth && !context->count[0];
       if (!peek) {
         if (!context->count[context->list_nest_depth] ||
@@ -485,15 +477,22 @@
         context->pos = pos;
       }
       return elem;
+    }
 
-    case EVENT_TYPE_STRING:
-      if ((pos + sizeof(int32_t)) > context->len) {
+    case EVENT_TYPE_STRING: {
+      if ((pos + sizeof(android_event_string_t)) > context->len) {
         elem.type = EVENT_TYPE_UNKNOWN;
         elem.complete = true;
         return elem;
       }
-      elem.len = *reinterpret_cast<int32_t*>(&context->storage[pos]);
-      pos += sizeof(int32_t);
+      auto* event_string = reinterpret_cast<android_event_string_t*>(&context->storage[pos]);
+      pos += sizeof(android_event_string_t);
+      // Wire format is int32_t, but elem.len is uint16_t...
+      if (event_string->length >= UINT16_MAX) {
+        elem.type = EVENT_TYPE_UNKNOWN;
+        return elem;
+      }
+      elem.len = event_string->length;
       if ((pos + elem.len) > context->len) {
         elem.len = context->len - pos; /* truncate string */
         elem.complete = true;
@@ -502,7 +501,7 @@
           return elem;
         }
       }
-      elem.data.string = (char*)&context->storage[pos];
+      elem.data.string = event_string->data;
       /* common tangeable object suffix */
       pos += elem.len;
       elem.complete = !context->list_nest_depth && !context->count[0];
@@ -514,13 +513,16 @@
         context->pos = pos;
       }
       return elem;
+    }
 
-    case EVENT_TYPE_LIST:
-      if ((pos + sizeof(uint8_t)) > context->len) {
+    case EVENT_TYPE_LIST: {
+      if ((pos + sizeof(android_event_list_t)) > context->len) {
         elem.type = EVENT_TYPE_UNKNOWN;
         elem.complete = true;
         return elem;
       }
+      auto* event_list = reinterpret_cast<android_event_list_t*>(&context->storage[pos]);
+      pos += sizeof(android_event_list_t);
       elem.complete = context->list_nest_depth >= ANDROID_MAX_LIST_NEST_DEPTH;
       if (peek) {
         return elem;
@@ -528,15 +530,17 @@
       if (context->count[context->list_nest_depth]) {
         context->count[context->list_nest_depth]--;
       }
-      context->list_stop = !context->storage[pos];
+      context->list_stop = event_list->element_count == 0;
       context->list_nest_depth++;
       if (context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) {
-        context->count[context->list_nest_depth] = context->storage[pos];
+        context->count[context->list_nest_depth] = event_list->element_count;
       }
-      context->pos = pos + sizeof(uint8_t);
+      context->pos = pos;
       return elem;
+    }
 
     case EVENT_TYPE_LIST_STOP: /* Suprise Newline terminates lists. */
+      pos++;
       if (!peek) {
         context->pos = pos;
       }
diff --git a/liblog/logd_reader.cpp b/liblog/logd_reader.cpp
index dcdff05..619cf8c 100644
--- a/liblog/logd_reader.cpp
+++ b/liblog/logd_reader.cpp
@@ -316,16 +316,11 @@
   return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
 }
 
-static void caught_signal(int signum __unused) {}
-
 static int logdOpen(struct android_log_logger_list* logger_list,
                     struct android_log_transport_context* transp) {
   struct android_log_logger* logger;
-  struct sigaction ignore;
-  struct sigaction old_sigaction;
-  unsigned int old_alarm = 0;
   char buffer[256], *cp, c;
-  int e, ret, remaining, sock;
+  int ret, remaining, sock;
 
   if (!logger_list) {
     return -EINVAL;
@@ -387,29 +382,13 @@
     cp += ret;
   }
 
-  if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
-    /* Deal with an unresponsive logd */
-    memset(&ignore, 0, sizeof(ignore));
-    ignore.sa_handler = caught_signal;
-    sigemptyset(&ignore.sa_mask);
-    /* particularily useful if tombstone is reporting for logd */
-    sigaction(SIGALRM, &ignore, &old_sigaction);
-    old_alarm = alarm(30);
-  }
-  ret = write(sock, buffer, cp - buffer);
-  e = errno;
-  if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
-    if (e == EINTR) {
-      e = ETIMEDOUT;
-    }
-    alarm(old_alarm);
-    sigaction(SIGALRM, &old_sigaction, NULL);
-  }
+  ret = TEMP_FAILURE_RETRY(write(sock, buffer, cp - buffer));
+  int write_errno = errno;
 
   if (ret <= 0) {
     close(sock);
-    if ((ret == -1) && e) {
-      return -e;
+    if (ret == -1) {
+      return -write_errno;
     }
     if (ret == 0) {
       return -EIO;
@@ -427,52 +406,21 @@
 /* Read from the selected logs */
 static int logdRead(struct android_log_logger_list* logger_list,
                     struct android_log_transport_context* transp, struct log_msg* log_msg) {
-  int ret, e;
-  struct sigaction ignore;
-  struct sigaction old_sigaction;
-  unsigned int old_alarm = 0;
-
-  ret = logdOpen(logger_list, transp);
+  int ret = logdOpen(logger_list, transp);
   if (ret < 0) {
     return ret;
   }
 
   memset(log_msg, 0, sizeof(*log_msg));
 
-  unsigned int new_alarm = 0;
-  if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
-    if ((logger_list->mode & ANDROID_LOG_WRAP) &&
-        (logger_list->start.tv_sec || logger_list->start.tv_nsec)) {
-      /* b/64143705 */
-      new_alarm = (ANDROID_LOG_WRAP_DEFAULT_TIMEOUT * 11) / 10 + 10;
-      logger_list->mode &= ~ANDROID_LOG_WRAP;
-    } else {
-      new_alarm = 30;
-    }
-
-    memset(&ignore, 0, sizeof(ignore));
-    ignore.sa_handler = caught_signal;
-    sigemptyset(&ignore.sa_mask);
-    /* particularily useful if tombstone is reporting for logd */
-    sigaction(SIGALRM, &ignore, &old_sigaction);
-    old_alarm = alarm(new_alarm);
-  }
-
   /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
-  ret = recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
-  e = errno;
-
-  if (new_alarm) {
-    if ((ret == 0) || (e == EINTR)) {
-      e = EAGAIN;
-      ret = -1;
-    }
-    alarm(old_alarm);
-    sigaction(SIGALRM, &old_sigaction, NULL);
+  ret = TEMP_FAILURE_RETRY(recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0));
+  if ((logger_list->mode & ANDROID_LOG_NONBLOCK) && ret == 0) {
+    return -EAGAIN;
   }
 
-  if ((ret == -1) && e) {
-    return -e;
+  if (ret == -1) {
+    return -errno;
   }
   return ret;
 }
diff --git a/liblog/logprint.cpp b/liblog/logprint.cpp
index dd2c797..82fbafd 100644
--- a/liblog/logprint.cpp
+++ b/liblog/logprint.cpp
@@ -35,8 +35,10 @@
 #include <wchar.h>
 
 #include <cutils/list.h>
+
 #include <log/log.h>
 #include <log/logprint.h>
+#include <private/android_logger.h>
 
 #include "log_portability.h"
 
@@ -635,8 +637,7 @@
 
   if (eventDataLen < 1) return -1;
 
-  type = *eventData++;
-  eventDataLen--;
+  type = *eventData;
 
   cp = NULL;
   len = 0;
@@ -725,22 +726,24 @@
     case EVENT_TYPE_INT:
       /* 32-bit signed int */
       {
-        int32_t ival;
-
-        if (eventDataLen < 4) return -1;
-        ival = *reinterpret_cast<const int32_t*>(eventData);
-        eventData += 4;
-        eventDataLen -= 4;
-
-        lval = ival;
+        if (eventDataLen < sizeof(android_event_int_t)) return -1;
+        auto* event_int = reinterpret_cast<const android_event_int_t*>(eventData);
+        lval = event_int->data;
+        eventData += sizeof(android_event_int_t);
+        eventDataLen -= sizeof(android_event_int_t);
       }
       goto pr_lval;
     case EVENT_TYPE_LONG:
       /* 64-bit signed long */
-      if (eventDataLen < 8) return -1;
-      lval = *reinterpret_cast<const int64_t*>(eventData);
-      eventData += 8;
-      eventDataLen -= 8;
+      if (eventDataLen < sizeof(android_event_long_t)) {
+        return -1;
+      }
+      {
+        auto* event_long = reinterpret_cast<const android_event_long_t*>(eventData);
+        lval = event_long->data;
+      }
+      eventData += sizeof(android_event_long_t);
+      eventDataLen -= sizeof(android_event_long_t);
     pr_lval:
       outCount = snprintf(outBuf, outBufLen, "%" PRId64, lval);
       if (outCount < outBufLen) {
@@ -754,14 +757,11 @@
     case EVENT_TYPE_FLOAT:
       /* float */
       {
-        uint32_t ival;
-        float fval;
-
-        if (eventDataLen < 4) return -1;
-        ival = *reinterpret_cast<const uint32_t*>(eventData);
-        fval = *(float*)&ival;
-        eventData += 4;
-        eventDataLen -= 4;
+        if (eventDataLen < sizeof(android_event_float_t)) return -1;
+        auto* event_float = reinterpret_cast<const android_event_float_t*>(eventData);
+        float fval = event_float->data;
+        eventData += sizeof(android_event_int_t);
+        eventDataLen -= sizeof(android_event_int_t);
 
         outCount = snprintf(outBuf, outBufLen, "%f", fval);
         if (outCount < outBufLen) {
@@ -776,12 +776,11 @@
     case EVENT_TYPE_STRING:
       /* UTF-8 chars, not NULL-terminated */
       {
-        unsigned int strLen;
-
-        if (eventDataLen < 4) return -1;
-        strLen = *reinterpret_cast<const uint32_t*>(eventData);
-        eventData += 4;
-        eventDataLen -= 4;
+        if (eventDataLen < sizeof(android_event_string_t)) return -1;
+        auto* event_string = reinterpret_cast<const android_event_string_t*>(eventData);
+        unsigned int strLen = event_string->length;
+        eventData += sizeof(android_event_string_t);
+        eventDataLen -= sizeof(android_event_string_t);
 
         if (eventDataLen < strLen) {
           result = -1; /* mark truncated */
@@ -814,20 +813,19 @@
     case EVENT_TYPE_LIST:
       /* N items, all different types */
       {
-        unsigned char count;
-        int i;
+        if (eventDataLen < sizeof(android_event_list_t)) return -1;
+        auto* event_list = reinterpret_cast<const android_event_list_t*>(eventData);
 
-        if (eventDataLen < 1) return -1;
-
-        count = *eventData++;
-        eventDataLen--;
+        int8_t count = event_list->element_count;
+        eventData += sizeof(android_event_list_t);
+        eventDataLen -= sizeof(android_event_list_t);
 
         if (outBufLen <= 0) goto no_room;
 
         *outBuf++ = '[';
         outBufLen--;
 
-        for (i = 0; i < count; i++) {
+        for (int i = 0; i < count; i++) {
           result = android_log_printBinaryEvent(&eventData, &eventDataLen, &outBuf, &outBufLen,
                                                 fmtStr, fmtLen);
           if (result != 0) goto bail;
@@ -1017,10 +1015,11 @@
     }
   }
   inCount = buf->len;
-  if (inCount < 4) return -1;
-  tagIndex = *reinterpret_cast<const uint32_t*>(eventData);
-  eventData += 4;
-  inCount -= 4;
+  if (inCount < sizeof(android_event_header_t)) return -1;
+  auto* event_header = reinterpret_cast<const android_event_header_t*>(eventData);
+  tagIndex = event_header->tag;
+  eventData += sizeof(android_event_header_t);
+  inCount -= sizeof(android_event_header_t);
 
   entry->tagLen = 0;
   entry->tag = NULL;
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 9780b28..cfcfd99 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -1924,10 +1924,10 @@
     char* original = eventData;
 
     // Tag
-    int tag = *reinterpret_cast<int32_t*>(eventData);
-    eventData += 4;
+    auto* event_header = reinterpret_cast<android_event_header_t*>(eventData);
+    eventData += sizeof(android_event_header_t);
 
-    if (tag != TAG) {
+    if (event_header->tag != TAG) {
       continue;
     }
 
@@ -1938,45 +1938,37 @@
     }
 
     // List type
-    ASSERT_EQ(EVENT_TYPE_LIST, eventData[0]);
-    eventData++;
-
-    // Number of elements in list
-    ASSERT_EQ(3, eventData[0]);
-    eventData++;
+    auto* event_list = reinterpret_cast<android_event_list_t*>(eventData);
+    ASSERT_EQ(EVENT_TYPE_LIST, event_list->type);
+    ASSERT_EQ(3, event_list->element_count);
+    eventData += sizeof(android_event_list_t);
 
     // Element #1: string type for subtag
-    ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
-    eventData++;
-
+    auto* event_string_subtag = reinterpret_cast<android_event_string_t*>(eventData);
+    ASSERT_EQ(EVENT_TYPE_STRING, event_string_subtag->type);
     unsigned subtag_len = strlen(SUBTAG);
     if (subtag_len > 32) subtag_len = 32;
-    ASSERT_EQ(subtag_len, *reinterpret_cast<uint32_t*>(eventData));
-    eventData += 4;
-
-    if (memcmp(SUBTAG, eventData, subtag_len)) {
+    ASSERT_EQ(static_cast<int32_t>(subtag_len), event_string_subtag->length);
+    if (memcmp(SUBTAG, &event_string_subtag->data, subtag_len)) {
       continue;
     }
-    eventData += subtag_len;
+    eventData += sizeof(android_event_string_t) + subtag_len;
 
     // Element #2: int type for uid
-    ASSERT_EQ(EVENT_TYPE_INT, eventData[0]);
-    eventData++;
-
-    ASSERT_EQ(UID, *reinterpret_cast<int32_t*>(eventData));
-    eventData += 4;
+    auto* event_int_uid = reinterpret_cast<android_event_int_t*>(eventData);
+    ASSERT_EQ(EVENT_TYPE_INT, event_int_uid->type);
+    ASSERT_EQ(UID, event_int_uid->data);
+    eventData += sizeof(android_event_int_t);
 
     // Element #3: string type for data
-    ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
-    eventData++;
-
-    size_t dataLen = *reinterpret_cast<int32_t*>(eventData);
-    eventData += 4;
+    auto* event_string_data = reinterpret_cast<android_event_string_t*>(eventData);
+    ASSERT_EQ(EVENT_TYPE_STRING, event_string_data->type);
+    size_t dataLen = event_string_data->length;
     if (DATA_LEN < 512) ASSERT_EQ(DATA_LEN, (int)dataLen);
-
-    if (memcmp(payload, eventData, dataLen)) {
+    if (memcmp(payload, &event_string_data->data, dataLen)) {
       continue;
     }
+    eventData += sizeof(android_event_string_t);
 
     if (DATA_LEN >= 512) {
       eventData += dataLen;
@@ -2082,10 +2074,12 @@
     if (!eventData) continue;
 
     // Tag
-    int tag = *reinterpret_cast<int32_t*>(eventData);
-    eventData += 4;
+    auto* event_header = reinterpret_cast<android_event_header_t*>(eventData);
+    eventData += sizeof(android_event_header_t);
 
-    if (tag != TAG) continue;
+    if (event_header->tag != TAG) {
+      continue;
+    }
 
     if (!SUBTAG) {
       // This tag should not have been written because the data was null
@@ -2135,10 +2129,10 @@
     }
 
     // Tag
-    int tag = *reinterpret_cast<int32_t*>(eventData);
-    eventData += 4;
+    auto* event_header = reinterpret_cast<android_event_header_t*>(eventData);
+    eventData += sizeof(android_event_header_t);
 
-    if (tag != TAG) {
+    if (event_header->tag != TAG) {
       continue;
     }
 
@@ -2149,21 +2143,17 @@
     }
 
     // List type
-    ASSERT_EQ(EVENT_TYPE_LIST, eventData[0]);
-    eventData++;
-
-    // Number of elements in list
-    ASSERT_EQ(3, eventData[0]);
-    eventData++;
+    auto* event_list = reinterpret_cast<android_event_list_t*>(eventData);
+    ASSERT_EQ(EVENT_TYPE_LIST, event_list->type);
+    ASSERT_EQ(3, event_list->element_count);
+    eventData += sizeof(android_event_list_t);
 
     // Element #1: string type for subtag
-    ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
-    eventData++;
+    auto* event_string = reinterpret_cast<android_event_string_t*>(eventData);
+    ASSERT_EQ(EVENT_TYPE_STRING, event_string->type);
+    ASSERT_EQ(static_cast<int32_t>(strlen(SUBTAG)), event_string->length);
 
-    ASSERT_EQ(strlen(SUBTAG), *reinterpret_cast<uint32_t*>(eventData));
-    eventData += 4;
-
-    if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) {
+    if (memcmp(SUBTAG, &event_string->data, strlen(SUBTAG))) {
       continue;
     }
     ++count;
@@ -2673,13 +2663,14 @@
     // test buffer reading API
     int buffer_to_string = -1;
     if (eventData) {
-      snprintf(msgBuf, sizeof(msgBuf), "I/[%" PRIu32 "]", *reinterpret_cast<uint32_t*>(eventData));
+      auto* event_header = reinterpret_cast<android_event_header_t*>(eventData);
+      eventData += sizeof(android_event_header_t);
+      snprintf(msgBuf, sizeof(msgBuf), "I/[%" PRId32 "]", event_header->tag);
       print_barrier();
       fprintf(stderr, "%-10s(%5u): ", msgBuf, pid);
       memset(msgBuf, 0, sizeof(msgBuf));
-      buffer_to_string = android_log_buffer_to_string(
-          eventData + sizeof(uint32_t), log_msg.entry.len - sizeof(uint32_t),
-          msgBuf, sizeof(msgBuf));
+      buffer_to_string =
+          android_log_buffer_to_string(eventData, log_msg.entry.len, msgBuf, sizeof(msgBuf));
       fprintf(stderr, "%s\n", msgBuf);
       print_barrier();
     }
diff --git a/liblog/tests/log_wrap_test.cpp b/liblog/tests/log_wrap_test.cpp
index c7dd8e8..e06964f 100644
--- a/liblog/tests/log_wrap_test.cpp
+++ b/liblog/tests/log_wrap_test.cpp
@@ -58,60 +58,27 @@
 
   android_logger_list_close(logger_list);
 }
-
-static void caught_signal(int /* signum */) {
-}
 #endif
 
 // b/64143705 confirm fixed
 TEST(liblog, wrap_mode_blocks) {
 #ifdef __ANDROID__
+  // The read call is expected to take up to 2 hours in the happy case.  There was a previous bug
+  // where it would take only 30 seconds due to an alarm() in logd_reader.cpp.  That alarm has been
+  // removed, so we check here that the read call blocks for a reasonable amount of time (5s).
+
+  struct sigaction ignore = {.sa_handler = [](int) { _exit(0); }};
+  struct sigaction old_sigaction;
+  sigaction(SIGALRM, &ignore, &old_sigaction);
+  alarm(5);
 
   android::base::Timer timer;
+  read_with_wrap();
 
-  // The read call is expected to take up to 2 hours in the happy case.
-  // We only want to make sure it waits for longer than 30s, but we can't
-  // use an alarm as the implementation uses it. So we run the test in
-  // a separate process.
-  pid_t pid = fork();
-
-  if (pid == 0) {
-    // child
-    read_with_wrap();
-    _exit(0);
-  }
-
-  struct sigaction ignore, old_sigaction;
-  memset(&ignore, 0, sizeof(ignore));
-  ignore.sa_handler = caught_signal;
-  sigemptyset(&ignore.sa_mask);
-  sigaction(SIGALRM, &ignore, &old_sigaction);
-  alarm(45);
-
-  bool killed = false;
-  for (;;) {
-    siginfo_t info = {};
-    // This wait will succeed if the child exits, or fail with EINTR if the
-    // alarm goes off first - a loose approximation to a timed wait.
-    int ret = waitid(P_PID, pid, &info, WEXITED);
-    if (ret >= 0 || errno != EINTR) {
-      EXPECT_EQ(ret, 0);
-      if (!killed) {
-        EXPECT_EQ(info.si_status, 0);
-      }
-      break;
-    }
-    unsigned int alarm_left = alarm(0);
-    if (alarm_left > 0) {
-      alarm(alarm_left);
-    } else {
-      kill(pid, SIGTERM);
-      killed = true;
-    }
-  }
+  FAIL() << "read_with_wrap() should not return before the alarm is triggered.";
 
   alarm(0);
-  EXPECT_GT(timer.duration(), std::chrono::seconds(40));
+  sigaction(SIGALRM, &old_sigaction, nullptr);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
diff --git a/libmeminfo/tools/showmap.cpp b/libmeminfo/tools/showmap.cpp
index 8ea2108..72ab0f3 100644
--- a/libmeminfo/tools/showmap.cpp
+++ b/libmeminfo/tools/showmap.cpp
@@ -18,6 +18,7 @@
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/mman.h>
 #include <sys/signal.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -139,6 +140,9 @@
     if (!g_verbose && !g_show_addr) {
         printf("   # ");
     }
+    if (g_verbose) {
+        printf(" flags ");
+    }
     printf(" object\n");
 }
 
@@ -150,6 +154,9 @@
     if (!g_verbose && !g_show_addr) {
         printf("---- ");
     }
+    if (g_verbose) {
+        printf("------ ");
+    }
     printf("------------------------------\n");
 }
 
@@ -169,6 +176,18 @@
     if (!g_verbose && !g_show_addr) {
         printf("%4" PRIu32 " ", v.count);
     }
+    if (g_verbose) {
+        if (total) {
+            printf("       ");
+        } else {
+            std::string flags_str("---");
+            if (v.vma.flags & PROT_READ) flags_str[0] = 'r';
+            if (v.vma.flags & PROT_WRITE) flags_str[1] = 'w';
+            if (v.vma.flags & PROT_EXEC) flags_str[2] = 'x';
+
+            printf("%6s ", flags_str.c_str());
+        }
+    }
 }
 
 static int showmap(void) {
diff --git a/libunwindstack/DexFile.cpp b/libunwindstack/DexFile.cpp
index eaf867f..dff7a8b 100644
--- a/libunwindstack/DexFile.cpp
+++ b/libunwindstack/DexFile.cpp
@@ -22,6 +22,9 @@
 
 #include <memory>
 
+#define LOG_TAG "unwind"
+#include <log/log.h>
+
 #include <android-base/unique_fd.h>
 #include <art_api/dex_file_support.h>
 
@@ -32,6 +35,19 @@
 
 namespace unwindstack {
 
+static bool CheckDexSupport() {
+  if (std::string err_msg; !art_api::dex::TryLoadLibdexfileExternal(&err_msg)) {
+    ALOGW("Failed to initialize DEX file support: %s", err_msg.c_str());
+    return false;
+  }
+  return true;
+}
+
+static bool HasDexSupport() {
+  static bool has_dex_support = CheckDexSupport();
+  return has_dex_support;
+}
+
 std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory,
                                          MapInfo* info) {
   if (!info->name.empty()) {
@@ -57,6 +73,10 @@
 
 std::unique_ptr<DexFileFromFile> DexFileFromFile::Create(uint64_t dex_file_offset_in_file,
                                                          const std::string& file) {
+  if (UNLIKELY(!HasDexSupport())) {
+    return nullptr;
+  }
+
   android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
   if (fd == -1) {
     return nullptr;
@@ -75,6 +95,10 @@
 std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory,
                                                              Memory* memory,
                                                              const std::string& name) {
+  if (UNLIKELY(!HasDexSupport())) {
+    return nullptr;
+  }
+
   std::vector<uint8_t> backing_memory;
 
   for (size_t size = 0;;) {
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 18cd9f5..e286877 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -31,6 +31,7 @@
 #include <sys/mman.h>
 #include <sys/resource.h>
 #include <sys/socket.h>
+#include <sys/syscall.h>
 #include <sys/sysinfo.h>
 #include <sys/time.h>
 #include <sys/types.h>
@@ -139,6 +140,15 @@
 /* ro.lmk.psi_complete_stall_ms property defaults */
 #define DEF_COMPLETE_STALL 700
 
+static inline int sys_pidfd_open(pid_t pid, unsigned int flags) {
+    return syscall(__NR_pidfd_open, pid, flags);
+}
+
+static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
+                                        unsigned int flags) {
+    return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags);
+}
+
 /* default to old in-kernel interface if no memory pressure events */
 static bool use_inkernel_interface = true;
 static bool has_inkernel_module;
@@ -169,6 +179,11 @@
 
 static int level_oomadj[VMPRESS_LEVEL_COUNT];
 static int mpevfd[VMPRESS_LEVEL_COUNT] = { -1, -1, -1 };
+static bool pidfd_supported;
+static int last_kill_pid_or_fd = -1;
+static struct timespec last_kill_tm;
+
+/* lmkd configurable parameters */
 static bool debug_process_killing;
 static bool enable_pressure_upgrade;
 static int64_t upgrade_pressure;
@@ -197,6 +212,8 @@
     POLLING_DO_NOT_CHANGE,
     POLLING_START,
     POLLING_STOP,
+    POLLING_PAUSE,
+    POLLING_RESUME,
 };
 
 /*
@@ -207,6 +224,7 @@
  */
 struct polling_params {
     struct event_handler_info* poll_handler;
+    struct event_handler_info* paused_handler;
     struct timespec poll_start_tm;
     struct timespec last_poll_tm;
     int polling_interval_ms;
@@ -235,8 +253,11 @@
 /* vmpressure event handler data */
 static struct event_handler_info vmpressure_hinfo[VMPRESS_LEVEL_COUNT];
 
-/* 3 memory pressure levels, 1 ctrl listen socket, 2 ctrl data socket, 1 lmk events */
-#define MAX_EPOLL_EVENTS (2 + MAX_DATA_CONN + VMPRESS_LEVEL_COUNT)
+/*
+ * 1 ctrl listen socket, 2 ctrl data socket, 3 memory pressure levels,
+ * 1 lmk events + 1 fd to wait for process death
+ */
+#define MAX_EPOLL_EVENTS (1 + MAX_DATA_CONN + VMPRESS_LEVEL_COUNT + 1 + 1)
 static int epollfd;
 static int maxevents;
 
@@ -466,6 +487,7 @@
 struct proc {
     struct adjslot_list asl;
     int pid;
+    int pidfd;
     uid_t uid;
     int oomadj;
     struct proc *pidhash_next;
@@ -682,6 +704,13 @@
         prevp->pidhash_next = procp->pidhash_next;
 
     proc_unslot(procp);
+    /*
+     * Close pidfd here if we are not waiting for corresponding process to die,
+     * in which case stop_wait_for_proc_kill() will close the pidfd later
+     */
+    if (procp->pidfd >= 0 && procp->pidfd != last_kill_pid_or_fd) {
+        close(procp->pidfd);
+    }
     free(procp);
     return 0;
 }
@@ -906,16 +935,27 @@
 
     procp = pid_lookup(params.pid);
     if (!procp) {
-            procp = malloc(sizeof(struct proc));
-            if (!procp) {
-                // Oh, the irony.  May need to rebuild our state.
+        int pidfd = -1;
+
+        if (pidfd_supported) {
+            pidfd = TEMP_FAILURE_RETRY(sys_pidfd_open(params.pid, 0));
+            if (pidfd < 0) {
+                ALOGE("pidfd_open for pid %d failed; errno=%d", params.pid, errno);
                 return;
             }
+        }
 
-            procp->pid = params.pid;
-            procp->uid = params.uid;
-            procp->oomadj = params.oomadj;
-            proc_insert(procp);
+        procp = calloc(1, sizeof(struct proc));
+        if (!procp) {
+            // Oh, the irony.  May need to rebuild our state.
+            return;
+        }
+
+        procp->pid = params.pid;
+        procp->pidfd = pidfd;
+        procp->uid = params.uid;
+        procp->oomadj = params.oomadj;
+        proc_insert(procp);
     } else {
         proc_unslot(procp);
         procp->oomadj = params.oomadj;
@@ -1647,12 +1687,109 @@
     closedir(d);
 }
 
-static int last_killed_pid = -1;
+static bool is_kill_pending(void) {
+    char buf[24];
+
+    if (last_kill_pid_or_fd < 0) {
+        return false;
+    }
+
+    if (pidfd_supported) {
+        return true;
+    }
+
+    /* when pidfd is not supported base the decision on /proc/<pid> existence */
+    snprintf(buf, sizeof(buf), "/proc/%d/", last_kill_pid_or_fd);
+    if (access(buf, F_OK) == 0) {
+        return true;
+    }
+
+    return false;
+}
+
+static bool is_waiting_for_kill(void) {
+    return pidfd_supported && last_kill_pid_or_fd >= 0;
+}
+
+static void stop_wait_for_proc_kill(bool finished) {
+    struct epoll_event epev;
+
+    if (last_kill_pid_or_fd < 0) {
+        return;
+    }
+
+    if (debug_process_killing) {
+        struct timespec curr_tm;
+
+        if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
+            /*
+             * curr_tm is used here merely to report kill duration, so this failure is not fatal.
+             * Log an error and continue.
+             */
+            ALOGE("Failed to get current time");
+        }
+
+        if (finished) {
+            ALOGI("Process got killed in %ldms",
+                get_time_diff_ms(&last_kill_tm, &curr_tm));
+        } else {
+            ALOGI("Stop waiting for process kill after %ldms",
+                get_time_diff_ms(&last_kill_tm, &curr_tm));
+        }
+    }
+
+    if (pidfd_supported) {
+        /* unregister fd */
+        if (epoll_ctl(epollfd, EPOLL_CTL_DEL, last_kill_pid_or_fd, &epev) != 0) {
+            ALOGE("epoll_ctl for last killed process failed; errno=%d", errno);
+            return;
+        }
+        maxevents--;
+        close(last_kill_pid_or_fd);
+    }
+
+    last_kill_pid_or_fd = -1;
+}
+
+static void kill_done_handler(int data __unused, uint32_t events __unused,
+                              struct polling_params *poll_params) {
+    stop_wait_for_proc_kill(true);
+    poll_params->update = POLLING_RESUME;
+}
+
+static void start_wait_for_proc_kill(int pid_or_fd) {
+    static struct event_handler_info kill_done_hinfo = { 0, kill_done_handler };
+    struct epoll_event epev;
+
+    if (last_kill_pid_or_fd >= 0) {
+        /* Should not happen but if it does we should stop previous wait */
+        ALOGE("Attempt to wait for a kill while another wait is in progress");
+        stop_wait_for_proc_kill(false);
+    }
+
+    last_kill_pid_or_fd = pid_or_fd;
+
+    if (!pidfd_supported) {
+        /* If pidfd is not supported just store PID and exit */
+        return;
+    }
+
+    epev.events = EPOLLIN;
+    epev.data.ptr = (void *)&kill_done_hinfo;
+    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, last_kill_pid_or_fd, &epev) != 0) {
+        ALOGE("epoll_ctl for last kill failed; errno=%d", errno);
+        close(last_kill_pid_or_fd);
+        last_kill_pid_or_fd = -1;
+        return;
+    }
+    maxevents++;
+}
 
 /* Kill one process specified by procp.  Returns the size of the process killed */
 static int kill_one_process(struct proc* procp, int min_oom_score, int kill_reason,
-                            const char *kill_desc, union meminfo *mi) {
+                            const char *kill_desc, union meminfo *mi, struct timespec *tm) {
     int pid = procp->pid;
+    int pidfd = procp->pidfd;
     uid_t uid = procp->uid;
     int tgid;
     char *taskname;
@@ -1683,11 +1820,18 @@
     TRACE_KILL_START(pid);
 
     /* CAP_KILL required */
-    r = kill(pid, SIGKILL);
+    if (pidfd < 0) {
+        start_wait_for_proc_kill(pid);
+        r = kill(pid, SIGKILL);
+    } else {
+        start_wait_for_proc_kill(pidfd);
+        r = sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0);
+    }
 
     TRACE_KILL_END();
 
     if (r) {
+        stop_wait_for_proc_kill(false);
         ALOGE("kill(%d): errno=%d", pid, errno);
         /* Delete process record even when we fail to kill so that we don't get stuck on it */
         goto out;
@@ -1695,6 +1839,8 @@
 
     set_process_group_and_prio(pid, SP_FOREGROUND, ANDROID_PRIORITY_HIGHEST);
 
+    last_kill_tm = *tm;
+
     inc_killcnt(procp->oomadj);
 
     killinfo_log(procp, min_oom_score, tasksize, kill_reason, mi);
@@ -1707,8 +1853,6 @@
               uid, procp->oomadj, tasksize * page_k);
     }
 
-    last_killed_pid = pid;
-
     stats_write_lmk_kill_occurred(LMK_KILL_OCCURRED, uid, taskname,
             procp->oomadj, min_oom_score, tasksize, mem_st);
 
@@ -1728,7 +1872,7 @@
  * Returns size of the killed process.
  */
 static int find_and_kill_process(int min_score_adj, int kill_reason, const char *kill_desc,
-                                 union meminfo *mi) {
+                                 union meminfo *mi, struct timespec *tm) {
     int i;
     int killed_size = 0;
     bool lmk_state_change_start = false;
@@ -1743,7 +1887,7 @@
             if (!procp)
                 break;
 
-            killed_size = kill_one_process(procp, min_score_adj, kill_reason, kill_desc, mi);
+            killed_size = kill_one_process(procp, min_score_adj, kill_reason, kill_desc, mi, tm);
             if (killed_size >= 0) {
                 if (!lmk_state_change_start) {
                     lmk_state_change_start = true;
@@ -1822,23 +1966,6 @@
         level - 1 : level);
 }
 
-static bool is_kill_pending(void) {
-    char buf[24];
-
-    if (last_killed_pid < 0) {
-        return false;
-    }
-
-    snprintf(buf, sizeof(buf), "/proc/%d/", last_killed_pid);
-    if (access(buf, F_OK) == 0) {
-        return true;
-    }
-
-    // reset last killed PID because there's nothing pending
-    last_killed_pid = -1;
-    return false;
-}
-
 enum zone_watermark {
     WMARK_MIN = 0,
     WMARK_LOW,
@@ -1934,9 +2061,13 @@
 
     /* Skip while still killing a process */
     if (is_kill_pending()) {
-        /* TODO: replace this quick polling with pidfd polling if kernel supports */
         goto no_kill;
     }
+    /*
+     * Process is dead, stop waiting. This has no effect if pidfds are supported and
+     * death notification already caused waiting to stop.
+     */
+    stop_wait_for_proc_kill(true);
 
     if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
         ALOGE("Failed to get current time");
@@ -2067,7 +2198,8 @@
 
     /* Kill a process if necessary */
     if (kill_reason != NONE) {
-        int pages_freed = find_and_kill_process(min_score_adj, kill_reason, kill_desc, &mi);
+        int pages_freed = find_and_kill_process(min_score_adj, kill_reason, kill_desc, &mi,
+                                                &curr_tm);
         if (pages_freed > 0) {
             killing = true;
             if (cut_thrashing_limit) {
@@ -2081,6 +2213,13 @@
     }
 
 no_kill:
+    /* Do not poll if kernel supports pidfd waiting */
+    if (is_waiting_for_kill()) {
+        /* Pause polling if we are waiting for process death notification */
+        poll_params->update = POLLING_PAUSE;
+        return;
+    }
+
     /*
      * Start polling after initial PSI event;
      * extend polling while device is in direct reclaim or process is being killed;
@@ -2110,7 +2249,6 @@
     union meminfo mi;
     struct zoneinfo zi;
     struct timespec curr_tm;
-    static struct timespec last_kill_tm;
     static unsigned long kill_skip_count = 0;
     enum vmpressure_level level = (enum vmpressure_level)data;
     long other_free = 0, other_file = 0;
@@ -2159,15 +2297,26 @@
         return;
     }
 
-    if (kill_timeout_ms) {
-        // If we're within the timeout, see if there's pending reclaim work
-        // from the last killed process. If there is (as evidenced by
-        // /proc/<pid> continuing to exist), skip killing for now.
-        if ((get_time_diff_ms(&last_kill_tm, &curr_tm) < kill_timeout_ms) &&
-            (low_ram_device || is_kill_pending())) {
+    if (kill_timeout_ms && get_time_diff_ms(&last_kill_tm, &curr_tm) < kill_timeout_ms) {
+        /*
+         * If we're within the no-kill timeout, see if there's pending reclaim work
+         * from the last killed process. If so, skip killing for now.
+         */
+        if (is_kill_pending()) {
             kill_skip_count++;
             return;
         }
+        /*
+         * Process is dead, stop waiting. This has no effect if pidfds are supported and
+         * death notification already caused waiting to stop.
+         */
+        stop_wait_for_proc_kill(true);
+    } else {
+        /*
+         * Killing took longer than no-kill timeout. Stop waiting for the last process
+         * to die because we are ready to kill again.
+         */
+        stop_wait_for_proc_kill(false);
     }
 
     if (kill_skip_count > 0) {
@@ -2266,7 +2415,7 @@
 do_kill:
     if (low_ram_device) {
         /* For Go devices kill only one task */
-        if (find_and_kill_process(level_oomadj[level], -1, NULL, &mi) == 0) {
+        if (find_and_kill_process(level_oomadj[level], -1, NULL, &mi, &curr_tm) == 0) {
             if (debug_process_killing) {
                 ALOGI("Nothing to kill");
             }
@@ -2289,7 +2438,7 @@
             min_score_adj = level_oomadj[level];
         }
 
-        pages_freed = find_and_kill_process(min_score_adj, -1, NULL, &mi);
+        pages_freed = find_and_kill_process(min_score_adj, -1, NULL, &mi, &curr_tm);
 
         if (pages_freed == 0) {
             /* Rate limit kill reports when nothing was reclaimed */
@@ -2297,9 +2446,6 @@
                 report_skip_count++;
                 return;
             }
-        } else {
-            /* If we killed anything, update the last killed timestamp. */
-            last_kill_tm = curr_tm;
         }
 
         /* Log whenever we kill or when report rate limit allows */
@@ -2322,6 +2468,10 @@
 
         last_report_tm = curr_tm;
     }
+    if (is_waiting_for_kill()) {
+        /* pause polling if we are waiting for process death notification */
+        poll_params->update = POLLING_PAUSE;
+    }
 }
 
 static bool init_mp_psi(enum vmpressure_level level, bool use_new_strategy) {
@@ -2473,6 +2623,7 @@
         .fd = -1,
     };
     struct epoll_event epev;
+    int pidfd;
     int i;
     int ret;
 
@@ -2563,9 +2714,61 @@
         ALOGE("Failed to read %s: %s", file_data.filename, strerror(errno));
     }
 
+    /* check if kernel supports pidfd_open syscall */
+    pidfd = TEMP_FAILURE_RETRY(sys_pidfd_open(getpid(), 0));
+    if (pidfd < 0) {
+        pidfd_supported = (errno != ENOSYS);
+    } else {
+        pidfd_supported = true;
+        close(pidfd);
+    }
+    ALOGI("Process polling is %s", pidfd_supported ? "supported" : "not supported" );
+
     return 0;
 }
 
+static void call_handler(struct event_handler_info* handler_info,
+                         struct polling_params *poll_params, uint32_t events) {
+    struct timespec curr_tm;
+
+    handler_info->handler(handler_info->data, events, poll_params);
+    clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm);
+    poll_params->last_poll_tm = curr_tm;
+
+    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.
+         */
+        poll_params->poll_start_tm = curr_tm;
+        if (poll_params->poll_handler != handler_info) {
+            poll_params->poll_handler = handler_info;
+        }
+        break;
+    case POLLING_STOP:
+        poll_params->poll_handler = NULL;
+        break;
+    case POLLING_PAUSE:
+        poll_params->paused_handler = handler_info;
+        poll_params->poll_handler = NULL;
+        break;
+    case POLLING_RESUME:
+        poll_params->poll_start_tm = curr_tm;
+        poll_params->poll_handler = poll_params->paused_handler;
+        break;
+    case POLLING_DO_NOT_CHANGE:
+        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;
+        }
+        /* WARNING: skipping the rest of the function */
+        return;
+    }
+    poll_params->update = POLLING_DO_NOT_CHANGE;
+}
+
 static void mainloop(void) {
     struct event_handler_info* handler_info;
     struct polling_params poll_params;
@@ -2582,41 +2785,33 @@
         int i;
 
         if (poll_params.poll_handler) {
-            /* Calculate next timeout */
-            clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm);
-            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);
+            bool poll_now;
 
             clock_gettime(CLOCK_MONOTONIC_COARSE, &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.poll_handler == poll_params.paused_handler) {
+                /*
+                 * Just transitioned into POLLING_RESUME. Reset paused_handler
+                 * and poll immediately
+                 */
+                poll_params.paused_handler = NULL;
+                poll_now = true;
+                nevents = 0;
+            } else {
+                /* Calculate next timeout */
+                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;
 
-                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;
-                    }
-                }
+                /* Wait for events until the next polling timeout */
+                nevents = epoll_wait(epollfd, events, maxevents, delay);
+
+                /* Update current time after wait */
+                clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm);
+                poll_now = (get_time_diff_ms(&poll_params.last_poll_tm, &curr_tm) >=
+                    poll_params.polling_interval_ms);
+            }
+            if (poll_now) {
+                call_handler(poll_params.poll_handler, &poll_params, 0);
             }
         } else {
             /* Wait for events with no timeout */
@@ -2656,29 +2851,7 @@
             }
             if (evt->data.ptr) {
                 handler_info = (struct event_handler_info*)evt->data.ptr;
-                /* Set input params for the call */
-                handler_info->handler(handler_info->data, evt->events, &poll_params);
-
-                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;
-                }
+                call_handler(handler_info, &poll_params, evt->events);
             }
         }
     }
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index b7b0b2a..a99756a 100644
--- a/rootdir/etc/ld.config.legacy.txt
+++ b/rootdir/etc/ld.config.legacy.txt
@@ -87,12 +87,13 @@
 
 namespace.art.search.paths = /apex/com.android.art/${LIB}
 namespace.art.asan.search.paths = /apex/com.android.art/${LIB}
-namespace.art.links = default
+namespace.art.links = default,neuralnetworks
 # Need allow_all_shared_libs because libart.so can dlopen oat files in
 # /system/framework and /data.
 # TODO(b/130340935): Use a dynamically created linker namespace similar to
 # classloader-namespace for oat files, and tighten this up.
 namespace.art.link.default.allow_all_shared_libs = true
+namespace.art.link.neuralnetworks.shared_libs = libneuralnetworks.so
 
 ###############################################################################
 # "media" APEX namespace