am a18bcfa4: am 91ce3576: resolve merge conflicts of 290efd2 to klp-modular-dev-plus-aosp. automerge: e916313

* commit 'a18bcfa45e9d37650bca158577d02f5059453935':
diff --git a/adb/Android.mk b/adb/Android.mk
index af7d7e5..b70c153 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -111,6 +111,7 @@
 	jdwp_service.c \
 	framebuffer_service.c \
 	remount_service.c \
+	disable_verity_service.c \
 	usb_linux_client.c
 
 LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter -Werror
@@ -120,13 +121,25 @@
 LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1
 endif
 
+ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT)))
+LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
+endif
+
 LOCAL_MODULE := adbd
 
 LOCAL_FORCE_STATIC_EXECUTABLE := true
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
 LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
+LOCAL_C_INCLUDES += system/extras/ext4_utils system/core/fs_mgr/include
 
-LOCAL_STATIC_LIBRARIES := liblog libcutils libc libmincrypt libselinux
+LOCAL_STATIC_LIBRARIES := liblog \
+	libfs_mgr \
+	libcutils \
+	libc \
+	libmincrypt \
+	libselinux \
+	libext4_utils_static
+
 include $(BUILD_EXECUTABLE)
 
 
diff --git a/adb/adb.h b/adb/adb.h
index 4f06800..44e5981 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -329,6 +329,7 @@
 #if !ADB_HOST
 void framebuffer_service(int fd, void *cookie);
 void remount_service(int fd, void *cookie);
+void disable_verity_service(int fd, void* cookie);
 #endif
 
 /* packet allocator */
diff --git a/adb/commandline.c b/adb/commandline.c
index 05b4ef6..87baeb9 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -189,6 +189,7 @@
         "\n"
         "  adb restore <file>           - restore device contents from the <file> backup archive\n"
         "\n"
+        "  adb disable-verity           - disable dm-verity checking on USERDEBUG builds\n"
         "  adb help                     - show this help message\n"
         "  adb version                  - show version num\n"
         "\n"
@@ -205,8 +206,7 @@
         "  adb reboot-bootloader        - reboots the device into the bootloader\n"
         "  adb root                     - restarts the adbd daemon with root permissions\n"
         "  adb usb                      - restarts the adbd daemon listening on USB\n"
-        "  adb tcpip <port>             - restarts the adbd daemon listening on TCP on the specified port"
-        "\n"
+        "  adb tcpip <port>             - restarts the adbd daemon listening on TCP on the specified port\n"
         "networking:\n"
         "  adb ppp <tty> [parameters]   - Run PPP over USB.\n"
         " Note: you should not automatically start a PPP connection.\n"
@@ -1437,7 +1437,7 @@
     if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
             || !strcmp(argv[0], "reboot-bootloader")
             || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
-            || !strcmp(argv[0], "root")) {
+            || !strcmp(argv[0], "root") || !strcmp(argv[0], "disable-verity")) {
         char command[100];
         if (!strcmp(argv[0], "reboot-bootloader"))
             snprintf(command, sizeof(command), "reboot:bootloader");
diff --git a/adb/disable_verity_service.c b/adb/disable_verity_service.c
new file mode 100644
index 0000000..ed3da52
--- /dev/null
+++ b/adb/disable_verity_service.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2014 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 "sysdeps.h"
+
+#define  TRACE_TAG  TRACE_ADB
+#include "adb.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#include "cutils/properties.h"
+#include "ext4_sb.h"
+#include <fs_mgr.h>
+
+#define FSTAB_PREFIX "/fstab."
+struct fstab *fstab;
+
+__attribute__((__format__(printf, 2, 3))) __nonnull((2))
+static void write_console(int fd, const char* format, ...)
+{
+    char buffer[256];
+    va_list args;
+    va_start (args, format);
+    vsnprintf (buffer, sizeof(buffer), format, args);
+    va_end (args);
+
+    adb_write(fd, buffer, strnlen(buffer, sizeof(buffer)));
+}
+
+static int get_target_device_size(int fd, const char *blk_device,
+                                  uint64_t *device_size)
+{
+    int data_device;
+    struct ext4_super_block sb;
+    struct fs_info info;
+
+    info.len = 0;  /* Only len is set to 0 to ask the device for real size. */
+
+    data_device = adb_open(blk_device, O_RDONLY | O_CLOEXEC);
+    if (data_device < 0) {
+        write_console(fd, "Error opening block device (%s)\n", strerror(errno));
+        return -1;
+    }
+
+    if (lseek64(data_device, 1024, SEEK_SET) < 0) {
+        write_console(fd, "Error seeking to superblock\n");
+        adb_close(data_device);
+        return -1;
+    }
+
+    if (adb_read(data_device, &sb, sizeof(sb)) != sizeof(sb)) {
+        write_console(fd, "Error reading superblock\n");
+        adb_close(data_device);
+        return -1;
+    }
+
+    ext4_parse_sb(&sb, &info);
+    *device_size = info.len;
+
+    adb_close(data_device);
+    return 0;
+}
+
+static int disable_verity(int fd, const char *block_device,
+                          const char* mount_point)
+{
+    uint32_t magic_number;
+    const uint32_t voff = VERITY_METADATA_MAGIC_DISABLE;
+    uint64_t device_length;
+    int device;
+    int retval = -1;
+
+    device = adb_open(block_device, O_RDWR | O_CLOEXEC);
+    if (device == -1) {
+        write_console(fd, "Could not open block device %s (%s).\n",
+                      block_device, strerror(errno));
+        write_console(fd, "Maybe run adb remount?\n");
+        goto errout;
+    }
+
+    // find the start of the verity metadata
+    if (get_target_device_size(fd, (char*)block_device, &device_length) < 0) {
+        write_console(fd, "Could not get target device size.\n");
+        goto errout;
+    }
+
+    if (lseek64(device, device_length, SEEK_SET) < 0) {
+        write_console(fd,
+                      "Could not seek to start of verity metadata block.\n");
+        goto errout;
+    }
+
+    // check the magic number
+    if (adb_read(device, &magic_number, sizeof(magic_number))
+             != sizeof(magic_number)) {
+        write_console(fd, "Couldn't read magic number!\n");
+        goto errout;
+    }
+
+    if (magic_number == VERITY_METADATA_MAGIC_DISABLE) {
+        write_console(fd, "Verity already disabled on %s\n", mount_point);
+        goto errout;
+    }
+
+    if (magic_number != VERITY_METADATA_MAGIC_NUMBER) {
+        write_console(fd,
+                      "Couldn't find verity metadata at offset %"PRIu64"!\n",
+                      device_length);
+        goto errout;
+    }
+
+    if (lseek64(device, device_length, SEEK_SET) < 0) {
+        write_console(fd,
+                      "Could not seek to start of verity metadata block.\n");
+        goto errout;
+    }
+
+    if (adb_write(device, &voff, sizeof(voff)) != sizeof(voff)) {
+        write_console(fd, "Could not set verity disabled flag on device %s\n",
+                      block_device);
+        goto errout;
+    }
+
+    write_console(fd, "Verity disabled on %s\n", mount_point);
+    retval = 0;
+errout:
+    if (device != -1)
+        adb_close(device);
+    return retval;
+}
+
+void disable_verity_service(int fd, void* cookie)
+{
+#ifdef ALLOW_ADBD_DISABLE_VERITY
+    char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
+    char propbuf[PROPERTY_VALUE_MAX];
+    int i;
+    bool any_disabled = false;
+
+    property_get("ro.secure", propbuf, "0");
+    if (strcmp(propbuf, "1")) {
+        write_console(fd, "verity not enabled - ENG build\n");
+        goto errout;
+    }
+
+    property_get("ro.debuggable", propbuf, "0");
+    if (strcmp(propbuf, "1")) {
+        write_console(fd, "verity cannot be disabled - USER build\n");
+        goto errout;
+    }
+
+    property_get("ro.hardware", propbuf, "");
+    snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf);
+
+    fstab = fs_mgr_read_fstab(fstab_filename);
+    if (!fstab) {
+        write_console(fd, "Failed to open %s\nMaybe run adb root?\n",
+                      fstab_filename);
+        goto errout;
+    }
+
+    /* Loop through entries looking for ones that vold manages */
+    for (i = 0; i < fstab->num_entries; i++) {
+        if(fs_mgr_is_verified(&fstab->recs[i])) {
+            if (!disable_verity(fd, fstab->recs[i].blk_device,
+                                fstab->recs[i].mount_point)) {
+                any_disabled = true;
+            }
+       }
+    }
+
+    if (any_disabled) {
+        write_console(fd,
+                      "Now reboot your device for settings to take effect\n");
+    }
+#else
+    write_console(fd, "disable-verity only works for userdebug builds\n");
+#endif
+
+errout:
+    adb_close(fd);
+}
diff --git a/adb/remount_service.c b/adb/remount_service.c
index 72d15a1..36367a7 100644
--- a/adb/remount_service.c
+++ b/adb/remount_service.c
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "sysdeps.h"
+
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -22,7 +24,7 @@
 #include <sys/mount.h>
 #include <unistd.h>
 
-#include "sysdeps.h"
+#include "cutils/properties.h"
 
 #define  TRACE_TAG  TRACE_ADB
 #include "adb.h"
@@ -115,6 +117,36 @@
 void remount_service(int fd, void *cookie)
 {
     char buffer[200];
+    char prop_buf[PROPERTY_VALUE_MAX];
+
+    bool system_verified = false, vendor_verified = false;
+    property_get("partition.system.verified", prop_buf, "0");
+    if (!strcmp(prop_buf, "1")) {
+        system_verified = true;
+    }
+
+    property_get("partition.vendor.verified", prop_buf, "0");
+    if (!strcmp(prop_buf, "1")) {
+        vendor_verified = true;
+    }
+
+    if (system_verified || vendor_verified) {
+        // Allow remount but warn of likely bad effects
+        bool both = system_verified && vendor_verified;
+        snprintf(buffer, sizeof(buffer),
+                 "dm_verity is enabled on the %s%s%s partition%s.\n",
+                 system_verified ? "system" : "",
+                 both ? " and " : "",
+                 vendor_verified ? "vendor" : "",
+                 both ? "s" : "");
+        write_string(fd, buffer);
+        snprintf(buffer, sizeof(buffer),
+                 "Use \"adb disable-verity\" to disable verity.\n"
+                 "If you do not, remount may succeed, however, you will still "
+                 "not be able to write to these volumes.\n");
+        write_string(fd, buffer);
+    }
+
     if (remount("/system", &system_ro)) {
         snprintf(buffer, sizeof(buffer), "remount of system failed: %s\n",strerror(errno));
         write_string(fd, buffer);
diff --git a/adb/services.c b/adb/services.c
index e61371a..21b08dc 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -469,6 +469,8 @@
                 free(cookie);
             }
         }
