Merge "adb/fastboot: switch over to shared AdbWinApi."
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index a5e6f23..18f585d 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -22,6 +22,7 @@
 
 #include <atomic>
 #include <chrono>
+#include <condition_variable>
 #include <memory>
 #include <mutex>
 #include <string>
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 5cf2450..f221785 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -952,10 +952,18 @@
 }
 
 std::string list_transports(bool long_listing) {
-    std::string result;
-
     std::lock_guard<std::recursive_mutex> lock(transport_lock);
-    for (const auto& t : transport_list) {
+
+    auto sorted_transport_list = transport_list;
+    sorted_transport_list.sort([](atransport*& x, atransport*& y) {
+        if (x->type != y->type) {
+            return x->type < y->type;
+        }
+        return strcmp(x->serial, y->serial) < 0;
+    });
+
+    std::string result;
+    for (const auto& t : sorted_transport_list) {
         append_transport(t, &result, long_listing);
     }
     return result;
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index a1fcad8..ae0a401 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -272,6 +272,15 @@
     {"reboot_rtc", 132},
     {"cold_boot", 133},
     {"hard_rst", 134},
+    {"power-on", 135},
+    {"oem_adsp_resetting_the_soc", 136},
+    {"kpdpwr", 137},
+    {"oem_modem_timeout_waiting", 138},
+    {"usb_chg", 139},
+    {"warm_reset_0x02", 140},
+    {"warm_reset_0x80", 141},
+    {"pon_reason_0xb0", 142},
+    {"reboot_download", 143},
 };
 
 // Converts a string value representing the reason the system booted to an
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index e9a3ebd..4b32b9d 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -289,7 +289,7 @@
         munmap(map, sizeof(int));
         map[0] = '8';
     } else if (!strcasecmp(arg, "seccomp")) {
-        set_seccomp_filter();
+        set_system_seccomp_filter();
         syscall(99999);
 #if defined(__arm__)
     } else if (!strcasecmp(arg, "kuser_helper_version")) {
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 02bc4b8..05e6efa 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -395,9 +395,6 @@
   // crash_dump is ptracing us, fork off a copy of our address space for it to use.
   create_vm_process();
 
-  input_read.reset();
-  input_write.reset();
-
   // Don't leave a zombie child.
   int status;
   if (TEMP_FAILURE_RETRY(waitpid(crash_dump_pid, &status, 0)) == -1) {
@@ -406,6 +403,14 @@
   } else if (WIFSTOPPED(status) || WIFSIGNALED(status)) {
     async_safe_format_log(ANDROID_LOG_FATAL, "libc", "crash_dump helper crashed or stopped");
   }
+
+  if (thread_info->siginfo->si_signo != DEBUGGER_SIGNAL) {
+    // For crashes, we don't need to minimize pause latency.
+    // Wait for the dump to complete before having the process exit, to avoid being murdered by
+    // ActivityManager or init.
+    TEMP_FAILURE_RETRY(read(input_read, &buf, sizeof(buf)));
+  }
+
   return 0;
 }
 
@@ -495,6 +500,17 @@
     fatal_errno("failed to set dumpable");
   }
 
+  // On kernels with yama_ptrace enabled, also allow any process to attach.
+  bool restore_orig_ptracer = true;
+  if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) != 0) {
+    if (errno == EINVAL) {
+      // This kernel does not support PR_SET_PTRACER_ANY, or Yama is not enabled.
+      restore_orig_ptracer = false;
+    } else {
+      fatal_errno("failed to set traceable");
+    }
+  }
+
   // Essentially pthread_create without CLONE_FILES, so we still work during file descriptor
   // exhaustion.
   pid_t child_pid =
@@ -516,6 +532,11 @@
     fatal_errno("failed to restore dumpable");
   }
 
+  // Restore PR_SET_PTRACER to its original value.
+  if (restore_orig_ptracer && prctl(PR_SET_PTRACER, 0) != 0) {
+    fatal_errno("failed to restore traceable");
+  }
+
   if (info->si_signo == DEBUGGER_SIGNAL) {
     // If the signal is fatal, don't unlock the mutex to prevent other crashing threads from
     // starting to dump right before our death.
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 624637a..89a125b 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -402,6 +402,10 @@
     dump_signal_info(log, thread_info.siginfo);
   }
 
+  if (primary_thread) {
+    dump_abort_message(log, process_memory, abort_msg_address);
+  }
+
   dump_registers(log, thread_info.registers.get());
 
   std::vector<backtrace_frame_data_t> frames;
