Merge changes I9df4d6fa,I841123de

* changes:
  adb: move adb_strerror to sysdeps/win32/errno.cpp.
  adb: extend sync protocol's stat support.
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 0b1ba32..ef52189 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -46,21 +46,11 @@
 
 static const char* __adb_server_socket_spec;
 
-void adb_set_transport(TransportType type, const char* serial)
-{
+void adb_set_transport(TransportType type, const char* serial) {
     __adb_transport = type;
     __adb_serial = serial;
 }
 
-void adb_get_transport(TransportType* type, const char** serial) {
-    if (type) {
-        *type = __adb_transport;
-    }
-    if (serial) {
-        *serial = __adb_serial;
-    }
-}
-
 void adb_set_socket_spec(const char* socket_spec) {
     if (__adb_server_socket_spec) {
         LOG(FATAL) << "attempted to reinitialize adb_server_socket_spec " << socket_spec << " (was " << __adb_server_socket_spec << ")";
diff --git a/adb/adb_client.h b/adb/adb_client.h
index d35d705..d07c1e9 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -40,9 +40,6 @@
 // Set the preferred transport to connect to.
 void adb_set_transport(TransportType type, const char* _Nullable serial);
 
-// Get the preferred transport to connect to.
-void adb_get_transport(TransportType* _Nullable type, const char* _Nullable* _Nullable serial);
-
 // Set the socket specification for the adb server.
 // This function can only be called once, and the argument must live to the end of the process.
 void adb_set_socket_spec(const char* _Nonnull socket_spec);
diff --git a/base/Android.bp b/base/Android.bp
index e6ad15b..b9a6e0b 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -49,6 +49,11 @@
             srcs: ["errors_unix.cpp"],
             cppflags: ["-Wexit-time-destructors"],
         },
+        linux_bionic: {
+            srcs: ["errors_unix.cpp"],
+            cppflags: ["-Wexit-time-destructors"],
+            enabled: true,
+        },
         linux: {
             srcs: ["errors_unix.cpp"],
             cppflags: ["-Wexit-time-destructors"],
diff --git a/bootstat/bootstat.rc b/bootstat/bootstat.rc
index ba8f81c..c96e996 100644
--- a/bootstat/bootstat.rc
+++ b/bootstat/bootstat.rc
@@ -11,13 +11,8 @@
 on post-fs-data && property:init.svc.bootanim=running
     exec - root root -- /system/bin/bootstat -r post_decrypt_time_elapsed
 
-# The first marker, boot animation stopped, is considered the point at which
-# the user may interact with the device, so it is a good proxy for the boot
-# complete signal.
-#
-# The second marker ensures an encrypted device is decrypted before logging
-# boot time data.
-on property:init.svc.bootanim=stopped && property:vold.decrypt=trigger_restart_framework
+# Record boot complete metrics.
+on property:sys.boot_completed=1
     # Record boot_complete and related stats (decryption, etc).
     exec - root root -- /system/bin/bootstat --record_boot_complete
 
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 155b309..607745d 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -18,6 +18,7 @@
     debuggerd.cpp \
     elf_utils.cpp \
     getevent.cpp \
+    open_files_list.cpp \
     signal_sender.cpp \
     tombstone.cpp \
     utility.cpp \
@@ -108,9 +109,11 @@
 
 debuggerd_test_src_files := \
     utility.cpp \
+    open_files_list.cpp \
     test/dump_memory_test.cpp \
     test/elf_fake.cpp \
     test/log_fake.cpp \
+    test/open_files_list_test.cpp \
     test/property_fake.cpp \
     test/ptrace_fake.cpp \
     test/tombstone_test.cpp \
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 5ae66db..272fbf6 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -55,6 +55,7 @@
 
 #include "backtrace.h"
 #include "getevent.h"
+#include "open_files_list.h"
 #include "signal_sender.h"
 #include "tombstone.h"
 #include "utility.h"
@@ -452,7 +453,8 @@
 }
 
 static bool perform_dump(const debugger_request_t& request, int fd, int tombstone_fd,
-                         BacktraceMap* backtrace_map, const std::set<pid_t>& siblings,
+                         BacktraceMap* backtrace_map, const OpenFilesList& open_files,
+                         const std::set<pid_t>& siblings,
                          int* crash_signal, std::string* amfd_data) {
   if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) {
     ALOGE("debuggerd: failed to respond to client: %s\n", strerror(errno));
@@ -471,7 +473,8 @@
       case SIGSTOP:
         if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
           ALOGV("debuggerd: stopped -- dumping to tombstone");
-          engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings,
+          engrave_tombstone(tombstone_fd, backtrace_map, open_files,
+                            request.pid, request.tid, siblings,
                             request.abort_msg_address, amfd_data);
         } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) {
           ALOGV("debuggerd: stopped -- dumping to fd");
@@ -498,7 +501,8 @@
       case SIGTRAP:
         ALOGV("stopped -- fatal signal\n");
         *crash_signal = signal;
-        engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings,
+        engrave_tombstone(tombstone_fd, backtrace_map, open_files,
+                          request.pid, request.tid, siblings,
                           request.abort_msg_address, amfd_data);
         break;
 
@@ -593,6 +597,10 @@
   // Generate the backtrace map before dropping privileges.
   std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(request.pid));
 
+  // Collect the list of open files before dropping privileges.
+  OpenFilesList open_files;
+  populate_open_files_list(request.pid, &open_files);
+
   int amfd = -1;
   std::unique_ptr<std::string> amfd_data;
   if (request.action == DEBUGGER_ACTION_CRASH) {
@@ -610,8 +618,8 @@
   }
 
   int crash_signal = SIGKILL;
-  succeeded = perform_dump(request, fd, tombstone_fd, backtrace_map.get(), siblings,
-                           &crash_signal, amfd_data.get());
+  succeeded = perform_dump(request, fd, tombstone_fd, backtrace_map.get(), open_files,
+                           siblings, &crash_signal, amfd_data.get());
   if (succeeded) {
     if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
       if (!tombstone_path.empty()) {
diff --git a/debuggerd/open_files_list.cpp b/debuggerd/open_files_list.cpp
new file mode 100644
index 0000000..5ef2abc
--- /dev/null
+++ b/debuggerd/open_files_list.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DEBUG"
+
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android/log.h>
+
+#include "open_files_list.h"
+
+#include "utility.h"
+
+void populate_open_files_list(pid_t pid, OpenFilesList* list) {
+  std::string fd_dir_name = "/proc/" + std::to_string(pid) + "/fd";
+  std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(fd_dir_name.c_str()), closedir);
+  if (dir == nullptr) {
+    ALOGE("failed to open directory %s: %s", fd_dir_name.c_str(), strerror(errno));
+    return;
+  }
+
+  struct dirent* de;
+  while ((de = readdir(dir.get())) != nullptr) {
+    if (*de->d_name == '.') {
+      continue;
+    }
+
+    int fd = atoi(de->d_name);
+    std::string path = fd_dir_name + "/" + std::string(de->d_name);
+    std::string target;
+    if (android::base::Readlink(path, &target)) {
+      list->emplace_back(fd, target);
+    } else {
+      ALOGE("failed to readlink %s: %s", path.c_str(), strerror(errno));
+      list->emplace_back(fd, "???");
+    }
+  }
+}
+
+void dump_open_files_list_to_log(const OpenFilesList& files, log_t* log, const char* prefix) {
+  for (auto& file : files) {
+    _LOG(log, logtype::OPEN_FILES, "%sfd %i: %s\n", prefix, file.first, file.second.c_str());
+  }
+}
+
diff --git a/debuggerd/open_files_list.h b/debuggerd/open_files_list.h
new file mode 100644
index 0000000..b37228d
--- /dev/null
+++ b/debuggerd/open_files_list.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DEBUGGERD_OPEN_FILES_LIST_H
+#define _DEBUGGERD_OPEN_FILES_LIST_H
+
+#include <sys/types.h>
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "utility.h"
+
+typedef std::vector<std::pair<int, std::string>> OpenFilesList;
+
+/* Populates the given list with open files for the given process. */
+void populate_open_files_list(pid_t pid, OpenFilesList* list);
+
+/* Dumps the open files list to the log. */
+void dump_open_files_list_to_log(const OpenFilesList& files, log_t* log, const char* prefix);
+
+#endif // _DEBUGGERD_OPEN_FILES_LIST_H
diff --git a/debuggerd/test/open_files_list_test.cpp b/debuggerd/test/open_files_list_test.cpp
new file mode 100644
index 0000000..85e0695
--- /dev/null
+++ b/debuggerd/test/open_files_list_test.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "android-base/test_utils.h"
+
+#include "open_files_list.h"
+
+// Check that we can produce a list of open files for the current process, and
+// that it includes a known open file.
+TEST(OpenFilesListTest, BasicTest) {
+  // Open a temporary file that we can check for in the list of open files.
+  TemporaryFile tf;
+
+  // Get the list of open files for this process.
+  OpenFilesList list;
+  populate_open_files_list(getpid(), &list);
+
+  // Verify our open file is in the list.
+  bool found = false;
+  for (auto&  file : list) {
+    if (file.first == tf.fd) {
+      EXPECT_EQ(file.second, std::string(tf.path));
+      found = true;
+      break;
+    }
+  }
+  EXPECT_TRUE(found);
+}
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index b9fbe07..e76edb9 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -46,6 +46,7 @@
 #include "backtrace.h"
 #include "elf_utils.h"
 #include "machine.h"
+#include "open_files_list.h"
 #include "tombstone.h"
 
 #define STACK_WORDS 16
@@ -620,7 +621,8 @@
 }
 
 // Dumps all information about the specified pid to the tombstone.
-static void dump_crash(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid,
+static void dump_crash(log_t* log, BacktraceMap* map,
+                       const OpenFilesList& open_files, pid_t pid, pid_t tid,
                        const std::set<pid_t>& siblings, uintptr_t abort_msg_address) {
   // don't copy log messages to tombstone unless this is a dev device
   bool want_logs = __android_log_is_debuggable();
@@ -639,6 +641,9 @@
     }
   }
 
+  _LOG(log, logtype::OPEN_FILES, "\nopen files:\n");
+  dump_open_files_list_to_log(open_files, log, "    ");
+
   if (want_logs) {
     dump_logs(log, pid, 0);
   }
@@ -697,7 +702,8 @@
   return fd;
 }
 