+    } else if(!strncmp(name, "disable-verity:", 15)) {
+        ret = create_service_thread(disable_verity_service, NULL);
 #endif
     }
     if (ret >= 0) {
diff --git a/debuggerd/backtrace.cpp b/debuggerd/backtrace.cpp
index e49ef9b..c2a1dbc 100644
--- a/debuggerd/backtrace.cpp
+++ b/debuggerd/backtrace.cpp
@@ -88,7 +88,9 @@
     return;
   }
 
-  wait_for_stop(tid, total_sleep_time_usec);
+  if (!attached && wait_for_sigstop(tid, total_sleep_time_usec, detach_failed) == -1) {
+    return;
+  }
 
   UniquePtr<Backtrace> backtrace(Backtrace::Create(tid, BACKTRACE_CURRENT_THREAD));
   if (backtrace->Unwind(0)) {
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 61805c9..06c16f8 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -77,7 +77,7 @@
         "*\n"
         "* Wait for gdb to start, then press the VOLUME DOWN key\n"
         "* to let the process continue crashing.\n"
-        "********************************************************\n",
+        "********************************************************",
         request.pid, exe, request.tid);
 
   // Wait for VOLUME DOWN.
@@ -129,11 +129,11 @@
   socklen_t len = sizeof(cr);
   int status = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
   if (status != 0) {
-    ALOGE("cannot get credentials\n");
+    ALOGE("cannot get credentials");
     return -1;
   }
 
-  ALOGV("reading tid\n");
+  ALOGV("reading tid");
   fcntl(fd, F_SETFL, O_NONBLOCK);
 
   pollfd pollfds[1];
@@ -227,6 +227,7 @@
       ALOGE("ptrace attach failed: %s\n", strerror(errno));
     } else {
       bool detach_failed = false;
+      bool tid_unresponsive = false;
       bool attach_gdb = should_attach_gdb(&request);
       if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) {
         ALOGE("failed responding to client: %s\n", strerror(errno));
@@ -240,8 +241,9 @@
 
         int total_sleep_time_usec = 0;
         for (;;) {
-          int signal = wait_for_signal(request.tid, &total_sleep_time_usec);
-          if (signal < 0) {
+          int signal = wait_for_sigstop(request.tid, &total_sleep_time_usec, &detach_failed);
+          if (signal == -1) {
+            tid_unresponsive = true;
             break;
           }
 
@@ -308,27 +310,21 @@
         free(tombstone_path);
       }
 
-      ALOGV("detaching\n");
-      if (attach_gdb) {
-        // stop the process so we can debug
-        kill(request.pid, SIGSTOP);
-
-        // detach so we can attach gdbserver
-        if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) {
-          ALOGE("ptrace detach from %d failed: %s\n", request.tid, strerror(errno));
-          detach_failed = true;
+      if (!tid_unresponsive) {
+        ALOGV("detaching");
+        if (attach_gdb) {
+          // stop the process so we can debug
+          kill(request.pid, SIGSTOP);
         }
-
-        // if debug.db.uid is set, its value indicates if we should wait
-        // for user action for the crashing process.
-        // in this case, we log a message and turn the debug LED on
-        // waiting for a gdb connection (for instance)
-        wait_for_user_action(request);
-      } else {
-        // just detach
         if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) {
-          ALOGE("ptrace detach from %d failed: %s\n", request.tid, strerror(errno));
+          ALOGE("ptrace detach from %d failed: %s", request.tid, strerror(errno));
           detach_failed = true;
+        } else if (attach_gdb) {
+          // if debug.db.uid is set, its value indicates if we should wait
+          // for user action for the crashing process.
+          // in this case, we log a message and turn the debug LED on
+          // waiting for a gdb connection (for instance)
+          wait_for_user_action(request);
         }
       }
 
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index a7e1524..0c1b80f 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -374,11 +374,7 @@
   }
 }
 
-static void dump_thread(
-    Backtrace* backtrace, log_t* log, int* total_sleep_time_usec) {
-
-  wait_for_stop(backtrace->Tid(), total_sleep_time_usec);
-
+static void dump_thread(Backtrace* backtrace, log_t* log) {
   dump_registers(log, backtrace->Tid());
   dump_backtrace_and_stack(backtrace, log);
 
@@ -421,13 +417,17 @@
       continue;
     }
 
+    if (wait_for_sigstop(new_tid, total_sleep_time_usec, &detach_failed) == -1) {
+      continue;
+    }
+
     log->current_tid = new_tid;
     _LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
     dump_thread_info(log, pid, new_tid);
 
     UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, new_tid, map));
     if (backtrace->Unwind(0)) {
-      dump_thread(backtrace.get(), log, total_sleep_time_usec);
+      dump_thread(backtrace.get(), log);
     }
 
     log->current_tid = log->crashed_tid;
@@ -628,7 +628,7 @@
   UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get()));
   if (backtrace->Unwind(0)) {
     dump_abort_message(backtrace.get(), log, abort_msg_address);
-    dump_thread(backtrace.get(), log, total_sleep_time_usec);
+    dump_thread(backtrace.get(), log);
   }
 
   if (want_logs) {
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index 9a30fe3..2baf9de 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -28,8 +28,8 @@
 #include <backtrace/Backtrace.h>
 #include <log/log.h>
 
-const int sleep_time_usec = 50000;         // 0.05 seconds
-const int max_total_sleep_usec = 10000000; // 10 seconds
+const int SLEEP_TIME_USEC = 50000;         // 0.05 seconds
+const int MAX_TOTAL_SLEEP_USEC = 10000000; // 10 seconds
 
 static int write_to_am(int fd, const char* buf, int len) {
   int to_write = len;
@@ -91,48 +91,44 @@
   }
 }
 
-int wait_for_signal(pid_t tid, int* total_sleep_time_usec) {
+int wait_for_sigstop(pid_t tid, int* total_sleep_time_usec, bool* detach_failed) {
+  bool allow_dead_tid = false;
   for (;;) {
     int status;
-    pid_t n = waitpid(tid, &status, __WALL | WNOHANG);
-    if (n < 0) {
-      if (errno == EAGAIN)
-        continue;
-      ALOGE("waitpid failed: %s\n", strerror(errno));
-      return -1;
-    } else if (n > 0) {
-      ALOGV("waitpid: n=%d status=%08x\n", n, status);
+    pid_t n = TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL | WNOHANG));
+    if (n == -1) {
+      ALOGE("waitpid failed: tid %d, %s", tid, strerror(errno));
+      break;
+    } else if (n == tid) {
       if (WIFSTOPPED(status)) {
         return WSTOPSIG(status);
       } else {
         ALOGE("unexpected waitpid response: n=%d, status=%08x\n", n, status);
-        return -1;
+        // This is the only circumstance under which we can allow a detach
+        // to fail with ESRCH, which indicates the tid has exited.
+        allow_dead_tid = true;
+        break;
       }
     }
 
-    if (*total_sleep_time_usec > max_total_sleep_usec) {
-      ALOGE("timed out waiting for tid=%d to die\n", tid);
-      return -1;
-    }
-
-    // not ready yet
-    ALOGV("not ready yet\n");
-    usleep(sleep_time_usec);
-    *total_sleep_time_usec += sleep_time_usec;
-  }
-}
-
-void wait_for_stop(pid_t tid, int* total_sleep_time_usec) {
-  siginfo_t si;
-  while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) < 0 && errno == ESRCH) {
-    if (*total_sleep_time_usec > max_total_sleep_usec) {
-      ALOGE("timed out waiting for tid=%d to stop\n", tid);
+    if (*total_sleep_time_usec > MAX_TOTAL_SLEEP_USEC) {
+      ALOGE("timed out waiting for stop signal: tid=%d", tid);
       break;
     }
 
-    usleep(sleep_time_usec);
-    *total_sleep_time_usec += sleep_time_usec;
+    usleep(SLEEP_TIME_USEC);
+    *total_sleep_time_usec += SLEEP_TIME_USEC;
   }
+
+  if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) {
+    if (allow_dead_tid && errno == ESRCH) {
+      ALOGE("tid exited before attach completed: tid %d", tid);
+    } else {
+      *detach_failed = true;
+      ALOGE("detach failed: tid %d, %s", tid, strerror(errno));
+    }
+  }
+  return -1;
 }
 
 #if defined (__mips__)
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index 82413b8..58a882c 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -67,12 +67,11 @@
   LOGS
 };
 
-/* Log information onto the tombstone. */
+// Log information onto the tombstone.
 void _LOG(log_t* log, logtype ltype, const char *fmt, ...)
         __attribute__ ((format(printf, 3, 4)));
 
-int wait_for_signal(pid_t tid, int* total_sleep_time_usec);
-void wait_for_stop(pid_t tid, int* total_sleep_time_usec);
+int wait_for_sigstop(pid_t, int*, bool*);
 
 void dump_memory(log_t* log, pid_t tid, uintptr_t addr);
 
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 7cffc37..61bf1ee 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -13,6 +13,10 @@
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 LOCAL_CFLAGS := -Werror
 
+ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT)))
+LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
+endif
+
 include $(BUILD_STATIC_LIBRARY)
 
 
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 91e6c33..40878c1 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -245,6 +245,16 @@
     return strcmp(value, "1") ? 0 : 1;
 }
 
+static int device_is_secure() {
+    int ret = -1;
+    char value[PROP_VALUE_MAX];
+    ret = __system_property_get("ro.secure", value);
+    /* If error, we want to fail secure */
+    if (ret < 0)
+        return 1;
+    return strcmp(value, "0") ? 1 : 0;
+}
+
 /*
  * Tries to mount any of the consecutive fstab entries that match
  * the mountpoint of the one given by fstab->recs[start_idx].
@@ -350,9 +360,11 @@
             wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
         }
 
-        if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) &&
-            !device_is_debuggable()) {
-            if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
+        if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
+            int rc = fs_mgr_setup_verity(&fstab->recs[i]);
+            if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+                INFO("Verity disabled");
+            } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
                 ERROR("Could not set up verified partition, skipping!\n");
                 continue;
             }
@@ -467,9 +479,11 @@
                      fstab->recs[i].mount_point);
         }
 
-        if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) &&
-            !device_is_debuggable()) {
-            if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
+        if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
+            int rc = fs_mgr_setup_verity(&fstab->recs[i]);
+            if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+                INFO("Verity disabled");
+            } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
                 ERROR("Could not set up verified partition, skipping!\n");
                 continue;
             }
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 3f84179..ab8f128 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -418,6 +418,11 @@
     return fstab->fs_mgr_flags & MF_NONREMOVABLE;
 }
 
+int fs_mgr_is_verified(struct fstab_rec *fstab)
+{
+    return fstab->fs_mgr_flags & MF_VERIFY;
+}
+
 int fs_mgr_is_encryptable(struct fstab_rec *fstab)
 {
     return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT);
diff --git a/fs_mgr/fs_mgr_priv_verity.h b/fs_mgr/fs_mgr_priv_verity.h
index 6193784..f90e596 100644
--- a/fs_mgr/fs_mgr_priv_verity.h
+++ b/fs_mgr/fs_mgr_priv_verity.h
@@ -14,4 +14,7 @@
  * limitations under the License.
  */
 