@@ -419,10 +423,6 @@
   }
 
   if (primary_thread) {
-    dump_abort_message(log, process_memory, abort_msg_address);
-  }
-
-  if (primary_thread) {
     dump_memory_and_code(log, process_memory, thread_info.registers.get());
     if (map) {
       uintptr_t addr = 0;
diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp
index 7e10cc9..271b792 100644
--- a/fastboot/engine.cpp
+++ b/fastboot/engine.cpp
@@ -114,7 +114,7 @@
 
     if (cmdsize >= sizeof(a->cmd)) {
         free(a);
-        die("Command length (%d) exceeds maximum size (%d)", cmdsize, sizeof(a->cmd));
+        die("Command length (%zu) exceeds maximum size (%zu)", cmdsize, sizeof(a->cmd));
     }
 
     if (action_last) {
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 4b94f9c..a2b80ad 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -38,6 +38,7 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
+#include <cutils/android_filesystem_config.h>
 #include <cutils/android_reboot.h>
 #include <cutils/partition_utils.h>
 #include <cutils/properties.h>
@@ -353,7 +354,7 @@
         reserved_blocks = max_reserved_blocks;
     }
 
-    if (ext4_r_blocks_count(sb) == reserved_blocks) {
+    if ((ext4_r_blocks_count(sb) == reserved_blocks) && (sb->s_def_resgid == AID_RESERVED_DISK)) {
         return;
     }
 
@@ -363,11 +364,12 @@
         return;
     }
 
-    char buf[32];
-    const char* argv[] = {TUNE2FS_BIN, "-r", buf, blk_device};
-
-    snprintf(buf, sizeof(buf), "%" PRIu64, reserved_blocks);
     LINFO << "Setting reserved block count on " << blk_device << " to " << reserved_blocks;
+
+    auto reserved_blocks_str = std::to_string(reserved_blocks);
+    auto reserved_gid_str = std::to_string(AID_RESERVED_DISK);
+    const char* argv[] = {
+        TUNE2FS_BIN, "-r", reserved_blocks_str.c_str(), "-g", reserved_gid_str.c_str(), blk_device};
     if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
         LERROR << "Failed to run " TUNE2FS_BIN " to set the number of reserved blocks on "
                << blk_device;
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 34afed1..1c01d8c 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -638,6 +638,7 @@
  * frees up memory of the return value without touching a and b. */
 static struct fstab *in_place_merge(struct fstab *a, struct fstab *b)
 {
+    if (!a && !b) return nullptr;
     if (!a) return b;
     if (!b) return a;
 
@@ -654,12 +655,13 @@
     }
 
     for (int i = a->num_entries, j = 0; i < total_entries; i++, j++) {
-        // copy the pointer directly *without* malloc and memcpy
+        // Copy the structs by assignment.
         a->recs[i] = b->recs[j];
     }
 
-    // Frees up b, but don't free b->recs[X] to make sure they are
-    // accessible through a->recs[X].
+    // We can't call fs_mgr_free_fstab because a->recs still references the
+    // memory allocated by strdup.
+    free(b->recs);
     free(b->fstab_filename);
     free(b);
 
@@ -754,15 +756,17 @@
         default_fstab = get_fstab_path();
     }
 
-    if (default_fstab.empty()) {
-        LWARNING << __FUNCTION__ << "(): failed to find device default fstab";
+    struct fstab* fstab = nullptr;
+    if (!default_fstab.empty()) {
+        fstab = fs_mgr_read_fstab(default_fstab.c_str());
+    } else {
+        LINFO << __FUNCTION__ << "(): failed to find device default fstab";
     }
 
+    struct fstab* fstab_dt = fs_mgr_read_fstab_dt();
+
     // combines fstab entries passed in from device tree with
     // the ones found from default_fstab file
-    struct fstab *fstab_dt = fs_mgr_read_fstab_dt();
-    struct fstab *fstab = fs_mgr_read_fstab(default_fstab.c_str());
-
     return in_place_merge(fstab_dt, fstab);
 }
 
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 4b6c502..7aa94b0 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -58,7 +58,6 @@
 
 #include "init.h"
 #include "persistent_properties.h"
-#include "space_tokenizer.h"
 #include "util.h"
 
 using android::base::ReadFileToString;
@@ -69,6 +68,7 @@
 using android::base::Trim;
 using android::base::WriteStringToFile;
 using android::properties::BuildTrie;
+using android::properties::ParsePropertyInfoFile;
 using android::properties::PropertyInfoAreaFile;
 using android::properties::PropertyInfoEntry;
 
@@ -350,13 +350,15 @@
     ufds[0].events = POLLIN;
     ufds[0].revents = 0;
     while (*timeout_ms > 0) {
-      Timer timer;
-      int nr = poll(ufds, 1, *timeout_ms);
-      uint64_t millis = timer.duration().count();
-      *timeout_ms = (millis > *timeout_ms) ? 0 : *timeout_ms - millis;
+        auto start_time = std::chrono::steady_clock::now();
+        int nr = poll(ufds, 1, *timeout_ms);
+        auto now = std::chrono::steady_clock::now();
+        auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
+        uint64_t millis = time_elapsed.count();
+        *timeout_ms = (millis > *timeout_ms) ? 0 : *timeout_ms - millis;
 
-      if (nr > 0) {
-        return true;
+        if (nr > 0) {
+            return true;
       }
 
       if (nr == 0) {
@@ -726,22 +728,6 @@
     return 0;
 }
 
-Result<PropertyInfoEntry> ParsePropertyInfoLine(const std::string& line) {
-    auto tokenizer = SpaceTokenizer(line);
-
-    auto property = tokenizer.GetNext();
-    if (property.empty()) return Error() << "Did not find a property entry in '" << line << "'";
-
-    auto context = tokenizer.GetNext();
-    if (context.empty()) return Error() << "Did not find a context entry in '" << line << "'";
-
-    // It is not an error to not find these, as older files will not contain them.
-    auto exact_match = tokenizer.GetNext();
-    auto schema = tokenizer.GetRemaining();
-
-    return {property, context, schema, exact_match == "exact"};
-}
-
 bool LoadPropertyInfoFromFile(const std::string& filename,
                               std::vector<PropertyInfoEntry>* property_infos) {
     auto file_contents = std::string();
@@ -750,20 +736,14 @@
         return false;
     }
 
-    for (const auto& line : Split(file_contents, "\n")) {
-        auto trimmed_line = Trim(line);
-        if (trimmed_line.empty() || StartsWith(trimmed_line, "#")) {
-            continue;
-        }
-
-        auto property_info = ParsePropertyInfoLine(line);
-        if (!property_info) {
-            LOG(ERROR) << "Could not read line from '" << filename << "': " << property_info.error();
-            continue;
-        }
-
-        property_infos->emplace_back(*property_info);
+    auto errors = std::vector<std::string>{};
+    ParsePropertyInfoFile(file_contents, property_infos, &errors);
+    // Individual parsing errors are reported but do not cause a failed boot, which is what
+    // returning false would do here.
+    for (const auto& error : errors) {
+        LOG(ERROR) << "Could not read line from '" << filename << "': " << error;
     }
+
     return true;
 }
 
diff --git a/init/space_tokenizer.h b/init/space_tokenizer.h
deleted file mode 100644
index e7e22c5..0000000
--- a/init/space_tokenizer.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _INIT_SPACE_TOKENIZER_H
-#define _INIT_SPACE_TOKENIZER_H
-
-namespace android {
-namespace init {
-
-class SpaceTokenizer {
-  public:
-    SpaceTokenizer(const std::string& string)
-        : string_(string), it_(string_.begin()), end_(string_.end()) {}
-
-    std::string GetNext() {
-        auto next = std::string();
-        while (it_ != end_ && !isspace(*it_)) {
-            next.push_back(*it_++);
-        }
-        while (it_ != end_ && isspace(*it_)) {
-            it_++;
-        }
-        return next;
-    }
-
-    std::string GetRemaining() { return std::string(it_, end_); }
-
-  private:
-    std::string string_;
-    std::string::const_iterator it_;
-    std::string::const_iterator end_;
-};
-
-}  // namespace init
-}  // namespace android
-
-#endif
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 9cba109..6d00dc6 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -36,7 +36,7 @@
     export_include_dirs: ["include"],
     target: {
         vendor: {
-            export_include_dirs: ["include_vndk"],
+            override_export_include_dirs: ["include_vndk"],
         },
         linux_bionic: {
             enabled: true,
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 2ecf5bc..2f2e262 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -122,6 +122,7 @@
 #define AID_AUTOMOTIVE_EVS 1062  /* Automotive rear and surround view system */
 #define AID_LOWPAN 1063          /* LoWPAN subsystem */
 #define AID_HSM 1064             /* hardware security module subsystem */
+#define AID_RESERVED_DISK 1065   /* GID that has access to reserved disk space */
 /* Changes to this file must be made in AOSP, *not* in internal branches. */
 
 #define AID_SHELL 2000 /* adb and debug shell user */
diff --git a/libcutils/uevent.cpp b/libcutils/uevent.cpp
index a84e5b0..2dfceed 100644
--- a/libcutils/uevent.cpp
+++ b/libcutils/uevent.cpp
@@ -27,54 +27,6 @@
 
 #include <linux/netlink.h>
 
-#include <fstream>
-
-#include <private/android_filesystem_config.h>
-
-namespace {
-
-// Returns the uid of root in the current user namespace.
-// Returns AID_OVERFLOWUID if the root user is not mapped in the current
-// namespace.
-// Returns 0 if the kernel is not user namespace-aware (for backwards
-// compatibility) or if AID_OVERFLOWUID could not be validated to match what the
-// kernel would return.
-uid_t GetRootUid() {
-    constexpr uid_t kParentRootUid = 0;
-
-    std::ifstream uid_map_file("/proc/self/uid_map");
-    if (!uid_map_file) {
-        // The kernel does not support user namespaces.
-        return kParentRootUid;
-    }
-
-    uid_t current_namespace_uid, parent_namespace_uid;
-    uint32_t length;
-    while (uid_map_file >> current_namespace_uid >> parent_namespace_uid >> length) {
-        // Since kParentRootUid is 0, it should be the first entry in the mapped
-        // range.
-        if (parent_namespace_uid != kParentRootUid || length < 1) continue;
-        return current_namespace_uid;
-    }
-
-    // Sanity check: verify that the overflow UID is the one to be returned by
-    // the kernel.
-    std::ifstream overflowuid_file("/proc/sys/kernel/overflowuid");
-    if (!overflowuid_file) {
-        // It's better to return 0 in case we cannot make sure that the overflow
-        // UID matches.
-        return kParentRootUid;
-    }
-    uid_t kernel_overflow_uid;
-    if (!(overflowuid_file >> kernel_overflow_uid) || kernel_overflow_uid != AID_OVERFLOWUID)
-        return kParentRootUid;
-
-    // root is unmapped, use the kernel "overflow" uid.
-    return AID_OVERFLOWUID;
-}
-
-}  // namespace
-
 extern "C" {
 
 /**
@@ -99,7 +51,6 @@
 }
 
 ssize_t uevent_kernel_recv(int socket, void* buffer, size_t length, bool require_group, uid_t* uid) {
-    static const uid_t root_uid = GetRootUid();
     struct iovec iov = {buffer, length};
     struct sockaddr_nl addr;
     char control[CMSG_SPACE(sizeof(struct ucred))];
@@ -122,10 +73,6 @@
 
     cred = (struct ucred*)CMSG_DATA(cmsg);
     *uid = cred->uid;
-    if (cred->uid != root_uid) {
-        /* ignoring netlink message from non-root user */
-        goto out;
-    }
 
     if (addr.nl_pid != 0) {
         /* ignore non-kernel */
diff --git a/liblog/Android.bp b/liblog/Android.bp
index d5bb29e..7d9e306 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -55,7 +55,7 @@
             enabled: true,
         },
         vendor: {
-            export_include_dirs: ["include_vndk"],
+            override_export_include_dirs: ["include_vndk"],
         },
     },
 }
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
index 4b21edc..17983bc 100644
--- a/libnativeloader/Android.bp
+++ b/libnativeloader/Android.bp
@@ -19,4 +19,8 @@
         "-fvisibility=hidden",
     ],
     export_include_dirs: ["include"],
+    required: [
+        "llndk.libraries.txt",
+        "vndksp.libraries.txt",
+    ],
 }
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index e9f0c0f..6ddec4d 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -662,22 +662,51 @@
     return handle;
   }
 #else