-void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid,
+void engrave_tombstone(int tombstone_fd, BacktraceMap* map,
+                       const OpenFilesList& open_files, pid_t pid, pid_t tid,
                        const std::set<pid_t>& siblings, uintptr_t abort_msg_address,
                        std::string* amfd_data) {
   log_t log;
@@ -711,5 +717,5 @@
 
   log.tfd = tombstone_fd;
   log.amfd_data = amfd_data;
-  dump_crash(&log, map, pid, tid, siblings, abort_msg_address);
+  dump_crash(&log, map, open_files, pid, tid, siblings, abort_msg_address);
 }
diff --git a/debuggerd/tombstone.h b/debuggerd/tombstone.h
index e1c39c5..126f804 100644
--- a/debuggerd/tombstone.h
+++ b/debuggerd/tombstone.h
@@ -32,7 +32,8 @@
 int open_tombstone(std::string* path);
 
 /* Creates a tombstone file and writes the crash dump to it. */
-void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid,
+void engrave_tombstone(int tombstone_fd, BacktraceMap* map,
+                       const OpenFilesList& open_files, pid_t pid, pid_t tid,
                        const std::set<pid_t>& siblings, uintptr_t abort_msg_address,
                        std::string* amfd_data);
 
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index d820f0f..f7a3f73 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -70,7 +70,8 @@
   MAPS,
   MEMORY,
   STACK,
-  LOGS
+  LOGS,
+  OPEN_FILES
 };
 
 // Log information onto the tombstone.
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index e0d46d3..f682216 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/ioctl.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
 #include <sys/swap.h>
@@ -38,6 +39,7 @@
 #include <ext4_utils/ext4_sb.h>
 #include <ext4_utils/ext4_utils.h>
 #include <ext4_utils/wipe.h>
+#include <linux/fs.h>
 #include <linux/loop.h>
 #include <logwrap/logwrap.h>
 #include <private/android_filesystem_config.h>
@@ -50,8 +52,9 @@
 #define KEY_IN_FOOTER  "footer"
 
 #define E2FSCK_BIN      "/system/bin/e2fsck"
-#define F2FS_FSCK_BIN  "/system/bin/fsck.f2fs"
+#define F2FS_FSCK_BIN   "/system/bin/fsck.f2fs"
 #define MKSWAP_BIN      "/system/bin/mkswap"
+#define TUNE2FS_BIN     "/system/bin/tune2fs"
 
 #define FSCK_LOG_FILE   "/dev/fscklogs/log"
 
@@ -180,6 +183,99 @@
     return;
 }
 
+/* Function to read the primary superblock */
+static int read_super_block(int fd, struct ext4_super_block *sb)
+{
+    off64_t ret;
+
+    ret = lseek64(fd, 1024, SEEK_SET);
+    if (ret < 0)
+        return ret;
+
+    ret = read(fd, sb, sizeof(*sb));
+    if (ret < 0)
+        return ret;
+    if (ret != sizeof(*sb))
+        return ret;
+
+    return 0;
+}
+
+static ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
+{
+    return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
+            le32_to_cpu(es->s_blocks_count_lo);
+}
+
+static ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es)
+{
+    return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
+            le32_to_cpu(es->s_r_blocks_count_lo);
+}
+
+static void do_reserved_size(char *blk_device, char *fs_type, struct fstab_rec *rec)
+{
+    /* Check for the types of filesystems we know how to check */
+    if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
+        /*
+         * Some system images do not have tune2fs for licensing reasons
+         * Detect these and skip reserve blocks.
+         */
+        if (access(TUNE2FS_BIN, X_OK)) {
+            ERROR("Not running %s on %s (executable not in system image)\n",
+                  TUNE2FS_BIN, blk_device);
+        } else {
+            INFO("Running %s on %s\n", TUNE2FS_BIN, blk_device);
+
+            int status = 0;
+            int ret = 0;
+            unsigned long reserved_blocks = 0;
+            int fd = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC));
+            if (fd >= 0) {
+                struct ext4_super_block sb;
+                ret = read_super_block(fd, &sb);
+                if (ret < 0) {
+                    ERROR("Can't read '%s' super block: %s\n", blk_device, strerror(errno));
+                    goto out;
+                }
+                reserved_blocks = rec->reserved_size / EXT4_BLOCK_SIZE(&sb);
+                unsigned long reserved_threshold = ext4_blocks_count(&sb) * 0.02;
+                if (reserved_threshold < reserved_blocks) {
+                    WARNING("Reserved blocks %lu is too large\n", reserved_blocks);
+                    reserved_blocks = reserved_threshold;
+                }
+
+                if (ext4_r_blocks_count(&sb) == reserved_blocks) {
+                    INFO("Have reserved same blocks\n");
+                    goto out;
+                }
+            } else {
+                ERROR("Failed to open '%s': %s\n", blk_device, strerror(errno));
+                return;
+            }
+
+            char buf[16] = {0};
+            snprintf(buf, sizeof (buf), "-r %lu", reserved_blocks);
+            char *tune2fs_argv[] = {
+                TUNE2FS_BIN,
+                buf,
+                blk_device,
+            };
+
+            ret = android_fork_execvp_ext(ARRAY_SIZE(tune2fs_argv), tune2fs_argv,
+                                          &status, true, LOG_KLOG | LOG_FILE,
+                                          true, NULL, NULL, 0);
+
+            if (ret < 0) {
+                /* No need to check for error in fork, we can't really handle it now */
+                ERROR("Failed trying to run %s\n", TUNE2FS_BIN);
+            }
+      out:
+            close(fd);
+        }
+    }
+}
+
 static void remove_trailing_slashes(char *n)
 {
     int len;
@@ -325,6 +421,12 @@
                 check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
                          fstab->recs[i].mount_point);
             }
+
+            if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
+                do_reserved_size(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
+                                 &fstab->recs[i]);
+            }
+
             if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, &fstab->recs[i])) {
                 *attempted_idx = i;
                 mounted = 1;
@@ -690,6 +792,10 @@
                      fstab->recs[i].mount_point);
         }
 
+        if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
+            do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i]);
+        }
+
         if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
             int rc = fs_mgr_setup_verity(&fstab->recs[i]);
             if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index b219b38..472b421 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -33,6 +33,7 @@
     int swap_prio;
     int max_comp_streams;
     unsigned int zram_size;
+    uint64_t reserved_size;
 };
 
 struct flag_list {
@@ -80,6 +81,7 @@
     { "slotselect",  MF_SLOTSELECT },
     { "nofail",      MF_NOFAIL },
     { "latemount",   MF_LATEMOUNT },
+    { "reservedsize=", MF_RESERVEDSIZE },
     { "defaults",    0 },
     { 0,             0 },
 };
@@ -97,6 +99,20 @@
     return total;
 }
 
+static uint64_t parse_size(const char *arg)
+{
+    char *endptr;
+    uint64_t size = strtoull(arg, &endptr, 10);
+    if (*endptr == 'k' || *endptr == 'K')
+        size *= 1024LL;
+    else if (*endptr == 'm' || *endptr == 'M')
+        size *= 1024LL * 1024LL;
+    else if (*endptr == 'g' || *endptr == 'G')
+        size *= 1024LL * 1024LL * 1024LL;
+
+    return size;
+}
+
 static int parse_flags(char *flags, struct flag_list *fl,
                        struct fs_mgr_flag_values *flag_vals,
                        char *fs_options, int fs_options_len)
@@ -191,6 +207,11 @@
                         flag_vals->zram_size = calculate_zram_size(val);
                     else
                         flag_vals->zram_size = val;
+                } else if ((fl[i].flag == MF_RESERVEDSIZE) && flag_vals) {
+                    /* The reserved flag is followed by an = and the
+                     * reserved size of the partition.  Get it and return it.
+                     */
+                    flag_vals->reserved_size = parse_size(strchr(p, '=') + 1);
                 }
                 break;
             }
@@ -335,6 +356,7 @@
         fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
         fstab->recs[cnt].max_comp_streams = flag_vals.max_comp_streams;
         fstab->recs[cnt].zram_size = flag_vals.zram_size;
+        fstab->recs[cnt].reserved_size = flag_vals.reserved_size;
         cnt++;
     }
     /* If an A/B partition, modify block device to be the real block device */
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 741f5e9..23c97e4 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -86,6 +86,7 @@
 #define MF_LATEMOUNT    0x20000
 #define MF_NOFAIL       0x40000
 #define MF_MAX_COMP_STREAMS 0x100000
+#define MF_RESERVEDSIZE 0x200000
 
 #define DM_BUF_SIZE 4096
 
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 37df8f8..43aef20 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -75,6 +75,7 @@
     int swap_prio;
     int max_comp_streams;
     unsigned int zram_size;
+    uint64_t reserved_size;
 };
 
 // Callback function for verity status
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index c364317..c9e1923 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -96,6 +96,9 @@
 #define AID_DNS_TETHER    1052  /* DNS resolution daemon (tether: dnsmasq) */
 #define AID_WEBVIEW_ZYGOTE 1053 /* WebView zygote process */
 #define AID_VEHICLE_NETWORK 1054 /* Vehicle network service */
+#define AID_MEDIA_AUDIO   1055 /* GID for audio files on internal media storage */
+#define AID_MEDIA_VIDEO   1056 /* GID for video files on internal media storage */
+#define AID_MEDIA_IMAGE   1057 /* GID for image files on internal media storage */
 /* Changes to this file must be made in AOSP, *not* in internal branches. */
 
 #define AID_SHELL         2000  /* adb and debug shell user */