-int fs_mgr_setup_verity(struct fstab_rec *fstab);
\ No newline at end of file
+#define FS_MGR_SETUP_VERITY_DISABLED -2
+#define FS_MGR_SETUP_VERITY_FAIL -1
+#define FS_MGR_SETUP_VERITY_SUCCESS 0
+int fs_mgr_setup_verity(struct fstab_rec *fstab);
diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c
index b79a4a8..83e8043 100644
--- a/fs_mgr/fs_mgr_verity.c
+++ b/fs_mgr/fs_mgr_verity.c
@@ -43,7 +43,6 @@
 #include "fs_mgr_priv_verity.h"
 
 #define VERITY_METADATA_SIZE 32768
-#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001
 #define VERITY_TABLE_RSA_KEY "/verity_key"
 
 extern struct fs_info info;
@@ -123,28 +122,28 @@
     struct ext4_super_block sb;
     struct fs_info info = {0};
 
-    data_device = open(blk_device, O_RDONLY);
-    if (data_device < 0) {
+    data_device = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC));
+    if (data_device == -1) {
         ERROR("Error opening block device (%s)", strerror(errno));
         return -1;
     }
 
-    if (lseek64(data_device, 1024, SEEK_SET) < 0) {
+    if (TEMP_FAILURE_RETRY(lseek64(data_device, 1024, SEEK_SET)) < 0) {
         ERROR("Error seeking to superblock");
-        close(data_device);
+        TEMP_FAILURE_RETRY(close(data_device));
         return -1;
     }
 
-    if (read(data_device, &sb, sizeof(sb)) != sizeof(sb)) {
+    if (TEMP_FAILURE_RETRY(read(data_device, &sb, sizeof(sb))) != sizeof(sb)) {
         ERROR("Error reading superblock");
-        close(data_device);
+        TEMP_FAILURE_RETRY(close(data_device));
         return -1;
     }
 
     ext4_parse_sb(&sb, &info);
     *device_size = info.len;
 
-    close(data_device);
+    TEMP_FAILURE_RETRY(close(data_device));
     return 0;
 }
 
@@ -154,11 +153,13 @@
     unsigned table_length;
     uint64_t device_length;
     int protocol_version;
-    FILE *device;
-    int retval = -1;
+    int device;
+    int retval = FS_MGR_SETUP_VERITY_FAIL;
+    *signature = 0;
+    *table = 0;
 
-    device = fopen(block_device, "r");
-    if (!device) {
+    device = TEMP_FAILURE_RETRY(open(block_device, O_RDONLY | O_CLOEXEC));
+    if (device == -1) {
         ERROR("Could not open block device %s (%s).\n", block_device, strerror(errno));
         goto out;
     }
@@ -168,23 +169,35 @@
         ERROR("Could not get target device size.\n");
         goto out;
     }
-    if (fseek(device, device_length, SEEK_SET) < 0) {
+    if (TEMP_FAILURE_RETRY(lseek64(device, device_length, SEEK_SET)) < 0) {
         ERROR("Could not seek to start of verity metadata block.\n");
         goto out;
     }
 
     // check the magic number
-    if (!fread(&magic_number, sizeof(int), 1, device)) {
+    if (TEMP_FAILURE_RETRY(read(device, &magic_number, sizeof(magic_number))) !=
+            sizeof(magic_number)) {
         ERROR("Couldn't read magic number!\n");
         goto out;
     }
+
+#ifdef ALLOW_ADBD_DISABLE_VERITY
+    if (magic_number == VERITY_METADATA_MAGIC_DISABLE) {
+        retval = FS_MGR_SETUP_VERITY_DISABLED;
+        INFO("Attempt to cleanly disable verity - only works in USERDEBUG");
+        goto out;
+    }
+#endif
+
     if (magic_number != VERITY_METADATA_MAGIC_NUMBER) {
-        ERROR("Couldn't find verity metadata at offset %"PRIu64"!\n", device_length);
+        ERROR("Couldn't find verity metadata at offset %"PRIu64"!\n",
+              device_length);
         goto out;
     }
 
     // check the protocol version
-    if (!fread(&protocol_version, sizeof(int), 1, device)) {
+    if (TEMP_FAILURE_RETRY(read(device, &protocol_version,
+            sizeof(protocol_version))) != sizeof(protocol_version)) {
         ERROR("Couldn't read verity metadata protocol version!\n");
         goto out;
     }
@@ -194,43 +207,49 @@
     }
 
     // get the signature
-    *signature = (char*) malloc(RSANUMBYTES * sizeof(char));
+    *signature = (char*) malloc(RSANUMBYTES);
     if (!*signature) {
         ERROR("Couldn't allocate memory for signature!\n");
         goto out;
     }
-    if (!fread(*signature, RSANUMBYTES, 1, device)) {
+    if (TEMP_FAILURE_RETRY(read(device, *signature, RSANUMBYTES)) != RSANUMBYTES) {
         ERROR("Couldn't read signature from verity metadata!\n");
-        free(*signature);
         goto out;
     }
 
     // get the size of the table
-    if (!fread(&table_length, sizeof(int), 1, device)) {
+    if (TEMP_FAILURE_RETRY(read(device, &table_length, sizeof(table_length))) !=
+            sizeof(table_length)) {
         ERROR("Couldn't get the size of the verity table from metadata!\n");
-        free(*signature);
         goto out;
     }
 
     // get the table + null terminator
-    table_length += 1;
-    *table = malloc(table_length);
-    if(!*table) {
+    *table = malloc(table_length + 1);
+    if (!*table) {
         ERROR("Couldn't allocate memory for verity table!\n");
         goto out;
     }
-    if (!fgets(*table, table_length, device)) {
+    if (TEMP_FAILURE_RETRY(read(device, *table, table_length)) !=
+            (ssize_t)table_length) {
         ERROR("Couldn't read the verity table from metadata!\n");
-        free(*table);
-        free(*signature);
         goto out;
     }
 
-    retval = 0;
+    (*table)[table_length] = 0;
+    retval = FS_MGR_SETUP_VERITY_SUCCESS;
 
 out:
-    if (device)
-        fclose(device);
+    if (device != -1)
+        TEMP_FAILURE_RETRY(close(device));
+
+    if (retval != FS_MGR_SETUP_VERITY_SUCCESS) {
+        free(*table);
+        free(*signature);
+        *table = 0;
+        *signature = 0;
+    }
+
     return retval;
 }
 
@@ -358,10 +377,11 @@
 int fs_mgr_setup_verity(struct fstab_rec *fstab) {
 
     int retval = -1;
+    int fd = -1;
 
-    char *verity_blk_name;
-    char *verity_table;
-    char *verity_table_signature;
+    char *verity_blk_name = 0;
+    char *verity_table = 0;
+    char *verity_table_signature = 0;
 
     char buffer[DM_BUF_SIZE];
     struct dm_ioctl *io = (struct dm_ioctl *) buffer;
@@ -378,11 +398,19 @@
         return retval;
     }
 
+    // read the verity block at the end of the block device
+    // send error code up the chain so we can detect attempts to disable verity
+    retval = read_verity_metadata(fstab->blk_device,
+                                  &verity_table_signature,
+                                  &verity_table);
+    if (retval < 0) {
+        goto out;
+    }
+
     // get the device mapper fd
-    int fd;
     if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
         ERROR("Error opening device mapper (%s)", strerror(errno));
-        return retval;
+        goto out;
     }
 
     // create the device
@@ -397,13 +425,6 @@
         goto out;
     }
 
-    // read the verity block at the end of the block device
-    if (read_verity_metadata(fstab->blk_device,
-                                    &verity_table_signature,
-                                    &verity_table) < 0) {
-        goto out;
-    }
-
     // verify the signature on the table
     if (verify_table(verity_table_signature,
                             verity_table,
@@ -424,6 +445,7 @@
     // assign the new verity block device as the block device
     free(fstab->blk_device);
     fstab->blk_device = verity_blk_name;
+    verity_blk_name = 0;
 
     // make sure we've set everything up properly
     if (test_access(fstab->blk_device) < 0) {
@@ -434,6 +456,13 @@
     retval = set_verified_property(mount_point);
 
 out:
-    close(fd);
+    if (fd != -1) {
+        close(fd);
+    }
+
+    free(verity_table);
+    free(verity_table_signature);
+    free(verity_blk_name);
+
     return retval;
 }
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 0c7eb20..5e2ff41 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -20,6 +20,13 @@
 #include <stdint.h>
 #include <linux/dm-ioctl.h>
 
+// Magic number at start of verity metadata
+#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001
+
+// Replacement magic number at start of verity metadata to cleanly
+// turn verity off in userdebug builds.
+#define VERITY_METADATA_MAGIC_DISABLE 0x46464f56 // "VOFF"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -74,6 +81,7 @@
 struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path);
 int fs_mgr_is_voldmanaged(struct fstab_rec *fstab);
 int fs_mgr_is_nonremovable(struct fstab_rec *fstab);
+int fs_mgr_is_verified(struct fstab_rec *fstab);
 int fs_mgr_is_encryptable(struct fstab_rec *fstab);
 int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab);
 int fs_mgr_swapon_all(struct fstab *fstab);
diff --git a/include/nativebridge/native_bridge.h b/include/nativebridge/native_bridge.h
index ac254e9..523dc49 100644
--- a/include/nativebridge/native_bridge.h
+++ b/include/nativebridge/native_bridge.h
@@ -37,7 +37,7 @@
 
 // Do the early initialization part of the native bridge, if necessary. This should be done under
 // high privileges.
-void PreInitializeNativeBridge(const char* app_data_dir, const char* instruction_set);
+bool PreInitializeNativeBridge(const char* app_data_dir, const char* instruction_set);
 
 // Initialize the native bridge, if any. Should be called by Runtime::DidForkFromZygote. The JNIEnv*
 // will be used to modify the app environment for the bridge.
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index 2acc3c3..493511e 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -45,8 +45,6 @@
 
 #define POLICY_DEBUG 0
 
-#define CAN_SET_SP_SYSTEM 0 // non-zero means to implement set_sched_policy(tid, SP_SYSTEM)
-
 // This prctl is only available in Android kernels.
 #define PR_SET_TIMERSLACK_PID 41
 
@@ -60,9 +58,6 @@
 // File descriptors open to /dev/cpuctl/../tasks, setup by initialize, or -1 on error.
 static int bg_cgroup_fd = -1;
 static int fg_cgroup_fd = -1;
-#if CAN_SET_SP_SYSTEM
-static int system_cgroup_fd = -1;
-#endif
 
 /* Add tid to the scheduling group defined by the policy */
 static int add_tid_to_cgroup(int tid, SchedPolicy policy)
@@ -78,11 +73,6 @@
     case SP_AUDIO_SYS:
         fd = fg_cgroup_fd;
         break;
-#if CAN_SET_SP_SYSTEM
-    case SP_SYSTEM:
-        fd = system_cgroup_fd;
-        break;
-#endif
     default:
         fd = -1;
         break;
@@ -123,21 +113,13 @@
     if (!access("/dev/cpuctl/tasks", F_OK)) {
         __sys_supports_schedgroups = 1;
 
-#if CAN_SET_SP_SYSTEM
         filename = "/dev/cpuctl/tasks";
-        system_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
-        if (system_cgroup_fd < 0) {
-            SLOGV("open of %s failed: %s\n", filename, strerror(errno));
-        }
-#endif
-
-        filename = "/dev/cpuctl/apps/tasks";
         fg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
         if (fg_cgroup_fd < 0) {
             SLOGE("open of %s failed: %s\n", filename, strerror(errno));
         }
 
-        filename = "/dev/cpuctl/apps/bg_non_interactive/tasks";
+        filename = "/dev/cpuctl/bg_non_interactive/tasks";
         bg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC);
         if (bg_cgroup_fd < 0) {
             SLOGE("open of %s failed: %s\n", filename, strerror(errno));
@@ -233,11 +215,9 @@
         if (getSchedulerGroup(tid, grpBuf, sizeof(grpBuf)) < 0)
             return -1;
         if (grpBuf[0] == '\0') {
-            *policy = SP_SYSTEM;
-        } else if (!strcmp(grpBuf, "apps/bg_non_interactive")) {
-            *policy = SP_BACKGROUND;
-        } else if (!strcmp(grpBuf, "apps")) {
             *policy = SP_FOREGROUND;
+        } else if (!strcmp(grpBuf, "bg_non_interactive")) {
+            *policy = SP_BACKGROUND;
         } else {
             errno = ERANGE;
             return -1;
diff --git a/liblog/tests/Android.mk b/liblog/tests/Android.mk
index 255dc2e..cd1bf33 100644
--- a/liblog/tests/Android.mk
+++ b/liblog/tests/Android.mk
@@ -59,7 +59,8 @@
     -g \
     -Wall -Wextra \
     -Werror \
-    -fno-builtin
+    -fno-builtin \
+    -std=gnu++11
 
 test_src_files := \
     liblog_test.cpp
diff --git a/libnativebridge/Android.mk b/libnativebridge/Android.mk
index 6c2e43e..83169eb 100644
--- a/libnativebridge/Android.mk
+++ b/libnativebridge/Android.mk
@@ -13,7 +13,7 @@
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_CLANG := true
 LOCAL_CPP_EXTENSION := .cc
-LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CFLAGS += -Werror -Wall
 LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected
 LOCAL_LDFLAGS := -ldl
 LOCAL_MULTILIB := both
@@ -30,11 +30,11 @@
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_CLANG := true
 LOCAL_CPP_EXTENSION := .cc
-LOCAL_CFLAGS := -Werror -Wall
+LOCAL_CFLAGS += -Werror -Wall
 LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected
 LOCAL_LDFLAGS := -ldl
 LOCAL_MULTILIB := both
 
 include $(BUILD_HOST_SHARED_LIBRARY)
 
-include $(LOCAL_PATH)/tests/Android.mk
\ No newline at end of file
+include $(LOCAL_PATH)/tests/Android.mk
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index 3facedd..eab2de0 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -43,14 +43,16 @@
 enum class NativeBridgeState {
   kNotSetup,                        // Initial state.
   kOpened,                          // After successful dlopen.
+  kPreInitialized,                  // After successful pre-initialization.
   kInitialized,                     // After successful initialization.
   kClosed                           // Closed or errors.
 };
 
-static const char* kNotSetupString = "kNotSetup";
-static const char* kOpenedString = "kOpened";
-static const char* kInitializedString = "kInitialized";
-static const char* kClosedString = "kClosed";
+static constexpr const char* kNotSetupString = "kNotSetup";
+static constexpr const char* kOpenedString = "kOpened";
+static constexpr const char* kPreInitializedString = "kPreInitialized";
+static constexpr const char* kInitializedString = "kInitialized";
+static constexpr const char* kClosedString = "kClosed";
 
 static const char* GetNativeBridgeStateString(NativeBridgeState state) {
   switch (state) {
@@ -60,6 +62,9 @@
     case NativeBridgeState::kOpened:
       return kOpenedString;
 
+    case NativeBridgeState::kPreInitialized:
+      return kPreInitializedString;
+
     case NativeBridgeState::kInitialized:
       return kInitializedString;
 
@@ -82,8 +87,14 @@
 // Callbacks provided by the environment to the bridge. Passed to LoadNativeBridge.
 static const NativeBridgeRuntimeCallbacks* runtime_callbacks = nullptr;
 
-// The app's data directory.
-static char* app_data_dir = nullptr;
+// The app's code cache directory.
+static char* app_code_cache_dir = nullptr;
+
+// Code cache directory (relative to the application private directory)
+// Ideally we'd like to call into framework to retrieve this name. However that's considered an
+// implementation detail and will require either hacks or consistent refactorings. We compromise
+// and hard code the directory name again here.
+static constexpr const char* kCodeCacheDir = "code_cache";
 
 static constexpr uint32_t kNativeBridgeCallbackVersion = 1;
 
@@ -132,6 +143,13 @@
   return cb != nullptr && cb->version == kNativeBridgeCallbackVersion;
 }
 
+static void CloseNativeBridge(bool with_error) {
+  state = NativeBridgeState::kClosed;
+  had_error |= with_error;
+  delete[] app_code_cache_dir;
+  app_code_cache_dir = nullptr;
+}
+
 bool LoadNativeBridge(const char* nb_library_filename,
                       const NativeBridgeRuntimeCallbacks* runtime_cbs) {
   // We expect only one place that calls LoadNativeBridge: Runtime::Init. At that point we are not
@@ -149,12 +167,11 @@
   }
 
   if (nb_library_filename == nullptr || *nb_library_filename == 0) {
-    state = NativeBridgeState::kClosed;
-    return true;
+    CloseNativeBridge(false);
+    return false;
   } else {
     if (!NativeBridgeNameAcceptable(nb_library_filename)) {
-      state = NativeBridgeState::kClosed;
-      had_error = true;
+      CloseNativeBridge(true);
     } else {
       // Try to open the library.
       void* handle = dlopen(nb_library_filename, RTLD_LAZY);
@@ -178,8 +195,7 @@
       // Two failure conditions: could not find library (dlopen failed), or could not find native
       // bridge interface (dlsym failed). Both are an error and close the native bridge.
       if (callbacks == nullptr) {
-        had_error = true;
-        state = NativeBridgeState::kClosed;
+        CloseNativeBridge(true);
       } else {
         runtime_callbacks = runtime_cbs;
         state = NativeBridgeState::kOpened;
@@ -216,19 +232,32 @@
 template<typename T> void UNUSED(const T&) {}
 #endif
 
-void PreInitializeNativeBridge(const char* app_data_dir_in, const char* instruction_set) {
-  if (app_data_dir_in == nullptr) {
-    return;
+bool PreInitializeNativeBridge(const char* app_data_dir_in, const char* instruction_set) {
+  if (state != NativeBridgeState::kOpened) {
+    ALOGE("Invalid state: native bridge is expected to be opened.");
+    CloseNativeBridge(true);
+    return false;
   }
 
-  const size_t len = strlen(app_data_dir_in);
-  // Make a copy for us.
-  app_data_dir = new char[len];
-  strncpy(app_data_dir, app_data_dir_in, len);
+  if (app_data_dir_in == nullptr) {
+    ALOGE("Application private directory cannot be null.");
+    CloseNativeBridge(true);
+    return false;
+  }
+
+  // Create the path to the application code cache directory.
+  // The memory will be release after Initialization or when the native bridge is closed.
+  const size_t len = strlen(app_data_dir_in) + strlen(kCodeCacheDir) + 2; // '\0' + '/'
+  app_code_cache_dir = new char[len];
+  snprintf(app_code_cache_dir, len, "%s/%s", app_data_dir_in, kCodeCacheDir);
+
+  // Bind-mount /system/lib{,64}/<isa>/cpuinfo to /proc/cpuinfo.
+  // Failure is not fatal and will keep the native bridge in kPreInitialized.
+  state = NativeBridgeState::kPreInitialized;
 
 #ifndef __APPLE__
   if (instruction_set == nullptr) {
-    return;
+    return true;
   }
   size_t isa_len = strlen(instruction_set);
   if (isa_len > 10) {
@@ -237,11 +266,11 @@
     // be another instruction set in the future.
     ALOGW("Instruction set %s is malformed, must be less than or equal to 10 characters.",
           instruction_set);
-    return;
+    return true;
   }
 
-  // Bind-mount /system/lib{,64}/<isa>/cpuinfo to /proc/cpuinfo. If the file does not exist, the
-  // mount command will fail, so we safe the extra file existence check...
+  // If the file does not exist, the mount command will fail,
+  // so we save the extra file existence check.
   char cpuinfo_path[1024];
 
 #ifdef HAVE_ANDROID_OS
@@ -263,10 +292,12 @@
                                nullptr)) == -1) {   // "Data."
     ALOGW("Failed to bind-mount %s as /proc/cpuinfo: %s", cpuinfo_path, strerror(errno));
   }
-#else
+#else  // __APPLE__
   UNUSED(instruction_set);
   ALOGW("Mac OS does not support bind-mounting. Host simulation of native bridge impossible.");
 #endif
+
+  return true;
 }
 
 static void SetCpuAbi(JNIEnv* env, jclass build_class, const char* field, const char* value) {
@@ -353,20 +384,40 @@
   // We expect only one place that calls InitializeNativeBridge: Runtime::DidForkFromZygote. At that
   // point we are not multi-threaded, so we do not need locking here.
 
-  if (state == NativeBridgeState::kOpened) {
-    // Try to initialize.
-    if (callbacks->initialize(runtime_callbacks, app_data_dir, instruction_set)) {
-      SetupEnvironment(callbacks, env, instruction_set);
-      state = NativeBridgeState::kInitialized;
-    } else {
-      // Unload the library.
-      dlclose(native_bridge_handle);
-      had_error = true;
-      state = NativeBridgeState::kClosed;
+  if (state == NativeBridgeState::kPreInitialized) {
+    // Check for code cache: if it doesn't exist try to create it.
+    struct stat st;
+    if (stat(app_code_cache_dir, &st) == -1) {
+      if (errno == ENOENT) {
+        if (mkdir(app_code_cache_dir, S_IRWXU | S_IRWXG | S_IXOTH) == -1) {
+          ALOGE("Cannot create code cache directory %s: %s.", app_code_cache_dir, strerror(errno));
+          CloseNativeBridge(true);
+        }
+      } else {
+        ALOGE("Cannot stat code cache directory %s: %s.", app_code_cache_dir, strerror(errno));
+        CloseNativeBridge(true);
+      }
+    } else if (!S_ISDIR(st.st_mode)) {
+      ALOGE("Code cache is not a directory %s.", app_code_cache_dir);
+      CloseNativeBridge(true);
+    }
+
+    // If we're still PreInitialized (dind't fail the code cache checks) try to initialize.
+    if (state == NativeBridgeState::kPreInitialized) {
+      if (callbacks->initialize(runtime_callbacks, app_code_cache_dir, instruction_set)) {
+        SetupEnvironment(callbacks, env, instruction_set);
+        state = NativeBridgeState::kInitialized;
+        // We no longer need the code cache path, release the memory.
+        delete[] app_code_cache_dir;
+        app_code_cache_dir = nullptr;
+      } else {
+        // Unload the library.
+        dlclose(native_bridge_handle);
+        CloseNativeBridge(true);
+      }
     }
   } else {
-    had_error = true;
-    state = NativeBridgeState::kClosed;
+    CloseNativeBridge(true);
   }
 
   return state == NativeBridgeState::kInitialized;
@@ -378,22 +429,22 @@
 
   switch(state) {
     case NativeBridgeState::kOpened:
+    case NativeBridgeState::kPreInitialized:
     case NativeBridgeState::kInitialized:
       // Unload.
       dlclose(native_bridge_handle);
+      CloseNativeBridge(false);
       break;
 
     case NativeBridgeState::kNotSetup:
       // Not even set up. Error.
-      had_error = true;
+      CloseNativeBridge(true);
       break;
 
     case NativeBridgeState::kClosed:
       // Ignore.
       break;
   }
-
-  state = NativeBridgeState::kClosed;
 }
 
 bool NativeBridgeError() {
@@ -401,7 +452,9 @@
 }
 
 bool NativeBridgeAvailable() {
-  return state == NativeBridgeState::kOpened || state == NativeBridgeState::kInitialized;
+  return state == NativeBridgeState::kOpened
+      || state == NativeBridgeState::kPreInitialized
+      || state == NativeBridgeState::kInitialized;
 }
 
 bool NativeBridgeInitialized() {
diff --git a/libnativebridge/tests/Android.mk b/libnativebridge/tests/Android.mk
index 9c7e1b8..f28c490 100644
--- a/libnativebridge/tests/Android.mk
+++ b/libnativebridge/tests/Android.mk
@@ -1,19 +1,29 @@
 # Build the unit tests.
 LOCAL_PATH := $(call my-dir)
+
+include $(LOCAL_PATH)/Android.nativebridge-dummy.mk
+
 include $(CLEAR_VARS)
 
 # Build the unit tests.
 test_src_files := \
+    CodeCacheCreate_test.cpp \
+    CodeCacheExists_test.cpp \
+    CompleteFlow_test.cpp \
     InvalidCharsNativeBridge_test.cpp \
     NeedsNativeBridge_test.cpp \
     PreInitializeNativeBridge_test.cpp \
+    PreInitializeNativeBridgeFail1_test.cpp \
+    PreInitializeNativeBridgeFail2_test.cpp \
     ReSetupNativeBridge_test.cpp \
     UnavailableNativeBridge_test.cpp \
     ValidNameNativeBridge_test.cpp
 
+
 shared_libraries := \
     liblog \
-    libnativebridge
+    libnativebridge \
+    libnativebridge-dummy
 
 $(foreach file,$(test_src_files), \
     $(eval include $(CLEAR_VARS)) \
@@ -33,4 +43,4 @@
     $(eval LOCAL_SRC_FILES := $(file)) \
     $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
     $(eval include $(BUILD_HOST_NATIVE_TEST)) \
-)
\ No newline at end of file
+)
diff --git a/libnativebridge/tests/Android.nativebridge-dummy.mk b/libnativebridge/tests/Android.nativebridge-dummy.mk
new file mode 100644
index 0000000..1caf50a
--- /dev/null
+++ b/libnativebridge/tests/Android.nativebridge-dummy.mk
@@ -0,0 +1,34 @@
+LOCAL_PATH:= $(call my-dir)
+
+NATIVE_BRIDGE_COMMON_SRC_FILES := \
+  DummyNativeBridge.cpp
+
+# Shared library for target
+# ========================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libnativebridge-dummy
+
+LOCAL_SRC_FILES:= $(NATIVE_BRIDGE_COMMON_SRC_FILES)
+LOCAL_CLANG := true
+LOCAL_CFLAGS += -Werror -Wall
+LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected
+LOCAL_LDFLAGS := -ldl
+LOCAL_MULTILIB := both
+
+include $(BUILD_SHARED_LIBRARY)
+
+# Shared library for host
+# ========================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libnativebridge-dummy
+
+LOCAL_SRC_FILES:= $(NATIVE_BRIDGE_COMMON_SRC_FILES)
+LOCAL_CLANG := true
+LOCAL_CFLAGS += -Werror -Wall
+LOCAL_CPPFLAGS := -std=gnu++11 -fvisibility=protected
+LOCAL_LDFLAGS := -ldl
+LOCAL_MULTILIB := both
+
+include $(BUILD_HOST_SHARED_LIBRARY)
diff --git a/libnativebridge/tests/CodeCacheCreate_test.cpp b/libnativebridge/tests/CodeCacheCreate_test.cpp
new file mode 100644
index 0000000..58270c4
--- /dev/null
+++ b/libnativebridge/tests/CodeCacheCreate_test.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 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 "NativeBridgeTest.h"
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+namespace android {
+
+// Tests that the bridge initialization creates the code_cache if it doesn't
+// exists.
+TEST_F(NativeBridgeTest, CodeCacheCreate) {
+    // Make sure that code_cache does not exists
+    struct stat st;
+    ASSERT_EQ(-1, stat(kCodeCache, &st));
+    ASSERT_EQ(ENOENT, errno);
+
+    // Init
+    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
+    ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
+    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
+    ASSERT_TRUE(NativeBridgeAvailable());
+    ASSERT_FALSE(NativeBridgeError());
+
+    // Check that code_cache was created
+    ASSERT_EQ(0, stat(kCodeCache, &st));
+    ASSERT_TRUE(S_ISDIR(st.st_mode));
+
+    // Clean up
+    UnloadNativeBridge();
+    ASSERT_EQ(0, rmdir(kCodeCache));
+
+    ASSERT_FALSE(NativeBridgeError());
+}
+
+}  // namespace android
diff --git a/libnativebridge/tests/CodeCacheExists_test.cpp b/libnativebridge/tests/CodeCacheExists_test.cpp
new file mode 100644
index 0000000..8ba0158
--- /dev/null
+++ b/libnativebridge/tests/CodeCacheExists_test.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 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 "NativeBridgeTest.h"
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+namespace android {
+
+// Tests that the bridge is initialized without errors if the code_cache already
+// exists.
+TEST_F(NativeBridgeTest, CodeCacheExists) {
+    // Make sure that code_cache does not exists
+    struct stat st;
+    ASSERT_EQ(-1, stat(kCodeCache, &st));
+    ASSERT_EQ(ENOENT, errno);
+
+    // Create the code_cache
+    ASSERT_EQ(0, mkdir(kCodeCache, S_IRWXU | S_IRWXG | S_IXOTH));
+
+    // Init
+    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
+    ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
+    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
+    ASSERT_TRUE(NativeBridgeAvailable());
+    ASSERT_FALSE(NativeBridgeError());
+
+    // Check that the code cache is still there
+    ASSERT_EQ(0, stat(kCodeCache, &st));
+    ASSERT_TRUE(S_ISDIR(st.st_mode));
+
+    // Clean up
+    UnloadNativeBridge();
+    ASSERT_EQ(0, rmdir(kCodeCache));
+
+    ASSERT_FALSE(NativeBridgeError());
+}
+
+}  // namespace android
diff --git a/libnativebridge/tests/CompleteFlow_test.cpp b/libnativebridge/tests/CompleteFlow_test.cpp
new file mode 100644
index 0000000..cf06d2c
--- /dev/null
+++ b/libnativebridge/tests/CompleteFlow_test.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 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 "NativeBridgeTest.h"
+
+#include <unistd.h>
+
+namespace android {
+
+TEST_F(NativeBridgeTest, CompleteFlow) {
+    // Init
+    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
+    ASSERT_TRUE(NativeBridgeAvailable());
+    ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
+    ASSERT_TRUE(NativeBridgeAvailable());
+    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
+    ASSERT_TRUE(NativeBridgeAvailable());
+
+    // Basic calls to check that nothing crashes
+    ASSERT_FALSE(NativeBridgeIsSupported(nullptr));
+    ASSERT_EQ(nullptr, NativeBridgeLoadLibrary(nullptr, 0));
+    ASSERT_EQ(nullptr, NativeBridgeGetTrampoline(nullptr, nullptr, nullptr, 0));
+
+    // Unload
+    UnloadNativeBridge();
+    ASSERT_FALSE(NativeBridgeAvailable());
+    ASSERT_FALSE(NativeBridgeError());
+
+    // Clean-up code_cache
+    ASSERT_EQ(0, rmdir(kCodeCache));
+}
+
+}  // namespace android
diff --git a/libnativebridge/tests/DummyNativeBridge.cpp b/libnativebridge/tests/DummyNativeBridge.cpp
new file mode 100644
index 0000000..b9894f6
--- /dev/null
+++ b/libnativebridge/tests/DummyNativeBridge.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+// A dummy implementation of the native-bridge interface.
+
+#include "nativebridge/native_bridge.h"
+
+// NativeBridgeCallbacks implementations
+extern "C" bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
+                                         const char* /* app_code_cache_dir */,
+                                         const char* /* isa */) {
+  return true;
+}
+
+extern "C" void* native_bridge_loadLibrary(const char* /* libpath */, int /* flag */) {
+  return nullptr;
+}
+
+extern "C" void* native_bridge_getTrampoline(void* /* handle */, const char* /* name */,
+                                             const char* /* shorty */, uint32_t /* len */) {
+  return nullptr;
+}
+
+extern "C" bool native_bridge_isSupported(const char* /* libpath */) {
+  return false;
+}
+
+extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge_getAppEnv(
+    const char* /* abi */) {
+  return nullptr;
+}
+
+android::NativeBridgeCallbacks NativeBridgeItf {
+  .version = 1,
+  .initialize = &native_bridge_initialize,
+  .loadLibrary = &native_bridge_loadLibrary,
+  .getTrampoline = &native_bridge_getTrampoline,
+  .isSupported = &native_bridge_isSupported,
+  .getAppEnv = &native_bridge_getAppEnv
+};
diff --git a/libnativebridge/tests/NativeBridgeTest.h b/libnativebridge/tests/NativeBridgeTest.h
index 0d731cb..6a5c126 100644
--- a/libnativebridge/tests/NativeBridgeTest.h
+++ b/libnativebridge/tests/NativeBridgeTest.h
@@ -22,6 +22,9 @@
 #include <nativebridge/native_bridge.h>
 #include <gtest/gtest.h>
 
+constexpr const char* kNativeBridgeLibrary = "libnativebridge-dummy.so";
+constexpr const char* kCodeCache = "./code_cache";
+
 namespace android {
 
 class NativeBridgeTest : public testing::Test {
diff --git a/libnativebridge/tests/PreInitializeNativeBridgeFail1_test.cpp b/libnativebridge/tests/PreInitializeNativeBridgeFail1_test.cpp
new file mode 100644
index 0000000..69c30a1
--- /dev/null
+++ b/libnativebridge/tests/PreInitializeNativeBridgeFail1_test.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 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 "NativeBridgeTest.h"
+
+#include <cstdio>
+#include <cstring>
+#include <cutils/log.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+namespace android {
+
+TEST_F(NativeBridgeTest, PreInitializeNativeBridgeFail1) {
+  // Needs a valid application directory.
+  ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
+  ASSERT_FALSE(PreInitializeNativeBridge(nullptr, "isa"));
+  ASSERT_TRUE(NativeBridgeError());
+}
+
+}  // namespace android
diff --git a/libnativebridge/tests/PreInitializeNativeBridgeFail2_test.cpp b/libnativebridge/tests/PreInitializeNativeBridgeFail2_test.cpp
new file mode 100644
index 0000000..74e96e0
--- /dev/null
+++ b/libnativebridge/tests/PreInitializeNativeBridgeFail2_test.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 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 "NativeBridgeTest.h"
+
+#include <cstdio>
+#include <cstring>
+#include <cutils/log.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+namespace android {
+
+TEST_F(NativeBridgeTest, PreInitializeNativeBridgeFail2) {
+  // Needs LoadNativeBridge() first
+  ASSERT_FALSE(PreInitializeNativeBridge(nullptr, "isa"));
+  ASSERT_TRUE(NativeBridgeError());
+}
+
+}  // namespace android
diff --git a/libnativebridge/tests/PreInitializeNativeBridge_test.cpp b/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
index 84078f7..cec26ce 100644
--- a/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
+++ b/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
@@ -31,6 +31,7 @@
 static constexpr const char* kTestData = "PreInitializeNativeBridge test.";
 
 TEST_F(NativeBridgeTest, PreInitializeNativeBridge) {
+    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
 #ifndef __APPLE__         // Mac OS does not support bind-mount.
 #ifndef HAVE_ANDROID_OS   // Cannot write into the hard-wired location.
     // Try to create our mount namespace.
@@ -41,8 +42,7 @@
         fprintf(cpuinfo, kTestData);
         fclose(cpuinfo);
 
-        // Call the setup.
-        PreInitializeNativeBridge("does not matter 1", "short 2");
+        ASSERT_TRUE(PreInitializeNativeBridge("does not matter 1", "short 2"));
 
         // Read /proc/cpuinfo
         FILE* proc_cpuinfo = fopen("/proc/cpuinfo", "r");
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index f8d6162..51feff3 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -22,15 +22,26 @@
 #include <sys/klog.h>
 #include <sys/prctl.h>
 #include <sys/uio.h>
+#include <syslog.h>
 
 #include "libaudit.h"
 #include "LogAudit.h"
 
+#define KMSG_PRIORITY(PRI)         \
+    '<',                           \
+    '0' + (LOG_AUTH | (PRI)) / 10, \
+    '0' + (LOG_AUTH | (PRI)) % 10, \
+    '>'
+
 LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmsg)
         : SocketListener(getLogSocket(), false)
         , logbuf(buf)
         , reader(reader)
         , fdDmesg(-1) {
+    static const char auditd_message[] = { KMSG_PRIORITY(LOG_INFO),
+        'l', 'o', 'g', 'd', '.', 'a', 'u', 'd', 'i', 't', 'd', ':',
+        ' ', 's', 't', 'a', 'r', 't', '\n' };
+    write(fdDmsg, auditd_message, sizeof(auditd_message));
     logDmesg();
     fdDmesg = fdDmsg;
 }
@@ -75,13 +86,19 @@
         memmove(cp, cp + 1, strlen(cp + 1) + 1);
     }
 
+    bool info = strstr(str, " permissive=1") || strstr(str, " policy loaded ");
     if (fdDmesg >= 0) {
-        struct iovec iov[2];
+        struct iovec iov[3];
+        static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) };
+        static const char log_warning[] = { KMSG_PRIORITY(LOG_WARNING) };
 
-        iov[0].iov_base = str;
-        iov[0].iov_len = strlen(str);
-        iov[1].iov_base = const_cast<char *>("\n");
-        iov[1].iov_len = 1;
+        iov[0].iov_base = info ? const_cast<char *>(log_info)
+                               : const_cast<char *>(log_warning);
+        iov[0].iov_len = info ? sizeof(log_info) : sizeof(log_warning);
+        iov[1].iov_base = str;
+        iov[1].iov_len = strlen(str);
+        iov[2].iov_base = const_cast<char *>("\n");
+        iov[2].iov_len = 1;
 
         writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
     }
@@ -175,10 +192,7 @@
     if (!newstr) {
         rc = -ENOMEM;
     } else {
-        *newstr = (strstr(str, " permissive=1")
-                || strstr(str, " policy loaded "))
-                    ? ANDROID_LOG_INFO
-                    : ANDROID_LOG_WARN;
+        *newstr = info ? ANDROID_LOG_INFO : ANDROID_LOG_WARN;
         strlcpy(newstr + 1, comm, l);
         strncpy(newstr + 1 + l, str, estr - str);
         strcpy(newstr + 1 + l + (estr - str), ecomm);
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index cd9ea20..8c1c344 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -93,9 +93,9 @@
 }
 
 LogBuffer::LogBuffer(LastLogTimes *times)
-        : mTimes(*times) {
+        : dgramQlenStatistics(false)
+        , mTimes(*times) {
     pthread_mutex_init(&mLogElementsLock, NULL);
-    dgram_qlen_statistics = false;
 
     static const char global_tuneable[] = "persist.logd.size"; // Settings App
     static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
@@ -150,10 +150,10 @@
     while (--it != mLogElements.begin()) {
         if ((*it)->getRealTime() <= realtime) {
             // halves the peak performance, use with caution
-            if (dgram_qlen_statistics) {
+            if (dgramQlenStatistics) {
                 LogBufferElementCollection::iterator ib = it;
                 unsigned short buckets, num = 1;
-                for (unsigned short i = 0; (buckets = stats.dgram_qlen(i)); ++i) {
+                for (unsigned short i = 0; (buckets = stats.dgramQlen(i)); ++i) {
                     buckets -= num;
                     num += buckets;
                     while (buckets && (--ib != mLogElements.begin())) {
@@ -267,8 +267,7 @@
 
             if (uid == caller_uid) {
                 it = mLogElements.erase(it);
-                unsigned short len = e->getMsgLen();
-                stats.subtract(len, id, uid, e->getPid());
+                stats.subtract(e->getMsgLen(), id, uid, e->getPid());
                 delete e;
                 pruneRows--;
                 if (pruneRows == 0) {
@@ -318,23 +317,19 @@
 
             uid_t uid = e->getUid();
 
-            if (uid == worst) {
+            if ((uid == worst) || mPrune.naughty(e)) { // Worst or BlackListed
                 it = mLogElements.erase(it);
                 unsigned short len = e->getMsgLen();
-                stats.subtract(len, id, worst, e->getPid());
-                delete e;
-                kick = true;
-                pruneRows--;
-                if ((pruneRows == 0) || (worst_sizes < second_worst_sizes)) {
-                    break;
-                }
-                worst_sizes -= len;
-            } else if (mPrune.naughty(e)) { // BlackListed
-                it = mLogElements.erase(it);
-                stats.subtract(e->getMsgLen(), id, uid, e->getPid());
+                stats.subtract(len, id, uid, e->getPid());
                 delete e;
                 pruneRows--;
-                if (pruneRows == 0) {
+                if (uid == worst) {
+                    kick = true;
+                    if ((pruneRows == 0) || (worst_sizes < second_worst_sizes)) {
+                        break;
+                    }
+                    worst_sizes -= len;
+                } else if (pruneRows == 0) {
                     break;
                 }
             } else {
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 4b982a8..879baea 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -37,8 +37,7 @@
     pthread_mutex_t mLogElementsLock;
 
     LogStatistics stats;
-
-    bool dgram_qlen_statistics;
+    bool dgramQlenStatistics;
 
     PruneList mPrune;
 
@@ -66,7 +65,11 @@
 
     void enableDgramQlenStatistics() {
         stats.enableDgramQlenStatistics();
-        dgram_qlen_statistics = true;
+        dgramQlenStatistics = true;
+    }
+
+    void enableStatistics() {
+        stats.enableStatistics();
     }
 
     int initPrune(char *cp) { return mPrune.init(cp); }
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index a2f27c6..2a45590 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -51,11 +51,11 @@
 }
 
 bool PidStatistics::pidGone() {
-    if (mGone) {
+    if (mGone || (pid == gone)) {
         return true;
     }
-    if (pid == gone) {
-        return true;
+    if (pid == 0) {
+        return false;
     }
     if (kill(pid, 0) && (errno != EPERM)) {
         mGone = true;
@@ -90,9 +90,14 @@
 }
 
 // must call free to release return value
+//  If only we could sniff our own logs for:
+//   <time> <pid> <pid> E AndroidRuntime: Process: <name>, PID: <pid>
+//  which debuggerd prints as a process is crashing.
 char *PidStatistics::pidToName(pid_t pid) {
     char *retval = NULL;
-    if (pid != gone) {
+    if (pid == 0) { // special case from auditd for kernel
+        retval = strdup("logd.auditd");
+    } else if (pid != gone) {
         char buffer[512];
         snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
         int fd = open(buffer, O_RDONLY);
@@ -122,7 +127,7 @@
     PidStatisticsCollection::iterator it;
     for (it = begin(); it != end();) {
         delete (*it);
-        it = Pids.erase(it);
+        it = erase(it);
     }
 }
 
@@ -130,7 +135,7 @@
     mSizes += size;
     ++mElements;
 
-    PidStatistics *p;
+    PidStatistics *p = NULL;
     PidStatisticsCollection::iterator last;
     PidStatisticsCollection::iterator it;
     for (last = it = begin(); it != end(); last = it, ++it) {
@@ -141,12 +146,12 @@
         }
     }
     // insert if the gone entry.
-    bool insert = (last != it) && (p->getPid() == p->gone);
+    bool insert_before_last = (last != it) && p && (p->getPid() == p->gone);
     p = new PidStatistics(pid, pidToName(pid));
-    if (insert) {
-        Pids.insert(last, p);
+    if (insert_before_last) {
+        insert(last, p);
     } else {
-        Pids.push_back(p);
+        push_back(p);
     }
     p->add(size);
 }
@@ -163,17 +168,17 @@
                 size_t szsTotal = p->sizesTotal();
                 size_t elsTotal = p->elementsTotal();
                 delete p;
-                Pids.erase(it);
+                erase(it);
                 it = end();
                 --it;
                 if (it == end()) {
                     p = new PidStatistics(p->gone);
-                    Pids.push_back(p);
+                    push_back(p);
                 } else {
                     p = *it;
                     if (p->getPid() != p->gone) {
                         p = new PidStatistics(p->gone);
-                        Pids.push_back(p);
+                        push_back(p);
                     }
                 }
                 p->addTotal(szsTotal, elsTotal);
@@ -194,8 +199,8 @@
                 PidStatistics *n = (*it);
                 if ((n->getPid() != n->gone) && (n->sizes() > l->sizes())) {
                     pass = true;
-                    Pids.erase(it);
-                    Pids.insert(lt, n);
+                    erase(it);
+                    insert(lt, n);
                     it = lt;
                     n = l;
                 }
@@ -302,6 +307,10 @@
 }
 
 void LidStatistics::subtract(unsigned short size, uid_t uid, pid_t pid) {
+    if (uid == (uid_t) -1) { // init
+        uid = (uid_t) AID_ROOT;
+    }
+
     UidStatisticsCollection::iterator it;
     for (it = begin(); it != end(); ++it) {
         UidStatistics *u = *it;
@@ -384,24 +393,25 @@
 }
 
 LogStatistics::LogStatistics()
-        : start(CLOCK_MONOTONIC) {
+        : mStatistics(false)
+        , dgramQlenStatistics(false)
+        , start(CLOCK_MONOTONIC) {
     log_id_for_each(i) {
         mSizes[i] = 0;
         mElements[i] = 0;
     }
 
-    dgram_qlen_statistics = false;
-    for(unsigned short bucket = 0; dgram_qlen(bucket); ++bucket) {
+    for(unsigned short bucket = 0; dgramQlen(bucket); ++bucket) {
         mMinimum[bucket].tv_sec = mMinimum[bucket].tv_sec_max;
         mMinimum[bucket].tv_nsec = mMinimum[bucket].tv_nsec_max;
     }
 }
 
-//   Each bucket below represents a dgram_qlen of log messages. By
+//   Each bucket below represents a dgramQlen of log messages. By
 //   finding the minimum period of time from start to finish
-//   of each dgram_qlen, we can get a performance expectation for
+//   of each dgramQlen, we can get a performance expectation for
 //   the user space logger. The net result is that the period
-//   of time divided by the dgram_qlen will give us the average time
+//   of time divided by the dgramQlen will give us the average time
 //   between log messages; at the point where the average time
 //   is greater than the throughput capability of the logger
 //   we will not longer require the benefits of the FIFO formed
@@ -412,7 +422,7 @@
 //
 //   for example (reformatted):
 //
-//       Minimum time between log events per dgram_qlen:
+//       Minimum time between log events per dgramQlen:
 //       1   2   3   5   10  20  30  50  100  200 300 400 500 600
 //       5u2 12u 13u 15u 16u 27u 30u 36u 407u 3m1 3m3 3m9 3m9 5m5
 //
@@ -426,12 +436,12 @@
 //   a large engineering margin so the rule of thumb that lead us to 100 is
 //   fine.
 //
-// bucket dgram_qlen are tuned for /proc/sys/net/unix/max_dgram_qlen = 300
+// bucket dgramQlen are tuned for /proc/sys/net/unix/max_dgram_qlen = 300
 const unsigned short LogStatistics::mBuckets[] = {
     1, 2, 3, 5, 10, 20, 30, 50, 100, 200, 300, 400, 500, 600
 };
 
-unsigned short LogStatistics::dgram_qlen(unsigned short bucket) {
+unsigned short LogStatistics::dgramQlen(unsigned short bucket) {
     if (bucket >= sizeof(mBuckets) / sizeof(mBuckets[0])) {
         return 0;
     }
@@ -455,6 +465,9 @@
                         log_id_t log_id, uid_t uid, pid_t pid) {
     mSizes[log_id] += size;
     ++mElements[log_id];
+    if (!mStatistics) {
+        return;
+    }
     id(log_id).add(size, uid, pid);
 }
 
@@ -462,6 +475,9 @@
                              log_id_t log_id, uid_t uid, pid_t pid) {
     mSizes[log_id] -= size;
     --mElements[log_id];
+    if (!mStatistics) {
+        return;
+    }
     id(log_id).subtract(size, uid, pid);
 }
 
@@ -545,25 +561,28 @@
 
     spaces = 1;
     log_time t(CLOCK_MONOTONIC);
-    unsigned long long d = t.nsec() - start.nsec();
-    string.appendFormat("\nTotal%4llu:%02llu:%02llu.%09llu",
+    unsigned long long d;
+    if (mStatistics) {
+        d = t.nsec() - start.nsec();
+        string.appendFormat("\nTotal%4llu:%02llu:%02llu.%09llu",
                   d / NS_PER_SEC / 60 / 60, (d / NS_PER_SEC / 60) % 60,
                   (d / NS_PER_SEC) % 60, d % NS_PER_SEC);
 
-    log_id_for_each(i) {
-        if (!(logMask & (1 << i))) {
-            continue;
+        log_id_for_each(i) {
+            if (!(logMask & (1 << i))) {
+                continue;
+            }
+            oldLength = string.length();
+            if (spaces < 0) {
+                spaces = 0;
+            }
+            string.appendFormat("%*s%zu/%zu", spaces, "",
+                                sizesTotal(i), elementsTotal(i));
+            spaces += spaces_total + oldLength - string.length();
         }
-        oldLength = string.length();
-        if (spaces < 0) {
-            spaces = 0;
-        }
-        string.appendFormat("%*s%zu/%zu", spaces, "",
-                            sizesTotal(i), elementsTotal(i));
-        spaces += spaces_total + oldLength - string.length();
+        spaces = 1;
     }
 
-    spaces = 1;
     d = t.nsec() - oldest.nsec();
     string.appendFormat("\nNow%6llu:%02llu:%02llu.%09llu",
                   d / NS_PER_SEC / 60 / 60, (d / NS_PER_SEC / 60) % 60,
@@ -686,23 +705,23 @@
         pids.clear();
     }
 
-    if (dgram_qlen_statistics) {
+    if (dgramQlenStatistics) {
         const unsigned short spaces_time = 6;
         const unsigned long long max_seconds = 100000;
         spaces = 0;
-        string.append("\n\nMinimum time between log events per dgram_qlen:\n");
-        for(unsigned short i = 0; dgram_qlen(i); ++i) {
+        string.append("\n\nMinimum time between log events per max_dgram_qlen:\n");
+        for(unsigned short i = 0; dgramQlen(i); ++i) {
             oldLength = string.length();
             if (spaces < 0) {
                 spaces = 0;
             }
-            string.appendFormat("%*s%u", spaces, "", dgram_qlen(i));
+            string.appendFormat("%*s%u", spaces, "", dgramQlen(i));
             spaces += spaces_time + oldLength - string.length();
         }
         string.append("\n");
         spaces = 0;
         unsigned short n;
-        for(unsigned short i = 0; (n = dgram_qlen(i)); ++i) {
+        for(unsigned short i = 0; (n = dgramQlen(i)); ++i) {
             unsigned long long duration = minimum(i);
             if (duration) {
                 duration /= n;
@@ -724,8 +743,8 @@
                             / (NS_PER_SEC / 1000));
                 } else if (duration >= (NS_PER_SEC / (1000000 / 10))) {
                     string.appendFormat("%lluu",
-                         (duration + (NS_PER_SEC / 2 / 1000000))
-                             / (NS_PER_SEC / 1000000));
+                        (duration + (NS_PER_SEC / 2 / 1000000))
+                            / (NS_PER_SEC / 1000000));
                 } else {
                     string.appendFormat("%llun", duration);
                 }
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 3733137..f6c4329 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -72,6 +72,10 @@
 
     PidStatisticsCollection Pids;
 
+    void insert(PidStatisticsCollection::iterator i, PidStatistics *p)
+        { Pids.insert(i, p); }
+    void push_back(PidStatistics *p) { Pids.push_back(p); }
+
     size_t mSizes;
     size_t mElements;
 
@@ -81,6 +85,8 @@
 
     PidStatisticsCollection::iterator begin() { return Pids.begin(); }
     PidStatisticsCollection::iterator end() { return Pids.end(); }
+    PidStatisticsCollection::iterator erase(PidStatisticsCollection::iterator i)
+        { return Pids.erase(i); }
 
     uid_t getUid() { return uid; }
 
@@ -138,7 +144,8 @@
     size_t mSizes[LOG_ID_MAX];
     size_t mElements[LOG_ID_MAX];
 
-    bool dgram_qlen_statistics;
+    bool mStatistics;
+    bool dgramQlenStatistics;
 
     static const unsigned short mBuckets[14];
     log_time mMinimum[sizeof(mBuckets) / sizeof(mBuckets[0])];
@@ -150,8 +157,9 @@
 
     LidStatistics &id(log_id_t log_id) { return LogIds[log_id]; }
 
-    void enableDgramQlenStatistics() { dgram_qlen_statistics = true; }
-    static unsigned short dgram_qlen(unsigned short bucket);
+    void enableDgramQlenStatistics() { dgramQlenStatistics = true; }
+    void enableStatistics() { mStatistics = true; }
+    static unsigned short dgramQlen(unsigned short bucket);
     unsigned long long minimum(unsigned short bucket);
     void recordDiff(log_time diff, unsigned short bucket);
 
diff --git a/logd/README.property b/logd/README.property
index f4b3c3c..b7fcece 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -4,6 +4,9 @@
 logd.auditd                 bool  true   Enable selinux audit daemon
 logd.auditd.dmesg           bool  true   selinux audit messages duplicated and
                                          sent on to dmesg log
+logd.statistics             bool depends Enable logcat -S statistics.
+ro.config.low_ram           bool  false  if true, logd.statistics default false
+ro.build.type               string       if user, logd.statistics default false
 logd.statistics.dgram_qlen  bool  false  Record dgram_qlen statistics. This
                                          represents a performance impact and
                                          is used to determine the platform's
diff --git a/logd/main.cpp b/logd/main.cpp
index 1e1a718..54da7e3 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -152,6 +152,15 @@
     if (property_get_bool("logd.statistics.dgram_qlen", false)) {
         logBuf->enableDgramQlenStatistics();
     }
+    {
+        char property[PROPERTY_VALUE_MAX];
+        property_get("ro.build.type", property, "");
+        if (property_get_bool("logd.statistics",
+                   !!strcmp(property, "user")
+                && !property_get_bool("ro.config.low_ram", false))) {
+            logBuf->enableStatistics();
+        }
+    }
 
     // LogReader listens on /dev/socket/logdr. When a client
     // connects, log entries in the LogBuffer are written to the client.
diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in
index 67222d7..30bef46 100644
--- a/rootdir/init.environ.rc.in
+++ b/rootdir/init.environ.rc.in
@@ -10,4 +10,3 @@
     export LOOP_MOUNTPOINT /mnt/obb
     export BOOTCLASSPATH %BOOTCLASSPATH%
     export SYSTEMSERVERCLASSPATH %SYSTEMSERVERCLASSPATH%
-    export LD_PRELOAD libsigchain.so
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 8ba7c10..89f9aa6 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -119,25 +119,18 @@
     mount cgroup none /dev/cpuctl cpu
     chown system system /dev/cpuctl
     chown system system /dev/cpuctl/tasks
-    chmod 0660 /dev/cpuctl/tasks
+    chmod 0666 /dev/cpuctl/tasks
     write /dev/cpuctl/cpu.shares 1024
-    write /dev/cpuctl/cpu.rt_runtime_us 950000
+    write /dev/cpuctl/cpu.rt_runtime_us 800000
     write /dev/cpuctl/cpu.rt_period_us 1000000
 
-    mkdir /dev/cpuctl/apps
-    chown system system /dev/cpuctl/apps/tasks
-    chmod 0666 /dev/cpuctl/apps/tasks
-    write /dev/cpuctl/apps/cpu.shares 1024
-    write /dev/cpuctl/apps/cpu.rt_runtime_us 800000
-    write /dev/cpuctl/apps/cpu.rt_period_us 1000000
-
-    mkdir /dev/cpuctl/apps/bg_non_interactive
-    chown system system /dev/cpuctl/apps/bg_non_interactive/tasks
-    chmod 0666 /dev/cpuctl/apps/bg_non_interactive/tasks
+    mkdir /dev/cpuctl/bg_non_interactive
+    chown system system /dev/cpuctl/bg_non_interactive/tasks
+    chmod 0666 /dev/cpuctl/bg_non_interactive/tasks
     # 5.0 %
-    write /dev/cpuctl/apps/bg_non_interactive/cpu.shares 52
-    write /dev/cpuctl/apps/bg_non_interactive/cpu.rt_runtime_us 700000
-    write /dev/cpuctl/apps/bg_non_interactive/cpu.rt_period_us 1000000
+    write /dev/cpuctl/bg_non_interactive/cpu.shares 52
+    write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 700000
+    write /dev/cpuctl/bg_non_interactive/cpu.rt_period_us 1000000
 
     # qtaguid will limit access to specific data based on group memberships.
     #   net_bw_acct grants impersonation of socket owners.
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index eff24c3..474f630 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -88,6 +88,7 @@
 /dev/ppp                  0660   radio      vpn
 
 # sysfs properties
+/sys/devices/platform/trusty.*      trusty_version        0440  root   log
 /sys/devices/virtual/input/input*   enable      0660  root   input
 /sys/devices/virtual/input/input*   poll_delay  0660  root   input
 /sys/devices/virtual/usb_composite/*   enable      0664  root   system
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index d8d397e..84714cf 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -176,6 +176,7 @@
     readlink \
     renice \
     restorecon \
+    prlimit \
     rmmod \
     route \
     runcon \
diff --git a/toolbox/prlimit.c b/toolbox/prlimit.c
new file mode 100644
index 0000000..8cf202a
--- /dev/null
+++ b/toolbox/prlimit.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014, The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of Google, Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+static void
+usage(const char *s)
+{
+    fprintf(stderr, "usage: %s pid resource cur max\n", s);
+    exit(EXIT_FAILURE);
+}
+
+int prlimit_main(int argc, char *argv[])
+{
+    pid_t pid;
+    struct rlimit64 rl;
+    int resource;
+    int rc;
+
+    if (argc != 5)
+        usage(*argv);
+
+    if (sscanf(argv[1], "%d", &pid) != 1)
+        usage(*argv);
+
+    if (sscanf(argv[2], "%d", &resource) != 1)
+        usage(*argv);
+
+    if (sscanf(argv[3], "%llu", &rl.rlim_cur) != 1)
+        usage(*argv);
+
+    if (sscanf(argv[4], "%llu", &rl.rlim_max) != 1)
+        usage(*argv);
+
+    printf("setting resource %d of pid %d to [%llu,%llu]\n", resource, pid,
+            rl.rlim_cur, rl.rlim_max);
+    rc = prlimit64(pid, resource, &rl, NULL);
+    if (rc < 0) {
+        perror("prlimit");
+        exit(EXIT_FAILURE);
+    }
+
+    return 0;
+}
diff --git a/toolbox/top.c b/toolbox/top.c
index 280a032..b1a275c 100644
--- a/toolbox/top.c
+++ b/toolbox/top.c
@@ -32,6 +32,7 @@
 #include <ctype.h>
 #include <dirent.h>
 #include <grp.h>
+#include <inttypes.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -59,13 +60,13 @@
     char name[PROC_NAME_LEN];
     char tname[THREAD_NAME_LEN];
     char state;
-    long unsigned utime;
-    long unsigned stime;
-    long unsigned delta_utime;
-    long unsigned delta_stime;
-    long unsigned delta_time;
-    long vss;
-    long rss;
+    uint64_t utime;
+    uint64_t stime;
+    uint64_t delta_utime;
+    uint64_t delta_stime;
+    uint64_t delta_time;
+    uint64_t vss;
+    uint64_t rss;
     int prs;
     int num_threads;
     char policy[POLICY_NAME_LEN];
@@ -344,10 +345,19 @@
     proc->tname[THREAD_NAME_LEN-1] = 0;
 
     /* Scan rest of string. */
-    sscanf(close_paren + 1, " %c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
-                 "%lu %lu %*d %*d %*d %*d %*d %*d %*d %lu %ld "
-                 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d",
-                 &proc->state, &proc->utime, &proc->stime, &proc->vss, &proc->rss, &proc->prs);
+    sscanf(close_paren + 1,
+           " %c " "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
+           "%" SCNu64
+           "%" SCNu64 "%*d %*d %*d %*d %*d %*d %*d "
+           "%" SCNu64
+           "%" SCNu64 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
+           "%d",
+           &proc->state,
+           &proc->utime,
+           &proc->stime,
+           &proc->vss,
+           &proc->rss,
+           &proc->prs);
 
     return 0;
 }
@@ -470,12 +480,15 @@
             snprintf(user_buf, 20, "%d", proc->uid);
             user_str = user_buf;
         }
-        if (!threads)
-            printf("%5d %2d %3ld%% %c %5d %6ldK %6ldK %3s %-8.8s %s\n", proc->pid, proc->prs, proc->delta_time * 100 / total_delta_time, proc->state, proc->num_threads,
-                proc->vss / 1024, proc->rss * getpagesize() / 1024, proc->policy, user_str, proc->name[0] != 0 ? proc->name : proc->tname);
-        else
-            printf("%5d %5d %2d %3ld%% %c %6ldK %6ldK %3s %-8.8s %-15s %s\n", proc->pid, proc->tid, proc->prs, proc->delta_time * 100 / total_delta_time, proc->state,
-                proc->vss / 1024, proc->rss * getpagesize() / 1024, proc->policy, user_str, proc->tname, proc->name);
+        if (!threads) {
+            printf("%5d %2d %3" PRIu64 "%% %c %5d %6" PRIu64 "K %6" PRIu64 "K %3s %-8.8s %s\n",
+                   proc->pid, proc->prs, proc->delta_time * 100 / total_delta_time, proc->state, proc->num_threads,
+                   proc->vss / 1024, proc->rss * getpagesize() / 1024, proc->policy, user_str, proc->name[0] != 0 ? proc->name : proc->tname);
+        } else {
+            printf("%5d %5d %2d %3" PRIu64 "%% %c %6" PRIu64 "K %6" PRIu64 "K %3s %-8.8s %-15s %s\n",
+                   proc->pid, proc->tid, proc->prs, proc->delta_time * 100 / total_delta_time, proc->state,
+                   proc->vss / 1024, proc->rss * getpagesize() / 1024, proc->policy, user_str, proc->tname, proc->name);
+        }
     }
 }