-  UNUSED(env, target_sdk_version, class_loader, library_path);
-  *needs_native_bridge = false;
-  void* handle = dlopen(path, RTLD_NOW);
-  if (handle == nullptr) {
-    if (NativeBridgeIsSupported(path)) {
-      *needs_native_bridge = true;
-      handle = NativeBridgeLoadLibrary(path, RTLD_NOW);
-      if (handle == nullptr) {
-        *error_msg = NativeBridgeGetError();
-      }
+  UNUSED(env, target_sdk_version, class_loader);
+
+  // Do some best effort to emulate library-path support. It will not
+  // work for dependencies.
+  //
+  // Note: null has a special meaning and must be preserved.
+  std::string c_library_path;  // Empty string by default.
+  if (library_path != nullptr && path != nullptr && path[0] != '/') {
+    ScopedUtfChars library_path_utf_chars(env, library_path);
+    c_library_path = library_path_utf_chars.c_str();
+  }
+
+  std::vector<std::string> library_paths = base::Split(c_library_path, ":");
+
+  for (const std::string& lib_path : library_paths) {
+    *needs_native_bridge = false;
+    const char* path_arg;
+    std::string complete_path;
+    if (path == nullptr) {
+      // Preserve null.
+      path_arg = nullptr;
     } else {
-      *needs_native_bridge = false;
+      complete_path = lib_path;
+      if (!complete_path.empty()) {
+        complete_path.append("/");
+      }
+      complete_path.append(path);
+      path_arg = complete_path.c_str();
+    }
+    void* handle = dlopen(path_arg, RTLD_NOW);
+    if (handle != nullptr) {
+      return handle;
+    }
+    if (NativeBridgeIsSupported(path_arg)) {
+      *needs_native_bridge = true;
+      handle = NativeBridgeLoadLibrary(path_arg, RTLD_NOW);
+      if (handle != nullptr) {
+        return handle;
+      }
+      *error_msg = NativeBridgeGetError();
+    } else {
       *error_msg = dlerror();
     }
   }
-  return handle;
+  return nullptr;
 #endif
 }
 
diff --git a/libsuspend/Android.bp b/libsuspend/Android.bp
index fa06dc4..b3e36c2 100644
--- a/libsuspend/Android.bp
+++ b/libsuspend/Android.bp
@@ -14,6 +14,7 @@
     export_include_dirs: ["include"],
     local_include_dirs: ["include"],
     shared_libs: [
+        "libbase",
         "liblog",
         "libcutils",
     ],
diff --git a/libsuspend/autosuspend_wakeup_count.cpp b/libsuspend/autosuspend_wakeup_count.cpp
index 30f8427..cfca765 100644
--- a/libsuspend/autosuspend_wakeup_count.cpp
+++ b/libsuspend/autosuspend_wakeup_count.cpp
@@ -17,7 +17,6 @@
 #define LOG_TAG "libsuspend"
 //#define LOG_NDEBUG 0
 
-#include <errno.h>
 #include <fcntl.h>
 #include <pthread.h>
 #include <semaphore.h>
@@ -29,22 +28,29 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <log/log.h>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
 
 #include "autosuspend_ops.h"
 
-#define SYS_POWER_STATE "/sys/power/state"
-#define SYS_POWER_WAKEUP_COUNT "/sys/power/wakeup_count"
-
 #define BASE_SLEEP_TIME 100000
+#define MAX_SLEEP_TIME 60000000
 
 static int state_fd;
 static int wakeup_count_fd;
+
+using android::base::ReadFdToString;
+using android::base::Trim;
+using android::base::WriteStringToFd;
+
 static pthread_t suspend_thread;
 static sem_t suspend_lockout;
 static const char* sleep_state = "mem";
 static void (*wakeup_func)(bool success) = NULL;
 static int sleep_time = BASE_SLEEP_TIME;
+static constexpr char sys_power_state[] = "/sys/power/state";
+static constexpr char sys_power_wakeup_count[] = "/sys/power/wakeup_count";
 
 static void update_sleep_time(bool success) {
     if (success) {
@@ -52,13 +58,10 @@
         return;
     }
     // double sleep time after each failure up to one minute
-    sleep_time = MIN(sleep_time * 2, 60000000);
+    sleep_time = MIN(sleep_time * 2, MAX_SLEEP_TIME);
 }
 
 static void* suspend_thread_func(void* arg __attribute__((unused))) {
-    char buf[80];
-    char wakeup_count[20];
-    int wakeup_count_len;
     int ret;
     bool success = true;
 
@@ -66,95 +69,84 @@
         update_sleep_time(success);
         usleep(sleep_time);
         success = false;
-        ALOGV("%s: read wakeup_count", __func__);
+        LOG(VERBOSE) << "read wakeup_count";
         lseek(wakeup_count_fd, 0, SEEK_SET);
-        wakeup_count_len =
-            TEMP_FAILURE_RETRY(read(wakeup_count_fd, wakeup_count, sizeof(wakeup_count)));
-        if (wakeup_count_len < 0) {
-            strerror_r(errno, buf, sizeof(buf));
-            ALOGE("Error reading from %s: %s", SYS_POWER_WAKEUP_COUNT, buf);
-            wakeup_count_len = 0;
-            continue;
-        }
-        if (!wakeup_count_len) {
-            ALOGE("Empty wakeup count");
+        std::string wakeup_count;
+        if (!ReadFdToString(wakeup_count_fd, &wakeup_count)) {
+            PLOG(ERROR) << "error reading from " << sys_power_wakeup_count;
             continue;
         }
 
-        ALOGV("%s: wait", __func__);
+        wakeup_count = Trim(wakeup_count);
+        if (wakeup_count.empty()) {
+            LOG(ERROR) << "empty wakeup count";
+            continue;
+        }
+
+        LOG(VERBOSE) << "wait";
         ret = sem_wait(&suspend_lockout);
         if (ret < 0) {
-            strerror_r(errno, buf, sizeof(buf));
-            ALOGE("Error waiting on semaphore: %s", buf);
+            PLOG(ERROR) << "error waiting on semaphore";
             continue;
         }
 
-        ALOGV("%s: write %*s to wakeup_count", __func__, wakeup_count_len, wakeup_count);
-        ret = TEMP_FAILURE_RETRY(write(wakeup_count_fd, wakeup_count, wakeup_count_len));
-        if (ret < 0) {
-            strerror_r(errno, buf, sizeof(buf));
-            ALOGE("Error writing to %s: %s", SYS_POWER_WAKEUP_COUNT, buf);
-        } else {
-            ALOGV("%s: write %s to %s", __func__, sleep_state, SYS_POWER_STATE);
-            ret = TEMP_FAILURE_RETRY(write(state_fd, sleep_state, strlen(sleep_state)));
-            if (ret >= 0) {
-                success = true;
-            }
+        LOG(VERBOSE) << "write " << wakeup_count << " to wakeup_count";
+        if (WriteStringToFd(wakeup_count, wakeup_count_fd)) {
+            LOG(VERBOSE) << "write " << sleep_state << " to " << sys_power_state;
+            success = WriteStringToFd(sleep_state, state_fd);
+
             void (*func)(bool success) = wakeup_func;
             if (func != NULL) {
                 (*func)(success);
             }
+        } else {
+            PLOG(ERROR) << "error writing to " << sys_power_wakeup_count;
         }
 
-        ALOGV("%s: release sem", __func__);
+        LOG(VERBOSE) << "release sem";
         ret = sem_post(&suspend_lockout);
         if (ret < 0) {
-            strerror_r(errno, buf, sizeof(buf));
-            ALOGE("Error releasing semaphore: %s", buf);
+            PLOG(ERROR) << "error releasing semaphore";
         }
     }
     return NULL;
 }
 
 static int autosuspend_wakeup_count_enable(void) {
-    char buf[80];
     int ret;
 
-    ALOGV("autosuspend_wakeup_count_enable");
+    LOG(VERBOSE) << "autosuspend_wakeup_count_enable";
 
     ret = sem_post(&suspend_lockout);
 
     if (ret < 0) {
-        strerror_r(errno, buf, sizeof(buf));
-        ALOGE("Error changing semaphore: %s", buf);
+        PLOG(ERROR) << "error changing semaphore";
     }
 
-    ALOGV("autosuspend_wakeup_count_enable done");
+    LOG(VERBOSE) << "autosuspend_wakeup_count_enable done";
 
     return ret;
 }
 
 static int autosuspend_wakeup_count_disable(void) {
-    char buf[80];
     int ret;
 
-    ALOGV("autosuspend_wakeup_count_disable");
+    LOG(VERBOSE) << "autosuspend_wakeup_count_disable";
 
     ret = sem_wait(&suspend_lockout);
 
     if (ret < 0) {
-        strerror_r(errno, buf, sizeof(buf));
-        ALOGE("Error changing semaphore: %s", buf);
+        PLOG(ERROR) << "error changing semaphore";
     }
 
-    ALOGV("autosuspend_wakeup_count_disable done");
+    LOG(VERBOSE) << "autosuspend_wakeup_count_disable done";
 
     return ret;
 }
 
 static void autosuspend_set_wakeup_callback(void (*func)(bool success)) {
     if (wakeup_func != NULL) {
-        ALOGE("Duplicate wakeup callback applied, keeping original");
+        LOG(ERROR) << "duplicate wakeup callback applied, keeping original";
         return;
     }
     wakeup_func = func;
@@ -168,36 +160,31 @@
 
 struct autosuspend_ops* autosuspend_wakeup_count_init(void) {
     int ret;
-    char buf[80];
 
-    state_fd = TEMP_FAILURE_RETRY(open(SYS_POWER_STATE, O_RDWR));
+    state_fd = TEMP_FAILURE_RETRY(open(sys_power_state, O_RDWR));
     if (state_fd < 0) {
-        strerror_r(errno, buf, sizeof(buf));
-        ALOGE("Error opening %s: %s", SYS_POWER_STATE, buf);
+        PLOG(ERROR) << "error opening " << sys_power_state;
         goto err_open_state;
     }
 
-    wakeup_count_fd = TEMP_FAILURE_RETRY(open(SYS_POWER_WAKEUP_COUNT, O_RDWR));
+    wakeup_count_fd = TEMP_FAILURE_RETRY(open(sys_power_wakeup_count, O_RDWR));
     if (wakeup_count_fd < 0) {
-        strerror_r(errno, buf, sizeof(buf));
-        ALOGE("Error opening %s: %s", SYS_POWER_WAKEUP_COUNT, buf);
+        PLOG(ERROR) << "error opening " << sys_power_wakeup_count;
         goto err_open_wakeup_count;
     }
 
     ret = sem_init(&suspend_lockout, 0, 0);
     if (ret < 0) {
-        strerror_r(errno, buf, sizeof(buf));
-        ALOGE("Error creating semaphore: %s", buf);
+        PLOG(ERROR) << "error creating semaphore";
         goto err_sem_init;
     }
     ret = pthread_create(&suspend_thread, NULL, suspend_thread_func, NULL);
     if (ret) {
-        strerror_r(ret, buf, sizeof(buf));
-        ALOGE("Error creating thread: %s", buf);
+        LOG(ERROR) << "error creating thread: " << strerror(ret);
         goto err_pthread_create;
     }
 
-    ALOGI("Selected wakeup count");
+    LOG(INFO) << "selected wakeup count";
     return &autosuspend_wakeup_count_ops;
 
 err_pthread_create:
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 466be4a..ad673dc 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -587,10 +587,11 @@
   // an entry whose name is "name" and whose size is 12 (contents =
   // "abdcdefghijk").
   ZipEntry entry;
-  ZipString empty_name;
-  SetZipString(&empty_name, "name");
+  ZipString name;
+  std::string name_str = "name";
+  SetZipString(&name, name_str);
 
-  ASSERT_EQ(0, FindEntry(handle, empty_name, &entry));
+  ASSERT_EQ(0, FindEntry(handle, name, &entry));
   ASSERT_EQ(static_cast<uint32_t>(12), entry.uncompressed_length);
 
   entry_out->resize(12);
@@ -610,7 +611,7 @@
   ASSERT_EQ('k', entry[11]);
 }
 
-TEST(ziparchive, InvalidDataDescriptors) {
+TEST(ziparchive, InvalidDataDescriptors_csize) {
   std::vector<uint8_t> invalid_csize = kDataDescriptorZipFile;
   invalid_csize[kCSizeOffset] = 0xfe;
 
@@ -619,13 +620,15 @@
   ExtractEntryToMemory(invalid_csize, &entry, &error_code);
 
   ASSERT_EQ(kInconsistentInformation, error_code);
+}
 
+TEST(ziparchive, InvalidDataDescriptors_size) {
   std::vector<uint8_t> invalid_size = kDataDescriptorZipFile;
-  invalid_csize[kSizeOffset] = 0xfe;
+  invalid_size[kSizeOffset] = 0xfe;
 
-  error_code = 0;
-  entry.clear();
-  ExtractEntryToMemory(invalid_csize, &entry, &error_code);
+  std::vector<uint8_t> entry;
+  int32_t error_code = 0;
+  ExtractEntryToMemory(invalid_size, &entry, &error_code);
 
   ASSERT_EQ(kInconsistentInformation, error_code);
 }
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 5cfa2c8..fd83ecc 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -900,7 +900,9 @@
     downgrade_pressure = (int64_t)property_get_int32("ro.lmk.downgrade_pressure", 60);
     is_go_device = property_get_bool("ro.config.low_ram", false);
 
-    mlockall(MCL_FUTURE);
+    if (mlockall(MCL_CURRENT | MCL_FUTURE))
+        ALOGW("mlockall failed: errno=%d", errno);
+
     sched_setscheduler(0, SCHED_FIFO, &param);
     if (!init())
         mainloop();
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 1d0cc33..b76160d 100755
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -45,7 +45,7 @@
         '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) % 10, '>'
 
 LogAudit::LogAudit(LogBuffer* buf, LogReader* reader, int fdDmesg)
-    : SocketListener(mSock = getLogSocket(), false),
+    : SocketListener(getLogSocket(), false),
       logbuf(buf),
       reader(reader),
       fdDmesg(fdDmesg),
@@ -53,8 +53,7 @@
                                               BOOL_DEFAULT_TRUE)),
       events(__android_logger_property_get_bool("ro.logd.auditd.events",
                                                 BOOL_DEFAULT_TRUE)),
-      initialized(false),
-      tooFast(false) {
+      initialized(false) {
     static const char auditd_message[] = { KMSG_PRIORITY(LOG_INFO),
                                            'l',
                                            'o',
@@ -78,54 +77,12 @@
     write(fdDmesg, auditd_message, sizeof(auditd_message));
 }
 
-void LogAudit::checkRateLimit() {
-    // trim list for AUDIT_RATE_LIMIT_BURST_DURATION of history
-    log_time oldest(AUDIT_RATE_LIMIT_BURST_DURATION, 0);
-    bucket.emplace(android_log_clockid());
-    oldest = bucket.back() - oldest;
-    while (bucket.front() < oldest) bucket.pop();
-
-    static const size_t upperThreshold =
-        ((AUDIT_RATE_LIMIT_BURST_DURATION *
-          (AUDIT_RATE_LIMIT_DEFAULT + AUDIT_RATE_LIMIT_MAX)) +
-         1) /
-        2;
-    if (bucket.size() >= upperThreshold) {
-        // Hit peak, slow down source
-        if (!tooFast) {
-            tooFast = true;
-            audit_rate_limit(mSock, AUDIT_RATE_LIMIT_MAX);
-        }
-
-        // We do not need to hold on to the full set of timing data history,
-        // let's ensure it does not grow without bounds.  This also ensures
-        // that std::dequeue underneath behaves almost like a ring buffer.
-        do {
-            bucket.pop();
-        } while (bucket.size() >= upperThreshold);
-        return;
-    }
-
-    if (!tooFast) return;
-
-    static const size_t lowerThreshold =
-        AUDIT_RATE_LIMIT_BURST_DURATION * AUDIT_RATE_LIMIT_MAX;
-
-    if (bucket.size() >= lowerThreshold) return;
-
-    tooFast = false;
-    // Went below max sustained rate, allow source to speed up
-    audit_rate_limit(mSock, AUDIT_RATE_LIMIT_DEFAULT);
-}
-
 bool LogAudit::onDataAvailable(SocketClient* cli) {
     if (!initialized) {
         prctl(PR_SET_NAME, "logd.auditd");
         initialized = true;
     }
 
-    checkRateLimit();
-
     struct audit_message rep;
 
     rep.nlh.nlmsg_type = 0;
@@ -486,6 +443,5 @@
         audit_close(fd);
         fd = -1;
     }
-    (void)audit_rate_limit(fd, AUDIT_RATE_LIMIT_DEFAULT);
     return fd;
 }
diff --git a/logd/LogAudit.h b/logd/LogAudit.h
index 2bd02d4..5904966 100644
--- a/logd/LogAudit.h
+++ b/logd/LogAudit.h
@@ -18,7 +18,6 @@
 #define _LOGD_LOG_AUDIT_H__
 
 #include <map>
-#include <queue>
 
 #include <sysutils/SocketListener.h>
 
@@ -34,11 +33,6 @@
     bool events;
     bool initialized;
 
-    bool tooFast;
-    int mSock;
-    std::queue<log_time> bucket;
-    void checkRateLimit();
-
    public:
     LogAudit(LogBuffer* buf, LogReader* reader, int fdDmesg);
     int log(char* buf, size_t len);
diff --git a/logd/libaudit.c b/logd/libaudit.c
index dfd56f2..9d9a857 100644
--- a/logd/libaudit.c
+++ b/logd/libaudit.c
@@ -160,7 +160,8 @@
      * and the the mask set to AUDIT_STATUS_PID
      */
     status.pid = pid;
-    status.mask = AUDIT_STATUS_PID;
+    status.mask = AUDIT_STATUS_PID | AUDIT_STATUS_RATE_LIMIT;
+    status.rate_limit = AUDIT_RATE_LIMIT; /* audit entries per second */
 
     /* Let the kernel know this pid will be registering for audit events */
     rc = audit_send(fd, AUDIT_SET, &status, sizeof(status));
@@ -183,26 +184,6 @@
     return 0;
 }
 
-int audit_rate_limit(int fd, unsigned rate_limit) {
-    int rc;
-    struct audit_message rep;
-    struct audit_status status;
-
-    memset(&status, 0, sizeof(status));
-
-    status.mask = AUDIT_STATUS_RATE_LIMIT;
-    status.rate_limit = rate_limit; /* audit entries per second */
-
-    rc = audit_send(fd, AUDIT_SET, &status, sizeof(status));
-    if (rc < 0) {
-        return rc;
-    }
-
-    audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0);
-
-    return 0;
-}
-
 int audit_open() {
     return socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_AUDIT);
 }