@@ -210,6 +213,9 @@
     { "dns_tether",    AID_DNS_TETHER, },
     { "webview_zygote", AID_WEBVIEW_ZYGOTE, },
     { "vehicle_network", AID_VEHICLE_NETWORK, },
+    { "media_audio",   AID_MEDIA_AUDIO, },
+    { "media_video",   AID_MEDIA_VIDEO, },
+    { "media_image",   AID_MEDIA_IMAGE, },
 
     { "shell",         AID_SHELL, },
     { "cache",         AID_CACHE, },
diff --git a/init/action.cpp b/init/action.cpp
index 0ea7e14..65bf292 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -121,7 +121,7 @@
     Timer t;
     int result = command.InvokeFunc();
 
-    double duration_ms = t.duration() * 1000;
+    double duration_ms = t.duration_s() * 1000;
     // Any action longer than 50ms will be warned to user as slow operation
     if (duration_ms > 50.0 ||
         android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 6d58754..76e3d6e 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -146,8 +146,7 @@
         LOG(ERROR) << "failed to set bootloader message: " << err;
         return -1;
     }
-    android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
-    while (1) { pause(); }  // never reached
+    reboot("recovery");
 }
 
 static void unmount_and_fsck(const struct mntent *entry) {
@@ -727,7 +726,7 @@
         ServiceManager::GetInstance().ForEachService(
             [] (Service* s) { s->Terminate(); });
 
-        while (t.duration() < delay) {
+        while (t.duration_s() < delay) {
             ServiceManager::GetInstance().ReapAnyOutstandingChildren();
 
             int service_count = 0;
@@ -751,11 +750,10 @@
             // Wait a bit before recounting the number or running services.
             std::this_thread::sleep_for(50ms);
         }
-        LOG(VERBOSE) << "Terminating running services took " << t.duration() << " seconds";
+        LOG(VERBOSE) << "Terminating running services took " << t;
     }
 
-    return android_reboot_with_callback(cmd, 0, reboot_target,
-                                        callback_on_ro_remount);
+    return android_reboot_with_callback(cmd, 0, reboot_target, callback_on_ro_remount);
 }
 
 static int do_trigger(const std::vector<std::string>& args) {
diff --git a/init/devices.cpp b/init/devices.cpp
index 2db24b7..6af237c 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -868,7 +868,7 @@
     if (pid == 0) {
         Timer t;
         process_firmware_event(uevent);
-        LOG(INFO) << "loading " << uevent->path << " took " << t.duration() << "s";
+        LOG(INFO) << "loading " << uevent->path << " took " << t;
         _exit(EXIT_SUCCESS);
     } else if (pid == -1) {
         PLOG(ERROR) << "could not fork to process firmware event for " << uevent->firmware;
@@ -1043,7 +1043,7 @@
     coldboot("/sys/block");
     coldboot("/sys/devices");
     close(open(COLDBOOT_DONE, O_WRONLY|O_CREAT|O_CLOEXEC, 0000));
-    LOG(INFO) << "Coldboot took " << t.duration() << "s.";
+    LOG(INFO) << "Coldboot took " << t;
 }
 
 int get_device_fd() {
diff --git a/init/init.cpp b/init/init.cpp
index 734f129..95cb62f 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -43,7 +43,6 @@
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
-#include <cutils/android_reboot.h>
 #include <cutils/fs.h>
 #include <cutils/iosched_policy.h>
 #include <cutils/list.h>
@@ -163,14 +162,21 @@
     Timer t;
 
     LOG(VERBOSE) << "Waiting for " COLDBOOT_DONE "...";
-    // Any longer than 1s is an unreasonable length of time to delay booting.
-    // If you're hitting this timeout, check that you didn't make your
-    // sepolicy regular expressions too expensive (http://b/19899875).
-    if (wait_for_file(COLDBOOT_DONE, 1s)) {
+
+    // Historically we had a 1s timeout here because we weren't otherwise
+    // tracking boot time, and many OEMs made their sepolicy regular
+    // expressions too expensive (http://b/19899875).
+
+    // Now we're tracking boot time, just log the time taken to a system
+    // property. We still panic if it takes more than a minute though,
+    // because any build that slow isn't likely to boot at all, and we'd
+    // rather any test lab devices fail back to the bootloader.
+    if (wait_for_file(COLDBOOT_DONE, 60s) < 0) {
         LOG(ERROR) << "Timed out waiting for " COLDBOOT_DONE;
+        panic();
     }
 
-    LOG(VERBOSE) << "Waiting for " COLDBOOT_DONE " took " << t.duration() << "s.";
+    property_set("ro.boottime.init.cold_boot_wait", std::to_string(t.duration_ns()).c_str());
     return 0;
 }
 
@@ -351,11 +357,17 @@
     if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv);
 }
 
+static int property_enable_triggers_action(const std::vector<std::string>& args)
+{
+    /* Enable property triggers. */
+    property_triggers_enabled = 1;
+    return 0;
+}
+
 static int queue_property_triggers_action(const std::vector<std::string>& args)
 {
+    ActionManager::GetInstance().QueueBuiltinAction(property_enable_triggers_action, "enable_property_trigger");
     ActionManager::GetInstance().QueueAllPropertyTriggers();
-    /* enable property triggers */
-    property_triggers_enabled = 1;
     return 0;
 }
 
@@ -403,9 +415,8 @@
 }
 
 static void security_failure() {
-    LOG(ERROR) << "Security failure; rebooting into recovery mode...";
-    android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
-    while (true) { pause(); }  // never reached
+    LOG(ERROR) << "Security failure...";
+    panic();
 }
 
 static void selinux_initialize(bool in_kernel_domain) {
@@ -437,8 +448,8 @@
             security_failure();
         }
 
-        LOG(INFO) << "(Initializing SELinux " << (is_enforcing ? "enforcing" : "non-enforcing")
-                  << " took " << t.duration() << "s.)";
+        // init's first stage can't set properties, so pass the time to the second stage.
+        setenv("INIT_SELINUX_TOOK", std::to_string(t.duration_ns()).c_str(), 1);
     } else {
         selinux_init_all_handles();
     }
@@ -644,7 +655,13 @@
         export_kernel_boot_props();
 
         // Make the time that init started available for bootstat to log.
-        property_set("init.start", getenv("INIT_STARTED_AT"));
+        property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));
+        property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));
+
+        // Clean up our environment.
+        unsetenv("INIT_SECOND_STAGE");
+        unsetenv("INIT_STARTED_AT");
+        unsetenv("INIT_SELINUX_TOOK");
 
         // Now set up SELinux for second stage.
         selinux_initialize(false);
@@ -725,15 +742,15 @@
         // By default, sleep until something happens.
         int epoll_timeout_ms = -1;
 
-        // If there's more work to do, wake up again immediately.
-        if (am.HasMoreCommands()) epoll_timeout_ms = 0;
-
         // If there's a process that needs restarting, wake up in time for that.
         if (process_needs_restart_at != 0) {
             epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;
             if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
         }
 
+        // If there's more work to do, wake up again immediately.
+        if (am.HasMoreCommands()) epoll_timeout_ms = 0;
+
         bootchart_sample(&epoll_timeout_ms);
 
         epoll_event ev;
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index d017390..406b339 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -110,7 +110,7 @@
     // Nexus 9 boot time, so it's disabled by default.
     if (false) DumpState();
 
-    LOG(VERBOSE) << "(Parsing " << path << " took " << t.duration() << "s.)";
+    LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)";
     return true;
 }
 
diff --git a/init/property_service.cpp b/init/property_service.cpp
index e198297..aed8438 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -169,11 +169,18 @@
     return true;
 }
 
-static int property_set_impl(const char* name, const char* value) {
+int property_set(const char* name, const char* value) {
     size_t valuelen = strlen(value);
 
-    if (!is_legal_property_name(name)) return -1;
-    if (valuelen >= PROP_VALUE_MAX) return -1;
+    if (!is_legal_property_name(name)) {
+        LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: bad name";
+        return -1;
+    }
+    if (valuelen >= PROP_VALUE_MAX) {
+        LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
+                   << "value too long";
+        return -1;
+    }
 
     if (strcmp("selinux.restorecon_recursive", name) == 0 && valuelen > 0) {
         if (restorecon(value, SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
@@ -182,49 +189,42 @@
     }
 
     prop_info* pi = (prop_info*) __system_property_find(name);
-
-    if(pi != 0) {
-        /* ro.* properties may NEVER be modified once set */
-        if(!strncmp(name, "ro.", 3)) return -1;
+    if (pi != nullptr) {
+        // ro.* properties are actually "write-once".
+        if (!strncmp(name, "ro.", 3)) {
+            LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
+                       << "property already set";
+            return -1;
+        }
 
         __system_property_update(pi, value, valuelen);
     } else {
         int rc = __system_property_add(name, strlen(name), value, valuelen);
         if (rc < 0) {
+            LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
+                       << "__system_property_add failed";
             return rc;
         }
     }
-    /* If name starts with "net." treat as a DNS property. */
+
+    // If name starts with "net." treat as a DNS property.
     if (strncmp("net.", name, strlen("net.")) == 0)  {
         if (strcmp("net.change", name) == 0) {
             return 0;
         }
-       /*
-        * The 'net.change' property is a special property used track when any
-        * 'net.*' property name is updated. It is _ONLY_ updated here. Its value
-        * contains the last updated 'net.*' property.
-        */
+        // The 'net.change' property is a special property used track when any
+        // 'net.*' property name is updated. It is _ONLY_ updated here. Its value
+        // contains the last updated 'net.*' property.
         property_set("net.change", name);
-    } else if (persistent_properties_loaded &&
-            strncmp("persist.", name, strlen("persist.")) == 0) {
-        /*
-         * Don't write properties to disk until after we have read all default properties
-         * to prevent them from being overwritten by default values.
-         */
+    } else if (persistent_properties_loaded && strncmp("persist.", name, strlen("persist.")) == 0) {
+        // Don't write properties to disk until after we have read all default properties
+        // to prevent them from being overwritten by default values.
         write_persistent_property(name, value);
     }
     property_changed(name, value);
     return 0;
 }
 
-int property_set(const char* name, const char* value) {
-    int rc = property_set_impl(name, value);
-    if (rc == -1) {
-        LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed";
-    }
-    return rc;
-}
-
 static void handle_property_set_fd()
 {
     prop_msg msg;
@@ -388,7 +388,7 @@
     }
     data.push_back('\n');
     load_properties(&data[0], filter);
-    LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t.duration() << "s.)";
+    LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)";
 }
 
 static void load_persistent_properties() {
diff --git a/init/readme.txt b/init/readme.txt
index 7e9d21b..7549e3c 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -440,16 +440,27 @@
 Init provides information about the services that it is responsible
 for via the below properties.
 
-init.start
-  Time after boot in ns (via the CLOCK_BOOTTIME clock) at which the first
-  stage of init started.
-
 init.svc.<name>
   State of a named service ("stopped", "stopping", "running", "restarting")
 
-init.svc.<name>.start
+
+Boot timing
+-----------
+Init records some boot timing information in system properties.
+
+ro.boottime.init
+  Time after boot in ns (via the CLOCK_BOOTTIME clock) at which the first
+  stage of init started.
+
+ro.boottime.init.selinux
+  How long it took the first stage to initialize SELinux.
+
+ro.boottime.init.cold_boot_wait
+  How long init waited for ueventd's coldboot phase to end.
+
+ro.boottime.<service-name>
   Time after boot in ns (via the CLOCK_BOOTTIME clock) that the service was
-  most recently started.
+  first started.
 
 
 Bootcharting
diff --git a/init/service.cpp b/init/service.cpp
index 1f53a1b..4b9724d 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -36,7 +36,6 @@
 #include <android-base/parseint.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
-#include <cutils/android_reboot.h>
 #include <system/thread_defs.h>
 
 #include <processgroup/processgroup.h>
@@ -190,9 +189,9 @@
     property_set(prop_name.c_str(), new_state.c_str());
 
     if (new_state == "running") {
-        prop_name += ".start";
         uint64_t start_ns = time_started_.time_since_epoch().count();
-        property_set(prop_name.c_str(), StringPrintf("%" PRIu64, start_ns).c_str());
+        property_set(StringPrintf("ro.boottime.%s", name_.c_str()).c_str(),
+                     StringPrintf("%" PRIu64, start_ns).c_str());
     }
 }
 
@@ -283,10 +282,8 @@
     if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) {
         if (now < time_crashed_ + 4min) {
             if (++crash_count_ > 4) {
-                LOG(ERROR) << "critical process '" << name_ << "' exited 4 times in 4 minutes; "
-                           << "rebooting into recovery mode";
-                android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
-                return false;
+                LOG(ERROR) << "critical process '" << name_ << "' exited 4 times in 4 minutes";
+                panic();
             }
         } else {
             time_crashed_ = now;
diff --git a/init/signal_handler.cpp b/init/signal_handler.cpp
index 0dea3e0..1041b82 100644
--- a/init/signal_handler.cpp
+++ b/init/signal_handler.cpp
@@ -24,7 +24,6 @@
 #include <unistd.h>
 
 #include <android-base/stringprintf.h>
-#include <cutils/android_reboot.h>
 #include <cutils/list.h>
 #include <cutils/sockets.h>
 
diff --git a/init/util.cpp b/init/util.cpp
index 5205ea0..38e3b8d 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -41,6 +41,8 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+
+#include <cutils/android_reboot.h>
 /* for ANDROID_SOCKET_* */
 #include <cutils/sockets.h>
 
@@ -472,3 +474,22 @@
 
     return true;
 }
+
+void reboot(const char* destination) {
+    android_reboot(ANDROID_RB_RESTART2, 0, destination);
+    // We're init, so android_reboot will actually have been a syscall so there's nothing
+    // to wait for. If android_reboot returns, just abort so that the kernel will reboot
+    // itself when init dies.
+    PLOG(FATAL) << "reboot failed";
+    abort();
+}
+
+void panic() {
+    LOG(ERROR) << "panic: rebooting to bootloader";
+    reboot("bootloader");
+}
+
+std::ostream& operator<<(std::ostream& os, const Timer& t) {
+    os << t.duration_s() << " seconds";
+    return os;
+}
diff --git a/init/util.h b/init/util.h
index d56da39..4b54361 100644
--- a/init/util.h
+++ b/init/util.h
@@ -21,8 +21,9 @@
 #include <sys/types.h>
 
 #include <chrono>
-#include <string>
 #include <functional>
+#include <ostream>
+#include <string>
 
 #define COLDBOOT_DONE "/dev/.coldboot_done"
 
@@ -51,15 +52,21 @@
   Timer() : start_(boot_clock::now()) {
   }
 
-  double duration() {
+  double duration_s() const {
     typedef std::chrono::duration<double> double_duration;
     return std::chrono::duration_cast<double_duration>(boot_clock::now() - start_).count();
   }
 
+  int64_t duration_ns() const {
+    return (boot_clock::now() - start_).count();
+  }
+
  private:
   boot_clock::time_point start_;
 };
 
+std::ostream& operator<<(std::ostream& os, const Timer& t);
+
 unsigned int decode_uid(const char *s);
 
 int mkdir_recursive(const char *pathname, mode_t mode);
@@ -72,4 +79,8 @@
 std::string bytes_to_hex(const uint8_t *bytes, size_t bytes_len);
 bool is_dir(const char* pathname);
 bool expand_props(const std::string& src, std::string* dst);
+
+void reboot(const char* destination) __attribute__((__noreturn__));
+void panic() __attribute__((__noreturn__));
+
 #endif
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index bb17325..0f01872 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -38,40 +38,15 @@
 include $(LLVM_ROOT_PATH)/llvm.mk
 
 #-------------------------------------------------------------------------
-# The libbacktrace_offline shared library.
+# The libbacktrace_offline static library.
 #-------------------------------------------------------------------------
 libbacktrace_offline_src_files := \
 	BacktraceOffline.cpp \
 
-# Use shared llvm library on device to save space.
-libbacktrace_offline_shared_libraries_target := \
-	libbacktrace \
+# Use shared libraries so their headers get included during build.
+libbacktrace_offline_shared_libraries := \
 	libbase \
-	liblog \
 	libunwind \
-	libutils \
-	libLLVM \
-
-libbacktrace_offline_static_libraries_target := \
-	libziparchive \
-	libz \
-
-# Use static llvm libraries on host to remove dependency on 32-bit llvm shared library
-# which is not included in the prebuilt.
-libbacktrace_offline_static_libraries_host := \
-	libbacktrace \
-	libunwind \
-	libziparchive \
-	libz \
-	libbase \
-	liblog \
-	libutils \
-	libLLVMObject \
-	libLLVMBitReader \
-	libLLVMMC \
-	libLLVMMCParser \
-	libLLVMCore \
-	libLLVMSupport \
 
 module := libbacktrace_offline
 build_type := target
@@ -113,10 +88,16 @@
 backtrace_test_shared_libraries_target += \
 	libdl \
 	libutils \
-	libLLVM \
 
+# Statically link LLVMlibraries to remove dependency on llvm shared library.
 backtrace_test_static_libraries := \
 	libbacktrace_offline \
+	libLLVMObject \
+	libLLVMBitReader \
+	libLLVMMC \
+	libLLVMMCParser \
+	libLLVMCore \
+	libLLVMSupport \
 
 backtrace_test_static_libraries_target := \
 	libziparchive \
@@ -126,12 +107,6 @@
 	libziparchive \
 	libz \
 	libutils \
-	libLLVMObject \
-	libLLVMBitReader \
-	libLLVMMC \
-	libLLVMMCParser \
-	libLLVMCore \
-	libLLVMSupport \
 
 backtrace_test_ldlibs_host += \
 	-ldl \
diff --git a/libcutils/android_reboot.c b/libcutils/android_reboot.c
index af7e189..159a9d4 100644
--- a/libcutils/android_reboot.c
+++ b/libcutils/android_reboot.c
@@ -42,24 +42,6 @@
     struct mntent entry;
 } mntent_list;
 
-static bool has_mount_option(const char* opts, const char* opt_to_find)
-{
-  bool ret = false;
-  char* copy = NULL;
-  char* opt;
-  char* rem;
-
-  while ((opt = strtok_r(copy ? NULL : (copy = strdup(opts)), ",", &rem))) {
-      if (!strcmp(opt, opt_to_find)) {
-          ret = true;
-          break;
-      }
-  }
-
-  free(copy);
-  return ret;
-}
-
 static bool is_block_device(const char* fsname)
 {
     return !strncmp(fsname, "/dev/block", 10);
@@ -78,8 +60,7 @@
         return;
     }
     while ((mentry = getmntent(fp)) != NULL) {
-        if (is_block_device(mentry->mnt_fsname) &&
-            has_mount_option(mentry->mnt_opts, "rw")) {
+        if (is_block_device(mentry->mnt_fsname) && hasmntopt(mentry, "rw")) {
             mntent_list* item = (mntent_list*)calloc(1, sizeof(mntent_list));
             item->entry = *mentry;
             item->entry.mnt_fsname = strdup(mentry->mnt_fsname);
@@ -170,8 +151,7 @@
             goto out;
         }
         while ((mentry = getmntent(fp)) != NULL) {
-            if (!is_block_device(mentry->mnt_fsname) ||
-                !has_mount_option(mentry->mnt_opts, "ro")) {
+            if (!is_block_device(mentry->mnt_fsname) || !hasmntopt(mentry, "ro")) {
                 continue;
             }
             mntent_list* item = find_item(&rw_entries, mentry->mnt_fsname);
diff --git a/libcutils/tests/Android.bp b/libcutils/tests/Android.bp
index 72e2eac..abe3c21 100644
--- a/libcutils/tests/Android.bp
+++ b/libcutils/tests/Android.bp
@@ -24,14 +24,15 @@
                 "PropertiesTest.cpp",
                 "sched_policy_test.cpp",
                 "trace-dev_test.cpp",
+                "test_str_parms.cpp",
+                "android_get_control_socket_test.cpp",
+                "android_get_control_file_test.cpp"
             ],
         },
 
         not_windows: {
             srcs: [
                 "test_str_parms.cpp",
-                "android_get_control_socket_test.cpp",
-                "android_get_control_file_test.cpp"
             ],
         },
     },
diff --git a/libion/ion.c b/libion/ion.c
index 2db8845..a7b22b8 100644
--- a/libion/ion.c
+++ b/libion/ion.c
@@ -34,7 +34,7 @@
 
 int ion_open()
 {
-    int fd = open("/dev/ion", O_RDONLY);
+    int fd = open("/dev/ion", O_RDONLY | O_CLOEXEC);
     if (fd < 0)
         ALOGE("open /dev/ion failed!\n");
     return fd;
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 16aa4fa..e59a460 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -27,7 +27,7 @@
     "fake_writer.c",
 ]
 liblog_target_sources = [
-    "event_tag_map.c",
+    "event_tag_map.cpp",
     "config_read.c",
     "log_time.cpp",
     "log_is_loggable.c",
@@ -68,11 +68,14 @@
             enabled: true,
         },
         not_windows: {
-            srcs: ["event_tag_map.c"],
+            srcs: ["event_tag_map.cpp"],
         },
         linux: {
             host_ldlibs: ["-lrt"],
         },
+        linux_bionic: {
+            enabled: true,
+        },
     },
 
     cflags: [
diff --git a/liblog/event_tag_map.c b/liblog/event_tag_map.cpp
similarity index 100%
rename from liblog/event_tag_map.c
rename to liblog/event_tag_map.cpp
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index 170c8d1..f19c3ab 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -48,7 +48,7 @@
 
 static int check_log_uid_permissions()
 {
-#if defined(__BIONIC__)
+#if defined(__ANDROID__)
     uid_t uid = __android_log_uid();
 
     /* Matches clientHasLogCredentials() in logd */
@@ -130,7 +130,7 @@
     return kLogNotAvailable;
 }
 
-#if defined(__BIONIC__)
+#if defined(__ANDROID__)
 static atomic_uintptr_t tagMap;
 #endif
 
@@ -140,7 +140,7 @@
 LIBLOG_ABI_PUBLIC void __android_log_close()
 {
     struct android_log_transport_write *transport;
-#if defined(__BIONIC__)
+#if defined(__ANDROID__)
     EventTagMap *m;
 #endif
 
@@ -170,7 +170,7 @@
         }
     }
 
-#if defined(__BIONIC__)
+#if defined(__ANDROID__)
     /*
      * Additional risk here somewhat mitigated by immediately unlock flushing
      * the processor cache. The multi-threaded race that we choose to accept,
@@ -188,7 +188,7 @@
 
     __android_log_unlock();
 
-#if defined(__BIONIC__)
+#if defined(__ANDROID__)
     if (m != (EventTagMap *)(uintptr_t)-1LL) android_closeEventTagMap(m);
 #endif
 
@@ -261,7 +261,7 @@
         return -EINVAL;
     }
 
-#if defined(__BIONIC__)
+#if defined(__ANDROID__)
     if (log_id == LOG_ID_SECURITY) {
         if (vec[0].iov_len < 4) {
             return -EINVAL;
diff --git a/liblog/tests/Android.mk b/liblog/tests/Android.mk
index 158987a..ec5a99b 100644
--- a/liblog/tests/Android.mk
+++ b/liblog/tests/Android.mk
@@ -74,3 +74,38 @@
 LOCAL_SHARED_LIBRARIES := liblog libcutils libbase
 LOCAL_SRC_FILES := $(test_src_files)
 include $(BUILD_NATIVE_TEST)
+
+cts_executable := CtsLiblogTestCases
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := $(cts_executable)
+LOCAL_MODULE_TAGS := tests
+LOCAL_CFLAGS += $(test_c_flags)
+LOCAL_SRC_FILES := $(test_src_files)
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SHARED_LIBRARIES := liblog libcutils libbase
+LOCAL_STATIC_LIBRARIES := libgtest libgtest_main
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_CTS_TEST_PACKAGE := android.core.liblog
+include $(BUILD_CTS_EXECUTABLE)
+
+ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := $(cts_executable)_list
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := $(test_c_flags) -DHOST
+LOCAL_C_INCLUDES := external/gtest/include
+LOCAL_SRC_FILES := $(test_src_files)
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_CXX_STL := libc++
+LOCAL_SHARED_LIBRARIES := liblog libcutils libbase
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_HOST_NATIVE_TEST)
+
+endif  # ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
diff --git a/liblog/tests/AndroidTest.xml b/liblog/tests/AndroidTest.xml
new file mode 100644
index 0000000..b8d87e6
--- /dev/null
+++ b/liblog/tests/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for CTS Logging Library test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="CtsLiblogTestCases->/data/local/tmp/CtsLiblogTestCases" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="CtsLiblogTestCases" />
+        <option name="runtime-hint" value="65s" />
+    </test>
+</configuration>
diff --git a/liblog/tests/libc_test.cpp b/liblog/tests/libc_test.cpp
index f05a955..8cea7dc 100644
--- a/liblog/tests/libc_test.cpp
+++ b/liblog/tests/libc_test.cpp
@@ -20,6 +20,7 @@
 #include <stdio.h>
 
 TEST(libc, __pstore_append) {
+#ifdef __ANDROID__
     FILE *fp;
     ASSERT_TRUE(NULL != (fp = fopen("/dev/pmsg0", "a")));
     static const char message[] = "libc.__pstore_append\n";
@@ -42,4 +43,7 @@
                 "Reboot, ensure string libc.__pstore_append is in /sys/fs/pstore/pmsg-ramoops-0\n"
                );
     }
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 44045c3..5420f68 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -20,7 +20,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <unordered_set>
+
 #include <cutils/sockets.h>
+#include <log/event_tag_map.h>
 #include <private/android_logger.h>
 
 #include "benchmark.h"
@@ -689,3 +692,96 @@
     StopBenchmarkTiming();
 }
 BENCHMARK(BM_security);
+
+// Keep maps around for multiple iterations
+static std::unordered_set<uint32_t> set;
+static const EventTagMap* map;
+
+static bool prechargeEventMap() {
+    if (map) return true;
+
+    fprintf(stderr, "Precharge: start\n");
+
+    map = android_openEventTagMap(NULL);
+    for (uint32_t tag = 1; tag < USHRT_MAX; ++tag) {
+        size_t len;
+        if (android_lookupEventTag_len(map, &len, tag) == NULL) continue;
+        set.insert(tag);
+    }
+
+    fprintf(stderr, "Precharge: stop %zu\n", set.size());
+
+    return true;
+}
+
+/*
+ *	Measure the time it takes for android_lookupEventTag_len
+ */
+static void BM_lookupEventTag(int iters) {
+
+    prechargeEventMap();
+
+    std::unordered_set<uint32_t>::const_iterator it = set.begin();
+
+    StartBenchmarkTiming();
+
+    for (int i = 0; i < iters; ++i) {
+        size_t len;
+        android_lookupEventTag_len(map, &len, (*it));
+        ++it;
+        if (it == set.end()) it = set.begin();
+    }
+
+    StopBenchmarkTiming();
+}
+BENCHMARK(BM_lookupEventTag);
+
+/*
+ *	Measure the time it takes for android_lookupEventTag_len
+ */
+static uint32_t notTag = 1;
+
+static void BM_lookupEventTag_NOT(int iters) {
+
+    prechargeEventMap();
+
+    while (set.find(notTag) != set.end()) {
+        ++notTag;
+        if (notTag >= USHRT_MAX) notTag = 1;
+    }
+
+    StartBenchmarkTiming();
+
+    for (int i = 0; i < iters; ++i) {
+        size_t len;
+        android_lookupEventTag_len(map, &len, notTag);
+    }
+
+    StopBenchmarkTiming();
+
+    ++notTag;
+    if (notTag >= USHRT_MAX) notTag = 1;
+}
+BENCHMARK(BM_lookupEventTag_NOT);
+
+/*
+ *	Measure the time it takes for android_lookupEventFormat_len
+ */
+static void BM_lookupEventFormat(int iters) {
+
+    prechargeEventMap();
+
+    std::unordered_set<uint32_t>::const_iterator it = set.begin();
+
+    StartBenchmarkTiming();
+
+    for (int i = 0; i < iters; ++i) {
+        size_t len;
+        android_lookupEventFormat_len(map, &len, (*it));
+        ++it;
+        if (it == set.end()) it = set.begin();
+    }
+
+    StopBenchmarkTiming();
+}
+BENCHMARK(BM_lookupEventFormat);
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 02a572d..d80f8b2 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -30,7 +30,9 @@
 
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
+#ifdef __ANDROID__ // includes sys/properties.h which does not exist outside
 #include <cutils/properties.h>
+#endif
 #include <gtest/gtest.h>
 #include <log/logprint.h>
 #include <log/log_event_list.h>
@@ -53,6 +55,7 @@
     _rc; })
 
 TEST(liblog, __android_log_buf_print) {
+#ifdef __ANDROID__
     EXPECT_LT(0, __android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO,
                                          "TEST__android_log_buf_print",
                                          "radio"));