diff --git a/logd/libaudit.h b/logd/libaudit.h
index a2afe47..2a93ea3 100644
--- a/logd/libaudit.h
+++ b/logd/libaudit.h
@@ -89,22 +89,8 @@
  */
 extern int audit_setup(int fd, pid_t pid);
 
-/**
- * Sets the rate limit to receive audit netlink events from the kernel
- * @param fd
- *  The fd returned by a call to audit_open()
- * @param max_rate
- *  The cap of the maximum number of audit messages a second
- * @return
- *  This function returns 0 on success, -errno on error.
- */
-
-/* Guidelines to follow for dynamic rate_limit */
-#define AUDIT_RATE_LIMIT_DEFAULT 20        /* acceptable burst rate      */
-#define AUDIT_RATE_LIMIT_BURST_DURATION 10 /* number of seconds of burst */
-#define AUDIT_RATE_LIMIT_MAX 5             /* acceptable sustained rate  */
-
-extern int audit_rate_limit(int fd, unsigned rate_limit);
+/* Max audit messages per second  */
+#define AUDIT_RATE_LIMIT 5
 
 __END_DECLS
 
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 9e1541b..7d7a22f 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -1195,51 +1195,14 @@
                           << "fail as this device is in a bad state, "
                           << "but is not strictly a unit test failure.";
     }