@@ -65,9 +68,13 @@
                                          "TEST__android_log_buf_print",
                                          "main"));
     usleep(1000);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, __android_log_buf_write) {
+#ifdef __ANDROID__
     EXPECT_LT(0, __android_log_buf_write(LOG_ID_RADIO, ANDROID_LOG_INFO,
                                          "TEST__android_log_buf_write",
                                          "radio"));
@@ -80,9 +87,13 @@
                                          "TEST__android_log_buf_write",
                                          "main"));
     usleep(1000);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, __android_log_btwrite) {
+#ifdef __ANDROID__
     int intBuf = 0xDEADBEEF;
     EXPECT_LT(0, __android_log_btwrite(0,
                                       EVENT_TYPE_INT,
@@ -97,20 +108,26 @@
                                       EVENT_TYPE_STRING,
                                       Buf, sizeof(Buf) - 1));
     usleep(1000);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
+#ifdef __ANDROID__
 static void* ConcurrentPrintFn(void *arg) {
     int ret = __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO,
                                   "TEST__android_log_print", "Concurrent %" PRIuPTR,
                                   reinterpret_cast<uintptr_t>(arg));
     return reinterpret_cast<void*>(ret);
 }
+#endif
 
 #define NUM_CONCURRENT 64
 #define _concurrent_name(a,n) a##__concurrent##n
 #define concurrent_name(a,n) _concurrent_name(a,n)
 
 TEST(liblog, concurrent_name(__android_log_buf_print, NUM_CONCURRENT)) {
+#ifdef __ANDROID__
     pthread_t t[NUM_CONCURRENT];
     int i;
     for (i=0; i < NUM_CONCURRENT; i++) {
@@ -128,8 +145,12 @@
         }
     }
     ASSERT_LT(0, ret);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
+#ifdef __ANDROID__
 std::string popenToString(std::string command) {
     std::string ret;
 
@@ -193,8 +214,10 @@
     }
     return false;
 }
+#endif
 
 TEST(liblog, __android_log_btwrite__android_logger_list_read) {
+#ifdef __ANDROID__
     struct logger_list *logger_list;
 
     pid_t pid = getpid();
@@ -257,14 +280,20 @@
     EXPECT_EQ(1, second_count);
 
     android_logger_list_close(logger_list);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
+#ifdef __ANDROID__
 static inline int32_t get4LE(const char* src)
 {
     return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
 }
+#endif
 
 static void bswrite_test(const char *message) {
+#ifdef __ANDROID__
     struct logger_list *logger_list;
 
     pid_t pid = getpid();
@@ -347,6 +376,10 @@
     EXPECT_EQ(1, count);
 
     android_logger_list_close(logger_list);
+#else
+    message = NULL;
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, __android_log_bswrite_and_print) {
@@ -370,6 +403,7 @@
 }
 
 static void buf_write_test(const char *message) {
+#ifdef __ANDROID__
     struct logger_list *logger_list;
 
     pid_t pid = getpid();
@@ -436,6 +470,10 @@
     EXPECT_EQ(1, count);
 
     android_logger_list_close(logger_list);
+#else
+    message = NULL;
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, __android_log_buf_write_and_print__empty) {
@@ -451,6 +489,7 @@
 }
 
 TEST(liblog, __security) {
+#ifdef __ANDROID__
     static const char persist_key[] = "persist.logd.security";
     static const char readonly_key[] = "ro.device_owner";
     static const char nothing_val[] = "_NOTHING_TO_SEE_HERE_";
@@ -485,9 +524,13 @@
     property_set(persist_key, "");
     EXPECT_FALSE(__android_log_security());
     property_set(persist_key, persist);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, __security_buffer) {
+#ifdef __ANDROID__
     struct logger_list *logger_list;
     android_event_long_t buffer;
 
@@ -621,9 +664,12 @@
                 "not system, content submitted but can not check end-to-end\n");
     }
     EXPECT_EQ(clientHasSecurityCredentials ? 1 : 0, count);
-
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
+#ifdef __ANDROID__
 static unsigned signaled;
 static log_time signal_time;
 
@@ -682,8 +728,10 @@
         *uticks = *sticks = 0;
     }
 }