-    // sepolicy_rate_limiter_maximum
-    {  // maximum precharch test block.
-        static constexpr int rate = AUDIT_RATE_LIMIT_MAX;
-        static constexpr int duration = 2;
-        // Two seconds of a liveable sustained rate
-        EXPECT_EQ(rate * duration,
-                  count_avc(sepolicy_rate(rate, rate * duration)));
-    }
-    // sepolicy_rate_limiter_sub_burst
-    {  // maximum period below half way between sustainable and burst rate
-        static constexpr int threshold =
-            ((AUDIT_RATE_LIMIT_BURST_DURATION *
-              (AUDIT_RATE_LIMIT_DEFAULT + AUDIT_RATE_LIMIT_MAX)) +
-             1) /
-            2;
-        static constexpr int rate =
-            (threshold / AUDIT_RATE_LIMIT_BURST_DURATION) - 1;
-        static constexpr int duration = AUDIT_RATE_LIMIT_BURST_DURATION;
-        EXPECT_EQ(rate * duration,
-                  count_avc(sepolicy_rate(rate, rate * duration)));
-    }
-    // sepolicy_rate_limiter_spam
-    {  // hit avc: hard beyond reason block.
-        // maximum period of double the maximum burst rate
-        static constexpr int threshold =
-            ((AUDIT_RATE_LIMIT_BURST_DURATION *
-              (AUDIT_RATE_LIMIT_DEFAULT + AUDIT_RATE_LIMIT_MAX)) +
-             1) /
-            2;
-        static constexpr int rate = AUDIT_RATE_LIMIT_DEFAULT * 2;
-        static constexpr int duration = threshold / AUDIT_RATE_LIMIT_DEFAULT;
-        EXPECT_GE(
-            ((AUDIT_RATE_LIMIT_DEFAULT * duration) * 115) / 100,  // +15% margin
-            count_avc(sepolicy_rate(rate, rate * duration)));
-        // give logd another 3 seconds to react to the burst before checking
-        sepolicy_rate(rate, rate * 3);
-        // maximum period at double maximum burst rate (spam filter kicked in)
-        EXPECT_GE(threshold * 2,
-                  count_avc(sepolicy_rate(
-                      rate, rate * AUDIT_RATE_LIMIT_BURST_DURATION)));
-        // cool down, and check unspammy rate still works
-        sleep(2);
-        EXPECT_LE(AUDIT_RATE_LIMIT_BURST_DURATION - 1,  // allow _one_ lost
-                  count_avc(sepolicy_rate(1, AUDIT_RATE_LIMIT_BURST_DURATION)));
-    }
+
+    static const int rate = AUDIT_RATE_LIMIT;
+    static const int duration = 2;
+    // Two seconds of sustained denials. Depending on the overlap in the time
+    // window that the kernel is considering vs what this test is considering,
+    // allow some additional denials to prevent a flaky test.
+    EXPECT_LE(count_avc(sepolicy_rate(rate, rate * duration)),
+              rate * duration + rate);
 #else
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
diff --git a/property_service/OWNERS b/property_service/OWNERS
new file mode 100644
index 0000000..babbe4d
--- /dev/null
+++ b/property_service/OWNERS
@@ -0,0 +1 @@
+tomcherry@google.com
diff --git a/property_service/libpropertyinfoparser/Android.bp b/property_service/libpropertyinfoparser/Android.bp
index 3e732b5..ffaa2b3 100644
--- a/property_service/libpropertyinfoparser/Android.bp
+++ b/property_service/libpropertyinfoparser/Android.bp
@@ -1,10 +1,15 @@
 cc_library_static {
     name: "libpropertyinfoparser",
+    host_supported: true,
     srcs: ["property_info_parser.cpp"],
 
     cpp_std: "experimental",
-    sanitize: {
-        misc_undefined: ["signed-integer-overflow"],
+    target: {
+        linux: {
+            sanitize: {
+                misc_undefined: ["signed-integer-overflow"],
+            },
+        },
     },
     cppflags: [
         "-Wall",
diff --git a/property_service/libpropertyinfoparser/include/property_info_parser/property_info_parser.h b/property_service/libpropertyinfoparser/include/property_info_parser/property_info_parser.h
index 8c3507e..2ee8161 100644
--- a/property_service/libpropertyinfoparser/include/property_info_parser/property_info_parser.h
+++ b/property_service/libpropertyinfoparser/include/property_info_parser/property_info_parser.h
@@ -18,6 +18,7 @@
 #define PROPERTY_INFO_PARSER_H
 
 #include <stdint.h>
+#include <stdlib.h>
 
 namespace android {
 namespace properties {
diff --git a/property_service/libpropertyinfoserializer/Android.bp b/property_service/libpropertyinfoserializer/Android.bp
index 20e5e13..0a1593b 100644
--- a/property_service/libpropertyinfoserializer/Android.bp
+++ b/property_service/libpropertyinfoserializer/Android.bp
@@ -1,8 +1,13 @@
 cc_defaults {
     name: "propertyinfoserializer_defaults",
+    host_supported: true,
     cpp_std: "experimental",
-    sanitize: {
-        misc_undefined: ["signed-integer-overflow"],
+    target: {
+        linux: {
+            sanitize: {
+                misc_undefined: ["signed-integer-overflow"],
+            },
+        },
     },
     cppflags: [
         "-Wall",
@@ -19,6 +24,7 @@
     name: "libpropertyinfoserializer",
     defaults: ["propertyinfoserializer_defaults"],
     srcs: [
+        "property_info_file.cpp",
         "property_info_serializer.cpp",
         "trie_builder.cpp",
         "trie_serializer.cpp",
diff --git a/property_service/libpropertyinfoserializer/include/property_info_serializer/property_info_serializer.h b/property_service/libpropertyinfoserializer/include/property_info_serializer/property_info_serializer.h
index f7e708e..d2ec385 100644
--- a/property_service/libpropertyinfoserializer/include/property_info_serializer/property_info_serializer.h
+++ b/property_service/libpropertyinfoserializer/include/property_info_serializer/property_info_serializer.h
@@ -41,6 +41,10 @@
                const std::string& default_context, const std::string& default_schema,
                std::string* serialized_trie, std::string* error);
 
+void ParsePropertyInfoFile(const std::string& file_contents,
+                           std::vector<PropertyInfoEntry>* property_infos,
+                           std::vector<std::string>* errors);
+
 }  // namespace properties
 }  // namespace android
 
diff --git a/property_service/libpropertyinfoserializer/property_info_file.cpp b/property_service/libpropertyinfoserializer/property_info_file.cpp
new file mode 100644
index 0000000..702f219
--- /dev/null
+++ b/property_service/libpropertyinfoserializer/property_info_file.cpp
@@ -0,0 +1,62 @@
+#include <property_info_serializer/property_info_serializer.h>
+
+#include <android-base/strings.h>
+
+#include "space_tokenizer.h"
+
+using android::base::Split;
+using android::base::StartsWith;
+using android::base::Trim;
+
+namespace android {
+namespace properties {
+
+bool ParsePropertyInfoLine(const std::string& line, PropertyInfoEntry* out, std::string* error) {
+  auto tokenizer = SpaceTokenizer(line);
+
+  auto property = tokenizer.GetNext();
+  if (property.empty()) {
+    *error = "Did not find a property entry in '" + line + "'";
+    return false;
+  }
+
+  auto context = tokenizer.GetNext();
+  if (context.empty()) {
+    *error = "Did not find a context entry in '" + line + "'";
+    return false;
+  }
+
+  // It is not an error to not find these, as older files will not contain them.
+  auto exact_match = tokenizer.GetNext();
+  auto schema = tokenizer.GetRemaining();
+
+  *out = {property, context, schema, exact_match == "exact"};
+  return true;
+}
+
+void ParsePropertyInfoFile(const std::string& file_contents,
+                           std::vector<PropertyInfoEntry>* property_infos,
+                           std::vector<std::string>* errors) {
+  // Do not clear property_infos to allow this function to be called on multiple files, with
+  // their results concatenated.
+  errors->clear();
+
+  for (const auto& line : Split(file_contents, "\n")) {
+    auto trimmed_line = Trim(line);
+    if (trimmed_line.empty() || StartsWith(trimmed_line, "#")) {
+      continue;
+    }
+
+    auto property_info_entry = PropertyInfoEntry{};
+    auto parse_error = std::string{};
+    if (!ParsePropertyInfoLine(trimmed_line, &property_info_entry, &parse_error)) {
+      errors->emplace_back(parse_error);
+      continue;
+    }
+
+    property_infos->emplace_back(property_info_entry);
+  }
+}
+
+}  // namespace properties
+}  // namespace android
diff --git a/property_service/libpropertyinfoserializer/space_tokenizer.h b/property_service/libpropertyinfoserializer/space_tokenizer.h
new file mode 100644
index 0000000..fba0c58
--- /dev/null
+++ b/property_service/libpropertyinfoserializer/space_tokenizer.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PROPERTY_INFO_SERIALIZER_SPACE_TOKENIZER_H
+#define PROPERTY_INFO_SERIALIZER_SPACE_TOKENIZER_H
+
+namespace android {
+namespace properties {
+
+class SpaceTokenizer {
+ public:
+  SpaceTokenizer(const std::string& string)
+      : string_(string), it_(string_.begin()), end_(string_.end()) {}
+
+  std::string GetNext() {
+    auto next = std::string();
+    while (it_ != end_ && !isspace(*it_)) {
+      next.push_back(*it_++);
+    }
+    while (it_ != end_ && isspace(*it_)) {
+      it_++;
+    }
+    return next;
+  }
+
+  std::string GetRemaining() { return std::string(it_, end_); }
+
+ private:
+  std::string string_;
+  std::string::const_iterator it_;
+  std::string::const_iterator end_;
+};
+
+}  // namespace properties
+}  // namespace android
+
+#endif
diff --git a/property_service/property_info_checker/Android.bp b/property_service/property_info_checker/Android.bp
new file mode 100644
index 0000000..6e9e7f1
--- /dev/null
+++ b/property_service/property_info_checker/Android.bp
@@ -0,0 +1,19 @@
+cc_binary {
+    name: "property_info_checker",
+    host_supported: true,
+    static_executable: true,
+    cpp_std: "experimental",
+    target: {
+        linux: {
+            sanitize: {
+                misc_undefined: ["signed-integer-overflow"],
+            },
+        },
+    },
+    static_libs: [
+        "libpropertyinfoserializer",
+        "libpropertyinfoparser",
+        "libbase",
+    ],
+    srcs: ["property_info_checker.cpp"],
+}
diff --git a/property_service/property_info_checker/property_info_checker.cpp b/property_service/property_info_checker/property_info_checker.cpp
new file mode 100644
index 0000000..e4f8264
--- /dev/null
+++ b/property_service/property_info_checker/property_info_checker.cpp
@@ -0,0 +1,51 @@
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+
+#include <property_info_serializer/property_info_serializer.h>
+
+using android::base::ReadFileToString;
+using android::properties::BuildTrie;
+using android::properties::ParsePropertyInfoFile;
+using android::properties::PropertyInfoEntry;
+
+int main(int argc, char** argv) {
+  if (argc < 2) {
+    std::cerr << "A list of property info files to be checked is expected on the command line"
+              << std::endl;
+    return -1;
+  }
+
+  auto property_info_entries = std::vector<PropertyInfoEntry>{};
+
+  for (int i = 1; i < argc; ++i) {
+    auto filename = argv[i];
+    auto file_contents = std::string{};
+    if (!ReadFileToString(filename, &file_contents)) {
+      std::cerr << "Could not read properties from '" << filename << "'" << std::endl;
+      return -1;
+    }
+
+    auto errors = std::vector<std::string>{};
+    ParsePropertyInfoFile(file_contents, &property_info_entries, &errors);
+    if (!errors.empty()) {
+      for (const auto& error : errors) {
+        std::cerr << "Could not read line from '" << filename << "': " << error << std::endl;
+      }
+      return -1;
+    }
+  }
+
+  auto serialized_contexts = std::string{};
+  auto build_trie_error = std::string{};
+
+  if (!BuildTrie(property_info_entries, "u:object_r:default_prop:s0", "\\s*", &serialized_contexts,
+                 &build_trie_error)) {
+    std::cerr << "Unable to serialize property contexts: " << build_trie_error << std::endl;
+    return -1;
+  }
+
+  return 0;
+}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 492d63a..19269d8 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -77,7 +77,7 @@
 #
 # create some directories (some are mount points) and symlinks
 LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
-    sbin dev proc sys system data oem acct config storage mnt $(BOARD_ROOT_EXTRA_FOLDERS)); \
+    sbin dev proc sys system data odm oem acct config storage mnt $(BOARD_ROOT_EXTRA_FOLDERS)); \
     ln -sf /system/bin $(TARGET_ROOT_OUT)/bin; \
     ln -sf /system/etc $(TARGET_ROOT_OUT)/etc; \
     ln -sf /data/user_de/0/com.android.shell/files/bugreports $(TARGET_ROOT_OUT)/bugreports; \
diff --git a/rootdir/etc/ld.config.txt.in b/rootdir/etc/ld.config.txt.in
index 70363569..ffc4359 100644
--- a/rootdir/etc/ld.config.txt.in
+++ b/rootdir/etc/ld.config.txt.in
@@ -277,12 +277,6 @@
 namespace.vndk.search.paths  = /system/${LIB}/vndk-sp${VNDK_VER}
 namespace.vndk.search.paths += /system/${LIB}/vndk${VNDK_VER}
 
-# This is exceptionally required since android.hidl.memory@1.0-impl.so is here
-namespace.vndk.permitted.paths = /system/${LIB}/vndk-sp${VNDK_VER}/hw
-
-namespace.vndk.asan.permitted.paths += /data/asan/system/${LIB}/vndk-sp${VNDK_VER}/hw
-namespace.vndk.asan.permitted.paths +=           /system/${LIB}/vndk-sp${VNDK_VER}/hw
-
 namespace.vndk.asan.search.paths  = /data/asan/system/${LIB}/vndk-sp${VNDK_VER}
 namespace.vndk.asan.search.paths +=           /system/${LIB}/vndk-sp${VNDK_VER}
 namespace.vndk.asan.search.paths += /data/asan/system/${LIB}/vndk${VNDK_VER}
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index d836c4e..ac87979 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -2,7 +2,7 @@
     class main
     priority -20
     user root
-    group root readproc
+    group root readproc reserved_disk
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index 80bb673..a535846 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -2,7 +2,7 @@
     class main
     priority -20
     user root
-    group root readproc
+    group root readproc reserved_disk
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
@@ -17,7 +17,7 @@
     class main
     priority -20
     user root
-    group root readproc
+    group root readproc reserved_disk
     socket zygote_secondary stream 660 root system
     onrestart restart zygote
     writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 05ec16f..6fc810b 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -2,7 +2,7 @@
     class main
     priority -20
     user root
-    group root readproc
+    group root readproc reserved_disk
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index 09db7b0..7ddd52e 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -2,7 +2,7 @@
     class main
     priority -20
     user root
-    group root readproc
+    group root readproc reserved_disk
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
@@ -17,7 +17,7 @@
     class main
     priority -20
     user root
-    group root readproc
+    group root readproc reserved_disk
     socket zygote_secondary stream 660 root system
     onrestart restart zygote
     writepid /dev/cpuset/foreground/tasks
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
index 9c2cafa..b5d16b8 100644
--- a/toolbox/Android.bp
+++ b/toolbox/Android.bp
@@ -1,11 +1,18 @@
-common_cflags = [
-    "-Werror",
-    "-Wno-unused-parameter",
-    "-Wno-unused-const-variable",
-    "-include bsd-compatibility.h"
-]
+cc_defaults {
+    name: "toolbox_defaults",
+
+    cflags: [
+        "-Werror",
+        "-Wno-unused-parameter",
+        "-Wno-unused-const-variable",
+        "-include bsd-compatibility.h",
+    ],
+    local_include_dirs: ["upstream-netbsd/include/"],
+}
 
 cc_library_static {
+    name: "libtoolbox_dd",
+    defaults: ["toolbox_defaults"],
     srcs: [
         "upstream-netbsd/bin/dd/args.c",
         "upstream-netbsd/bin/dd/conv.c",
@@ -19,17 +26,61 @@
         "upstream-netbsd/lib/libc/string/swab.c",
         "upstream-netbsd/lib/libutil/raise_default_signal.c",
     ],
-    cflags: common_cflags + [
+    cflags: [
         "-Dmain=dd_main",
         "-DNO_CONV",
     ],
-    local_include_dirs: ["upstream-netbsd/include/"],
-    name: "libtoolbox_dd",
+}
+
+genrule {
+    name: "toolbox_tools",
+    cmd: "echo '/* file generated automatically */' >$(out) && for t in toolbox dd getevent newfs_msdos; do echo \"TOOL($$t)\" >>$(out); done",
+    out: ["tools.h"],
+}
+
+genrule {
+    name: "toolbox_input_labels",
+    tool_files: ["generate-input.h-labels.py"],
+    cmd: "$(location) $(in) >$(out)",
+    srcs: [":kernel_input_headers"],
+    out: ["input.h-labels.h"],
+}
+
+cc_binary {
+    name: "toolbox",
+    defaults: ["toolbox_defaults"],
+    srcs: [
+        "toolbox.c",
+        "getevent.c",
+        "newfs_msdos.c",
+    ],
+    generated_headers: [
+        "toolbox_tools",
+        "toolbox_input_labels",
+    ],
+    whole_static_libs: ["libtoolbox_dd"],
+    shared_libs: [
+        "libcutils",
+    ],
+
+    symlinks: [
+        "dd",
+        "getevent",
+        "newfs_msdos",
+    ],
+}
+
+// We only want 'r' on userdebug and eng builds.
+cc_binary {
+    name: "r",
+    defaults: ["toolbox_defaults"],
+    srcs: ["r.c"],
 }
 
 // We build BSD grep separately, so it can provide egrep and fgrep too.
 cc_defaults {
     name: "grep_common",
+    defaults: ["toolbox_defaults"],
     srcs: [
         "upstream-netbsd/usr.bin/grep/fastgrep.c",
         "upstream-netbsd/usr.bin/grep/file.c",
@@ -37,9 +88,10 @@
         "upstream-netbsd/usr.bin/grep/queue.c",
         "upstream-netbsd/usr.bin/grep/util.c",
     ],
-    cflags: common_cflags,
-    local_include_dirs: ["upstream-netbsd/include/"],
-    symlinks: ["egrep", "fgrep"],
+    symlinks: [
+        "egrep",
+        "fgrep",
+    ],
 
     sanitize: {
         integer_overflow: false,
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
deleted file mode 100644
index c4795a7..0000000
--- a/toolbox/Android.mk
+++ /dev/null
@@ -1,70 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-common_cflags := \
-    -Werror -Wno-unused-parameter -Wno-unused-const-variable \
-    -include bsd-compatibility.h \
-
-include $(CLEAR_VARS)
-
-BSD_TOOLS := \
-    dd \
-
-OUR_TOOLS := \
-    getevent \
-    newfs_msdos \
-
-ALL_TOOLS = $(BSD_TOOLS) $(OUR_TOOLS)
-
-LOCAL_SRC_FILES := \
-    toolbox.c \
-    $(patsubst %,%.c,$(OUR_TOOLS)) \
-
-LOCAL_CFLAGS += $(common_cflags)
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/upstream-netbsd/include/
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-
-LOCAL_WHOLE_STATIC_LIBRARIES := $(patsubst %,libtoolbox_%,$(BSD_TOOLS))
-
-LOCAL_MODULE := toolbox
-
-# Install the symlinks.
-LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,$(ALL_TOOLS),ln -sf toolbox $(TARGET_OUT)/bin/$(t);)
-
-# Including this will define $(intermediates).
-#
-include $(BUILD_EXECUTABLE)
-
-$(LOCAL_PATH)/toolbox.c: $(intermediates)/tools.h
-
-TOOLS_H := $(intermediates)/tools.h
-$(TOOLS_H): PRIVATE_TOOLS := toolbox $(ALL_TOOLS)
-$(TOOLS_H): PRIVATE_CUSTOM_TOOL = echo "/* file generated automatically */" > $@ ; for t in $(PRIVATE_TOOLS) ; do echo "TOOL($$t)" >> $@ ; done
-$(TOOLS_H): $(LOCAL_PATH)/Android.mk
-$(TOOLS_H):
-	$(transform-generated-source)
-
-$(LOCAL_PATH)/getevent.c: $(intermediates)/input.h-labels.h
-
-UAPI_INPUT_EVENT_CODES_H := bionic/libc/kernel/uapi/linux/input.h bionic/libc/kernel/uapi/linux/input-event-codes.h
-INPUT_H_LABELS_H := $(intermediates)/input.h-labels.h
-$(INPUT_H_LABELS_H): PRIVATE_LOCAL_PATH := $(LOCAL_PATH)
-# The PRIVATE_CUSTOM_TOOL line uses = to evaluate the output path late.
-# We copy the input path so it can't be accidentally modified later.
-$(INPUT_H_LABELS_H): PRIVATE_UAPI_INPUT_EVENT_CODES_H := $(UAPI_INPUT_EVENT_CODES_H)
-$(INPUT_H_LABELS_H): PRIVATE_CUSTOM_TOOL = $(PRIVATE_LOCAL_PATH)/generate-input.h-labels.py $(PRIVATE_UAPI_INPUT_EVENT_CODES_H) > $@
-# The dependency line though gets evaluated now, so the PRIVATE_ copy doesn't exist yet,
-# and the original can't yet have been modified, so this is both sufficient and necessary.
-$(INPUT_H_LABELS_H): $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/generate-input.h-labels.py $(UAPI_INPUT_EVENT_CODES_H)
-$(INPUT_H_LABELS_H):
-	$(transform-generated-source)
-
-# We only want 'r' on userdebug and eng builds.
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := r.c
-LOCAL_CFLAGS += $(common_cflags)
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/upstream-netbsd/include/
-LOCAL_MODULE := r
-LOCAL_MODULE_TAGS := debug
-include $(BUILD_EXECUTABLE)
diff --git a/trusty/storage/proxy/storage.c b/trusty/storage/proxy/storage.c
index c61e89d..5b83e21 100644
--- a/trusty/storage/proxy/storage.c
+++ b/trusty/storage/proxy/storage.c
@@ -379,7 +379,7 @@
     }
 
     if (req->size > MAX_READ_SIZE) {
-        ALOGW("%s: request is too large (%zd > %zd) - refusing\n",
+        ALOGW("%s: request is too large (%u > %d) - refusing\n",
               __func__, req->size, MAX_READ_SIZE);
         msg->result = STORAGE_ERR_NOT_VALID;
         goto err_response;