+#endif
 
 TEST(liblog, android_logger_list_read__cpu_signal) {
+#ifdef __ANDROID__
     struct logger_list *logger_list;
     unsigned long long v = 0xDEADBEEFA55A0000ULL;
 
@@ -768,8 +816,12 @@
     EXPECT_GT(one_percent_ticks, user_ticks);
     EXPECT_GT(one_percent_ticks, system_ticks);
     EXPECT_GT(one_percent_ticks, user_ticks + system_ticks);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
+#ifdef __ANDROID__
 /*
  *  Strictly, we are not allowed to log messages in a signal context, the
  * correct way to handle this is to ensure the messages are constructed in
@@ -832,8 +884,10 @@
     pthread_attr_destroy(&attr);
     return 0;
 }
+#endif
 
 TEST(liblog, android_logger_list_read__cpu_thread) {
+#ifdef __ANDROID__
     struct logger_list *logger_list;
     unsigned long long v = 0xDEADBEAFA55A0000ULL;
 
@@ -919,11 +973,16 @@
     EXPECT_GT(one_percent_ticks, user_ticks);
     EXPECT_GT(one_percent_ticks, system_ticks);
     EXPECT_GT(one_percent_ticks, user_ticks + system_ticks);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
+#ifdef __ANDROID__
 static const char max_payload_tag[] = "TEST_max_payload_and_longish_tag_XXXX";
 #define SIZEOF_MAX_PAYLOAD_BUF (LOGGER_ENTRY_MAX_PAYLOAD - \
                                 sizeof(max_payload_tag) - 1)
+#endif
 static const char max_payload_buf[] = "LEONATO\n\
 I learn in this letter that Don Peter of Arragon\n\
 comes this night to Messina\n\
@@ -1056,6 +1115,7 @@
 takes his leave.";
 
 TEST(liblog, max_payload) {
+#ifdef __ANDROID__
     pid_t pid = getpid();
     char tag[sizeof(max_payload_tag)];
     memcpy(tag, max_payload_tag, sizeof(tag));
@@ -1113,9 +1173,13 @@
     EXPECT_EQ(true, matches);
 
     EXPECT_LE(SIZEOF_MAX_PAYLOAD_BUF, static_cast<size_t>(max_len));
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, __android_log_buf_print__maxtag) {
+#ifdef __ANDROID__
     struct logger_list *logger_list;
 
     pid_t pid = getpid();
@@ -1169,9 +1233,13 @@
     EXPECT_EQ(1, count);
 
     android_logger_list_close(logger_list);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, too_big_payload) {
+#ifdef __ANDROID__
     pid_t pid = getpid();
     static const char big_payload_tag[] = "TEST_big_payload_XXXX";
     char tag[sizeof(big_payload_tag)];
@@ -1226,9 +1294,13 @@
               static_cast<size_t>(max_len));
 
     EXPECT_EQ(ret, max_len + static_cast<ssize_t>(sizeof(big_payload_tag)));
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, dual_reader) {
+#ifdef __ANDROID__
     struct logger_list *logger_list1;
 
     // >25 messages due to liblog.__android_log_buf_print__concurrentXX above.
@@ -1273,9 +1345,13 @@
 
     EXPECT_EQ(25, count1);
     EXPECT_EQ(15, count2);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, android_logger_get_) {
+#ifdef __ANDROID__
     struct logger_list * logger_list = android_logger_list_alloc(ANDROID_LOG_WRONLY, 0, 0);
 
     for(int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
@@ -1307,14 +1383,20 @@
     }
 
     android_logger_list_close(logger_list);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
+#ifdef __ANDROID__
 static bool checkPriForTag(AndroidLogFormat *p_format, const char *tag, android_LogPriority pri) {
     return android_log_shouldPrintLine(p_format, tag, pri)
         && !android_log_shouldPrintLine(p_format, tag, (android_LogPriority)(pri - 1));
 }
+#endif
 
 TEST(liblog, filterRule) {
+#ifdef __ANDROID__
     static const char tag[] = "random";
 
     AndroidLogFormat *p_format = android_log_format_new();
@@ -1376,9 +1458,13 @@
 #endif
 
     android_log_format_free(p_format);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, is_loggable) {
+#ifdef __ANDROID__
     static const char tag[] = "is_loggable";
     static const char log_namespace[] = "persist.log.tag.";
     static const size_t base_offset = 8; /* skip "persist." */
@@ -1671,9 +1757,13 @@
     key[sizeof(log_namespace) - 2] = '\0';
     property_set(key, hold[2]);
     property_set(key + base_offset, hold[3]);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__typical) {
+#ifdef __ANDROID__
     const int TAG = 123456781;
     const char SUBTAG[] = "test-subtag";
     const int UID = -1;
@@ -1755,9 +1845,13 @@
     EXPECT_EQ(1, count);
 
     android_logger_list_close(logger_list);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__data_too_large) {
+#ifdef __ANDROID__
     const int TAG = 123456782;
     const char SUBTAG[] = "test-subtag";
     const int UID = -1;
@@ -1846,9 +1940,13 @@
     EXPECT_EQ(1, count);
 
     android_logger_list_close(logger_list);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__null_data) {
+#ifdef __ANDROID__
     const int TAG = 123456783;
     const char SUBTAG[] = "test-subtag";
     const int UID = -1;
@@ -1892,9 +1990,13 @@
     EXPECT_EQ(0, count);
 
     android_logger_list_close(logger_list);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__subtag_too_long) {
+#ifdef __ANDROID__
     const int TAG = 123456784;
     const char SUBTAG[] = "abcdefghijklmnopqrstuvwxyz now i know my abc";
     const int UID = -1;
@@ -1977,6 +2079,9 @@
     EXPECT_EQ(1, count);
 
     android_logger_list_close(logger_list);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, __android_log_bswrite_and_print___max) {
@@ -1988,6 +2093,7 @@
 }
 
 TEST(liblog, android_errorWriteLog__android_logger_list_read__success) {
+#ifdef __ANDROID__
     const int TAG = 123456785;
     const char SUBTAG[] = "test-subtag";
     struct logger_list *logger_list;
@@ -2046,9 +2152,13 @@
     EXPECT_EQ(1, count);
 
     android_logger_list_close(logger_list);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, android_errorWriteLog__android_logger_list_read__null_subtag) {
+#ifdef __ANDROID__
     const int TAG = 123456786;
     struct logger_list *logger_list;
 
@@ -2088,8 +2198,12 @@
     EXPECT_EQ(0, count);
 
     android_logger_list_close(logger_list);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
+#ifdef __ANDROID__
 static int is_real_element(int type) {
     return ((type == EVENT_TYPE_INT) ||
             (type == EVENT_TYPE_LONG) ||
@@ -2583,48 +2697,90 @@
 
     android_logger_list_close(logger_list);
 }
+#endif
 
 TEST(liblog, create_android_logger_int32) {
+#ifdef __ANDROID__
     create_android_logger(event_test_int32);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, create_android_logger_int64) {
+#ifdef __ANDROID__
     create_android_logger(event_test_int64);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, create_android_logger_list_int64) {
+#ifdef __ANDROID__
     create_android_logger(event_test_list_int64);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, create_android_logger_simple_automagic_list) {
+#ifdef __ANDROID__
     create_android_logger(event_test_simple_automagic_list);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, create_android_logger_list_empty) {
+#ifdef __ANDROID__
     create_android_logger(event_test_list_empty);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, create_android_logger_complex_nested_list) {
+#ifdef __ANDROID__
     create_android_logger(event_test_complex_nested_list);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, create_android_logger_7_level_prefix) {
+#ifdef __ANDROID__
     create_android_logger(event_test_7_level_prefix);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, create_android_logger_7_level_suffix) {
+#ifdef __ANDROID__
     create_android_logger(event_test_7_level_suffix);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, create_android_logger_android_log_error_write) {
+#ifdef __ANDROID__
     create_android_logger(event_test_android_log_error_write);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, create_android_logger_android_log_error_write_null) {
+#ifdef __ANDROID__
     create_android_logger(event_test_android_log_error_write_null);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, create_android_logger_overflow) {
+#ifdef __ANDROID__
     android_log_context ctx;
 
     EXPECT_TRUE(NULL != (ctx = create_android_logger(1005)));
@@ -2649,9 +2805,13 @@
     EXPECT_GT(0, android_log_write_list_begin(ctx));
     EXPECT_LE(0, android_log_destroy(&ctx));
     ASSERT_TRUE(NULL == ctx);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
 TEST(liblog, android_log_write_list_buffer) {
+#ifdef __ANDROID__
     __android_log_event_list ctx(1005);
     ctx << 1005 << "tag_def" << "(tag|1),(name|3),(format|3)";
     std::string buffer(ctx);
@@ -2662,12 +2822,18 @@
     EXPECT_EQ(android_log_buffer_to_string(buffer.data(), buffer.length(),
                                            msgBuf, sizeof(msgBuf)), 0);
     EXPECT_STREQ(msgBuf, "[1005,tag_def,(tag|1),(name|3),(format|3)]");
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
+#ifdef __ANDROID__
 static const char __pmsg_file[] =
         "/data/william-shakespeare/MuchAdoAboutNothing.txt";
+#endif
 
 TEST(liblog, __android_log_pmsg_file_write) {
+#ifdef __ANDROID__
     __android_log_close();
     bool pmsgActiveAfter__android_log_close = isPmsgActive();
     bool logdwActiveAfter__android_log_close = isLogdwActive();
@@ -2704,8 +2870,12 @@
     logdwActiveAfter__android_pmsg_file_write = isLogdwActive();
     EXPECT_TRUE(pmsgActiveAfter__android_pmsg_file_write);
     EXPECT_TRUE(logdwActiveAfter__android_pmsg_file_write);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
+#ifdef __ANDROID__
 ssize_t __pmsg_fn(log_id_t logId, char prio, const char *filename,
                   const char *buf, size_t len, void *arg) {
     EXPECT_TRUE(NULL == arg);
@@ -2727,8 +2897,10 @@
            (len != sizeof(max_payload_buf)) ||
            !!strcmp(max_payload_buf, buf) ? -ENOEXEC : 1;
 }
+#endif
 
 TEST(liblog, __android_log_pmsg_file_read) {
+#ifdef __ANDROID__
     signaled = 0;
 
     __android_log_close();
@@ -2756,8 +2928,12 @@
 
     EXPECT_LT(0, ret);
     EXPECT_EQ(1U, signaled);
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
 
+#ifdef __ANDROID__
 // meant to be handed to ASSERT_TRUE / EXPECT_TRUE only to expand the message
 static testing::AssertionResult IsOk(bool ok, std::string &message) {
     return ok ?
@@ -2765,6 +2941,26 @@
         (testing::AssertionFailure() << message);
 }
 
+// must be: '<needle:> 0 kB'
+static bool isZero(const std::string &content, std::string::size_type pos,
+                   const char* needle) {
+    std::string::size_type offset = content.find(needle, pos);
+    return (offset != std::string::npos) &&
+           ((offset = content.find_first_not_of(" \t", offset +
+                      strlen(needle))) != std::string::npos) &&
+           (content.find_first_not_of("0", offset) != offset);
+}
+
+// must not be: '<needle:> 0 kB'
+static bool isNotZero(const std::string &content, std::string::size_type pos,
+                      const char* needle) {
+    std::string::size_type offset = content.find(needle, pos);
+    return (offset != std::string::npos) &&
+           ((offset = content.find_first_not_of(" \t", offset +
+                      strlen(needle))) != std::string::npos) &&
+           (content.find_first_not_of("123456789", offset) != offset);
+}
+
 static void event_log_tags_test_smap(pid_t pid) {
     std::string filename = android::base::StringPrintf("/proc/%d/smaps", pid);
 
@@ -2772,6 +2968,7 @@
     if (!android::base::ReadFileToString(filename, &content)) return;
 
     bool shared_ok = false;
+    bool private_ok = false;
     bool anonymous_ok = false;
     bool pass_ok = false;
 
@@ -2781,25 +2978,28 @@
         pos += strlen(event_log_tags);
 
         // must not be: 'Shared_Clean: 0 kB'
-        static const char shared_clean[] = "Shared_Clean:";
-        std::string::size_type clean = content.find(shared_clean, pos);
-        bool ok = (clean != std::string::npos) &&
-                  ((clean = content.find_first_not_of(" \t", clean +
-                                strlen(shared_clean))) != std::string::npos) &&
-                  (content.find_first_not_of("123456789", clean) != clean);
+        bool ok = isNotZero(content, pos, "Shared_Clean:") ||
+                  // If not /etc/event-log-tags, thus r/w, then half points
+                  // back for not 'Shared_Dirty: 0 kB'
+                  ((content.substr(pos - 5 - strlen(event_log_tags), 5) != "/etc/") &&
+                      isNotZero(content, pos, "Shared_Dirty:"));
         if (ok && !pass_ok) {
             shared_ok = true;
         } else if (!ok) {
             shared_ok = false;
         }
 
+        // must be: 'Private_Dirty: 0 kB' and 'Private_Clean: 0 kB'
+        ok = isZero(content, pos, "Private_Dirty:") ||
+             isZero(content, pos, "Private_Clean:");
+        if (ok && !pass_ok) {
+            private_ok = true;
+        } else if (!ok) {
+            private_ok = false;
+        }
+
         // must be: 'Anonymous: 0 kB'
-        static const char anonymous[] = "Anonymous:";
-        std::string::size_type anon = content.find(anonymous, pos);
-        ok = (anon != std::string::npos) &&
-             ((anon = content.find_first_not_of(" \t", anon +
-                          strlen(anonymous))) != std::string::npos) &&
-             (content.find_first_not_of("0", anon) != anon);
+        ok = isZero(content, pos, "Anonymous:");
         if (ok && !pass_ok) {
             anonymous_ok = true;
         } else if (!ok) {
@@ -2811,7 +3011,7 @@
     content = "";
 
     if (!pass_ok) return;
-    if (shared_ok && anonymous_ok) return;
+    if (shared_ok && anonymous_ok && private_ok) return;
 
     filename = android::base::StringPrintf("/proc/%d/comm", pid);
     android::base::ReadFileToString(filename, &content);
@@ -2819,10 +3019,13 @@
                   pid, content.substr(0, content.find("\n")).c_str());
 
     EXPECT_TRUE(IsOk(shared_ok, content));
+    EXPECT_TRUE(IsOk(private_ok, content));
     EXPECT_TRUE(IsOk(anonymous_ok, content));
 }
+#endif
 
 TEST(liblog, event_log_tags) {
+#ifdef __ANDROID__
     std::unique_ptr<DIR, int(*)(DIR*)> proc_dir(opendir("/proc"), closedir);
     ASSERT_FALSE(!proc_dir);
 
@@ -2836,4 +3039,7 @@
         if (id != pid) continue;
         event_log_tags_test_smap(pid);
     }
+#else
+    GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
 }
diff --git a/libsparse/include/sparse/sparse.h b/libsparse/include/sparse/sparse.h
index 42d4adb..356f65f 100644
--- a/libsparse/include/sparse/sparse.h
+++ b/libsparse/include/sparse/sparse.h
@@ -176,6 +176,13 @@
 int64_t sparse_file_len(struct sparse_file *s, bool sparse, bool crc);
 
 /**
+ * sparse_file_block_size
+ *
+ * @s - sparse file cookie
+ */
+unsigned int sparse_file_block_size(struct sparse_file *s);
+
+/**
  * sparse_file_callback - call a callback for blocks in sparse file
  *
  * @s - sparse file cookie
@@ -197,6 +204,24 @@
 		int (*write)(void *priv, const void *data, int len), void *priv);
 
 /**
+ * sparse_file_foreach_chunk - call a callback for data blocks in sparse file
+ *
+ * @s - sparse file cookie
+ * @sparse - write in the Android sparse file format
+ * @crc - append a crc chunk
+ * @write - function to call for each block
+ * @priv - value that will be passed as the first argument to write
+ *
+ * The function has the same behavior as 'sparse_file_callback', except it only
+ * iterates on blocks that contain data.
+ *
+ * Returns 0 on success, negative errno on error.
+ */
+int sparse_file_foreach_chunk(struct sparse_file *s, bool sparse, bool crc,
+	int (*write)(void *priv, const void *data, int len, unsigned int block,
+		     unsigned int nr_blocks),
+	void *priv);
+/**
  * sparse_file_read - read a file into a sparse file cookie
  *
  * @s - sparse file cookie
diff --git a/libsparse/sparse.c b/libsparse/sparse.c
index 311678a..b175860 100644
--- a/libsparse/sparse.c
+++ b/libsparse/sparse.c
@@ -199,6 +199,57 @@
 	return ret;
 }
 
+struct chunk_data {
+	void		*priv;
+	unsigned int	block;
+	unsigned int	nr_blocks;
+	int (*write)(void *priv, const void *data, int len, unsigned int block,
+		     unsigned int nr_blocks);
+};
+
+static int foreach_chunk_write(void *priv, const void *data, int len)
+{
+	struct chunk_data *chk = priv;
+
+	return chk->write(chk->priv, data, len, chk->block, chk->nr_blocks);
+}
+
+int sparse_file_foreach_chunk(struct sparse_file *s, bool sparse, bool crc,
+	int (*write)(void *priv, const void *data, int len, unsigned int block,
+		     unsigned int nr_blocks),
+	void *priv)
+{
+	int ret;
+	int chunks;
+	struct chunk_data chk;
+	struct output_file *out;
+	struct backed_block *bb;
+
+	chk.priv = priv;
+	chk.write = write;
+	chk.block = chk.nr_blocks = 0;
+	chunks = sparse_count_chunks(s);
+	out = output_file_open_callback(foreach_chunk_write, &chk,
+					s->block_size, s->len, false, sparse,
+					chunks, crc);
+
+	if (!out)
+		return -ENOMEM;
+
+	for (bb = backed_block_iter_new(s->backed_block_list); bb;
+			bb = backed_block_iter_next(bb)) {
+		chk.block = backed_block_block(bb);
+		chk.nr_blocks = (backed_block_len(bb) - 1) / s->block_size + 1;
+		ret = sparse_file_write_block(out, bb);
+		if (ret)
+			return ret;
+	}
+
+	output_file_close(out);
+
+	return ret;
+}
+
 static int out_counter_write(void *priv, const void *data __unused, int len)
 {
 	int64_t *count = priv;
@@ -230,6 +281,11 @@
 	return count;
 }
 
+unsigned int sparse_file_block_size(struct sparse_file *s)
+{
+	return s->block_size;
+}
+
 static struct backed_block *move_chunks_up_to_len(struct sparse_file *from,
 		struct sparse_file *to, unsigned int len)
 {
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 25c779e..217b8c3 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -86,6 +86,13 @@
                 "ProcessCallStack.cpp",
             ],
         },
+        linux_bionic: {
+            enabled: true,
+            srcs: [
+                "Looper.cpp",
+                "ProcessCallStack.cpp",
+            ],
+        },
 
         darwin: {
             cflags: ["-Wno-unused-parameter"],
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 5ed0fe8..fce1378 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -62,7 +62,17 @@
         android: {
             static_libs: ["libz"],
         },
-        host: {
+        linux_bionic: {
+            static_libs: ["libz"],
+            enabled: true,
+        },
+        linux: {
+            shared_libs: ["libz-host"],
+        },
+        darwin: {
+            shared_libs: ["libz-host"],
+        },
+        windows: {
             shared_libs: ["libz-host"],
         },
     },
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 94b8691..c204a16 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -321,7 +321,7 @@
                     "  -g, --buffer-size                      Get the size of the ring buffer.\n"
                     "  -G <size>, --buffer-size=<size>\n"
                     "                  Set size of log ring buffer, may suffix with K or M.\n"
-                    "  -L, -last       Dump logs from prior to last reboot\n"
+                    "  -L, --last      Dump logs from prior to last reboot\n"
                     // Leave security (Device Owner only installations) and
                     // kernel (userdebug and eng) buffers undocumented.
                     "  -b <buffer>, --buffer=<buffer>         Request alternate ring buffer, 'main',\n"
diff --git a/sdcard/sdcard.cpp b/sdcard/sdcard.cpp
index bc502a0..df3ce85 100644
--- a/sdcard/sdcard.cpp
+++ b/sdcard/sdcard.cpp
@@ -331,6 +331,27 @@
     return true;
 }
 
+static bool sdcardfs_setup_bind_remount(const std::string& source_path, const std::string& dest_path,
+                                        gid_t gid, mode_t mask) {
+    std::string opts = android::base::StringPrintf("mask=%d,gid=%d", mask, gid);
+
+    if (mount(source_path.c_str(), dest_path.c_str(), nullptr,
+            MS_BIND, nullptr) != 0) {
+        PLOG(ERROR) << "failed to bind mount sdcardfs filesystem";
+        return false;
+    }
+
+    if (mount(source_path.c_str(), dest_path.c_str(), "none",
+            MS_REMOUNT | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) != 0) {
+        PLOG(ERROR) << "failed to mount sdcardfs filesystem";
+        if (umount2(dest_path.c_str(), MNT_DETACH))
+            PLOG(WARNING) << "Failed to unmount bind";
+        return false;
+    }
+
+    return true;
+}
+
 static void run_sdcardfs(const std::string& source_path, const std::string& label, uid_t uid,
         gid_t gid, userid_t userid, bool multi_user, bool full_write) {
     std::string dest_path_default = "/mnt/runtime/default/" + label;
@@ -343,9 +364,8 @@
         // permissions are completely masked off.
         if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid,
                                                       AID_SDCARD_RW, 0006)
-                || !sdcardfs_setup(source_path, dest_path_read, uid, gid, multi_user, userid,
-                                                      AID_EVERYBODY, 0027)
-                || !sdcardfs_setup(source_path, dest_path_write, uid, gid, multi_user, userid,
+                || !sdcardfs_setup_bind_remount(dest_path_default, dest_path_read, AID_EVERYBODY, 0027)
+                || !sdcardfs_setup_bind_remount(dest_path_default, dest_path_write,
                                                       AID_EVERYBODY, full_write ? 0007 : 0027)) {
             LOG(FATAL) << "failed to sdcardfs_setup";
         }
@@ -355,9 +375,9 @@
         // deep inside attr_from_stat().
         if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid,
                                                       AID_SDCARD_RW, 0006)
-                || !sdcardfs_setup(source_path, dest_path_read, uid, gid, multi_user, userid,
+                || !sdcardfs_setup_bind_remount(dest_path_default, dest_path_read,
                                                       AID_EVERYBODY, full_write ? 0027 : 0022)
-                || !sdcardfs_setup(source_path, dest_path_write, uid, gid, multi_user, userid,
+                || !sdcardfs_setup_bind_remount(dest_path_default, dest_path_write,
                                                       AID_EVERYBODY, full_write ? 0007 : 0022)) {
             LOG(FATAL) << "failed to sdcardfs_setup";
         }
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 5319ff4..d6ead1a 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -81,15 +81,6 @@
 $(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)
-
 
 # We build BSD grep separately, so it can provide egrep and fgrep too.
 include $(CLEAR_VARS)
diff --git a/toolbox/r.c b/toolbox/r.c
deleted file mode 100644
index b96cdb2..0000000
--- a/toolbox/r.c
+++ /dev/null
@@ -1,102 +0,0 @@
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#if __LP64__
-#define strtoptr strtoull
-#else
-#define strtoptr strtoul
-#endif
-
-static int usage()
-{
-    fprintf(stderr,"r [-b|-s] <address> [<value>]\n");
-    return -1;
-}
-
-int main(int argc, char *argv[])
-{
-    if(argc < 2) return usage();
-
-    int width = 4;
-    if(!strcmp(argv[1], "-b")) {
-        width = 1;
-        argc--;
-        argv++;
-    } else if(!strcmp(argv[1], "-s")) {
-        width = 2;
-        argc--;
-        argv++;
-    }
-
-    if(argc < 2) return usage();
-    uintptr_t addr = strtoptr(argv[1], 0, 16);
-
-    uintptr_t endaddr = 0;
-    char* end = strchr(argv[1], '-');
-    if (end)
-        endaddr = strtoptr(end + 1, 0, 16);
-
-    if (!endaddr)
-        endaddr = addr + width - 1;
-
-    if (endaddr <= addr) {
-        fprintf(stderr, "end address <= start address\n");
-        return -1;
-    }
-
-    bool set = false;
-    uint32_t value = 0;
-    if(argc > 2) {
-        set = true;
-        value = strtoul(argv[2], 0, 16);
-    }
-
-    int fd = open("/dev/mem", O_RDWR | O_SYNC);
-    if(fd < 0) {
-        fprintf(stderr,"cannot open /dev/mem\n");
-        return -1;
-    }
-
-    off64_t mmap_start = addr & ~(PAGE_SIZE - 1);
-    size_t mmap_size = endaddr - mmap_start + 1;
-    mmap_size = (mmap_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
-
-    void* page = mmap64(0, mmap_size, PROT_READ | PROT_WRITE,
-                        MAP_SHARED, fd, mmap_start);
-
-    if(page == MAP_FAILED){
-        fprintf(stderr,"cannot mmap region\n");
-        return -1;
-    }
-
-    while (addr <= endaddr) {
-        switch(width){
-        case 4: {
-            uint32_t* x = (uint32_t*) (((uintptr_t) page) + (addr & 4095));
-            if(set) *x = value;
-            fprintf(stderr,"%08"PRIxPTR": %08x\n", addr, *x);
-            break;
-        }
-        case 2: {
-            uint16_t* x = (uint16_t*) (((uintptr_t) page) + (addr & 4095));
-            if(set) *x = value;
-            fprintf(stderr,"%08"PRIxPTR": %04x\n", addr, *x);
-            break;
-        }
-        case 1: {
-            uint8_t* x = (uint8_t*) (((uintptr_t) page) + (addr & 4095));
-            if(set) *x = value;
-            fprintf(stderr,"%08"PRIxPTR": %02x\n", addr, *x);
-            break;
-        }
-        }
-        addr += width;
-    }
-    return 0;
-}