Merge "Implements \'adb bugreport <ZIP_FILE>\'." into nyc-dev
am: e04c9f3

* commit 'e04c9f34364d76ad0f3580f566ea710285426c83':
  Implements 'adb bugreport <ZIP_FILE>'.

Change-Id: I7c5112d8e804394c705bee3e4cae227f5da68702
diff --git a/adb/Android.mk b/adb/Android.mk
index f1d3bee..6693619 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -108,7 +108,7 @@
 
 # Even though we're building a static library (and thus there's no link step for
 # this to take effect), this adds the includes to our path.
-LOCAL_STATIC_LIBRARIES := libbase
+LOCAL_STATIC_LIBRARIES := libcrypto_utils_static libcrypto_static libbase
 
 include $(BUILD_STATIC_LIBRARY)
 
@@ -131,7 +131,7 @@
 
 # Even though we're building a static library (and thus there's no link step for
 # this to take effect), this adds the includes to our path.
-LOCAL_STATIC_LIBRARIES := libcrypto_static libbase
+LOCAL_STATIC_LIBRARIES := libcrypto_utils_static libcrypto_static libbase
 
 LOCAL_C_INCLUDES_windows := development/host/windows/usb/api/
 LOCAL_MULTILIB := first
@@ -151,7 +151,7 @@
     shell_service_test.cpp \
 
 LOCAL_SANITIZE := $(adb_target_sanitize)
-LOCAL_STATIC_LIBRARIES := libadbd
+LOCAL_STATIC_LIBRARIES := libadbd libcrypto_utils_static libcrypto_static
 LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
 include $(BUILD_NATIVE_TEST)
 
@@ -191,6 +191,7 @@
 LOCAL_SHARED_LIBRARIES := libbase
 LOCAL_STATIC_LIBRARIES := \
     libadb \
+    libcrypto_utils_static \
     libcrypto_static \
     libcutils \
     libdiagnose_usb \
@@ -219,7 +220,7 @@
 LOCAL_SRC_FILES := test_track_devices.cpp
 LOCAL_SANITIZE := $(adb_host_sanitize)
 LOCAL_SHARED_LIBRARIES := libbase
-LOCAL_STATIC_LIBRARIES := libadb libcrypto_static libcutils
+LOCAL_STATIC_LIBRARIES := libadb libcrypto_utils_static libcrypto_static libcutils
 LOCAL_LDLIBS += -lrt -ldl -lpthread
 include $(BUILD_HOST_EXECUTABLE)
 endif
@@ -271,6 +272,7 @@
 LOCAL_STATIC_LIBRARIES := \
     libadb \
     libbase \
+    libcrypto_utils_static \
     libcrypto_static \
     libdiagnose_usb \
     liblog \
@@ -342,11 +344,11 @@
     libfec_rs \
     libselinux \
     liblog \
-    libmincrypt \
     libext4_utils_static \
     libsquashfs_utils \
     libcutils \
     libbase \
+    libcrypto_utils_static \
     libcrypto_static \
     libminijail
 
diff --git a/adb/adb.cpp b/adb/adb.cpp
index cb54d04..efa18c2 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -353,7 +353,8 @@
                 send_auth_publickey(t);
             }
         } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
-            if (adb_auth_verify(t->token, p->data, p->msg.data_length)) {
+            if (adb_auth_verify(t->token, sizeof(t->token),
+                                p->data, p->msg.data_length)) {
                 adb_auth_verified(t);
                 t->failed_auth_attempts = 0;
             } else {
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index a13604a..1ab5e1a 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -43,9 +43,15 @@
 void *adb_auth_nextkey(void *current);
 int adb_auth_get_userkey(unsigned char *data, size_t len);
 
-static inline int adb_auth_generate_token(void *token, size_t token_size) { return 0; }
-static inline int adb_auth_verify(void *token, void *sig, int siglen) { return 0; }
-static inline void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t) { }
+static inline int adb_auth_generate_token(void *token, size_t token_size) {
+    return 0;
+}
+static inline int adb_auth_verify(void *token, size_t token_size,
+                                  void *sig, int siglen) {
+    return 0;
+}
+static inline void adb_auth_confirm_key(unsigned char *data, size_t len,
+                                        atransport *t) {}
 
 #else // !ADB_HOST
 
@@ -54,12 +60,15 @@
     return 0;
 }
 static inline void *adb_auth_nextkey(void *current) { return NULL; }
-static inline int adb_auth_get_userkey(unsigned char *data, size_t len) { return 0; }
+static inline int adb_auth_get_userkey(unsigned char *data, size_t len) {
+    return 0;
+}
 
 void adbd_auth_init(void);
 void adbd_cloexec_auth_socket();
 int adb_auth_generate_token(void *token, size_t token_size);
-int adb_auth_verify(uint8_t* token, uint8_t* sig, int siglen);
+int adb_auth_verify(uint8_t* token, size_t token_size,
+                    uint8_t* sig, int siglen);
 void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
 
 #endif // ADB_HOST
diff --git a/adb/adb_auth_client.cpp b/adb/adb_auth_client.cpp
index 128c3df..415ab8e 100644
--- a/adb/adb_auth_client.cpp
+++ b/adb/adb_auth_client.cpp
@@ -23,10 +23,14 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <openssl/obj_mac.h>
+#include <openssl/rsa.h>
+#include <openssl/sha.h>
+
+#include <crypto_utils/android_pubkey.h>
+
 #include "cutils/list.h"
 #include "cutils/sockets.h"
-#include "mincrypt/rsa.h"
-#include "mincrypt/sha.h"
 
 #include "adb.h"
 #include "fdevent.h"
@@ -34,7 +38,7 @@
 
 struct adb_public_key {
     struct listnode node;
-    RSAPublicKey key;
+    RSA* key;
 };
 
 static const char *key_paths[] = {
@@ -66,9 +70,8 @@
     }
 
     while (fgets(buf, sizeof(buf), f)) {
-        /* Allocate 4 extra bytes to decode the base64 data in-place */
         auto key = reinterpret_cast<adb_public_key*>(
-            calloc(1, sizeof(adb_public_key) + 4));
+            calloc(1, sizeof(adb_public_key)));
         if (key == nullptr) {
             D("Can't malloc key");
             break;
@@ -78,15 +81,18 @@
         if (sep)
             *sep = '\0';
 
-        ret = __b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4);
-        if (ret != sizeof(key->key)) {
+        // b64_pton requires one additional byte in the target buffer for
+        // decoding to succeed. See http://b/28035006 for details.
+        uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
+        ret = __b64_pton(buf, keybuf, sizeof(keybuf));
+        if (ret != ANDROID_PUBKEY_ENCODED_SIZE) {
             D("%s: Invalid base64 data ret=%d", file, ret);
             free(key);
             continue;
         }
 
-        if (key->key.len != RSANUMWORDS) {
-            D("%s: Invalid key len %d", file, key->key.len);
+        if (!android_pubkey_decode(keybuf, ret, &key->key)) {
+            D("%s: Failed to parse key", file);
             free(key);
             continue;
         }
@@ -104,7 +110,9 @@
     while (!list_empty(list)) {
         item = list_head(list);
         list_remove(item);
-        free(node_to_item(item, struct adb_public_key, node));
+        adb_public_key* key = node_to_item(item, struct adb_public_key, node);
+        RSA_free(key->key);
+        free(key);
     }
 }
 
@@ -139,20 +147,17 @@
     return ret * token_size;
 }
 
-int adb_auth_verify(uint8_t* token, uint8_t* sig, int siglen)
+int adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int siglen)
 {
     struct listnode *item;
     struct listnode key_list;
     int ret = 0;
 
-    if (siglen != RSANUMBYTES)
-        return 0;
-
     load_keys(&key_list);
 
     list_for_each(item, &key_list) {
         adb_public_key* key = node_to_item(item, struct adb_public_key, node);
-        ret = RSA_verify(&key->key, sig, siglen, token, SHA_DIGEST_SIZE);
+        ret = RSA_verify(NID_sha1, token, token_size, sig, siglen, key->key);
         if (ret)
             break;
     }
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index 8f154fd..ab641eb 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -37,14 +37,9 @@
 
 #include "adb.h"
 
-/* HACK: we need the RSAPublicKey struct
- * but RSA_verify conflits with openssl */
-#define RSA_verify RSA_verify_mincrypt
-#include "mincrypt/rsa.h"
-#undef RSA_verify
-
 #include <android-base/errors.h>
 #include <android-base/strings.h>
+#include <crypto_utils/android_pubkey.h>
 #include <cutils/list.h>
 
 #include <openssl/evp.h>
@@ -68,54 +63,6 @@
 static struct listnode key_list;
 
 
-/* Convert OpenSSL RSA private key to android pre-computed RSAPublicKey format */
-static int RSA_to_RSAPublicKey(RSA *rsa, RSAPublicKey *pkey)
-{
-    int ret = 1;
-    unsigned int i;
-
-    BN_CTX* ctx = BN_CTX_new();
-    BIGNUM* r32 = BN_new();
-    BIGNUM* rr = BN_new();
-    BIGNUM* r = BN_new();
-    BIGNUM* rem = BN_new();
-    BIGNUM* n = BN_new();
-    BIGNUM* n0inv = BN_new();
-
-    if (RSA_size(rsa) != RSANUMBYTES) {
-        ret = 0;
-        goto out;
-    }
-
-    BN_set_bit(r32, 32);
-    BN_copy(n, rsa->n);
-    BN_set_bit(r, RSANUMWORDS * 32);
-    BN_mod_sqr(rr, r, n, ctx);
-    BN_div(NULL, rem, n, r32, ctx);
-    BN_mod_inverse(n0inv, rem, r32, ctx);
-
-    pkey->len = RSANUMWORDS;
-    pkey->n0inv = 0 - BN_get_word(n0inv);
-    for (i = 0; i < RSANUMWORDS; i++) {
-        BN_div(rr, rem, rr, r32, ctx);
-        pkey->rr[i] = BN_get_word(rem);
-        BN_div(n, rem, n, r32, ctx);
-        pkey->n[i] = BN_get_word(rem);
-    }
-    pkey->exponent = BN_get_word(rsa->e);
-
-out:
-    BN_free(n0inv);
-    BN_free(n);
-    BN_free(rem);
-    BN_free(r);
-    BN_free(rr);
-    BN_free(r32);
-    BN_CTX_free(ctx);
-
-    return ret;
-}
-
 static void get_user_info(char *buf, size_t len)
 {
     char hostname[1024], username[1024];
@@ -156,53 +103,55 @@
 
 static int write_public_keyfile(RSA *private_key, const char *private_key_path)
 {
-    RSAPublicKey pkey;
+    uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
+    uint8_t* base64_key_data = nullptr;
+    size_t base64_key_length = 0;
     FILE *outfile = NULL;
     char path[PATH_MAX], info[MAX_PAYLOAD_V1];
-    uint8_t* encoded = nullptr;
-    size_t encoded_length;
     int ret = 0;
 
-    if (snprintf(path, sizeof(path), "%s.pub", private_key_path) >=
-        (int)sizeof(path)) {
-        D("Path too long while writing public key");
-        return 0;
-    }
-
-    if (!RSA_to_RSAPublicKey(private_key, &pkey)) {
+    if (!android_pubkey_encode(private_key, binary_key_data,
+                               sizeof(binary_key_data))) {
         D("Failed to convert to publickey");
-        return 0;
-    }
-
-    outfile = fopen(path, "w");
-    if (!outfile) {
-        D("Failed to open '%s'", path);
-        return 0;
+        goto out;
     }
 
     D("Writing public key to '%s'", path);
 
 #if defined(OPENSSL_IS_BORINGSSL)
-    if (!EVP_EncodedLength(&encoded_length, sizeof(pkey))) {
+    if (!EVP_EncodedLength(&base64_key_length, sizeof(binary_key_data))) {
         D("Public key too large to base64 encode");
         goto out;
     }
 #else
     /* While we switch from OpenSSL to BoringSSL we have to implement
      * |EVP_EncodedLength| here. */
-    encoded_length = 1 + ((sizeof(pkey) + 2) / 3 * 4);
+    base64_key_length = 1 + ((sizeof(binary_key_data) + 2) / 3 * 4);
 #endif
 
-    encoded = new uint8_t[encoded_length];
-    if (encoded == nullptr) {
+    base64_key_data = new uint8_t[base64_key_length];
+    if (base64_key_data == nullptr) {
         D("Allocation failure");
         goto out;
     }
 
-    encoded_length = EVP_EncodeBlock(encoded, (uint8_t*) &pkey, sizeof(pkey));
+    base64_key_length = EVP_EncodeBlock(base64_key_data, binary_key_data,
+                                        sizeof(binary_key_data));
     get_user_info(info, sizeof(info));
 
-    if (fwrite(encoded, encoded_length, 1, outfile) != 1 ||
+    if (snprintf(path, sizeof(path), "%s.pub", private_key_path) >=
+        (int)sizeof(path)) {
+        D("Path too long while writing public key");
+        goto out;
+    }
+
+    outfile = fopen(path, "w");
+    if (!outfile) {
+        D("Failed to open '%s'", path);
+        goto out;
+    }
+
+    if (fwrite(base64_key_data, base64_key_length, 1, outfile) != 1 ||
         fwrite(info, strlen(info), 1, outfile) != 1) {
         D("Write error while writing public key");
         goto out;
@@ -214,7 +163,7 @@
     if (outfile != NULL) {
         fclose(outfile);
     }
-    delete[] encoded;
+    delete[] base64_key_data;
     return ret;
 }
 
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 4721e2f..7f40b96 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -43,24 +43,15 @@
 
 static const char* root_seclabel = nullptr;
 
-static void drop_capabilities_bounding_set_if_needed() {
-#ifdef ALLOW_ADBD_ROOT
+static void drop_capabilities_bounding_set_if_needed(struct minijail *j) {
+#if defined(ALLOW_ADBD_ROOT)
     char value[PROPERTY_VALUE_MAX];
     property_get("ro.debuggable", value, "");
     if (strcmp(value, "1") == 0) {
         return;
     }
 #endif
-    for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
-        if (i == CAP_SETUID || i == CAP_SETGID) {
-            // CAP_SETUID CAP_SETGID needed by /system/bin/run-as
-            continue;
-        }
-
-        if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0) == -1) {
-            PLOG(FATAL) << "Could not drop capabilities";
-        }
-    }
+    minijail_capbset_drop(j, CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID));
 }
 
 static bool should_drop_privileges() {
@@ -131,7 +122,7 @@
     // Don't listen on a port (default 5037) if running in secure mode.
     // Don't run as root if running in secure mode.
     if (should_drop_privileges()) {
-        drop_capabilities_bounding_set_if_needed();
+        drop_capabilities_bounding_set_if_needed(jail.get());
 
         minijail_change_gid(jail.get(), AID_SHELL);
         minijail_change_uid(jail.get(), AID_SHELL);
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index ce10708..3eeed34 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -246,7 +246,7 @@
         char** current = environ;
         while (char* env_cstr = *current++) {
             std::string env_string = env_cstr;
-            char* delimiter = strchr(env_string.c_str(), '=');
+            char* delimiter = strchr(&env_string[0], '=');
 
             // Drop any values that don't contain '='.
             if (delimiter) {
diff --git a/adb/socket.h b/adb/socket.h
index 9eb1b19..4acdf4a 100644
--- a/adb/socket.h
+++ b/adb/socket.h
@@ -118,7 +118,7 @@
 namespace internal {
 
 #if ADB_HOST
-char* skip_host_serial(const char* service);
+char* skip_host_serial(char* service);
 #endif
 
 }  // namespace internal
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index 5cbef6d..20a3bbb 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -275,8 +275,8 @@
 
 // Checks that skip_host_serial(serial) returns a pointer to the part of |serial| which matches
 // |expected|, otherwise logs the failure to gtest.
-void VerifySkipHostSerial(const std::string& serial, const char* expected) {
-    const char* result = internal::skip_host_serial(serial.c_str());
+void VerifySkipHostSerial(std::string serial, const char* expected) {
+    char* result = internal::skip_host_serial(&serial[0]);
     if (expected == nullptr) {
         EXPECT_EQ(nullptr, result);
     } else {
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index c083ee1..aecaba2 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -634,7 +634,7 @@
 // Where <port> must be a base-10 number and <prefix> may be any of {usb,product,model,device}.
 //
 // The returned pointer will point to the ':' just before <command>, or nullptr if not found.
-char* skip_host_serial(const char* service) {
+char* skip_host_serial(char* service) {
     static const std::vector<std::string>& prefixes =
         *(new std::vector<std::string>{"usb:", "product:", "model:", "device:"});
 
diff --git a/base/include/android-base/errors.h b/base/include/android-base/errors.h
index ca621fa..04c299c 100644
--- a/base/include/android-base/errors.h
+++ b/base/include/android-base/errors.h
@@ -27,8 +27,8 @@
 // special handling to get the error string. Refer to Microsoft documentation
 // to determine which error code to check for each function.
 
-#ifndef BASE_ERRORS_H
-#define BASE_ERRORS_H
+#ifndef ANDROID_BASE_ERRORS_H
+#define ANDROID_BASE_ERRORS_H
 
 #include <string>
 
@@ -43,4 +43,4 @@
 }  // namespace base
 }  // namespace android
 
-#endif  // BASE_ERRORS_H
+#endif  // ANDROID_BASE_ERRORS_H
diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h
index 5342d98..aa18ea7 100644
--- a/base/include/android-base/file.h
+++ b/base/include/android-base/file.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BASE_FILE_H
-#define BASE_FILE_H
+#ifndef ANDROID_BASE_FILE_H
+#define ANDROID_BASE_FILE_H
 
 #include <sys/stat.h>
 #include <string>
@@ -46,4 +46,4 @@
 }  // namespace base
 }  // namespace android
 
-#endif  // BASE_FILE_H
+#endif // ANDROID_BASE_FILE_H
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index c82f858..b86c232 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -13,8 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef BASE_LOGGING_H
-#define BASE_LOGGING_H
+
+#ifndef ANDROID_BASE_LOGGING_H
+#define ANDROID_BASE_LOGGING_H
 
 // NOTE: For Windows, you must include logging.h after windows.h to allow the
 // following code to suppress the evil ERROR macro:
@@ -146,6 +147,14 @@
 #define UNIMPLEMENTED(level) \
   LOG(level) << __PRETTY_FUNCTION__ << " unimplemented "
 
+#ifdef __clang_analyzer__
+// ClangL static analyzer does not see the conditional statement inside
+// LogMessage's destructor that will abort on FATAL severity.
+#define ABORT_AFTER_LOG_FATAL for (;;abort())
+#else
+#define ABORT_AFTER_LOG_FATAL
+#endif
+
 // Check whether condition x holds and LOG(FATAL) if not. The value of the
 // expression x is only evaluated once. Extra logging can be appended using <<
 // after. For example:
@@ -154,6 +163,7 @@
 //       "Check failed: false == true".
 #define CHECK(x)                                                              \
   LIKELY((x)) ||                                                              \
+    ABORT_AFTER_LOG_FATAL                                                     \
     ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
                                 ::android::base::FATAL, -1).stream()          \
         << "Check failed: " #x << " "
@@ -163,6 +173,7 @@
   for (auto _values = ::android::base::MakeEagerEvaluator(LHS, RHS);        \
        UNLIKELY(!(_values.lhs OP _values.rhs));                             \
        /* empty */)                                                         \
+  ABORT_AFTER_LOG_FATAL                                                     \
   ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
                               ::android::base::FATAL, -1).stream()          \
       << "Check failed: " << #LHS << " " << #OP << " " << #RHS              \
@@ -186,6 +197,7 @@
   if (LIKELY((strcmp(s1, s2) == 0) == sense))                              \
     ;                                                                      \
   else                                                                     \
+    ABORT_AFTER_LOG_FATAL                                                  \
     LOG(FATAL) << "Check failed: "                                         \
                << "\"" << s1 << "\""                                       \
                << (sense ? " == " : " != ") << "\"" << s2 << "\""
@@ -200,6 +212,7 @@
     int rc = call args;                                                \
     if (rc != 0) {                                                     \
       errno = rc;                                                      \
+      ABORT_AFTER_LOG_FATAL                                            \
       PLOG(FATAL) << #call << " failed for " << what; \
     }                                                                  \
   } while (false)
@@ -334,4 +347,4 @@
 }  // namespace base
 }  // namespace android
 
-#endif  // BASE_LOGGING_H
+#endif  // ANDROID_BASE_LOGGING_H
diff --git a/base/include/android-base/macros.h b/base/include/android-base/macros.h
index b1ce7c6..913a9a0 100644
--- a/base/include/android-base/macros.h
+++ b/base/include/android-base/macros.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef UTILS_MACROS_H
-#define UTILS_MACROS_H
+#ifndef ANDROID_BASE_MACROS_H
+#define ANDROID_BASE_MACROS_H
 
 #include <stddef.h>  // for size_t
 #include <unistd.h>  // for TEMP_FAILURE_RETRY
@@ -185,4 +185,4 @@
   } while (0)
 #endif
 
-#endif  // UTILS_MACROS_H
+#endif  // ANDROID_BASE_MACROS_H
diff --git a/base/include/android-base/memory.h b/base/include/android-base/memory.h
index 882582f..3a2f8fa 100644
--- a/base/include/android-base/memory.h
+++ b/base/include/android-base/memory.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BASE_MEMORY_H
-#define BASE_MEMORY_H
+#ifndef ANDROID_BASE_MEMORY_H
+#define ANDROID_BASE_MEMORY_H
 
 namespace android {
 namespace base {
@@ -44,4 +44,4 @@
 } // namespace base
 } // namespace android
 
-#endif // BASE_MEMORY_H
+#endif  // ANDROID_BASE_MEMORY_H
diff --git a/base/include/android-base/parseint.h b/base/include/android-base/parseint.h
index 0543795..ed75e2d 100644
--- a/base/include/android-base/parseint.h
+++ b/base/include/android-base/parseint.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BASE_PARSEINT_H
-#define BASE_PARSEINT_H
+#ifndef ANDROID_BASE_PARSEINT_H
+#define ANDROID_BASE_PARSEINT_H
 
 #include <errno.h>
 #include <stdlib.h>
@@ -70,4 +70,4 @@
 }  // namespace base
 }  // namespace android
 
-#endif  // BASE_PARSEINT_H
+#endif  // ANDROID_BASE_PARSEINT_H
diff --git a/base/include/android-base/parsenetaddress.h b/base/include/android-base/parsenetaddress.h
index 2de5ac9..b4ac025 100644
--- a/base/include/android-base/parsenetaddress.h
+++ b/base/include/android-base/parsenetaddress.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BASE_PARSENETADDRESS_H
-#define BASE_PARSENETADDRESS_H
+#ifndef ANDROID_BASE_PARSENETADDRESS_H
+#define ANDROID_BASE_PARSENETADDRESS_H
 
 #include <string>
 
@@ -35,4 +35,4 @@
 }  // namespace base
 }  // namespace android
 
-#endif  // BASE_PARSENETADDRESS_H
+#endif  // ANDROID_BASE_PARSENETADDRESS_H
diff --git a/base/include/android-base/stringprintf.h b/base/include/android-base/stringprintf.h
index d68af87..cf666ab 100644
--- a/base/include/android-base/stringprintf.h
+++ b/base/include/android-base/stringprintf.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BASE_STRINGPRINTF_H
-#define BASE_STRINGPRINTF_H
+#ifndef ANDROID_BASE_STRINGPRINTF_H
+#define ANDROID_BASE_STRINGPRINTF_H
 
 #include <stdarg.h>
 #include <string>
@@ -53,4 +53,4 @@
 }  // namespace base
 }  // namespace android
 
-#endif  // BASE_STRINGPRINTF_H
+#endif  // ANDROID_BASE_STRINGPRINTF_H
diff --git a/base/include/android-base/strings.h b/base/include/android-base/strings.h
index 20da144..69781cd 100644
--- a/base/include/android-base/strings.h
+++ b/base/include/android-base/strings.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BASE_STRINGS_H
-#define BASE_STRINGS_H
+#ifndef ANDROID_BASE_STRINGS_H
+#define ANDROID_BASE_STRINGS_H
 
 #include <sstream>
 #include <string>
@@ -65,4 +65,4 @@
 }  // namespace base
 }  // namespace android
 
-#endif  // BASE_STRINGS_H
+#endif  // ANDROID_BASE_STRINGS_H
diff --git a/base/include/android-base/test_utils.h b/base/include/android-base/test_utils.h
index 3f6872c..4ea3c8e 100644
--- a/base/include/android-base/test_utils.h
+++ b/base/include/android-base/test_utils.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef TEST_UTILS_H
-#define TEST_UTILS_H
+#ifndef ANDROID_BASE_TEST_UTILS_H
+#define ANDROID_BASE_TEST_UTILS_H
 
 #include <string>
 
@@ -48,4 +48,4 @@
   DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
 };
 
-#endif // TEST_UTILS_H
+#endif  // ANDROID_BASE_TEST_UTILS_H
diff --git a/base/include/android-base/thread_annotations.h b/base/include/android-base/thread_annotations.h
index 90979df..2422102 100644
--- a/base/include/android-base/thread_annotations.h
+++ b/base/include/android-base/thread_annotations.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef UTILS_THREAD_ANNOTATIONS_H
-#define UTILS_THREAD_ANNOTATIONS_H
+#ifndef ANDROID_BASE_THREAD_ANNOTATIONS_H
+#define ANDROID_BASE_THREAD_ANNOTATIONS_H
 
 #if defined(__SUPPORT_TS_ANNOTATION__) || defined(__clang__)
 #define THREAD_ANNOTATION_ATTRIBUTE__(x)   __attribute__((x))
@@ -80,4 +80,4 @@
 #define NO_THREAD_SAFETY_ANALYSIS \
       THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
 
-#endif  // UTILS_THREAD_ANNOTATIONS_H
+#endif  // ANDROID_BASE_THREAD_ANNOTATIONS_H
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index d3b27ca..8bc49ce 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -21,18 +21,18 @@
 
 #include <android-base/macros.h>
 
-/* Container for a file descriptor that automatically closes the descriptor as
- * it goes out of scope.
- *
- *      unique_fd ufd(open("/some/path", "r"));
- *
- *      if (ufd.get() < 0) // invalid descriptor
- *          return error;
- *
- *      // Do something useful
- *
- *      return 0; // descriptor is closed here
- */
+// Container for a file descriptor that automatically closes the descriptor as
+// it goes out of scope.
+//
+//      unique_fd ufd(open("/some/path", "r"));
+//      if (ufd.get() == -1) return error;
+//
+//      // Do something useful, possibly including 'return'.
+//
+//      return 0; // Descriptor is closed for you.
+//
+// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
+// you find this class if you're searching for one of those names.
 namespace android {
 namespace base {
 
@@ -44,14 +44,18 @@
   ~unique_fd() { clear(); }
 
   unique_fd(unique_fd&& other) : value_(other.release()) {}
-  unique_fd& operator = (unique_fd&& s) {
+  unique_fd& operator=(unique_fd&& s) {
     reset(s.release());
     return *this;
   }
 
   void reset(int new_value) {
-    if (value_ >= 0)
+    if (value_ != -1) {
+      // Even if close(2) fails with EINTR, the fd will have been closed.
+      // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone else's fd.
+      // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
       close(value_);
+    }
     value_ = new_value;
   }
 
@@ -60,8 +64,9 @@
   }
 
   int get() const { return value_; }
+  operator int() const { return get(); }
 
-  int release() {
+  int release() __attribute__((warn_unused_result)) {
     int ret = value_;
     value_ = -1;
     return ret;
@@ -76,4 +81,4 @@
 }  // namespace base
 }  // namespace android
 
-#endif // ANDROID_BASE_UNIQUE_FD_H
+#endif  // ANDROID_BASE_UNIQUE_FD_H
diff --git a/base/include/android-base/utf8.h b/base/include/android-base/utf8.h
index 3b0ed0a..2d5a6f6 100755
--- a/base/include/android-base/utf8.h
+++ b/base/include/android-base/utf8.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef BASE_UTF8_H
-#define BASE_UTF8_H
+#ifndef ANDROID_BASE_UTF8_H
+#define ANDROID_BASE_UTF8_H
 
 #ifdef _WIN32
 #include <string>
@@ -84,4 +84,4 @@
 }  // namespace base
 }  // namespace android
 
-#endif  // BASE_UTF8_H
+#endif  // ANDROID_BASE_UTF8_H
diff --git a/base/test_utils.cpp b/base/test_utils.cpp
index 337ba7c..635af6c 100644
--- a/base/test_utils.cpp
+++ b/base/test_utils.cpp
@@ -16,7 +16,6 @@
 
 #include "android-base/logging.h"
 #include "android-base/test_utils.h"
-#include "utils/Compat.h" // For OS_PATH_SEPARATOR.
 
 #include <fcntl.h>
 #include <stdio.h>
@@ -27,6 +26,9 @@
 #if defined(_WIN32)
 #include <windows.h>
 #include <direct.h>
+#define OS_PATH_SEPARATOR '\\'
+#else
+#define OS_PATH_SEPARATOR '/'
 #endif
 
 #include <string>
diff --git a/bootstat/boot_event_record_store_test.cpp b/bootstat/boot_event_record_store_test.cpp
index b7dd9ba..01c2cc1 100644
--- a/bootstat/boot_event_record_store_test.cpp
+++ b/bootstat/boot_event_record_store_test.cpp
@@ -41,7 +41,7 @@
 // the value of the record.
 bool CreateEmptyBootEventRecord(const std::string& record_path, int32_t value) {
   android::base::unique_fd record_fd(creat(record_path.c_str(), S_IRUSR | S_IWUSR));
-  if (record_fd.get() == -1) {
+  if (record_fd == -1) {
     return false;
   }
 
@@ -49,7 +49,7 @@
   // ensure the validity of the file mtime value, i.e., to check that the record
   // file mtime values are not changed once set.
   // TODO(jhawkins): Remove this block.
-  if (!android::base::WriteStringToFd(std::to_string(value), record_fd.get())) {
+  if (!android::base::WriteStringToFd(std::to_string(value), record_fd)) {
     return false;
   }
 
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 08fc5af..976ba66 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -48,6 +48,21 @@
   }
 }
 
+// Records the named boot |event| to the record store. If |value| is non-empty
+// and is a proper string representation of an integer value, the converted
+// integer value is associated with the boot event.
+void RecordBootEventFromCommandLine(
+    const std::string& event, const std::string& value_str) {
+  BootEventRecordStore boot_event_store;
+  if (!value_str.empty()) {
+    int32_t value = 0;
+    value = std::stoi(value_str);
+    boot_event_store.AddBootEventWithValue(event, value);
+  } else {
+    boot_event_store.AddBootEvent(event);
+  }
+}
+
 void PrintBootEvents() {
   printf("Boot events:\n");
   printf("------------\n");
@@ -67,6 +82,7 @@
           "  -l, --log             Log all metrics to logstorage\n"
           "  -p, --print           Dump the boot event records to the console\n"
           "  -r, --record          Record the timestamp of a named boot event\n"
+          "  --value               Optional value to associate with the boot event\n"
           "  --record_boot_reason  Record the reason why the device booted\n"
           "  --record_time_since_factory_reset Record the time since the device was reset\n");
 }
@@ -121,6 +137,30 @@
   {"Reboot", 18},
   {"rtc", 19},
   {"edl", 20},
+  {"oem_pon1", 21},
+  {"oem_powerkey", 22},
+  {"oem_unknown_reset", 23},
+  {"srto: HWWDT reset SC", 24},
+  {"srto: HWWDT reset platform", 25},
+  {"srto: bootloader", 26},
+  {"srto: kernel panic", 27},
+  {"srto: kernel watchdog reset", 28},
+  {"srto: normal", 29},
+  {"srto: reboot", 30},
+  {"srto: reboot-bootloader", 31},
+  {"srto: security watchdog reset", 32},
+  {"srto: wakesrc", 33},
+  {"srto: watchdog", 34},
+  {"srto:1-1", 35},
+  {"srto:omap_hsmm", 36},
+  {"srto:phy0", 37},
+  {"srto:rtc0", 38},
+  {"srto:touchpad", 39},
+  {"watchdog", 40},
+  {"watchdogr", 41},
+  {"wdog_bark", 42},
+  {"wdog_bite", 43},
+  {"wdog_reset", 44},
 };
 
 // Converts a string value representing the reason the system booted to an
@@ -266,6 +306,7 @@
   LOG(INFO) << "Service started: " << cmd_line;
 
   int option_index = 0;
+  static const char value_str[] = "value";
   static const char boot_complete_str[] = "record_boot_complete";
   static const char boot_reason_str[] = "record_boot_reason";
   static const char factory_reset_str[] = "record_time_since_factory_reset";
@@ -274,19 +315,26 @@
     { "log",             no_argument,       NULL,   'l' },
     { "print",           no_argument,       NULL,   'p' },
     { "record",          required_argument, NULL,   'r' },
+    { value_str,         required_argument, NULL,   0 },
     { boot_complete_str, no_argument,       NULL,   0 },
     { boot_reason_str,   no_argument,       NULL,   0 },
     { factory_reset_str, no_argument,       NULL,   0 },
     { NULL,              0,                 NULL,   0 }
   };
 
+  std::string boot_event;
+  std::string value;
   int opt = 0;
   while ((opt = getopt_long(argc, argv, "hlpr:", long_options, &option_index)) != -1) {
     switch (opt) {
       // This case handles long options which have no single-character mapping.
       case 0: {
         const std::string option_name = long_options[option_index].name;
-        if (option_name == boot_complete_str) {
+        if (option_name == value_str) {
+          // |optarg| is an external variable set by getopt representing
+          // the option argument.
+          value = optarg;
+        } else if (option_name == boot_complete_str) {
           RecordBootComplete();
         } else if (option_name == boot_reason_str) {
           RecordBootReason();
@@ -316,10 +364,7 @@
       case 'r': {
         // |optarg| is an external variable set by getopt representing
         // the option argument.
-        const char* event = optarg;
-
-        BootEventRecordStore boot_event_store;
-        boot_event_store.AddBootEvent(event);
+        boot_event = optarg;
         break;
       }
 
@@ -335,5 +380,9 @@
     }
   }
 
+  if (!boot_event.empty()) {
+    RecordBootEventFromCommandLine(boot_event, value);
+  }
+
   return 0;
 }
diff --git a/crash_reporter/crash_collector.cc b/crash_reporter/crash_collector.cc
index b3fdcb4..d993576 100644
--- a/crash_reporter/crash_collector.cc
+++ b/crash_reporter/crash_collector.cc
@@ -36,6 +36,7 @@
 #include <base/strings/string_util.h>
 #include <base/strings/stringprintf.h>
 #include <brillo/key_value_store.h>
+#include <brillo/osrelease_reader.h>
 #include <brillo/process.h>
 
 namespace {
@@ -52,6 +53,11 @@
 const char kUploadVarPrefix[] = "upload_var_";
 const char kUploadFilePrefix[] = "upload_file_";
 
+// Product information keys in the /etc/os-release.d folder.
+static const char kBdkVersionKey[] = "bdk_version";
+static const char kProductIDKey[] = "product_id";
+static const char kProductVersionKey[] = "product_version";
+
 // Normally this path is not used.  Unfortunately, there are a few edge cases
 // where we need this.  Any process that runs as kDefaultUserName that crashes
 // is consider a "user crash".  That includes the initial Chrome browser that
@@ -183,7 +189,7 @@
   return true;
 }
 
-bool CrashCollector::GetCreatedCrashDirectoryByEuid(uid_t euid,
+bool CrashCollector::GetCreatedCrashDirectoryByEuid(uid_t euid __unused,
                                                     FilePath *crash_directory,
                                                     bool *out_of_capacity) {
   if (out_of_capacity) *out_of_capacity = false;
@@ -384,14 +390,49 @@
                                         const std::string &payload_path) {
   int64_t payload_size = -1;
   base::GetFileSize(FilePath(payload_path), &payload_size);
+
+  brillo::OsReleaseReader reader;
+  if (!forced_osreleased_directory_.empty()) {
+    reader.LoadTestingOnly(forced_osreleased_directory_);
+  } else {
+    reader.Load();
+  }
+  std::string bdk_version = "undefined";
+  std::string product_id = "undefined";
+  std::string product_version = "undefined";
+
+  if (!reader.GetString(kBdkVersionKey, &bdk_version)) {
+    LOG(ERROR) << "Could not read " << kBdkVersionKey
+               << " from /etc/os-release.d/";
+  }
+
+  if (!reader.GetString(kProductIDKey, &product_id)) {
+    LOG(ERROR) << "Could not read " << kProductIDKey
+               << " from /etc/os-release.d/";
+  }
+
+  if (!reader.GetString(kProductVersionKey, &product_version)) {
+    LOG(ERROR) << "Could not read " << kProductVersionKey
+               << " from /etc/os-release.d/";
+  }
+
   std::string meta_data = StringPrintf("%sexec_name=%s\n"
                                        "payload=%s\n"
                                        "payload_size=%" PRId64 "\n"
+                                       "%s=%s\n"
+                                       "%s=%s\n"
+                                       "%s=%s\n"
                                        "done=1\n",
                                        extra_metadata_.c_str(),
                                        exec_name.c_str(),
                                        payload_path.c_str(),
-                                       payload_size);
+                                       payload_size,
+                                       kBdkVersionKey,
+                                       bdk_version.c_str(),
+                                       kProductIDKey,
+                                       product_id.c_str(),
+                                       kProductVersionKey,
+                                       product_version.c_str());
   // We must use WriteNewFile instead of base::WriteFile as we
   // do not want to write with root access to a symlink that an attacker
   // might have created.
diff --git a/crash_reporter/crash_collector.h b/crash_reporter/crash_collector.h
index 24cbfb3..21b9198 100644
--- a/crash_reporter/crash_collector.h
+++ b/crash_reporter/crash_collector.h
@@ -84,6 +84,12 @@
     forced_crash_directory_ = forced_directory;
   }
 
+  // For testing, set the root directory to read etc/os-release.d properties
+  // from.
+  void ForceOsReleaseDDirectory(const base::FilePath &forced_directory) {
+    forced_osreleased_directory_ = forced_directory;
+  }
+
   base::FilePath GetCrashDirectoryInfo(mode_t *mode,
                                        uid_t *directory_owner,
                                        gid_t *directory_group);
@@ -158,6 +164,7 @@
   IsFeedbackAllowedFunction is_feedback_allowed_function_;
   std::string extra_metadata_;
   base::FilePath forced_crash_directory_;
+  base::FilePath forced_osreleased_directory_;
   base::FilePath log_config_path_;
 
  private:
diff --git a/crash_reporter/crash_collector_test.cc b/crash_reporter/crash_collector_test.cc
index 11c8c0d..a386cd1 100644
--- a/crash_reporter/crash_collector_test.cc
+++ b/crash_reporter/crash_collector_test.cc
@@ -74,10 +74,11 @@
 TEST_F(CrashCollectorTest, WriteNewFile) {
   FilePath test_file = test_dir_.path().Append("test_new");
   const char kBuffer[] = "buffer";
-  EXPECT_EQ(strlen(kBuffer),
-            collector_.WriteNewFile(test_file,
-                                    kBuffer,
-                                    strlen(kBuffer)));
+  unsigned int numBytesWritten = collector_.WriteNewFile(
+      test_file,
+      kBuffer,
+      strlen(kBuffer));
+  EXPECT_EQ(strlen(kBuffer), numBytesWritten);
   EXPECT_LT(collector_.WriteNewFile(test_file,
                                     kBuffer,
                                     strlen(kBuffer)), 0);
@@ -94,7 +95,7 @@
 }
 
 TEST_F(CrashCollectorTest, FormatDumpBasename) {
-  struct tm tm = {0};
+  struct tm tm = {};
   tm.tm_sec = 15;
   tm.tm_min = 50;
   tm.tm_hour = 13;
@@ -182,9 +183,26 @@
   const char kMetaFileBasename[] = "generated.meta";
   FilePath meta_file = test_dir_.path().Append(kMetaFileBasename);
   FilePath payload_file = test_dir_.path().Append("payload-file");
+  FilePath osreleased_directory =
+      test_dir_.path().Append("etc").Append("os-release.d");
+  ASSERT_TRUE(base::CreateDirectory(osreleased_directory));
+  collector_.ForceOsReleaseDDirectory(test_dir_.path());
+
   std::string contents;
   const char kPayload[] = "foo";
   ASSERT_TRUE(base::WriteFile(payload_file, kPayload, strlen(kPayload)));
+  const char kBdkVersion[] = "1";
+  ASSERT_TRUE(base::WriteFile(osreleased_directory.Append("bdk_version"),
+                              kBdkVersion,
+                              strlen(kBdkVersion)));
+  const char kProductId[] = "baz";
+  ASSERT_TRUE(base::WriteFile(osreleased_directory.Append("product_id"),
+                              kProductId,
+                              strlen(kProductId)));
+  const char kProductVersion[] = "1.2.3.4";
+  ASSERT_TRUE(base::WriteFile(osreleased_directory.Append("product_version"),
+                              kProductVersion,
+                              strlen(kProductVersion)));
   collector_.AddCrashMetaData("foo", "bar");
   collector_.WriteCrashMetaData(meta_file, "kernel", payload_file.value());
   EXPECT_TRUE(base::ReadFileToString(meta_file, &contents));
@@ -193,6 +211,9 @@
           "exec_name=kernel\n"
           "payload=%s\n"
           "payload_size=3\n"
+          "bdk_version=1\n"
+          "product_id=baz\n"
+          "product_version=1.2.3.4\n"
           "done=1\n",
           test_dir_.path().Append("payload-file").value().c_str());
   EXPECT_EQ(kExpectedMeta, contents);
diff --git a/crash_reporter/kernel_collector_test.cc b/crash_reporter/kernel_collector_test.cc
index 015f624..60fd832 100644
--- a/crash_reporter/kernel_collector_test.cc
+++ b/crash_reporter/kernel_collector_test.cc
@@ -49,7 +49,9 @@
  protected:
   void WriteStringToFile(const FilePath &file_path,
                          const char *data) {
-    ASSERT_EQ(strlen(data), base::WriteFile(file_path, data, strlen(data)));
+    unsigned int numBytesWritten =
+        base::WriteFile(file_path, data, strlen(data));
+    ASSERT_EQ(strlen(data), numBytesWritten);
   }
 
   void SetUpSuccessfulCollect();
@@ -284,7 +286,7 @@
   size_t end_pos = filename.find_first_of("\n");
   ASSERT_NE(std::string::npos, end_pos);
   filename = filename.substr(0, end_pos);
-  ASSERT_EQ(0, filename.find(test_crash_directory().value()));
+  ASSERT_EQ(0U, filename.find(test_crash_directory().value()));
   ASSERT_TRUE(base::PathExists(FilePath(filename)));
   std::string contents;
   ASSERT_TRUE(base::ReadFileToString(FilePath(filename), &contents));
diff --git a/crash_reporter/unclean_shutdown_collector_test.cc b/crash_reporter/unclean_shutdown_collector_test.cc
index 56d2704..36372ae 100644
--- a/crash_reporter/unclean_shutdown_collector_test.cc
+++ b/crash_reporter/unclean_shutdown_collector_test.cc
@@ -73,7 +73,9 @@
  protected:
   void WriteStringToFile(const FilePath &file_path,
                          const char *data) {
-    ASSERT_EQ(strlen(data), base::WriteFile(file_path, data, strlen(data)));
+    unsigned int numBytesWritten =
+        base::WriteFile(file_path, data, strlen(data));
+    ASSERT_EQ(strlen(data), numBytesWritten);
   }
 
   UncleanShutdownCollectorMock collector_;
diff --git a/crash_reporter/user_collector.cc b/crash_reporter/user_collector.cc
index 98d7448..48b64e9 100644
--- a/crash_reporter/user_collector.cc
+++ b/crash_reporter/user_collector.cc
@@ -37,7 +37,6 @@
 #include <base/strings/string_split.h>
 #include <base/strings/string_util.h>
 #include <base/strings/stringprintf.h>
-#include <brillo/osrelease_reader.h>
 #include <brillo/process.h>
 #include <brillo/syslog_logging.h>
 #include <cutils/properties.h>
@@ -59,11 +58,6 @@
 const char *UserCollector::kUserId = "Uid:\t";
 const char *UserCollector::kGroupId = "Gid:\t";
 
-// Product information keys in the /etc/os-release.d folder.
-static const char kBdkVersionKey[] = "bdk_version";
-static const char kProductIDKey[] = "product_id";
-static const char kProductVersionKey[] = "product_version";
-
 
 using base::FilePath;
 using base::StringPrintf;
@@ -505,29 +499,6 @@
   if (GetLogContents(FilePath(log_config_path_), exec, log_path))
     AddCrashMetaData("log", log_path.value());
 
-  brillo::OsReleaseReader reader;
-  reader.Load();
-  std::string value = "undefined";
-  if (!reader.GetString(kBdkVersionKey, &value)) {
-    LOG(ERROR) << "Could not read " << kBdkVersionKey
-               << " from /etc/os-release.d/";
-  }
-  AddCrashMetaData(kBdkVersionKey, value);
-
-  value = "undefined";
-  if (!reader.GetString(kProductIDKey, &value)) {
-    LOG(ERROR) << "Could not read " << kProductIDKey
-               << " from /etc/os-release.d/";
-  }
-  AddCrashMetaData(kProductIDKey, value);
-
-  value = "undefined";
-  if (!reader.GetString(kProductVersionKey, &value)) {
-    LOG(ERROR) << "Could not read " << kProductVersionKey
-               << " from /etc/os-release.d/";
-  }
-  AddCrashMetaData(kProductVersionKey, value);
-
   ErrorType error_type =
       ConvertCoreToMinidump(pid, container_dir, core_path, minidump_path);
   if (error_type != kErrorNone) {
diff --git a/crash_reporter/user_collector_test.cc b/crash_reporter/user_collector_test.cc
index d9c9a5b..16a5cd5 100644
--- a/crash_reporter/user_collector_test.cc
+++ b/crash_reporter/user_collector_test.cc
@@ -101,15 +101,15 @@
       &pid, &signal, &uid, &gid, &exec_name));
   EXPECT_EQ(123456, pid);
   EXPECT_EQ(11, signal);
-  EXPECT_EQ(1000, uid);
-  EXPECT_EQ(2000, gid);
+  EXPECT_EQ(1000U, uid);
+  EXPECT_EQ(2000U, gid);
   EXPECT_EQ("foobar", exec_name);
   EXPECT_TRUE(collector_.ParseCrashAttributes("4321:6:barfoo",
       &pid, &signal, &uid, &gid, &exec_name));
   EXPECT_EQ(4321, pid);
   EXPECT_EQ(6, signal);
-  EXPECT_EQ(-1, uid);
-  EXPECT_EQ(-1, gid);
+  EXPECT_EQ(-1U, uid);
+  EXPECT_EQ(-1U, gid);
   EXPECT_EQ("barfoo", exec_name);
 
   EXPECT_FALSE(collector_.ParseCrashAttributes("123456:11",
@@ -186,10 +186,10 @@
         test_dir_.path().Append("test/this_link").value().c_str();
     this_link.assign(long_link.c_str(), len);
     ASSERT_EQ(len, this_link.size());
-    unlink(kLink);
     ASSERT_EQ(0, symlink(this_link.c_str(), kLink));
     ASSERT_TRUE(collector_.GetSymlinkTarget(FilePath(kLink), &result));
     ASSERT_EQ(this_link, result.value());
+    unlink(kLink);
   }
 }
 
@@ -333,8 +333,8 @@
   gid_t gid = 100;
   uid_t uid = 100;
   EXPECT_TRUE(collector_.GetUserInfoFromName("root", &uid, &gid));
-  EXPECT_EQ(0, uid);
-  EXPECT_EQ(0, gid);
+  EXPECT_EQ(0U, uid);
+  EXPECT_EQ(0U, gid);
 }
 
 TEST_F(UserCollectorTest, CopyOffProcFilesBadPath) {
@@ -387,7 +387,9 @@
 
   // maps file is not empty
   const char data[] = "test data";
-  ASSERT_EQ(sizeof(data), base::WriteFile(maps_file, data, sizeof(data)));
+  unsigned int numBytesWritten =
+      base::WriteFile(maps_file, data, sizeof(data));
+  ASSERT_EQ(sizeof(data), numBytesWritten);
   ASSERT_TRUE(base::PathExists(maps_file));
   EXPECT_TRUE(collector_.ValidateProcFiles(container_dir));
 }
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 12f507a..8a545a5 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -36,10 +36,10 @@
 
 #include <log/logger.h>
 
+#include <android-base/unique_fd.h>
 #include <cutils/debugger.h>
 #include <cutils/properties.h>
 #include <cutils/sockets.h>
-#include <nativehelper/ScopedFd.h>
 
 #include <linux/input.h>
 
@@ -643,7 +643,7 @@
 static void handle_request(int fd) {
   ALOGV("handle_request(%d)\n", fd);
 
-  ScopedFd closer(fd);
+  android::base::unique_fd closer(fd);
   debugger_request_t request;
   memset(&request, 0, sizeof(request));
   int status = read_request(fd, &request);
diff --git a/debuggerd/getevent.cpp b/debuggerd/getevent.cpp
index 751c4fb..e5acd17 100644
--- a/debuggerd/getevent.cpp
+++ b/debuggerd/getevent.cpp
@@ -26,6 +26,7 @@
 #include <sys/poll.h>
 #include <linux/input.h>
 #include <errno.h>
+#include <memory>
 #include <cutils/log.h>
 
 static struct pollfd* ufds;
@@ -143,22 +144,20 @@
 static int scan_dir(const char* dirname) {
   char devname[PATH_MAX];
   char* filename;
-  DIR* dir;
   struct dirent* de;
-  dir = opendir(dirname);
+  std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dirname), closedir);
   if (dir == NULL)
     return -1;
   strcpy(devname, dirname);
   filename = devname + strlen(devname);
   *filename++ = '/';
-  while ((de = readdir(dir))) {
+  while ((de = readdir(dir.get()))) {
     if ((de->d_name[0] == '.' && de->d_name[1] == '\0') ||
         (de->d_name[1] == '.' && de->d_name[2] == '\0'))
       continue;
     strcpy(filename, de->d_name);
     open_device(devname);
   }
-  closedir(dir);
   return 0;
 }
 
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 636092e..3f820b6 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -357,8 +357,8 @@
             "                                           formatting.\n"
             "  -s <specific device>                     Specify a device. For USB, provide either\n"
             "                                           a serial number or path to device port.\n"
-            "                                           For ethernet, provide an address in the"
-            "                                           form <protocol>:<hostname>[:port] where"
+            "                                           For ethernet, provide an address in the\n"
+            "                                           form <protocol>:<hostname>[:port] where\n"
             "                                           <protocol> is either tcp or udp.\n"
             "  -p <product>                             Specify product name.\n"
             "  -c <cmdline>                             Override kernel commandline.\n"
diff --git a/fastboot/usb_linux.cpp b/fastboot/usb_linux.cpp
index 02ffcd9..d4824fb 100644
--- a/fastboot/usb_linux.cpp
+++ b/fastboot/usb_linux.cpp
@@ -145,7 +145,7 @@
     int in, out;
     unsigned i;
     unsigned e;
-    
+
     if (check(ptr, len, USB_DT_DEVICE, USB_DT_DEVICE_SIZE))
         return -1;
     dev = (struct usb_device_descriptor *)ptr;
@@ -333,15 +333,14 @@
     char desc[1024];
     int n, in, out, ifc;
 
-    DIR *busdir;
     struct dirent *de;
     int fd;
     int writable;
 
-    busdir = opendir(base);
+    std::unique_ptr<DIR, decltype(&closedir)> busdir(opendir(base), closedir);
     if (busdir == 0) return 0;
 
-    while ((de = readdir(busdir)) && (usb == nullptr)) {
+    while ((de = readdir(busdir.get())) && (usb == nullptr)) {
         if (badname(de->d_name)) continue;
 
         if (!convert_to_devfs_name(de->d_name, devname, sizeof(devname))) {
@@ -377,7 +376,6 @@
             }
         }
     }
-    closedir(busdir);
 
     return usb;
 }
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 28fff3f..d0d5630 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -7,7 +7,7 @@
     libfec \
     libfec_rs \
     libbase \
-    libmincrypt \
+    libcrypto_utils_static \
     libcrypto_static \
     libext4_utils_static \
     libsquashfs_utils
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 70acd38..9fc5999 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -14,35 +14,32 @@
  * limitations under the License.
  */
 
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <ctype.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
-#include <errno.h>
+#include <sys/swap.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#include <libgen.h>
 #include <time.h>
-#include <sys/swap.h>
-#include <dirent.h>
-#include <ext4.h>
-#include <ext4_sb.h>
-#include <ext4_crypt_init_extensions.h>
+#include <unistd.h>
 
-#include <linux/loop.h>
-#include <private/android_filesystem_config.h>
+#include <ext4.h>
+#include <ext4_crypt_init_extensions.h>
+#include <ext4_sb.h>
+
 #include <cutils/android_reboot.h>
 #include <cutils/partition_utils.h>
 #include <cutils/properties.h>
+#include <linux/loop.h>
 #include <logwrap/logwrap.h>
-
-#include "mincrypt/rsa.h"
-#include "mincrypt/sha.h"
-#include "mincrypt/sha256.h"
+#include <private/android_filesystem_config.h>
 
 #include "ext4_utils.h"
 #include "wipe.h"
@@ -588,7 +585,7 @@
                   fstab->recs[top_idx].fs_type);
             if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
                 strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
-                int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY, 0644);
+                int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY);
                 if (fd >= 0) {
                     INFO("%s(): also wipe %s\n", __func__, fstab->recs[top_idx].key_loc);
                     wipe_block_device(fd, get_file_size(fd));
diff --git a/fs_mgr/fs_mgr_format.c b/fs_mgr/fs_mgr_format.c
index f8df081..0b52e00 100644
--- a/fs_mgr/fs_mgr_format.c
+++ b/fs_mgr/fs_mgr_format.c
@@ -33,15 +33,15 @@
 
 static int format_ext4(char *fs_blkdev, char *fs_mnt_point)
 {
-    unsigned int nr_sec;
+    uint64_t dev_sz;
     int fd, rc = 0;
 
-    if ((fd = open(fs_blkdev, O_WRONLY, 0644)) < 0) {
+    if ((fd = open(fs_blkdev, O_WRONLY)) < 0) {
         ERROR("Cannot open block device.  %s\n", strerror(errno));
         return -1;
     }
 
-    if ((ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
+    if ((ioctl(fd, BLKGETSIZE64, &dev_sz)) == -1) {
         ERROR("Cannot get block device size.  %s\n", strerror(errno));
         close(fd);
         return -1;
@@ -49,7 +49,7 @@
 
     /* Format the partition using the calculated length */
     reset_ext4fs_info();
-    info.len = ((off64_t)nr_sec * 512);
+    info.len = (off64_t)dev_sz;
 
     /* Use make_ext4fs_internal to avoid wiping an already-wiped partition. */
     rc = make_ext4fs_internal(fd, NULL, NULL, fs_mnt_point, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL);
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index b5141c9..129a5bb 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -14,29 +14,29 @@
  * limitations under the License.
  */
 
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <inttypes.h>
+#include <libgen.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <ctype.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
-#include <errno.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#include <libgen.h>
 #include <time.h>
+#include <unistd.h>
 
 #include <android-base/file.h>
-#include <private/android_filesystem_config.h>
+#include <crypto_utils/android_pubkey.h>
 #include <cutils/properties.h>
 #include <logwrap/logwrap.h>
-
-#include "mincrypt/rsa.h"
-#include "mincrypt/sha.h"
-#include "mincrypt/sha256.h"
+#include <openssl/obj_mac.h>
+#include <openssl/rsa.h>
+#include <openssl/sha.h>
+#include <private/android_filesystem_config.h>
 
 #include "fec/io.h"
 
@@ -83,48 +83,45 @@
 
 extern struct fs_info info;
 
-static RSAPublicKey *load_key(const char *path)
+static RSA *load_key(const char *path)
 {
-    RSAPublicKey* key = static_cast<RSAPublicKey*>(malloc(sizeof(RSAPublicKey)));
-    if (!key) {
-        ERROR("Can't malloc key\n");
-        return NULL;
-    }
+    uint8_t key_data[ANDROID_PUBKEY_ENCODED_SIZE];
 
     FILE* f = fopen(path, "r");
     if (!f) {
         ERROR("Can't open '%s'\n", path);
-        free(key);
+        free(key_data);
         return NULL;
     }
 
-    if (!fread(key, sizeof(*key), 1, f)) {
+    if (!fread(key_data, sizeof(key_data), 1, f)) {
         ERROR("Could not read key!\n");
         fclose(f);
-        free(key);
-        return NULL;
-    }
-
-    if (key->len != RSANUMWORDS) {
-        ERROR("Invalid key length %d\n", key->len);
-        fclose(f);
-        free(key);
+        free(key_data);
         return NULL;
     }
 
     fclose(f);
+
+    RSA* key = NULL;
+    if (!android_pubkey_decode(key_data, sizeof(key_data), &key)) {
+        ERROR("Could not parse key!\n");
+        free(key_data);
+        return NULL;
+    }
+
     return key;
 }
 
-static int verify_table(const uint8_t *signature, const char *table,
-        uint32_t table_length)
+static int verify_table(const uint8_t *signature, size_t signature_size,
+        const char *table, uint32_t table_length)
 {
-    RSAPublicKey *key;
-    uint8_t hash_buf[SHA256_DIGEST_SIZE];
+    RSA *key;
+    uint8_t hash_buf[SHA256_DIGEST_LENGTH];
     int retval = -1;
 
     // Hash the table
-    SHA256_hash((uint8_t*)table, table_length, hash_buf);
+    SHA256((uint8_t*)table, table_length, hash_buf);
 
     // Now get the public key from the keyfile
     key = load_key(VERITY_TABLE_RSA_KEY);
@@ -134,11 +131,8 @@
     }
 
     // verify the result
-    if (!RSA_verify(key,
-                    signature,
-                    RSANUMBYTES,
-                    (uint8_t*) hash_buf,
-                    SHA256_DIGEST_SIZE)) {
+    if (!RSA_verify(NID_sha256, hash_buf, sizeof(hash_buf), signature,
+                    signature_size, key)) {
         ERROR("Couldn't verify table\n");
         goto out;
     }
@@ -146,7 +140,7 @@
     retval = 0;
 
 out:
-    free(key);
+    RSA_free(key);
     return retval;
 }
 
@@ -610,8 +604,8 @@
     off64_t offset = 0;
     struct fec_handle *f = NULL;
     struct fec_verity_metadata verity;
-    uint8_t curr[SHA256_DIGEST_SIZE];
-    uint8_t prev[SHA256_DIGEST_SIZE];
+    uint8_t curr[SHA256_DIGEST_LENGTH];
+    uint8_t prev[SHA256_DIGEST_LENGTH];
 
     *match = 1;
 
@@ -629,7 +623,7 @@
         goto out;
     }
 
-    SHA256_hash(verity.signature, RSANUMBYTES, curr);
+    SHA256(verity.signature, sizeof(verity.signature), curr);
 
     if (snprintf(tag, sizeof(tag), VERITY_LASTSIG_TAG "_%s",
             basename(fstab->mount_point)) >= (int)sizeof(tag)) {
@@ -637,7 +631,7 @@
         goto out;
     }
 
-    if (metadata_find(fstab->verity_loc, tag, SHA256_DIGEST_SIZE,
+    if (metadata_find(fstab->verity_loc, tag, SHA256_DIGEST_LENGTH,
             &offset) < 0) {
         goto out;
     }
@@ -656,7 +650,7 @@
         goto out;
     }
 
-    *match = !memcmp(curr, prev, SHA256_DIGEST_SIZE);
+    *match = !memcmp(curr, prev, SHA256_DIGEST_LENGTH);
 
     if (!*match) {
         /* update current signature hash */
@@ -919,7 +913,7 @@
     }
 
     // verify the signature on the table
-    if (verify_table(verity.signature, verity.table,
+    if (verify_table(verity.signature, sizeof(verity.signature), verity.table,
             verity.table_length) < 0) {
         if (params.mode == VERITY_MODE_LOGGING) {
             // the user has been warned, allow mounting without dm-verity
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index b4fdab0..7254cf2 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -76,7 +76,7 @@
 
     void store_sid(uint32_t uid, uint64_t sid) {
         char filename[21];
-        sprintf(filename, "%u", uid);
+        snprintf(filename, sizeof(filename), "%u", uid);
         int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
         if (fd < 0) {
             ALOGE("could not open file: %s: %s", filename, strerror(errno));
@@ -102,7 +102,7 @@
 
     void maybe_store_sid(uint32_t uid, uint64_t sid) {
         char filename[21];
-        sprintf(filename, "%u", uid);
+        snprintf(filename, sizeof(filename), "%u", uid);
         if (access(filename, F_OK) == -1) {
             store_sid(uid, sid);
         }
@@ -111,7 +111,7 @@
     uint64_t read_sid(uint32_t uid) {
         char filename[21];
         uint64_t sid;
-        sprintf(filename, "%u", uid);
+        snprintf(filename, sizeof(filename), "%u", uid);
         int fd = open(filename, O_RDONLY);
         if (fd < 0) return 0;
         read(fd, &sid, sizeof(sid));
@@ -121,7 +121,7 @@
 
     void clear_sid(uint32_t uid) {
         char filename[21];
-        sprintf(filename, "%u", uid);
+        snprintf(filename, sizeof(filename), "%u", uid);
         if (remove(filename) < 0) {
             ALOGE("%s: could not remove file [%s], attempting 0 write", __func__, strerror(errno));
             store_sid(uid, 0);
diff --git a/healthd/Android.mk b/healthd/Android.mk
index a4469fc..d866887 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -8,6 +8,7 @@
 LOCAL_CFLAGS := -Werror
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_STATIC_LIBRARIES := libbinder
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
@@ -15,17 +16,27 @@
 LOCAL_MODULE := libbatterymonitor
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES := libutils
+LOCAL_STATIC_LIBRARIES := libutils libbinder
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
 
+ifeq ($(strip $(BOARD_CHARGER_NO_UI)),true)
+LOCAL_CHARGER_NO_UI := true
+endif
+ifdef BRILLO
+LOCAL_CHARGER_NO_UI := true
+endif
+
 LOCAL_SRC_FILES := \
 	healthd.cpp \
 	healthd_mode_android.cpp \
-	healthd_mode_charger.cpp \
 	BatteryPropertiesRegistrar.cpp
 
+ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true)
+LOCAL_SRC_FILES += healthd_mode_charger.cpp
+endif
+
 LOCAL_MODULE := healthd
 LOCAL_MODULE_TAGS := optional
 LOCAL_FORCE_STATIC_EXECUTABLE := true
@@ -42,9 +53,19 @@
 LOCAL_CFLAGS += -DCHARGER_ENABLE_SUSPEND
 endif
 
-LOCAL_C_INCLUDES := bootable/recovery
+ifeq ($(strip $(LOCAL_CHARGER_NO_UI)),true)
+LOCAL_CFLAGS += -DCHARGER_NO_UI
+endif
 
-LOCAL_STATIC_LIBRARIES := libbatterymonitor libbatteryservice libbinder libminui libpng libz libutils libcutils liblog libm libc
+LOCAL_C_INCLUDES := bootable/recovery $(LOCAL_PATH)/include
+
+LOCAL_STATIC_LIBRARIES := libbatterymonitor libbatteryservice libbinder
+
+ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true)
+LOCAL_STATIC_LIBRARIES += libminui libpng libz
+endif
+
+LOCAL_STATIC_LIBRARIES += libutils libcutils liblog libm libc
 
 ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
 LOCAL_STATIC_LIBRARIES += libsuspend
@@ -59,6 +80,7 @@
 include $(BUILD_EXECUTABLE)
 
 
+ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true)
 define _add-charger-image
 include $$(CLEAR_VARS)
 LOCAL_MODULE := system_core_charger_$(notdir $(1))
@@ -84,3 +106,4 @@
 
 _add-charger-image :=
 _img_modules :=
+endif # LOCAL_CHARGER_NO_UI
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index a8646c5..d287d10 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <memory>
 
 #include <batteryservice/BatteryService.h>
 #include <cutils/klog.h>
@@ -342,11 +343,10 @@
                                 " cc=%d", props.batteryCycleCount);
             }
         } else {
-            snprintf(dmesgline, sizeof(dmesgline),
+            len = snprintf(dmesgline, sizeof(dmesgline),
                  "battery none");
         }
 
-        len = strlen(dmesgline);
         snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
                  props.chargerAcOnline ? "a" : "",
                  props.chargerUsbOnline ? "u" : "",
@@ -488,13 +488,13 @@
     char pval[PROPERTY_VALUE_MAX];
 
     mHealthdConfig = hc;
-    DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH);
+    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(POWER_SUPPLY_SYSFS_PATH), closedir);
     if (dir == NULL) {
         KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH);
     } else {
         struct dirent* entry;
 
-        while ((entry = readdir(dir))) {
+        while ((entry = readdir(dir.get()))) {
             const char* name = entry->d_name;
 
             if (!strcmp(name, ".") || !strcmp(name, ".."))
@@ -632,22 +632,17 @@
                 break;
             }
         }
-        closedir(dir);
     }
 
-    // This indicates that there is no charger driver registered.
     // Typically the case for devices which do not have a battery and
     // and are always plugged into AC mains.
-    if (!mChargerNames.size()) {
-        KLOG_ERROR(LOG_TAG, "No charger supplies found\n");
-        mBatteryFixedCapacity = ALWAYS_PLUGGED_CAPACITY;
-        mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
-        mAlwaysPluggedDevice = true;
-    }
     if (!mBatteryDevicePresent) {
         KLOG_WARNING(LOG_TAG, "No battery devices found\n");
         hc->periodic_chores_interval_fast = -1;
         hc->periodic_chores_interval_slow = -1;
+        mBatteryFixedCapacity = ALWAYS_PLUGGED_CAPACITY;
+        mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE;
+        mAlwaysPluggedDevice = true;
     } else {
         if (mHealthdConfig->batteryStatusPath.isEmpty())
             KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n");
diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp
index d9ac356..20a6bf6 100644
--- a/healthd/healthd.cpp
+++ b/healthd/healthd.cpp
@@ -109,10 +109,17 @@
 };
 
 static struct healthd_mode_ops charger_ops = {
+#ifdef CHARGER_NO_UI
+    .init = healthd_mode_nop_init,
+    .preparetowait = healthd_mode_nop_preparetowait,
+    .heartbeat = healthd_mode_nop_heartbeat,
+    .battery_update = healthd_mode_nop_battery_update,
+#else
     .init = healthd_mode_charger_init,
     .preparetowait = healthd_mode_charger_preparetowait,
     .heartbeat = healthd_mode_charger_heartbeat,
     .battery_update = healthd_mode_charger_battery_update,
+#endif
 };
 
 static struct healthd_mode_ops recovery_ops = {
diff --git a/include/binderwrapper/binder_wrapper.h b/include/binderwrapper/binder_wrapper.h
index ccda825..a104bff 100644
--- a/include/binderwrapper/binder_wrapper.h
+++ b/include/binderwrapper/binder_wrapper.h
@@ -70,7 +70,7 @@
   // is currently registered for |binder|, it will be replaced.
   virtual bool RegisterForDeathNotifications(
       const sp<IBinder>& binder,
-      const base::Closure& callback) = 0;
+      const ::base::Closure& callback) = 0;
 
   // Unregisters the callback, if any, for |binder|.
   virtual bool UnregisterForDeathNotifications(const sp<IBinder>& binder) = 0;
diff --git a/include/binderwrapper/stub_binder_wrapper.h b/include/binderwrapper/stub_binder_wrapper.h
index 01c9648..9d4578e 100644
--- a/include/binderwrapper/stub_binder_wrapper.h
+++ b/include/binderwrapper/stub_binder_wrapper.h
@@ -98,7 +98,7 @@
                        const sp<IBinder>& binder) override;
   sp<BBinder> CreateLocalBinder() override;
   bool RegisterForDeathNotifications(const sp<IBinder>& binder,
-                                     const base::Closure& callback) override;
+                                     const ::base::Closure& callback) override;
   bool UnregisterForDeathNotifications(const sp<IBinder>& binder) override;
   uid_t GetCallingUid() override;
   pid_t GetCallingPid() override;
@@ -119,7 +119,7 @@
 
   // Map from binder handle to the callback that should be invoked on binder
   // death.
-  std::map<sp<IBinder>, base::Closure> death_callbacks_;
+  std::map<sp<IBinder>, ::base::Closure> death_callbacks_;
 
   // Values to return from GetCallingUid() and GetCallingPid();
   uid_t calling_uid_;
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index c220a0c..e540de2 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -89,6 +89,10 @@
 #define AID_DEBUGGERD     1045  /* debuggerd unprivileged user */
 #define AID_MEDIA_CODEC   1046  /* mediacodec process */
 #define AID_CAMERASERVER  1047  /* cameraserver process */
+#define AID_FIREWALL      1048  /* firewalld process */
+#define AID_TRUNKS        1049  /* trunksd process (TPM daemon) */
+#define AID_NVRAM         1050  /* Access-controlled NVRAM */
+/* Changes to this file must be made in AOSP, *not* in internal branches. */
 
 #define AID_SHELL         2000  /* adb and debug shell user */
 #define AID_CACHE         2001  /* cache access */
@@ -196,6 +200,9 @@
     { "debuggerd",     AID_DEBUGGERD, },
     { "mediacodec",    AID_MEDIA_CODEC, },
     { "cameraserver",  AID_CAMERASERVER, },
+    { "firewall",      AID_FIREWALL, },
+    { "trunks",        AID_TRUNKS, },
+    { "nvram",         AID_NVRAM, },
 
     { "shell",         AID_SHELL, },
     { "cache",         AID_CACHE, },
diff --git a/include/utils/Condition.h b/include/utils/Condition.h
index 5a72519..a420185 100644
--- a/include/utils/Condition.h
+++ b/include/utils/Condition.h
@@ -106,30 +106,40 @@
     return -pthread_cond_wait(&mCond, &mutex.mMutex);
 }
 inline status_t Condition::waitRelative(Mutex& mutex, nsecs_t reltime) {
-#if defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE)
-    struct timespec ts;
-    ts.tv_sec  = reltime/1000000000;
-    ts.tv_nsec = reltime%1000000000;
-    return -pthread_cond_timedwait_relative_np(&mCond, &mutex.mMutex, &ts);
-#else // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
     struct timespec ts;
 #if defined(__linux__)
     clock_gettime(CLOCK_REALTIME, &ts);
 #else // __APPLE__
-    // we don't support the clocks here.
+    // Apple doesn't support POSIX clocks.
     struct timeval t;
     gettimeofday(&t, NULL);
     ts.tv_sec = t.tv_sec;
-    ts.tv_nsec= t.tv_usec*1000;
+    ts.tv_nsec = t.tv_usec*1000;
 #endif
-    ts.tv_sec += reltime/1000000000;
-    ts.tv_nsec+= reltime%1000000000;
-    if (ts.tv_nsec >= 1000000000) {
+
+    // On 32-bit devices, tv_sec is 32-bit, but `reltime` is 64-bit.
+    int64_t reltime_sec = reltime/1000000000;
+
+    ts.tv_nsec += reltime%1000000000;
+    if (reltime_sec < INT64_MAX && ts.tv_nsec >= 1000000000) {
         ts.tv_nsec -= 1000000000;
-        ts.tv_sec  += 1;
+        ++reltime_sec;
     }
+
+    int64_t time_sec = ts.tv_sec;
+    if (time_sec > INT64_MAX - reltime_sec) {
+        time_sec = INT64_MAX;
+    } else {
+        time_sec += reltime_sec;
+    }
+
+#if defined(__LP64__)
+    ts.tv_sec = time_sec;
+#else
+    ts.tv_sec = (time_sec > INT32_MAX) ? INT32_MAX : time_sec;
+#endif
+
     return -pthread_cond_timedwait(&mCond, &mutex.mMutex, &ts);
-#endif // HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
 }
 inline void Condition::signal() {
     /*
diff --git a/include/utils/String16.h b/include/utils/String16.h
index 9a67c7a..4a5874a 100644
--- a/include/utils/String16.h
+++ b/include/utils/String16.h
@@ -17,8 +17,10 @@
 #ifndef ANDROID_STRING16_H
 #define ANDROID_STRING16_H
 
+#include <string> // for std::string
+
 #include <utils/Errors.h>
-#include <utils/Unicode.h>
+#include <utils/String8.h>
 #include <utils/TypeHelpers.h>
 
 // ---------------------------------------------------------------------------
@@ -62,9 +64,10 @@
     explicit                    String16(const char* o, size_t len);
 
                                 ~String16();
-    
+
     inline  const char16_t*     string() const;
-    
+
+    static inline std::string   std_string(const String16& str);
             size_t              size() const;
             void                setTo(const String16& other);
             status_t            setTo(const char16_t* other);
@@ -72,12 +75,12 @@
             status_t            setTo(const String16& other,
                                       size_t len,
                                       size_t begin=0);
-    
+
             status_t            append(const String16& other);
             status_t            append(const char16_t* other, size_t len);
-            
+
     inline  String16&           operator=(const String16& other);
-    
+
     inline  String16&           operator+=(const String16& other);
     inline  String16            operator+(const String16& other) const;
 
@@ -90,7 +93,7 @@
 
             bool                startsWith(const String16& prefix) const;
             bool                startsWith(const char16_t* prefix) const;
-            
+
             status_t            makeLower();
 
             status_t            replaceAll(char16_t replaceThis,
@@ -106,16 +109,16 @@
     inline  bool                operator!=(const String16& other) const;
     inline  bool                operator>=(const String16& other) const;
     inline  bool                operator>(const String16& other) const;
-    
+
     inline  bool                operator<(const char16_t* other) const;
     inline  bool                operator<=(const char16_t* other) const;
     inline  bool                operator==(const char16_t* other) const;
     inline  bool                operator!=(const char16_t* other) const;
     inline  bool                operator>=(const char16_t* other) const;
     inline  bool                operator>(const char16_t* other) const;
-    
+
     inline                      operator const char16_t*() const;
-    
+
 private:
             const char16_t*     mString;
 };
@@ -142,6 +145,11 @@
     return mString;
 }
 
+inline std::string String16::std_string(const String16& str)
+{
+    return std::string(String8(str).string());
+}
+
 inline String16& String16::operator=(const String16& other)
 {
     setTo(other);
diff --git a/include/utils/String8.h b/include/utils/String8.h
index 2a75b98..1d12994 100644
--- a/include/utils/String8.h
+++ b/include/utils/String8.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_STRING8_H
 #define ANDROID_STRING8_H
 
+#include <string> // for std::string
+
 #include <utils/Errors.h>
 #include <utils/Unicode.h>
 #include <utils/TypeHelpers.h>
@@ -49,7 +51,7 @@
                                 String8(const String8& o);
     explicit                    String8(const char* o);
     explicit                    String8(const char* o, size_t numChars);
-    
+
     explicit                    String8(const String16& o);
     explicit                    String8(const char16_t* o);
     explicit                    String8(const char16_t* o, size_t numChars);
@@ -63,12 +65,13 @@
     static String8              formatV(const char* fmt, va_list args);
 
     inline  const char*         string() const;
+    static inline std::string   std_string(const String8& str);
     inline  size_t              size() const;
     inline  size_t              bytes() const;
     inline  bool                isEmpty() const;
-    
+
             size_t              length() const;
-    
+
             void                clear();
 
             void                setTo(const String8& other);
@@ -95,10 +98,10 @@
 
     inline  String8&            operator=(const String8& other);
     inline  String8&            operator=(const char* other);
-    
+
     inline  String8&            operator+=(const String8& other);
     inline  String8             operator+(const String8& other) const;
-    
+
     inline  String8&            operator+=(const char* other);
     inline  String8             operator+(const char* other) const;
 
@@ -110,20 +113,20 @@
     inline  bool                operator!=(const String8& other) const;
     inline  bool                operator>=(const String8& other) const;
     inline  bool                operator>(const String8& other) const;
-    
+
     inline  bool                operator<(const char* other) const;
     inline  bool                operator<=(const char* other) const;
     inline  bool                operator==(const char* other) const;
     inline  bool                operator!=(const char* other) const;
     inline  bool                operator>=(const char* other) const;
     inline  bool                operator>(const char* other) const;
-    
+
     inline                      operator const char*() const;
-    
+
             char*               lockBuffer(size_t size);
             void                unlockBuffer();
             status_t            unlockBuffer(size_t size);
-            
+
             // return the index of the first byte of other in this at or after
             // start, or -1 if not found
             ssize_t             find(const char* other, size_t start = 0) const;
@@ -261,6 +264,11 @@
     return mString;
 }
 
+inline std::string String8::std_string(const String8& str)
+{
+    return std::string(str.string());
+}
+
 inline size_t String8::size() const
 {
     return length();
diff --git a/init/Android.mk b/init/Android.mk
index 4827fa3..2525b00 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -96,7 +96,7 @@
     libc \
     libselinux \
     liblog \
-    libmincrypt \
+    libcrypto_utils_static \
     libcrypto_static \
     libc++_static \
     libdl \
diff --git a/init/builtins.cpp b/init/builtins.cpp
index c8780bb..66133fb 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -29,6 +29,7 @@
 #include <sys/socket.h>
 #include <sys/mount.h>
 #include <sys/resource.h>
+#include <sys/syscall.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -48,7 +49,6 @@
 #include <cutils/partition_utils.h>
 #include <cutils/android_reboot.h>
 #include <logwrap/logwrap.h>
-#include <private/android_filesystem_config.h>
 
 #include "action.h"
 #include "bootchart.h"
@@ -65,19 +65,20 @@
 #define UNMOUNT_CHECK_MS 5000
 #define UNMOUNT_CHECK_TIMES 10
 
-// System call provided by bionic but not in any header file.
-extern "C" int init_module(void *, unsigned long, const char *);
-
 static const int kTerminateServiceDelayMicroSeconds = 50000;
 
 static int insmod(const char *filename, const char *options) {
-    std::string module;
-    if (!read_file(filename, &module)) {
+    int fd = open(filename, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+    if (fd == -1) {
+        ERROR("insmod: open(\"%s\") failed: %s", filename, strerror(errno));
         return -1;
     }
-
-    // TODO: use finit_module for >= 3.8 kernels.
-    return init_module(&module[0], module.size(), options);
+    int rc = syscall(__NR_finit_module, fd, options, 0);
+    if (rc == -1) {
+        ERROR("finit_module for \"%s\" failed: %s", filename, strerror(errno));
+    }
+    close(fd);
+    return rc;
 }
 
 static int __ifupdown(const char *interface, int up) {
diff --git a/init/devices.cpp b/init/devices.cpp
index 39cd706..e74140b 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -31,6 +31,8 @@
 #include <sys/un.h>
 #include <linux/netlink.h>
 
+#include <memory>
+
 #include <selinux/selinux.h>
 #include <selinux/label.h>
 #include <selinux/android.h>
@@ -411,7 +413,7 @@
 static char **get_character_device_symlinks(struct uevent *uevent)
 {
     const char *parent;
-    char *slash;
+    const char *slash;
     char **links;
     int link_num = 0;
     int width;
@@ -465,7 +467,7 @@
 {
     const char *device;
     struct platform_node *pdev;
-    char *slash;
+    const char *slash;
     const char *type;
     char buf[256];
     char link_path[256];
@@ -957,10 +959,9 @@
 
 static void coldboot(const char *path)
 {
-    DIR *d = opendir(path);
+    std::unique_ptr<DIR, decltype(&closedir)> d(opendir(path), closedir);
     if(d) {
-        do_coldboot(d);
-        closedir(d);
+        do_coldboot(d.get());
     }
 }
 
diff --git a/init/init.cpp b/init/init.cpp
index 84da2b9..78c33d5 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -18,7 +18,6 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <fstream>
 #include <libgen.h>
 #include <paths.h>
 #include <signal.h>
@@ -75,8 +74,7 @@
 
 static char qemu[32];
 
-int have_console;
-std::string console_name = "/dev/console";
+std::string default_console = "/dev/console";
 static time_t process_needs_restart;
 
 const char *ENV[32];
@@ -251,100 +249,6 @@
     return result;
 }
 
-static void security_failure() {
-    ERROR("Security failure; rebooting into recovery mode...\n");
-    android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
-    while (true) { pause(); }  // never reached
-}
-
-#define MMAP_RND_PATH "/proc/sys/vm/mmap_rnd_bits"
-#define MMAP_RND_COMPAT_PATH "/proc/sys/vm/mmap_rnd_compat_bits"
-
-/* __attribute__((unused)) due to lack of mips support: see mips block
- * in set_mmap_rnd_bits_action */
-static bool __attribute__((unused)) set_mmap_rnd_bits_min(int start, int min, bool compat) {
-    std::string path;
-    if (compat) {
-        path = MMAP_RND_COMPAT_PATH;
-    } else {
-        path = MMAP_RND_PATH;
-    }
-    std::ifstream inf(path, std::fstream::in);
-    if (!inf) {
-        return false;
-    }
-    while (start >= min) {
-        // try to write out new value
-        std::string str_val = std::to_string(start);
-        std::ofstream of(path, std::fstream::out);
-        if (!of) {
-            return false;
-        }
-        of << str_val << std::endl;
-        of.close();
-
-        // check to make sure it was recorded
-        inf.seekg(0);
-        std::string str_rec;
-        inf >> str_rec;
-        if (str_val.compare(str_rec) == 0) {
-            break;
-        }
-        start--;
-    }
-    inf.close();
-    return (start >= min);
-}
-
-/*
- * Set /proc/sys/vm/mmap_rnd_bits and potentially
- * /proc/sys/vm/mmap_rnd_compat_bits to the maximum supported values.
- * Returns -1 if unable to set these to an acceptable value.  Apply
- * upstream patch-sets https://lkml.org/lkml/2015/12/21/337 and
- * https://lkml.org/lkml/2016/2/4/831 to enable this.
- */
-static int set_mmap_rnd_bits_action(const std::vector<std::string>& args)
-{
-    int ret = -1;
-
-    /* values are arch-dependent */
-#if defined(__aarch64__)
-    /* arm64 supports 18 - 33 bits depending on pagesize and VA_SIZE */
-    if (set_mmap_rnd_bits_min(33, 24, false)
-            && set_mmap_rnd_bits_min(16, 16, true)) {
-        ret = 0;
-    }
-#elif defined(__x86_64__)
-    /* x86_64 supports 28 - 32 bits */
-    if (set_mmap_rnd_bits_min(32, 32, false)
-            && set_mmap_rnd_bits_min(16, 16, true)) {
-        ret = 0;
-    }
-#elif defined(__arm__) || defined(__i386__)
-    /* check to see if we're running on 64-bit kernel */
-    bool h64 = !access(MMAP_RND_COMPAT_PATH, F_OK);
-    /* supported 32-bit architecture must have 16 bits set */
-    if (set_mmap_rnd_bits_min(16, 16, h64)) {
-        ret = 0;
-    }
-#elif defined(__mips__) || defined(__mips64__)
-    // TODO: add mips support b/27788820
-    ret = 0;
-#else
-    ERROR("Unknown architecture\n");
-#endif
-
-#ifdef __BRILLO__
-    // TODO: b/27794137
-    ret = 0;
-#endif
-    if (ret == -1) {
-        ERROR("Unable to set adequate mmap entropy value!\n");
-        security_failure();
-    }
-    return ret;
-}
-
 static int keychord_init_action(const std::vector<std::string>& args)
 {
     keychord_init();
@@ -355,36 +259,8 @@
 {
     std::string console = property_get("ro.boot.console");
     if (!console.empty()) {
-        console_name = "/dev/" + console;
+        default_console = "/dev/" + console;
     }
-
-    int fd = open(console_name.c_str(), O_RDWR | O_CLOEXEC);
-    if (fd >= 0)
-        have_console = 1;
-    close(fd);
-
-    fd = open("/dev/tty0", O_WRONLY | O_CLOEXEC);
-    if (fd >= 0) {
-        const char *msg;
-            msg = "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"  // console is 40 cols x 30 lines
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "\n"
-        "             A N D R O I D ";
-        write(fd, msg, strlen(msg));
-        close(fd);
-    }
-
     return 0;
 }
 
@@ -515,24 +391,6 @@
     return true;
 }
 
-int selinux_reload_policy(void)
-{
-    INFO("SELinux: Attempting to reload policy files\n");
-
-    if (selinux_android_reload_policy() == -1) {
-        return -1;
-    }
-
-    if (sehandle)
-        selabel_close(sehandle);
-
-    if (sehandle_prop)
-        selabel_close(sehandle_prop);
-
-    selinux_init_all_handles();
-    return 0;
-}
-
 static int audit_callback(void *data, security_class_t /*cls*/, char *buf, size_t len) {
 
     property_audit_data *d = reinterpret_cast<property_audit_data*>(data);
@@ -547,6 +405,12 @@
     return 0;
 }
 
+static void security_failure() {
+    ERROR("Security failure; rebooting into recovery mode...\n");
+    android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
+    while (true) { pause(); }  // never reached
+}
+
 static void selinux_initialize(bool in_kernel_domain) {
     Timer t;
 
@@ -610,6 +474,7 @@
         #define MAKE_STR(x) __STRING(x)
         mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
         mount("sysfs", "/sys", "sysfs", 0, NULL);
+        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
     }
 
     // We must have some place other than / to create the device nodes for
@@ -695,7 +560,6 @@
     am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
     // ... so that we can start queuing up actions that require stuff from /dev.
     am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
-    am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
     am.QueueBuiltinAction(keychord_init_action, "keychord_init");
     am.QueueBuiltinAction(console_init_action, "console_init");
 
diff --git a/init/init.h b/init/init.h
index 345d442..0019337 100644
--- a/init/init.h
+++ b/init/init.h
@@ -26,8 +26,7 @@
 
 extern const char *ENV[32];
 extern bool waiting_for_exec;
-extern int have_console;
-extern std::string console_name;
+extern std::string default_console;
 extern struct selabel_handle *sehandle;
 extern struct selabel_handle *sehandle_prop;
 
@@ -35,8 +34,6 @@
 
 void property_changed(const char *name, const char *value);
 
-int selinux_reload_policy(void);
-
 void register_epoll_handler(int fd, void (*fn)());
 
 int add_environment(const char* key, const char* val);
diff --git a/init/parser.cpp b/init/parser.cpp
index 8193729..ae103ec 100644
--- a/init/parser.cpp
+++ b/init/parser.cpp
@@ -12,7 +12,7 @@
     char buf[128];
     int off;
 
-    snprintf(buf, 128, "%s: %d: ", state->filename, state->line);
+    snprintf(buf, sizeof(buf), "%s: %d: ", state->filename, state->line);
     buf[127] = 0;
     off = strlen(buf);
 
diff --git a/init/perfboot.py b/init/perfboot.py
index 91e6c2b..713290b 100755
--- a/init/perfboot.py
+++ b/init/perfboot.py
@@ -191,9 +191,9 @@
 
 def init_perf(device, output, record_list, tags):
     device.wait()
-    build_type = device.get_prop('ro.build.type')
+    debuggable = device.get_prop('ro.debuggable')
     original_dropbox_max_files = None
-    if build_type != 'user':
+    if debuggable == '1':
         # Workaround for Dropbox issue (http://b/20890386).
         original_dropbox_max_files = disable_dropbox(device)
 
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 5c1ae79..c617dc6 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -41,7 +41,6 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <sys/mman.h>
-#include <private/android_filesystem_config.h>
 
 #include <selinux/selinux.h>
 #include <selinux/label.h>
@@ -175,11 +174,7 @@
     if (!is_legal_property_name(name, namelen)) return -1;
     if (valuelen >= PROP_VALUE_MAX) return -1;
 
-    if (strcmp("selinux.reload_policy", name) == 0 && strcmp("1", value) == 0) {
-        if (selinux_reload_policy() != 0) {
-            ERROR("Failed to reload policy\n");
-        }
-    } else if (strcmp("selinux.restorecon_recursive", name) == 0 && valuelen > 0) {
+    if (strcmp("selinux.restorecon_recursive", name) == 0 && valuelen > 0) {
         if (restorecon_recursive(value) != 0) {
             ERROR("Failed to restorecon_recursive %s\n", value);
         }
diff --git a/init/readme.txt b/init/readme.txt
index ef85ccf..aa372eb 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -115,6 +115,13 @@
 Options are modifiers to services.  They affect how and when init
 runs the service.
 
+console [<console>]
+  This service needs a console. The optional second parameter chooses a
+  specific console instead of the default. The default "/dev/console" can
+  be changed by setting the "androidboot.console" kernel parameter. In
+  all cases the leading "/dev/" should be omitted, so "/dev/tty0" would be
+  specified as just "console tty0".
+
 critical
   This is a device-critical service. If it exits more than four times in
   four minutes, the device will reboot into recovery mode.
diff --git a/init/service.cpp b/init/service.cpp
index f1ffa18..f5b8b00 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -172,6 +172,7 @@
 
 bool Service::HandleConsole(const std::vector<std::string>& args, std::string* err) {
     flags_ |= SVC_CONSOLE;
+    console_ = args.size() > 1 ? "/dev/" + args[1] : "";
     return true;
 }
 
@@ -282,7 +283,7 @@
     constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
     static const Map option_handlers = {
         {"class",       {1,     1,    &Service::HandleClass}},
-        {"console",     {0,     0,    &Service::HandleConsole}},
+        {"console",     {0,     1,    &Service::HandleConsole}},
         {"critical",    {0,     0,    &Service::HandleCritical}},
         {"disabled",    {0,     0,    &Service::HandleDisabled}},
         {"group",       {1,     NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
@@ -329,10 +330,18 @@
     }
 
     bool needs_console = (flags_ & SVC_CONSOLE);
-    if (needs_console && !have_console) {
-        ERROR("service '%s' requires console\n", name_.c_str());
-        flags_ |= SVC_DISABLED;
-        return false;
+    if (needs_console) {
+        if (console_.empty()) {
+            console_ = default_console;
+        }
+
+        bool have_console = (open(console_.c_str(), O_RDWR | O_CLOEXEC) != -1);
+        if (!have_console) {
+            ERROR("service '%s' couldn't open console '%s': %s\n",
+                  name_.c_str(), console_.c_str(), strerror(errno));
+            flags_ |= SVC_DISABLED;
+            return false;
+        }
     }
 
     struct stat sb;
@@ -591,10 +600,8 @@
 }
 
 void Service::OpenConsole() const {
-    int fd;
-    if ((fd = open(console_name.c_str(), O_RDWR)) < 0) {
-        fd = open("/dev/null", O_RDWR);
-    }
+    int fd = open(console_.c_str(), O_RDWR);
+    if (fd == -1) fd = open("/dev/null", O_RDWR);
     ioctl(fd, TIOCSCTTY, 0);
     dup2(fd, 0);
     dup2(fd, 1);
diff --git a/init/service.h b/init/service.h
index d9d18ef..d6ce664 100644
--- a/init/service.h
+++ b/init/service.h
@@ -128,6 +128,7 @@
 
     std::string name_;
     std::string classname_;
+    std::string console_;
 
     unsigned flags_;
     pid_t pid_;
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index 249739b..73b2136 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -16,14 +16,17 @@
 
 #include <ctype.h>
 #include <fcntl.h>
+#include <grp.h>
 #include <poll.h>
+#include <pwd.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#include <sys/types.h>
+
 #include <android-base/stringprintf.h>
-#include <private/android_filesystem_config.h>
 #include <selinux/selinux.h>
 
 #include "ueventd.h"
@@ -84,15 +87,6 @@
     return 0;
 }
 
-static int get_android_id(const char *id)
-{
-    unsigned int i;
-    for (i = 0; i < ARRAY_SIZE(android_ids); i++)
-        if (!strcmp(id, android_ids[i].name))
-            return android_ids[i].aid;
-    return -1;
-}
-
 void set_device_permission(int nargs, char **args)
 {
     char *name;
@@ -103,7 +97,6 @@
     int prefix = 0;
     int wildcard = 0;
     char *endptr;
-    int ret;
     char *tmp = 0;
 
     if (nargs == 0)
@@ -151,21 +144,21 @@
         return;
     }
 
-    ret = get_android_id(args[2]);
-    if (ret < 0) {
+    struct passwd* pwd = getpwnam(args[2]);
+    if (!pwd) {
         ERROR("invalid uid '%s'\n", args[2]);
         free(tmp);
         return;
     }
-    uid = ret;
+    uid = pwd->pw_uid;
 
-    ret = get_android_id(args[3]);
-    if (ret < 0) {
+    struct group* grp = getgrnam(args[3]);
+    if (!grp) {
         ERROR("invalid gid '%s'\n", args[3]);
         free(tmp);
         return;
     }
-    gid = ret;
+    gid = grp->gr_gid;
 
     add_dev_perms(name, attr, perm, uid, gid, prefix, wildcard);
     free(tmp);
diff --git a/init/util.cpp b/init/util.cpp
index 84b4155..750e040 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <time.h>
 #include <ftw.h>
+#include <pwd.h>
 
 #include <selinux/label.h>
 #include <selinux/android.h>
@@ -39,38 +40,24 @@
 #include <cutils/sockets.h>
 #include <android-base/stringprintf.h>
 
-#include <private/android_filesystem_config.h>
-
 #include "init.h"
 #include "log.h"
 #include "property_service.h"
 #include "util.h"
 
-/*
- * android_name_to_id - returns the integer uid/gid associated with the given
- * name, or UINT_MAX on error.
- */
-static unsigned int android_name_to_id(const char *name)
-{
-    const struct android_id_info *info = android_ids;
-    unsigned int n;
-
-    for (n = 0; n < android_id_count; n++) {
-        if (!strcmp(info[n].name, name))
-            return info[n].aid;
-    }
-
-    return UINT_MAX;
-}
-
 static unsigned int do_decode_uid(const char *s)
 {
     unsigned int v;
 
     if (!s || *s == '\0')
         return UINT_MAX;
-    if (isalpha(s[0]))
-        return android_name_to_id(s);
+
+    if (isalpha(s[0])) {
+        struct passwd* pwd = getpwnam(s);
+        if (!pwd)
+            return UINT_MAX;
+        return pwd->pw_uid;
+    }
 
     errno = 0;
     v = (unsigned int) strtoul(s, 0, 0);
@@ -355,7 +342,7 @@
 {
     int ret;
     char buf[256];
-    char *slash;
+    const char *slash;
     int width;
 
     slash = strrchr(newpath, '/');
@@ -401,20 +388,18 @@
 
 void open_devnull_stdio(void)
 {
-    // Try to avoid the mknod() call if we can. Since SELinux makes
-    // a /dev/null replacement available for free, let's use it.
     int fd = open("/sys/fs/selinux/null", O_RDWR);
     if (fd == -1) {
-        // OOPS, /sys/fs/selinux/null isn't available, likely because
-        // /sys/fs/selinux isn't mounted. Fall back to mknod.
-        static const char *name = "/dev/__null__";
-        if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
-            fd = open(name, O_RDWR);
-            unlink(name);
-        }
-        if (fd == -1) {
-            exit(1);
-        }
+        /* Fail silently.
+         * stdout/stderr isn't available, and because
+         * klog_init() is called after open_devnull_stdio(), we can't
+         * log to dmesg. Reordering klog_init() to be called before
+         * open_devnull_stdio() isn't an option either, as then klog_fd
+         * will be assigned 0 or 1, which will end up getting clobbered
+         * by the code below. There's nowhere good to log.
+         */
+
+        exit(1);
     }
 
     dup2(fd, 0);
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index d5a7e06..a8a7c4a 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -71,14 +71,22 @@
 build_type := host
 libbacktrace_multilib := both
 include $(LOCAL_PATH)/Android.build.mk
+
+libbacktrace_shared_libraries :=
+
 libbacktrace_static_libraries := \
 	libbase \
 	liblog \
 	libunwind \
+	liblzma \
 
+module := libbacktrace
+build_type := target
 build_target := STATIC_LIBRARY
 include $(LOCAL_PATH)/Android.build.mk
-libbacktrace_static_libraries :=
+build_type := host
+libbacktrace_multilib := both
+include $(LOCAL_PATH)/Android.build.mk
 
 #-------------------------------------------------------------------------
 # The libbacktrace_offline shared library.
@@ -126,6 +134,28 @@
 libbacktrace_multilib := both
 include $(LOCAL_PATH)/Android.build.mk
 
+libbacktrace_offline_shared_libraries :=
+libbacktrace_offline_static_libraries := \
+	libbacktrace \
+	libbase \
+	libcutils \
+	liblog \
+	libunwind \
+	liblzma \
+	libziparchive \
+	libz \
+	libLLVMObject \
+	libLLVMBitReader \
+	libLLVMMC \
+	libLLVMMCParser \
+	libLLVMCore \
+	libLLVMSupport \
+
+module := libbacktrace_offline
+build_type := target
+build_target := STATIC_LIBRARY
+include $(LOCAL_PATH)/Android.build.mk
+
 #-------------------------------------------------------------------------
 # The libbacktrace_test library needed by backtrace_test.
 #-------------------------------------------------------------------------
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index f6b2591..df6c6c1 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -414,17 +414,16 @@
   char task_path[128];
   snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
 
-  DIR* tasks_dir = opendir(task_path);
+  std::unique_ptr<DIR, decltype(&closedir)> tasks_dir(opendir(task_path), closedir);
   ASSERT_TRUE(tasks_dir != nullptr);
   struct dirent* entry;
-  while ((entry = readdir(tasks_dir)) != nullptr) {
+  while ((entry = readdir(tasks_dir.get())) != nullptr) {
     char* end;
     pid_t tid = strtoul(entry->d_name, &end, 10);
     if (*end == '\0') {
       threads->push_back(tid);
     }
   }
-  closedir(tasks_dir);
 }
 
 TEST(libbacktrace, ptrace_threads) {
@@ -1445,9 +1444,9 @@
   }
   size_t new_pss = GetPssBytes();
   ASSERT_TRUE(new_pss != 0);
-  size_t abs_diff = (new_pss > stable_pss) ? new_pss - stable_pss : stable_pss - new_pss;
-  // As long as the new pss is within a certain amount, consider everything okay.
-  ASSERT_LE(abs_diff, MAX_LEAK_BYTES);
+  if (new_pss > stable_pss) {
+    ASSERT_LE(new_pss - stable_pss, MAX_LEAK_BYTES);
+  }
 }
 
 TEST(libbacktrace, check_for_leak_local) {
diff --git a/libbinderwrapper/real_binder_wrapper.cc b/libbinderwrapper/real_binder_wrapper.cc
index 1c51822..f93f183 100644
--- a/libbinderwrapper/real_binder_wrapper.cc
+++ b/libbinderwrapper/real_binder_wrapper.cc
@@ -29,7 +29,7 @@
 // be awkward.
 class RealBinderWrapper::DeathRecipient : public IBinder::DeathRecipient {
  public:
-  explicit DeathRecipient(const base::Closure& callback)
+  explicit DeathRecipient(const ::base::Closure& callback)
       : callback_(callback) {}
   ~DeathRecipient() = default;
 
@@ -40,7 +40,7 @@
 
  private:
   // Callback to run in response to binder death.
-  base::Closure callback_;
+  ::base::Closure callback_;
 
   DISALLOW_COPY_AND_ASSIGN(DeathRecipient);
 };
@@ -85,7 +85,7 @@
 
 bool RealBinderWrapper::RegisterForDeathNotifications(
     const sp<IBinder>& binder,
-    const base::Closure& callback) {
+    const ::base::Closure& callback) {
   sp<DeathRecipient> recipient(new DeathRecipient(callback));
   if (binder->linkToDeath(recipient) != OK) {
     LOG(ERROR) << "Failed to register for death notifications on "
diff --git a/libbinderwrapper/real_binder_wrapper.h b/libbinderwrapper/real_binder_wrapper.h
index ea08371..1675432 100644
--- a/libbinderwrapper/real_binder_wrapper.h
+++ b/libbinderwrapper/real_binder_wrapper.h
@@ -36,7 +36,7 @@
                        const sp<IBinder>& binder) override;
   sp<BBinder> CreateLocalBinder() override;
   bool RegisterForDeathNotifications(const sp<IBinder>& binder,
-                                     const base::Closure& callback) override;
+                                     const ::base::Closure& callback) override;
   bool UnregisterForDeathNotifications(const sp<IBinder>& binder) override;
   uid_t GetCallingUid() override;
   pid_t GetCallingPid() override;
diff --git a/libbinderwrapper/stub_binder_wrapper.cc b/libbinderwrapper/stub_binder_wrapper.cc
index 87c6ab7..8e75f62 100644
--- a/libbinderwrapper/stub_binder_wrapper.cc
+++ b/libbinderwrapper/stub_binder_wrapper.cc
@@ -64,7 +64,7 @@
 
 bool StubBinderWrapper::RegisterForDeathNotifications(
     const sp<IBinder>& binder,
-    const base::Closure& callback) {
+    const ::base::Closure& callback) {
   death_callbacks_[binder] = callback;
   return true;
 }
diff --git a/libcrypto_utils/Android.mk b/libcrypto_utils/Android.mk
new file mode 100644
index 0000000..5e9763f
--- /dev/null
+++ b/libcrypto_utils/Android.mk
@@ -0,0 +1,56 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcrypto_utils
+LOCAL_SRC_FILES := android_pubkey.c
+LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_SHARED_LIBRARIES := libcrypto
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcrypto_utils
+LOCAL_SRC_FILES := android_pubkey.c
+LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_SHARED_LIBRARIES := libcrypto-host
+include $(BUILD_HOST_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcrypto_utils_static
+LOCAL_SRC_FILES := android_pubkey.c
+LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_STATIC_LIBRARIES := libcrypto_static
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcrypto_utils_static
+LOCAL_MODULE_HOST_OS := darwin linux windows
+LOCAL_SRC_FILES := android_pubkey.c
+LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_STATIC_LIBRARIES := libcrypto_static
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libcrypto_utils/android_pubkey.c b/libcrypto_utils/android_pubkey.c
new file mode 100644
index 0000000..9cd9aab
--- /dev/null
+++ b/libcrypto_utils/android_pubkey.c
@@ -0,0 +1,167 @@
+/*
+ * 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 <crypto_utils/android_pubkey.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Better safe than sorry.
+#if (ANDROID_PUBKEY_MODULUS_SIZE % 4) != 0
+#error RSA modulus size must be multiple of the word size!
+#endif
+
+// Size of the RSA modulus in words.
+#define ANDROID_PUBKEY_MODULUS_SIZE_WORDS (ANDROID_PUBKEY_MODULUS_SIZE / 4)
+
+// This file implements encoding and decoding logic for Android's custom RSA
+// public key binary format. Public keys are stored as a sequence of
+// little-endian 32 bit words. Note that Android only supports little-endian
+// processors, so we don't do any byte order conversions when parsing the binary
+// struct.
+typedef struct RSAPublicKey {
+    // Modulus length. This must be ANDROID_PUBKEY_MODULUS_SIZE.
+    uint32_t modulus_size_words;
+
+    // Precomputed montgomery parameter: -1 / n[0] mod 2^32
+    uint32_t n0inv;
+
+    // RSA modulus as a little-endian array.
+    uint8_t modulus[ANDROID_PUBKEY_MODULUS_SIZE];
+
+    // Montgomery parameter R^2 as a little-endian array of little-endian words.
+    uint8_t rr[ANDROID_PUBKEY_MODULUS_SIZE];
+
+    // RSA modulus: 3 or 65537
+    uint32_t exponent;
+} RSAPublicKey;
+
+// Reverses byte order in |buffer|.
+static void reverse_bytes(uint8_t* buffer, size_t size) {
+  for (size_t i = 0; i < (size + 1) / 2; ++i) {
+    uint8_t tmp = buffer[i];
+    buffer[i] = buffer[size - i - 1];
+    buffer[size - i - 1] = tmp;
+  }
+}
+
+bool android_pubkey_decode(const uint8_t* key_buffer, size_t size, RSA** key) {
+  const RSAPublicKey* key_struct = (RSAPublicKey*)key_buffer;
+  bool ret = false;
+  uint8_t modulus_buffer[ANDROID_PUBKEY_MODULUS_SIZE];
+  RSA* new_key = RSA_new();
+  if (!new_key) {
+    goto cleanup;
+  }
+
+  // Check |size| is large enough and the modulus size is correct.
+  if (size < sizeof(RSAPublicKey)) {
+    goto cleanup;
+  }
+  if (key_struct->modulus_size_words != ANDROID_PUBKEY_MODULUS_SIZE_WORDS) {
+    goto cleanup;
+  }
+
+  // Convert the modulus to big-endian byte order as expected by BN_bin2bn.
+  memcpy(modulus_buffer, key_struct->modulus, sizeof(modulus_buffer));
+  reverse_bytes(modulus_buffer, sizeof(modulus_buffer));
+  new_key->n = BN_bin2bn(modulus_buffer, sizeof(modulus_buffer), NULL);
+  if (!new_key->n) {
+    goto cleanup;
+  }
+
+  // Read the exponent.
+  new_key->e = BN_new();
+  if (!new_key->e || !BN_set_word(new_key->e, key_struct->exponent)) {
+    goto cleanup;
+  }
+
+  // Note that we don't extract the montgomery parameters n0inv and rr from
+  // the RSAPublicKey structure. They assume a word size of 32 bits, but
+  // BoringSSL may use a word size of 64 bits internally, so we're lacking the
+  // top 32 bits of n0inv in general. For now, we just ignore the parameters
+  // and have BoringSSL recompute them internally. More sophisticated logic can
+  // be added here if/when we want the additional speedup from using the
+  // pre-computed montgomery parameters.
+
+  *key = new_key;
+  ret = true;
+
+cleanup:
+  if (!ret && new_key) {
+    RSA_free(new_key);
+  }
+  return ret;
+}
+
+static bool android_pubkey_encode_bignum(const BIGNUM* num, uint8_t* buffer) {
+  if (!BN_bn2bin_padded(buffer, ANDROID_PUBKEY_MODULUS_SIZE, num)) {
+    return false;
+  }
+
+  reverse_bytes(buffer, ANDROID_PUBKEY_MODULUS_SIZE);
+  return true;
+}
+
+bool android_pubkey_encode(const RSA* key, uint8_t* key_buffer, size_t size) {
+  RSAPublicKey* key_struct = (RSAPublicKey*)key_buffer;
+  bool ret = false;
+  BN_CTX* ctx = BN_CTX_new();
+  BIGNUM* r32 = BN_new();
+  BIGNUM* n0inv = BN_new();
+  BIGNUM* rr = BN_new();
+
+  if (sizeof(RSAPublicKey) > size ||
+      RSA_size(key) != ANDROID_PUBKEY_MODULUS_SIZE) {
+    goto cleanup;
+  }
+
+  // Store the modulus size.
+  key_struct->modulus_size_words = ANDROID_PUBKEY_MODULUS_SIZE_WORDS;
+
+  // Compute and store n0inv = -1 / N[0] mod 2^32.
+  if (!ctx || !r32 || !n0inv || !BN_set_bit(r32, 32) ||
+      !BN_mod(n0inv, key->n, r32, ctx) ||
+      !BN_mod_inverse(n0inv, n0inv, r32, ctx) || !BN_sub(n0inv, r32, n0inv)) {
+    goto cleanup;
+  }
+  key_struct->n0inv = (uint32_t)BN_get_word(n0inv);
+
+  // Store the modulus.
+  if (!android_pubkey_encode_bignum(key->n, key_struct->modulus)) {
+    goto cleanup;
+  }
+
+  // Compute and store rr = (2^(rsa_size)) ^ 2 mod N.
+  if (!ctx || !rr || !BN_set_bit(rr, ANDROID_PUBKEY_MODULUS_SIZE * 8) ||
+      !BN_mod_sqr(rr, rr, key->n, ctx) ||
+      !android_pubkey_encode_bignum(rr, key_struct->rr)) {
+    goto cleanup;
+  }
+
+  // Store the exponent.
+  key_struct->exponent = (uint32_t)BN_get_word(key->e);
+
+  ret = true;
+
+cleanup:
+  BN_free(rr);
+  BN_free(n0inv);
+  BN_free(r32);
+  BN_CTX_free(ctx);
+  return ret;
+}
diff --git a/libcrypto_utils/include/crypto_utils/android_pubkey.h b/libcrypto_utils/include/crypto_utils/android_pubkey.h
new file mode 100644
index 0000000..1045eba
--- /dev/null
+++ b/libcrypto_utils/include/crypto_utils/android_pubkey.h
@@ -0,0 +1,61 @@
+/*
+ * 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 CRYPTO_UTILS_ANDROID_PUBKEY_H
+#define CRYPTO_UTILS_ANDROID_PUBKEY_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <openssl/rsa.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Size of an RSA modulus such as an encrypted block or a signature.
+#define ANDROID_PUBKEY_MODULUS_SIZE (2048 / 8)
+
+// Size of an encoded RSA key.
+#define ANDROID_PUBKEY_ENCODED_SIZE \
+  (3 * sizeof(uint32_t) + 2 * ANDROID_PUBKEY_MODULUS_SIZE)
+
+/* Allocates a new RSA |key| object, decodes a public RSA key stored in
+ * Android's custom binary format from |key_buffer| and sets the key parameters
+ * in |key|. |size| specifies the size of the key buffer and must be at least
+ * |ANDROID_PUBKEY_ENCODED_SIZE|. The resulting |*key| can be used with the
+ * standard BoringSSL API to perform public operations.
+ *
+ * Returns true if successful, in which case the caller receives ownership of
+ * the |*key| object, i.e. needs to call RSA_free() when done with it. If there
+ * is an error, |key| is left untouched and the return value will be false.
+ */
+bool android_pubkey_decode(const uint8_t* key_buffer, size_t size, RSA** key);
+
+/* Encodes |key| in the Android RSA public key binary format and stores the
+ * bytes in |key_buffer|. |key_buffer| should be of size at least
+ * |ANDROID_PUBKEY_ENCODED_SIZE|.
+ *
+ * Returns true if successful, false on error.
+ */
+bool android_pubkey_encode(const RSA* key, uint8_t* key_buffer, size_t size);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif  // CRYPTO_UTILS_ANDROID_PUBKEY_H
diff --git a/libmincrypt/tools/Android.mk b/libcrypto_utils/tests/Android.mk
similarity index 68%
rename from libmincrypt/tools/Android.mk
rename to libcrypto_utils/tests/Android.mk
index 3154914..dad82f7 100644
--- a/libmincrypt/tools/Android.mk
+++ b/libcrypto_utils/tests/Android.mk
@@ -1,4 +1,5 @@
-# Copyright (C) 2008 The Android Open Source Project
+#
+# 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.
@@ -11,12 +12,13 @@
 # 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.
+#
 
 LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
-LOCAL_MODULE := dumpkey
-LOCAL_SRC_FILES := DumpPublicKey.java
-LOCAL_JAR_MANIFEST := DumpPublicKey.mf
-LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-host
-include $(BUILD_HOST_JAVA_LIBRARY)
+LOCAL_MODULE := libcrypto_utils_test
+LOCAL_SRC_FILES := android_pubkey_test.cpp
+LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c++11
+LOCAL_SHARED_LIBRARIES := libcrypto_utils libcrypto-host
+include $(BUILD_HOST_NATIVE_TEST)
diff --git a/libcrypto_utils/tests/android_pubkey_test.cpp b/libcrypto_utils/tests/android_pubkey_test.cpp
new file mode 100644
index 0000000..f8c2e0c
--- /dev/null
+++ b/libcrypto_utils/tests/android_pubkey_test.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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 <crypto_utils/android_pubkey.h>
+
+#include <string.h>
+
+#include <memory>
+
+#include <openssl/obj_mac.h>
+#include <openssl/rsa.h>
+
+#include <gtest/gtest.h>
+
+// Test digest to verify.
+const uint8_t kDigest[] = {
+    0x31, 0x5f, 0x5b, 0xdb, 0x76, 0xd0, 0x78, 0xc4, 0x3b, 0x8a, 0xc0,
+    0x06, 0x4e, 0x4a, 0x01, 0x64, 0x61, 0x2b, 0x1f, 0xce, 0x77, 0xc8,
+    0x69, 0x34, 0x5b, 0xfc, 0x94, 0xc7, 0x58, 0x94, 0xed, 0xd3,
+};
+
+// 2048 RSA test key.
+const uint8_t kKey2048[ANDROID_PUBKEY_ENCODED_SIZE] = {
+    0x40, 0x00, 0x00, 0x00, 0x05, 0x75, 0x61, 0xd1, 0x33, 0xf0, 0x2d, 0x12,
+    0x45, 0xfb, 0xae, 0x07, 0x02, 0x15, 0x4f, 0x3a, 0x2b, 0xa3, 0xbc, 0x49,
+    0xbd, 0x14, 0x07, 0xa0, 0xc0, 0x9f, 0x0c, 0x52, 0x60, 0x77, 0x9f, 0xa2,
+    0x31, 0xd0, 0xa7, 0xfb, 0x7e, 0xde, 0xfb, 0xc9, 0x05, 0xc0, 0x97, 0xf7,
+    0x74, 0x99, 0xe6, 0xd1, 0x08, 0xa6, 0xc2, 0x59, 0x5a, 0xd8, 0x37, 0x1d,
+    0xe0, 0x48, 0x5e, 0x63, 0x44, 0x04, 0x8b, 0x05, 0x20, 0xf6, 0x25, 0x67,
+    0x38, 0xb2, 0xb6, 0xf9, 0xbe, 0xb6, 0x1d, 0x7f, 0x1b, 0x71, 0x8a, 0xeb,
+    0xb7, 0xf8, 0x01, 0xc1, 0x5e, 0xf7, 0xfe, 0x48, 0x08, 0x27, 0x0f, 0x27,
+    0x2a, 0x64, 0x1a, 0x43, 0x8d, 0xcf, 0x5a, 0x33, 0x5c, 0x18, 0xc5, 0xf4,
+    0xe7, 0xfe, 0xee, 0xd3, 0x12, 0x62, 0xad, 0x61, 0x78, 0x9a, 0x03, 0xb0,
+    0xaf, 0xab, 0x91, 0x57, 0x46, 0xbf, 0x18, 0xc6, 0xbc, 0x0c, 0x6b, 0x55,
+    0xcd, 0xda, 0xc4, 0xcc, 0x98, 0x46, 0x91, 0x99, 0xbc, 0xa3, 0xca, 0x6c,
+    0x86, 0xa6, 0x1c, 0x8f, 0xca, 0xf8, 0xf6, 0x8a, 0x00, 0x8e, 0x05, 0xd7,
+    0x13, 0x43, 0xe2, 0xf2, 0x1a, 0x13, 0xf3, 0x50, 0x13, 0xa4, 0xf2, 0x4e,
+    0x41, 0xb1, 0x36, 0x78, 0x55, 0x4c, 0x5e, 0x27, 0xc5, 0xc0, 0x4b, 0xd8,
+    0x93, 0xaa, 0x7e, 0xf0, 0x90, 0x08, 0x10, 0x26, 0x72, 0x6d, 0xb9, 0x21,
+    0xae, 0x4d, 0x01, 0x4b, 0x55, 0x1d, 0xe7, 0x1e, 0x5e, 0x31, 0x6e, 0x62,
+    0xd1, 0x33, 0x26, 0xcb, 0xdb, 0xfe, 0x72, 0x98, 0xc8, 0x06, 0x1c, 0x12,
+    0xdf, 0xfc, 0x74, 0xe5, 0x7a, 0x6f, 0xf5, 0xa3, 0x63, 0x08, 0xe3, 0x02,
+    0x68, 0x4d, 0x7c, 0x70, 0x05, 0xec, 0x95, 0x7e, 0x24, 0xa4, 0xbc, 0x4c,
+    0xcd, 0x39, 0x14, 0xb5, 0x2a, 0x8f, 0xc1, 0xe3, 0x4e, 0xfa, 0xf8, 0x70,
+    0x50, 0x8f, 0xd5, 0x8e, 0xc7, 0xb5, 0x32, 0x89, 0x4d, 0xbb, 0x6a, 0xc1,
+    0xc1, 0xa2, 0x42, 0x57, 0x57, 0xbd, 0x2a, 0xdc, 0xa6, 0xfd, 0xc8, 0x86,
+    0x44, 0x6a, 0x03, 0x5d, 0x4d, 0x28, 0xe1, 0xde, 0xb4, 0xa9, 0xa5, 0x03,
+    0x61, 0x7a, 0x5f, 0xb1, 0x09, 0x17, 0x2b, 0x9c, 0xa2, 0x54, 0x28, 0xad,
+    0x34, 0xc9, 0x5f, 0x6c, 0x9f, 0xb8, 0xd2, 0xa9, 0x78, 0xa7, 0xaa, 0xb3,
+    0x11, 0x2f, 0x65, 0x9b, 0x4e, 0x67, 0x0c, 0xcc, 0x20, 0x36, 0xbf, 0x26,
+    0x2b, 0x4e, 0xc0, 0xd4, 0xbd, 0x22, 0x64, 0xc4, 0x1c, 0x56, 0x69, 0xdb,
+    0x5f, 0x89, 0xe1, 0x75, 0x68, 0x8d, 0x0e, 0xab, 0x1c, 0x10, 0x1a, 0xc0,
+    0x12, 0x5d, 0x6f, 0xbd, 0x09, 0xbb, 0x47, 0xcb, 0xe7, 0x34, 0xef, 0x56,
+    0xab, 0xea, 0xc3, 0xe9, 0x7f, 0x9a, 0x3d, 0xe9, 0x2d, 0x14, 0x61, 0x25,
+    0x37, 0x5c, 0x3b, 0x4b, 0xaf, 0x5a, 0x4b, 0xc8, 0x99, 0x1a, 0x32, 0x8f,
+    0x54, 0x07, 0xd3, 0x57, 0x8a, 0x3d, 0x2a, 0xf7, 0x9e, 0x7e, 0x92, 0x2a,
+    0x50, 0xe9, 0xd8, 0xdb, 0xd6, 0x03, 0xd3, 0x8e, 0x54, 0x32, 0xce, 0x87,
+    0x93, 0x92, 0xe7, 0x75, 0xe1, 0x6b, 0x78, 0x1a, 0x85, 0xc2, 0x46, 0xa1,
+    0x31, 0xbb, 0xc7, 0xb9, 0x1d, 0xd1, 0x71, 0xe0, 0xe2, 0x9b, 0x9c, 0x0d,
+    0xa3, 0xcf, 0x93, 0x4d, 0x87, 0x7b, 0x65, 0xd9, 0xda, 0x4c, 0xd9, 0x6a,
+    0xa6, 0x36, 0xc2, 0xc7, 0xe3, 0x33, 0xe2, 0xc3, 0x83, 0xd1, 0x72, 0x54,
+    0x30, 0x81, 0x5e, 0x34, 0x2c, 0x61, 0xee, 0xf4, 0x48, 0x97, 0xb6, 0xaa,
+    0x47, 0x6a, 0x05, 0x09, 0xd8, 0x4d, 0x90, 0xaf, 0xa8, 0x4e, 0x82, 0xe4,
+    0x8e, 0xb5, 0xe2, 0x65, 0x86, 0x67, 0xe9, 0x5b, 0x4b, 0x9a, 0x68, 0x08,
+    0x30, 0xf6, 0x25, 0x8b, 0x20, 0xda, 0x26, 0x6f, 0xbd, 0x0d, 0xa5, 0xd8,
+    0x6a, 0x7b, 0x01, 0x2f, 0xab, 0x7b, 0xb5, 0xfe, 0x62, 0x37, 0x2d, 0x94,
+    0x43, 0x2f, 0x4d, 0x16, 0x01, 0x00, 0x01, 0x00,
+};
+
+// 2048 bit RSA signature.
+const uint8_t kSignature2048[ANDROID_PUBKEY_MODULUS_SIZE] = {
+    0x3a, 0x11, 0x84, 0x40, 0xc1, 0x2f, 0x13, 0x8c, 0xde, 0xb0, 0xc3, 0x89,
+    0x8a, 0x63, 0xb2, 0x50, 0x93, 0x58, 0xc0, 0x0c, 0xb7, 0x08, 0xe7, 0x6c,
+    0x52, 0x87, 0x4e, 0x78, 0x89, 0xa3, 0x9a, 0x47, 0xeb, 0x11, 0x57, 0xbc,
+    0xb3, 0x97, 0xf8, 0x34, 0xf1, 0xf7, 0xbf, 0x3a, 0xfa, 0x1c, 0x6b, 0xdc,
+    0xd1, 0x02, 0xde, 0x9a, 0x0d, 0x72, 0xe7, 0x19, 0x63, 0x81, 0x46, 0x68,
+    0x1e, 0x63, 0x64, 0xc6, 0x59, 0xe7, 0x7c, 0x39, 0xed, 0x32, 0xd2, 0xd1,
+    0xd5, 0x1f, 0x13, 0x9b, 0x52, 0xdf, 0x34, 0xa3, 0xc0, 0xc4, 0x9a, 0x63,
+    0x9b, 0x9c, 0xbe, 0x22, 0xc8, 0xd8, 0x14, 0x2f, 0x4c, 0x78, 0x36, 0xdb,
+    0x16, 0x41, 0x67, 0xc1, 0x21, 0x8a, 0x73, 0xb2, 0xe5, 0xb0, 0xd3, 0x80,
+    0x91, 0x7a, 0xbf, 0xf9, 0x59, 0x4a, 0x4d, 0x78, 0x45, 0x44, 0xa1, 0x52,
+    0x86, 0x29, 0x48, 0x4d, 0xf0, 0x5d, 0xf2, 0x55, 0xa7, 0xcd, 0xc5, 0x2b,
+    0x7b, 0xe0, 0xb1, 0xf6, 0x2a, 0xd5, 0x61, 0xba, 0x1e, 0x1e, 0x3a, 0xf0,
+    0x55, 0xbc, 0x8c, 0x44, 0x41, 0xfc, 0xb8, 0x8c, 0x76, 0xbf, 0x80, 0x58,
+    0x82, 0x35, 0x4b, 0x0c, 0xfd, 0xef, 0xd5, 0x70, 0xd1, 0x64, 0xcb, 0x46,
+    0x58, 0x37, 0xbc, 0xa9, 0x7d, 0xd4, 0x70, 0xac, 0xce, 0xec, 0xca, 0x48,
+    0xcb, 0x0a, 0x40, 0x77, 0x04, 0x59, 0xca, 0x9c, 0x7d, 0x1a, 0x0b, 0xf0,
+    0xb5, 0xdd, 0xde, 0x71, 0x18, 0xb8, 0xef, 0x90, 0x2a, 0x09, 0x42, 0x39,
+    0x74, 0xff, 0x45, 0xa1, 0x39, 0x17, 0x50, 0x89, 0xa6, 0x5f, 0xbc, 0x9c,
+    0x0c, 0x9b, 0x47, 0x25, 0x79, 0x3e, 0xe3, 0xaa, 0xaf, 0xbe, 0x73, 0x6b,
+    0xcb, 0xe7, 0x35, 0xc1, 0x27, 0x09, 0xcd, 0xeb, 0xd7, 0xcf, 0x63, 0x83,
+    0x64, 0x8c, 0x45, 0x1c, 0x1d, 0x58, 0xcc, 0xd2, 0xf8, 0x2b, 0x4c, 0x4e,
+    0x14, 0x89, 0x2d, 0x70,
+};
+
+struct AndroidPubkeyTest : public ::testing::Test {
+  void SetUp() override {
+    RSA* new_key = nullptr;
+    ASSERT_TRUE(android_pubkey_decode(kKey2048, sizeof(kKey2048), &new_key));
+    key_.reset(new_key);
+  }
+
+  std::unique_ptr<RSA, void(*)(RSA*)> key_ = {nullptr, RSA_free};
+};
+
+TEST_F(AndroidPubkeyTest, Decode) {
+  // Make sure the decoded key successfully verifies a valid signature.
+  EXPECT_TRUE(RSA_verify(NID_sha256, kDigest, sizeof(kDigest), kSignature2048,
+                         sizeof(kSignature2048), key_.get()));
+}
+
+TEST_F(AndroidPubkeyTest, Encode) {
+  uint8_t key_data[ANDROID_PUBKEY_ENCODED_SIZE];
+  ASSERT_TRUE(android_pubkey_encode(key_.get(), key_data, sizeof(key_data)));
+  ASSERT_EQ(0, memcmp(kKey2048, key_data, sizeof(kKey2048)));
+}
diff --git a/libcutils/qtaguid.c b/libcutils/qtaguid.c
index 2fbe02e..dcd16ef 100644
--- a/libcutils/qtaguid.c
+++ b/libcutils/qtaguid.c
@@ -47,10 +47,7 @@
 
 /* Only call once per process. */
 void qtaguid_resTrack(void) {
-    resTrackFd = TEMP_FAILURE_RETRY(open("/dev/xt_qtaguid", O_RDONLY));
-    if (resTrackFd >=0) {
-        TEMP_FAILURE_RETRY(fcntl(resTrackFd, F_SETFD, FD_CLOEXEC));
-    }
+    resTrackFd = TEMP_FAILURE_RETRY(open("/dev/xt_qtaguid", O_RDONLY | O_CLOEXEC));
 }
 
 /*
@@ -63,7 +60,7 @@
 
     ALOGV("write_ctrl(%s)", cmd);
 
-    fd = TEMP_FAILURE_RETRY(open(CTRL_PROCPATH, O_WRONLY));
+    fd = TEMP_FAILURE_RETRY(open(CTRL_PROCPATH, O_WRONLY | O_CLOEXEC));
     if (fd < 0) {
         return -errno;
     }
@@ -86,7 +83,7 @@
     int param_fd;
     int res;
 
-    param_fd = TEMP_FAILURE_RETRY(open(param_path, O_WRONLY));
+    param_fd = TEMP_FAILURE_RETRY(open(param_path, O_WRONLY | O_CLOEXEC));
     if (param_fd < 0) {
         return -errno;
     }
diff --git a/libcutils/tests/PropertiesTest.cpp b/libcutils/tests/PropertiesTest.cpp
index 659821c..5f2396b 100644
--- a/libcutils/tests/PropertiesTest.cpp
+++ b/libcutils/tests/PropertiesTest.cpp
@@ -15,7 +15,7 @@
  */
 
 #define LOG_TAG "Properties_test"
-#include <utils/Log.h>
+#include <cutils/log.h>
 #include <gtest/gtest.h>
 
 #include <cutils/properties.h>
@@ -106,14 +106,14 @@
         ResetValue();
 
         // Since the value is null, default value will be returned
-        int len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT);
+        size_t len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT);
         EXPECT_EQ(strlen(PROPERTY_TEST_VALUE_DEFAULT), len);
         EXPECT_STREQ(PROPERTY_TEST_VALUE_DEFAULT, mValue);
     }
 
     // Trivial case => get returns what was set
     {
-        int len = SetAndGetProperty("hello_world");
+        size_t len = SetAndGetProperty("hello_world");
         EXPECT_EQ(strlen("hello_world"), len) << "hello_world key";
         EXPECT_STREQ("hello_world", mValue);
         ResetValue();
@@ -122,7 +122,7 @@
     // Set to empty string => get returns default always
     {
         const char* EMPTY_STRING_DEFAULT = "EMPTY_STRING";
-        int len = SetAndGetProperty("", EMPTY_STRING_DEFAULT);
+        size_t len = SetAndGetProperty("", EMPTY_STRING_DEFAULT);
         EXPECT_EQ(strlen(EMPTY_STRING_DEFAULT), len) << "empty key";
         EXPECT_STREQ(EMPTY_STRING_DEFAULT, mValue);
         ResetValue();
@@ -147,7 +147,7 @@
 
         // Expect that the value set fails since it's too long
         EXPECT_GT(0, property_set(PROPERTY_TEST_KEY, oneLongerString.c_str()));
-        int len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT);
+        size_t len = property_get(PROPERTY_TEST_KEY, mValue, PROPERTY_TEST_VALUE_DEFAULT);
 
         EXPECT_EQ(strlen(VALID_TEST_VALUE), len) << "set should've failed";
         EXPECT_STREQ(VALID_TEST_VALUE, mValue);
diff --git a/libdiskconfig/Android.mk b/libdiskconfig/Android.mk
index 624e385..a49ce58 100644
--- a/libdiskconfig/Android.mk
+++ b/libdiskconfig/Android.mk
@@ -13,6 +13,8 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_SYSTEM_SHARED_LIBRARIES := libcutils liblog libc
 LOCAL_CFLAGS := -Werror
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 include $(BUILD_SHARED_LIBRARY)
 
 ifeq ($(HOST_OS),linux)
@@ -21,5 +23,7 @@
 LOCAL_MODULE := libdiskconfig_host
 LOCAL_MODULE_TAGS := optional
 LOCAL_CFLAGS := -O2 -g -W -Wall -Werror -D_LARGEFILE64_SOURCE
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 include $(BUILD_HOST_STATIC_LIBRARY)
 endif # HOST_OS == linux
diff --git a/include/diskconfig/diskconfig.h b/libdiskconfig/include/diskconfig/diskconfig.h
similarity index 100%
rename from include/diskconfig/diskconfig.h
rename to libdiskconfig/include/diskconfig/diskconfig.h
diff --git a/libion/tests/Android.mk b/libion/tests/Android.mk
index 894f90e..d4d07c2 100644
--- a/libion/tests/Android.mk
+++ b/libion/tests/Android.mk
@@ -17,8 +17,9 @@
 LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
+LOCAL_CLANG := true
 LOCAL_MODULE := ion-unit-tests
-LOCAL_CFLAGS += -g -Wall -Werror -std=gnu++11 -Wno-missing-field-initializers
+LOCAL_CFLAGS += -g -Wall -Werror -Wno-missing-field-initializers
 LOCAL_SHARED_LIBRARIES += libion
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/../kernel-headers
 LOCAL_SRC_FILES := \
diff --git a/libion/tests/allocate_test.cpp b/libion/tests/allocate_test.cpp
index e26b302..3c4524e 100644
--- a/libion/tests/allocate_test.cpp
+++ b/libion/tests/allocate_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <memory>
 #include <sys/mman.h>
 
 #include <gtest/gtest.h>
@@ -90,7 +91,7 @@
 
 TEST_F(Allocate, Zeroed)
 {
-    void *zeroes = calloc(4096, 1);
+    auto zeroes_ptr = std::make_unique<char[]>(4096);
 
     for (unsigned int heapMask : m_allHeaps) {
         SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
@@ -125,14 +126,11 @@
         ptr = mmap(NULL, 4096, PROT_READ, MAP_SHARED, map_fd, 0);
         ASSERT_TRUE(ptr != NULL);
 
-        ASSERT_EQ(0, memcmp(ptr, zeroes, 4096));
+        ASSERT_EQ(0, memcmp(ptr, zeroes_ptr.get(), 4096));
 
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(zeroes);
-
 }
 
 TEST_F(Allocate, Large)
diff --git a/libion/tests/device_test.cpp b/libion/tests/device_test.cpp
index 6f6e1bd..0be52bf 100644
--- a/libion/tests/device_test.cpp
+++ b/libion/tests/device_test.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <fcntl.h>
+#include <memory>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -133,8 +134,8 @@
 
 TEST_F(Device, KernelReadCached)
 {
-    void *alloc = malloc(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
+    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
+    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
 
     for (unsigned int heapMask : m_allHeaps) {
         SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
@@ -161,14 +162,12 @@
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(alloc);
 }
 
 TEST_F(Device, KernelWriteCached)
 {
-    void *alloc = malloc(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
+    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
+    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
 
     for (int i = 0; i < 4096; i++)
         ((char *)buf)[i] = i;
@@ -195,14 +194,12 @@
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(alloc);
 }
 
 TEST_F(Device, DMAReadCached)
 {
-    void *alloc = malloc(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
+    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
+    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
 
     for (unsigned int heapMask : m_allHeaps) {
         SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
@@ -227,14 +224,12 @@
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(alloc);
 }
 
 TEST_F(Device, DMAWriteCached)
 {
-    void *alloc = malloc(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
+    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
+    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
 
     for (int i = 0; i < 4096; i++)
         ((char *)buf)[i] = i;
@@ -261,14 +256,12 @@
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(alloc);
 }
 
 TEST_F(Device, KernelReadCachedNeedsSync)
 {
-    void *alloc = malloc(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
+    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
+    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
 
     for (unsigned int heapMask : m_allHeaps) {
         SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
@@ -295,14 +288,12 @@
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(alloc);
 }
 
 TEST_F(Device, KernelWriteCachedNeedsSync)
 {
-    void *alloc = malloc(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
+    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
+    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
 
     for (int i = 0; i < 4096; i++)
         ((char *)buf)[i] = i;
@@ -329,14 +320,12 @@
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(alloc);
 }
 
 TEST_F(Device, DMAReadCachedNeedsSync)
 {
-    void *alloc = malloc(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
+    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
+    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
 
     for (unsigned int heapMask : m_allHeaps) {
         SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
@@ -363,14 +352,12 @@
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(alloc);
 }
 
 TEST_F(Device, DMAWriteCachedNeedsSync)
 {
-    void *alloc = malloc(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
+    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
+    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
 
     for (int i = 0; i < 4096; i++)
         ((char *)buf)[i] = i;
@@ -399,13 +386,11 @@
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(alloc);
 }
 TEST_F(Device, KernelRead)
 {
-    void *alloc = malloc(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
+    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
+    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
 
     for (unsigned int heapMask : m_allHeaps) {
         SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
@@ -432,14 +417,12 @@
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(alloc);
 }
 
 TEST_F(Device, KernelWrite)
 {
-    void *alloc = malloc(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
+    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
+    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
 
     for (int i = 0; i < 4096; i++)
         ((char *)buf)[i] = i;
@@ -466,14 +449,12 @@
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(alloc);
 }
 
 TEST_F(Device, DMARead)
 {
-    void *alloc = malloc(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
+    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
+    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
 
     for (unsigned int heapMask : m_allHeaps) {
         SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
@@ -498,14 +479,12 @@
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(alloc);
 }
 
 TEST_F(Device, DMAWrite)
 {
-    void *alloc = malloc(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
+    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
+    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
 
     for (int i = 0; i < 4096; i++)
         ((char *)buf)[i] = i;
@@ -532,13 +511,12 @@
         ASSERT_EQ(0, munmap(ptr, 4096));
         ASSERT_EQ(0, close(map_fd));
     }
-
-    free(alloc);
 }
 
 TEST_F(Device, IsCached)
 {
-    void *buf = malloc(4096);
+    auto buf_ptr = std::make_unique<char[]>(4096);
+    void *buf = buf_ptr.get();
 
     for (unsigned int heapMask : m_allHeaps) {
         SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 9b60d4a..88afc14 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -21,6 +21,7 @@
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
+#include <pwd.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -28,11 +29,11 @@
 #include <string.h>
 #include <inttypes.h>
 #include <sys/param.h>
+#include <sys/types.h>
 
 #include <cutils/list.h>
 #include <log/logd.h>
 #include <log/logprint.h>
-#include <private/android_filesystem_config.h>
 
 #include "log_portability.h"
 
@@ -1352,17 +1353,17 @@
     uid[0] = '\0';
     if (p_format->uid_output) {
         if (entry->uid >= 0) {
-            const struct android_id_info *info = android_ids;
-            size_t i;
 
-            for (i = 0; i < android_id_count; ++i) {
-                if (info->aid == (unsigned int)entry->uid) {
-                    break;
-                }
-                ++info;
-            }
-            if ((i < android_id_count) && (strlen(info->name) <= 5)) {
-                 snprintf(uid, sizeof(uid), "%5s:", info->name);
+            /*
+             * This code is Android specific, bionic guarantees that
+             * calls to non-reentrant getpwuid() are thread safe.
+             */
+#ifndef __BIONIC__
+#warning "This code assumes that getpwuid is thread safe, only true with Bionic!"
+#endif
+            struct passwd* pwd = getpwuid(entry->uid);
+            if (pwd && (strlen(pwd->pw_name) <= 5)) {
+                 snprintf(uid, sizeof(uid), "%5s:", pwd->pw_name);
             } else {
                  // Not worth parsing package list, names all longer than 5
                  snprintf(uid, sizeof(uid), "%5d:", entry->uid);
diff --git a/liblog/tests/libc_test.cpp b/liblog/tests/libc_test.cpp
index 9dd6f03..3d58147 100644
--- a/liblog/tests/libc_test.cpp
+++ b/liblog/tests/libc_test.cpp
@@ -14,126 +14,9 @@
  * limitations under the License.
  */
 
-#include <fcntl.h>
-#include <sys/cdefs.h>
-
 #include <gtest/gtest.h>
 
-// Should be in bionic test suite, *but* we are using liblog to confirm
-// end-to-end logging, so let the overly cute oedipus complex begin ...
-#include "../../../../bionic/libc/bionic/libc_logging.cpp" // not Standalone
-#define _ANDROID_LOG_H // Priorities redefined
-#define _LIBS_LOG_LOG_H // log ids redefined
-typedef unsigned char log_id_t; // log_id_t missing as a result
-#define _LIBS_LOG_LOG_READ_H // log_time redefined
-
-#include <log/log.h>
-#include <log/logger.h>
-#include <log/log_read.h>
-
-TEST(libc, __libc_android_log_event_int) {
-    struct logger_list *logger_list;
-
-    pid_t pid = getpid();
-
-    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
-        LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
-    struct timespec ts;
-    clock_gettime(CLOCK_MONOTONIC, &ts);
-    int value = ts.tv_nsec;
-
-    __libc_android_log_event_int(0, value);
-    usleep(1000000);
-
-    int count = 0;
-
-    for (;;) {
-        log_msg log_msg;
-        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-            break;
-        }
-
-        ASSERT_EQ(log_msg.entry.pid, pid);
-
-        if ((log_msg.entry.len != (4 + 1 + 4))
-         || ((int)log_msg.id() != LOG_ID_EVENTS)) {
-            continue;
-        }
-
-        char *eventData = log_msg.msg();
-
-        int incoming = (eventData[0] & 0xFF) |
-                      ((eventData[1] & 0xFF) << 8) |
-                      ((eventData[2] & 0xFF) << 16) |
-                      ((eventData[3] & 0xFF) << 24);
-
-        if (incoming != 0) {
-            continue;
-        }
-
-        if (eventData[4] != EVENT_TYPE_INT) {
-            continue;
-        }
-
-        incoming = (eventData[4 + 1 + 0] & 0xFF) |
-                  ((eventData[4 + 1 + 1] & 0xFF) << 8) |
-                  ((eventData[4 + 1 + 2] & 0xFF) << 16) |
-                  ((eventData[4 + 1 + 3] & 0xFF) << 24);
-
-        if (incoming == value) {
-            ++count;
-        }
-    }
-
-    EXPECT_EQ(1, count);
-
-    android_logger_list_close(logger_list);
-}
-
-TEST(libc, __libc_fatal_no_abort) {
-    struct logger_list *logger_list;
-
-    pid_t pid = getpid();
-
-    ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
-        (log_id_t)LOG_ID_CRASH, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
-    char b[80];
-    struct timespec ts;
-    clock_gettime(CLOCK_MONOTONIC, &ts);
-
-    __libc_fatal_no_abort("%u.%09u", (unsigned)ts.tv_sec, (unsigned)ts.tv_nsec);
-    snprintf(b, sizeof(b),"%u.%09u", (unsigned)ts.tv_sec, (unsigned)ts.tv_nsec);
-    usleep(1000000);
-
-    int count = 0;
-
-    for (;;) {
-        log_msg log_msg;
-        if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-            break;
-        }
-
-        ASSERT_EQ(log_msg.entry.pid, pid);
-
-        if ((int)log_msg.id() != LOG_ID_CRASH) {
-            continue;
-        }
-
-        char *data = log_msg.msg();
-
-        if ((*data == ANDROID_LOG_FATAL)
-                && !strcmp(data + 1, "libc")
-                && !strcmp(data + 1 + strlen(data + 1) + 1, b)) {
-            ++count;
-        }
-    }
-
-    EXPECT_EQ(1, count);
-
-    android_logger_list_close(logger_list);
-}
+#include <stdio.h>
 
 TEST(libc, __pstore_append) {
     FILE *fp;
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 329898f..456f8b3 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -174,7 +174,7 @@
     return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
 }
 
-TEST(liblog, __android_log_bswrite) {
+static void bswrite_test(const char *message) {
     struct logger_list *logger_list;
 
     pid_t pid = getpid();
@@ -182,10 +182,30 @@
     ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
         LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
 
-    static const char buffer[] = "Hello World";
     log_time ts(android_log_clockid());
 
-    ASSERT_LT(0, __android_log_bswrite(0, buffer));
+    ASSERT_LT(0, __android_log_bswrite(0, message));
+    size_t num_lines = 1, size = 0, length = 0, total = 0;
+    const char *cp = message;
+    while (*cp) {
+        if (*cp == '\n') {
+            if (cp[1]) {
+                ++num_lines;
+            }
+        } else {
+            ++size;
+        }
+        ++cp;
+        ++total;
+        ++length;
+        if ((LOGGER_ENTRY_MAX_PAYLOAD - 4 - 1 - 4) <= length) {
+            break;
+        }
+    }
+    while (*cp) {
+        ++cp;
+        ++total;
+    }
     usleep(1000000);
 
     int count = 0;
@@ -200,7 +220,7 @@
 
         if ((log_msg.entry.sec < (ts.tv_sec - 1))
          || ((ts.tv_sec + 1) < log_msg.entry.sec)
-         || (log_msg.entry.len != (4 + 1 + 4 + sizeof(buffer) - 1))
+         || ((size_t)log_msg.entry.len != (4 + 1 + 4 + length))
          || (log_msg.id() != LOG_ID_EVENTS)) {
             continue;
         }
@@ -211,21 +231,22 @@
             continue;
         }
 
-        int len = get4LE(eventData + 4 + 1);
-        if (len == (sizeof(buffer) - 1)) {
+        size_t len = get4LE(eventData + 4 + 1);
+        if (len == total) {
             ++count;
 
             AndroidLogFormat *logformat = android_log_format_new();
             EXPECT_TRUE(NULL != logformat);
             AndroidLogEntry entry;
             char msgBuf[1024];
-            EXPECT_EQ(0, android_log_processBinaryLogBuffer(&log_msg.entry_v1,
-                                                            &entry,
-                                                            NULL,
-                                                            msgBuf,
-                                                            sizeof(msgBuf)));
-            fflush(stderr);
-            EXPECT_EQ(31, android_log_printLogLine(logformat, fileno(stderr), &entry));
+            int processBinaryLogBuffer = android_log_processBinaryLogBuffer(
+                &log_msg.entry_v1, &entry, NULL, msgBuf, sizeof(msgBuf));
+            EXPECT_EQ((length == total) ? 0 : -1, processBinaryLogBuffer);
+            if (processBinaryLogBuffer == 0) {
+                fflush(stderr);
+                EXPECT_EQ((int)((20 * num_lines) + size),
+                    android_log_printLogLine(logformat, fileno(stderr), &entry));
+            }
             android_log_format_free(logformat);
         }
     }
@@ -235,18 +256,55 @@
     android_logger_list_close(logger_list);
 }
 
-TEST(liblog, __android_log_bswrite__empty_string) {
+TEST(liblog, __android_log_bswrite_and_print) {
+    bswrite_test("Hello World");
+}
+
+TEST(liblog, __android_log_bswrite_and_print__empty_string) {
+    bswrite_test("");
+}
+
+TEST(liblog, __android_log_bswrite_and_print__newline_prefix) {
+    bswrite_test("\nHello World\n");
+}
+
+TEST(liblog, __android_log_bswrite_and_print__newline_space_prefix) {
+    bswrite_test("\n Hello World \n");
+}
+
+TEST(liblog, __android_log_bswrite_and_print__multiple_newline) {
+    bswrite_test("one\ntwo\nthree\nfour\nfive\nsix\nseven\neight\nnine\nten");
+}
+
+static void buf_write_test(const char *message) {
     struct logger_list *logger_list;
 
     pid_t pid = getpid();
 
     ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
-        LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
+        LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
 
-    static const char buffer[] = "";
+    static const char tag[] = "TEST__android_log_buf_write";
     log_time ts(android_log_clockid());
 
-    ASSERT_LT(0, __android_log_bswrite(0, buffer));
+    EXPECT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO,
+                                         tag, message));
+    size_t num_lines = 1, size = 0, length = 0;
+    const char *cp = message;
+    while (*cp) {
+        if (*cp == '\n') {
+            if (cp[1]) {
+                ++num_lines;
+            }
+        } else {
+            ++size;
+        }
+        ++length;
+        if ((LOGGER_ENTRY_MAX_PAYLOAD - 2 - sizeof(tag)) <= length) {
+            break;
+        }
+        ++cp;
+    }
     usleep(1000000);
 
     int count = 0;
@@ -261,34 +319,25 @@
 
         if ((log_msg.entry.sec < (ts.tv_sec - 1))
          || ((ts.tv_sec + 1) < log_msg.entry.sec)
-         || (log_msg.entry.len != (4 + 1 + 4))
-         || (log_msg.id() != LOG_ID_EVENTS)) {
+         || ((size_t)log_msg.entry.len != (sizeof(tag) + length + 2))
+         || (log_msg.id() != LOG_ID_MAIN)) {
             continue;
         }
 
-        char *eventData = log_msg.msg();
+        ++count;
 
-        if (eventData[4] != EVENT_TYPE_STRING) {
-            continue;
-        }
-
-        int len = get4LE(eventData + 4 + 1);
-        if (len == 0) {
-            ++count;
-
-            AndroidLogFormat *logformat = android_log_format_new();
-            EXPECT_TRUE(NULL != logformat);
-            AndroidLogEntry entry;
-            char msgBuf[1024];
-            EXPECT_EQ(0, android_log_processBinaryLogBuffer(&log_msg.entry_v1,
-                                                            &entry,
-                                                            NULL,
-                                                            msgBuf,
-                                                            sizeof(msgBuf)));
+        AndroidLogFormat *logformat = android_log_format_new();
+        EXPECT_TRUE(NULL != logformat);
+        AndroidLogEntry entry;
+        int processLogBuffer = android_log_processLogBuffer(&log_msg.entry_v1,
+                                                            &entry);
+        EXPECT_EQ(0, processLogBuffer);
+        if (processLogBuffer == 0) {
             fflush(stderr);
-            EXPECT_EQ(20, android_log_printLogLine(logformat, fileno(stderr), &entry));
-            android_log_format_free(logformat);
+            EXPECT_EQ((int)(((11 + sizeof(tag)) * num_lines) + size),
+                android_log_printLogLine(logformat, fileno(stderr), &entry));
         }
+        android_log_format_free(logformat);
     }
 
     EXPECT_EQ(1, count);
@@ -296,6 +345,18 @@
     android_logger_list_close(logger_list);
 }
 
+TEST(liblog, __android_log_buf_write_and_print__empty) {
+    buf_write_test("");
+}
+
+TEST(liblog, __android_log_buf_write_and_print__newline_prefix) {
+    buf_write_test("\nHello World\n");
+}
+
+TEST(liblog, __android_log_buf_write_and_print__newline_space_prefix) {
+    buf_write_test("\n Hello World \n");
+}
+
 TEST(liblog, __security) {
     static const char persist_key[] = "persist.logd.security";
     static const char readonly_key[] = "ro.device_owner";
@@ -767,7 +828,7 @@
     EXPECT_GT(one_percent_ticks, user_ticks + system_ticks);
 }
 
-static const char max_payload_tag[] = "TEST_max_payload_XXXX";
+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)
 static const char max_payload_buf[] = "LEONATO\n\
@@ -1802,6 +1863,14 @@
     android_logger_list_close(logger_list);
 }
 
+TEST(liblog, __android_log_bswrite_and_print___max) {
+    bswrite_test(max_payload_buf);
+}
+
+TEST(liblog, __android_log_buf_write_and_print__max) {
+    buf_write_test(max_payload_buf);
+}
+
 TEST(liblog, android_errorWriteLog__android_logger_list_read__success) {
     const int TAG = 123456785;
     const char SUBTAG[] = "test-subtag";
diff --git a/libmemtrack/Android.mk b/libmemtrack/Android.mk
index 7b170f5..ffc7244 100644
--- a/libmemtrack/Android.mk
+++ b/libmemtrack/Android.mk
@@ -5,6 +5,8 @@
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := memtrack.c
 LOCAL_MODULE := libmemtrack
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
 LOCAL_C_INCLUDES += hardware/libhardware/include
 LOCAL_SHARED_LIBRARIES := libhardware liblog
 LOCAL_CFLAGS := -Wall -Werror
diff --git a/include/memtrack/memtrack.h b/libmemtrack/include/memtrack/memtrack.h
similarity index 98%
rename from include/memtrack/memtrack.h
rename to libmemtrack/include/memtrack/memtrack.h
index 3917300..8c0ab89 100644
--- a/include/memtrack/memtrack.h
+++ b/libmemtrack/include/memtrack/memtrack.h
@@ -19,7 +19,6 @@
 
 #include <sys/types.h>
 #include <stddef.h>
-#include <cutils/compiler.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/libmemunreachable/ProcessMappings.cpp b/libmemunreachable/ProcessMappings.cpp
index 7cca7c1..57b2321 100644
--- a/libmemunreachable/ProcessMappings.cpp
+++ b/libmemunreachable/ProcessMappings.cpp
@@ -30,11 +30,10 @@
 bool ProcessMappings(pid_t pid, allocator::vector<Mapping>& mappings) {
   char map_buffer[1024];
   snprintf(map_buffer, sizeof(map_buffer), "/proc/%d/maps", pid);
-  int fd = open(map_buffer, O_RDONLY);
-  if (fd < 0) {
+  android::base::unique_fd fd(open(map_buffer, O_RDONLY));
+  if (fd == -1) {
     return false;
   }
-  android::base::unique_fd fd_guard{fd};
 
   LineBuffer line_buf(fd, map_buffer, sizeof(map_buffer));
   char* line;
diff --git a/libmemunreachable/ThreadCapture.cpp b/libmemunreachable/ThreadCapture.cpp
index e8a8392..9155c29 100644
--- a/libmemunreachable/ThreadCapture.cpp
+++ b/libmemunreachable/ThreadCapture.cpp
@@ -108,12 +108,11 @@
   strlcat(path, pid_str, sizeof(path));
   strlcat(path, "/task", sizeof(path));
 
-  int fd = open(path, O_CLOEXEC | O_DIRECTORY | O_RDONLY);
-  if (fd < 0) {
+  android::base::unique_fd fd(open(path, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
+  if (fd == -1) {
     ALOGE("failed to open %s: %s", path, strerror(errno));
     return false;
   }
-  android::base::unique_fd fd_guard{fd};
 
   struct linux_dirent64 {
     uint64_t  d_ino;
@@ -125,7 +124,7 @@
   char dirent_buf[4096];
   ssize_t nread;
   do {
-    nread = syscall(SYS_getdents64, fd, dirent_buf, sizeof(dirent_buf));
+    nread = syscall(SYS_getdents64, fd.get(), dirent_buf, sizeof(dirent_buf));
     if (nread < 0) {
       ALOGE("failed to get directory entries from %s: %s", path, strerror(errno));
       return false;
diff --git a/libmemunreachable/tests/ThreadCapture_test.cpp b/libmemunreachable/tests/ThreadCapture_test.cpp
index cefe94e..41ed84e 100644
--- a/libmemunreachable/tests/ThreadCapture_test.cpp
+++ b/libmemunreachable/tests/ThreadCapture_test.cpp
@@ -28,8 +28,6 @@
 
 #include <gtest/gtest.h>
 
-#include <android-base/unique_fd.h>
-
 #include "Allocator.h"
 #include "ScopedDisableMalloc.h"
 #include "ScopedPipe.h"
diff --git a/libmincrypt/Android.mk b/libmincrypt/Android.mk
index 7906986..09fbbb1 100644
--- a/libmincrypt/Android.mk
+++ b/libmincrypt/Android.mk
@@ -14,5 +14,4 @@
 LOCAL_CFLAGS := -Wall -Werror
 include $(BUILD_HOST_STATIC_LIBRARY)
 
-include $(LOCAL_PATH)/tools/Android.mk \
-        $(LOCAL_PATH)/test/Android.mk
+include $(LOCAL_PATH)/test/Android.mk
diff --git a/libmincrypt/tools/DumpPublicKey.java b/libmincrypt/tools/DumpPublicKey.java
deleted file mode 100644
index 3eb1398..0000000
--- a/libmincrypt/tools/DumpPublicKey.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-package com.android.dumpkey;
-
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
-import java.io.FileInputStream;
-import java.math.BigInteger;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.security.KeyStore;
-import java.security.Key;
-import java.security.PublicKey;
-import java.security.Security;
-import java.security.interfaces.ECPublicKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.ECPoint;
-
-/**
- * Command line tool to extract RSA public keys from X.509 certificates
- * and output source code with data initializers for the keys.
- * @hide
- */
-class DumpPublicKey {
-    /**
-     * @param key to perform sanity checks on
-     * @return version number of key.  Supported versions are:
-     *     1: 2048-bit RSA key with e=3 and SHA-1 hash
-     *     2: 2048-bit RSA key with e=65537 and SHA-1 hash
-     *     3: 2048-bit RSA key with e=3 and SHA-256 hash
-     *     4: 2048-bit RSA key with e=65537 and SHA-256 hash
-     * @throws Exception if the key has the wrong size or public exponent
-     */
-    static int checkRSA(RSAPublicKey key, boolean useSHA256) throws Exception {
-        BigInteger pubexp = key.getPublicExponent();
-        BigInteger modulus = key.getModulus();
-        int version;
-
-        if (pubexp.equals(BigInteger.valueOf(3))) {
-            version = useSHA256 ? 3 : 1;
-        } else if (pubexp.equals(BigInteger.valueOf(65537))) {
-            version = useSHA256 ? 4 : 2;
-        } else {
-            throw new Exception("Public exponent should be 3 or 65537 but is " +
-                                pubexp.toString(10) + ".");
-        }
-
-        if (modulus.bitLength() != 2048) {
-             throw new Exception("Modulus should be 2048 bits long but is " +
-                        modulus.bitLength() + " bits.");
-        }
-
-        return version;
-    }
-
-    /**
-     * @param key to perform sanity checks on
-     * @return version number of key.  Supported versions are:
-     *     5: 256-bit EC key with curve NIST P-256
-     * @throws Exception if the key has the wrong size or public exponent
-     */
-    static int checkEC(ECPublicKey key) throws Exception {
-        if (key.getParams().getCurve().getField().getFieldSize() != 256) {
-            throw new Exception("Curve must be NIST P-256");
-        }
-
-        return 5;
-    }
-
-    /**
-     * Perform sanity check on public key.
-     */
-    static int check(PublicKey key, boolean useSHA256) throws Exception {
-        if (key instanceof RSAPublicKey) {
-            return checkRSA((RSAPublicKey) key, useSHA256);
-        } else if (key instanceof ECPublicKey) {
-            if (!useSHA256) {
-                throw new Exception("Must use SHA-256 with EC keys!");
-            }
-            return checkEC((ECPublicKey) key);
-        } else {
-            throw new Exception("Unsupported key class: " + key.getClass().getName());
-        }
-    }
-
-    /**
-     * @param key to output
-     * @return a String representing this public key.  If the key is a
-     *    version 1 key, the string will be a C initializer; this is
-     *    not true for newer key versions.
-     */
-    static String printRSA(RSAPublicKey key, boolean useSHA256) throws Exception {
-        int version = check(key, useSHA256);
-
-        BigInteger N = key.getModulus();
-
-        StringBuilder result = new StringBuilder();
-
-        int nwords = N.bitLength() / 32;    // # of 32 bit integers in modulus
-
-        if (version > 1) {
-            result.append("v");
-            result.append(Integer.toString(version));
-            result.append(" ");
-        }
-
-        result.append("{");
-        result.append(nwords);
-
-        BigInteger B = BigInteger.valueOf(0x100000000L);  // 2^32
-        BigInteger N0inv = B.subtract(N.modInverse(B));   // -1 / N[0] mod 2^32
-
-        result.append(",0x");
-        result.append(N0inv.toString(16));
-
-        BigInteger R = BigInteger.valueOf(2).pow(N.bitLength());
-        BigInteger RR = R.multiply(R).mod(N);    // 2^4096 mod N
-
-        // Write out modulus as little endian array of integers.
-        result.append(",{");
-        for (int i = 0; i < nwords; ++i) {
-            long n = N.mod(B).longValue();
-            result.append(n);
-
-            if (i != nwords - 1) {
-                result.append(",");
-            }
-
-            N = N.divide(B);
-        }
-        result.append("}");
-
-        // Write R^2 as little endian array of integers.
-        result.append(",{");
-        for (int i = 0; i < nwords; ++i) {
-            long rr = RR.mod(B).longValue();
-            result.append(rr);
-
-            if (i != nwords - 1) {
-                result.append(",");
-            }
-
-            RR = RR.divide(B);
-        }
-        result.append("}");
-
-        result.append("}");
-        return result.toString();
-    }
-
-    /**
-     * @param key to output
-     * @return a String representing this public key.  If the key is a
-     *    version 1 key, the string will be a C initializer; this is
-     *    not true for newer key versions.
-     */
-    static String printEC(ECPublicKey key) throws Exception {
-        int version = checkEC(key);
-
-        StringBuilder result = new StringBuilder();
-
-        result.append("v");
-        result.append(Integer.toString(version));
-        result.append(" ");
-
-        BigInteger X = key.getW().getAffineX();
-        BigInteger Y = key.getW().getAffineY();
-        int nbytes = key.getParams().getCurve().getField().getFieldSize() / 8;    // # of 32 bit integers in X coordinate
-
-        result.append("{");
-        result.append(nbytes);
-
-        BigInteger B = BigInteger.valueOf(0x100L);  // 2^8
-
-        // Write out Y coordinate as array of characters.
-        result.append(",{");
-        for (int i = 0; i < nbytes; ++i) {
-            long n = X.mod(B).longValue();
-            result.append(n);
-
-            if (i != nbytes - 1) {
-                result.append(",");
-            }
-
-            X = X.divide(B);
-        }
-        result.append("}");
-
-        // Write out Y coordinate as array of characters.
-        result.append(",{");
-        for (int i = 0; i < nbytes; ++i) {
-            long n = Y.mod(B).longValue();
-            result.append(n);
-
-            if (i != nbytes - 1) {
-                result.append(",");
-            }
-
-            Y = Y.divide(B);
-        }
-        result.append("}");
-
-        result.append("}");
-        return result.toString();
-    }
-
-    static String print(PublicKey key, boolean useSHA256) throws Exception {
-        if (key instanceof RSAPublicKey) {
-            return printRSA((RSAPublicKey) key, useSHA256);
-        } else if (key instanceof ECPublicKey) {
-            return printEC((ECPublicKey) key);
-        } else {
-            throw new Exception("Unsupported key class: " + key.getClass().getName());
-        }
-    }
-
-    public static void main(String[] args) {
-        if (args.length < 1) {
-            System.err.println("Usage: DumpPublicKey certfile ... > source.c");
-            System.exit(1);
-        }
-        Security.addProvider(new BouncyCastleProvider());
-        try {
-            for (int i = 0; i < args.length; i++) {
-                FileInputStream input = new FileInputStream(args[i]);
-                CertificateFactory cf = CertificateFactory.getInstance("X.509");
-                X509Certificate cert = (X509Certificate) cf.generateCertificate(input);
-
-                boolean useSHA256 = false;
-                String sigAlg = cert.getSigAlgName();
-                if ("SHA1withRSA".equals(sigAlg) || "MD5withRSA".equals(sigAlg)) {
-                    // SignApk has historically accepted "MD5withRSA"
-                    // certificates, but treated them as "SHA1withRSA"
-                    // anyway.  Continue to do so for backwards
-                    // compatibility.
-                  useSHA256 = false;
-                } else if ("SHA256withRSA".equals(sigAlg) || "SHA256withECDSA".equals(sigAlg)) {
-                  useSHA256 = true;
-                } else {
-                  System.err.println(args[i] + ": unsupported signature algorithm \"" +
-                                     sigAlg + "\"");
-                  System.exit(1);
-                }
-
-                PublicKey key = cert.getPublicKey();
-                check(key, useSHA256);
-                System.out.print(print(key, useSHA256));
-                System.out.println(i < args.length - 1 ? "," : "");
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            System.exit(1);
-        }
-        System.exit(0);
-    }
-}
diff --git a/libmincrypt/tools/DumpPublicKey.mf b/libmincrypt/tools/DumpPublicKey.mf
deleted file mode 100644
index 7bb3bc8..0000000
--- a/libmincrypt/tools/DumpPublicKey.mf
+++ /dev/null
@@ -1 +0,0 @@
-Main-Class: com.android.dumpkey.DumpPublicKey
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index 32a65ea..ecfd719 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -231,8 +231,10 @@
 static const char* kRuntimeISA = "arm";
 #elif defined(__aarch64__)
 static const char* kRuntimeISA = "arm64";
-#elif defined(__mips__)
+#elif defined(__mips__) && !defined(__LP64__)
 static const char* kRuntimeISA = "mips";
+#elif defined(__mips__) && defined(__LP64__)
+static const char* kRuntimeISA = "mips64";
 #elif defined(__i386__)
 static const char* kRuntimeISA = "x86";
 #elif defined(__x86_64__)
diff --git a/libnativebridge/tests/NeedsNativeBridge_test.cpp b/libnativebridge/tests/NeedsNativeBridge_test.cpp
index e1c0876..2067ed2 100644
--- a/libnativebridge/tests/NeedsNativeBridge_test.cpp
+++ b/libnativebridge/tests/NeedsNativeBridge_test.cpp
@@ -18,15 +18,17 @@
 
 namespace android {
 
-static const char* kISAs[] = { "arm", "arm64", "mips", "x86", "x86_64", "random", "64arm", "64_x86",
-                               "64_x86_64", "", "reallylongstringabcd", nullptr };
+static const char* kISAs[] = { "arm", "arm64", "mips", "mips64", "x86", "x86_64", "random", "64arm",
+                               "64_x86", "64_x86_64", "", "reallylongstringabcd", nullptr };
 
 #if defined(__arm__)
 static const char* kRuntimeISA = "arm";
 #elif defined(__aarch64__)
 static const char* kRuntimeISA = "arm64";
-#elif defined(__mips__)
+#elif defined(__mips__) && !defined(__LP64__)
 static const char* kRuntimeISA = "mips";
+#elif defined(__mips__) && defined(__LP64__)
+static const char* kRuntimeISA = "mips64";
 #elif defined(__i386__)
 static const char* kRuntimeISA = "x86";
 #elif defined(__x86_64__)
diff --git a/libnetutils/Android.mk b/libnetutils/Android.mk
index ff899c0..ce7c3ba 100644
--- a/libnetutils/Android.mk
+++ b/libnetutils/Android.mk
@@ -15,6 +15,9 @@
 
 LOCAL_CFLAGS := -Werror
 
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+
 include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
diff --git a/include/netutils/dhcp.h b/libnetutils/include/netutils/dhcp.h
similarity index 100%
rename from include/netutils/dhcp.h
rename to libnetutils/include/netutils/dhcp.h
diff --git a/include/netutils/ifc.h b/libnetutils/include/netutils/ifc.h
similarity index 100%
rename from include/netutils/ifc.h
rename to libnetutils/include/netutils/ifc.h
diff --git a/libpackagelistparser/packagelistparser.c b/libpackagelistparser/packagelistparser.c
index 16052e2..e309027 100644
--- a/libpackagelistparser/packagelistparser.c
+++ b/libpackagelistparser/packagelistparser.c
@@ -27,7 +27,7 @@
 #include <sys/limits.h>
 
 #define LOG_TAG "packagelistparser"
-#include <utils/Log.h>
+#include <cutils/log.h>
 
 #include <packagelistparser/packagelistparser.h>
 
diff --git a/libpixelflinger/codeflinger/GGLAssembler.h b/libpixelflinger/codeflinger/GGLAssembler.h
index 9db20df..ecc242a 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.h
+++ b/libpixelflinger/codeflinger/GGLAssembler.h
@@ -288,6 +288,14 @@
 
 
 private:
+    // GGLAssembler hides RegisterAllocator's and ARMAssemblerProxy's reset
+    // methods by providing a reset method with a different parameter set. The
+    // intent of GGLAssembler's reset method is to wrap the inherited reset
+    // methods, so make these methods private in order to prevent direct calls
+    // to these methods from clients.
+    using RegisterAllocator::reset;
+    using ARMAssemblerProxy::reset;
+
     struct tex_coord_t {
         reg_t       s;
         reg_t       t;
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 1bc1659..cfc9ae2 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -29,6 +29,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <memory>
 
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
@@ -201,11 +202,11 @@
 
 static void removeUidProcessGroups(const char *uid_path)
 {
-    DIR *uid = opendir(uid_path);
+    std::unique_ptr<DIR, decltype(&closedir)> uid(opendir(uid_path), closedir);
     if (uid != NULL) {
         struct dirent cur;
         struct dirent *dir;
-        while ((readdir_r(uid, &cur, &dir) == 0) && dir) {
+        while ((readdir_r(uid.get(), &cur, &dir) == 0) && dir) {
             char path[PROCESSGROUP_MAX_PATH_LEN];
 
             if (dir->d_type != DT_DIR) {
@@ -220,7 +221,6 @@
             SLOGV("removing %s\n", path);
             rmdir(path);
         }
-        closedir(uid);
     }
 }
 
@@ -228,13 +228,13 @@
 {
     SLOGV("removeAllProcessGroups()");
     const char *cgroup_root_path = getCgroupRootPath();
-    DIR *root = opendir(cgroup_root_path);
+    std::unique_ptr<DIR, decltype(&closedir)> root(opendir(cgroup_root_path), closedir);
     if (root == NULL) {
         SLOGE("failed to open %s: %s", cgroup_root_path, strerror(errno));
     } else {
         struct dirent cur;
         struct dirent *dir;
-        while ((readdir_r(root, &cur, &dir) == 0) && dir) {
+        while ((readdir_r(root.get(), &cur, &dir) == 0) && dir) {
             char path[PROCESSGROUP_MAX_PATH_LEN];
 
             if (dir->d_type != DT_DIR) {
@@ -249,7 +249,6 @@
             SLOGV("removing %s\n", path);
             rmdir(path);
         }
-        closedir(root);
     }
 }
 
diff --git a/libsync/sync_test.c b/libsync/sync_test.c
index ee9ea3c..9a5f7d8 100644
--- a/libsync/sync_test.c
+++ b/libsync/sync_test.c
@@ -92,7 +92,7 @@
 
         for (j = 0; j < 2; j++) {
             unsigned val = i + j * 3 + 1;
-            sprintf(str, "test_fence%d-%d", i, j);
+            snprintf(str, sizeof(str), "test_fence%d-%d", i, j);
             int fd = sw_sync_fence_create(sync_timeline_fd, str, val);
             if (fd < 0) {
                 printf("can't create sync pt %d: %s", val, strerror(errno));
@@ -106,7 +106,7 @@
 
     sync_data[3].thread_no = 3;
     for (j = 0; j < 2; j++) {
-        sprintf(str, "merged_fence%d", j);
+        snprintf(str, sizeof(str), "merged_fence%d", j);
         sync_data[3].fd[j] = sync_merge(str, sync_data[0].fd[j], sync_data[1].fd[j]);
         if (sync_data[3].fd[j] < 0) {
             printf("can't merge sync pts %d and %d: %s\n",
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index 168899c..4d602a6 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -206,7 +206,7 @@
 
             do {
                 alen = sizeof(ss);
-                c = accept(mSock, addrp, &alen);
+                c = accept4(mSock, addrp, &alen, SOCK_CLOEXEC);
                 SLOGV("%s got %d from accept", mSocketName, c);
             } while (c < 0 && errno == EINTR);
             if (c < 0) {
@@ -214,7 +214,6 @@
                 sleep(1);
                 continue;
             }
-            fcntl(c, F_SETFD, FD_CLOEXEC);
             pthread_mutex_lock(&mClientsLock);
             mClients->push_back(new SocketClient(c, true, mUseCmdNum));
             pthread_mutex_unlock(&mClientsLock);
diff --git a/libutils/ProcessCallStack.cpp b/libutils/ProcessCallStack.cpp
index cdb586d..4e87a98 100644
--- a/libutils/ProcessCallStack.cpp
+++ b/libutils/ProcessCallStack.cpp
@@ -21,6 +21,7 @@
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
+#include <memory>
 
 #include <utils/Log.h>
 #include <utils/Errors.h>
@@ -130,11 +131,10 @@
 }
 
 void ProcessCallStack::update() {
-    DIR *dp;
     struct dirent *ep;
     struct dirent entry;
 
-    dp = opendir(PATH_SELF_TASK);
+    std::unique_ptr<DIR, decltype(&closedir)> dp(opendir(PATH_SELF_TASK), closedir);
     if (dp == NULL) {
         ALOGE("%s: Failed to update the process's call stacks: %s",
               __FUNCTION__, strerror(errno));
@@ -159,7 +159,7 @@
      * - Read every file in directory => get every tid
      */
     int code;
-    while ((code = readdir_r(dp, &entry, &ep)) == 0 && ep != NULL) {
+    while ((code = readdir_r(dp.get(), &entry, &ep)) == 0 && ep != NULL) {
         pid_t tid = -1;
         sscanf(ep->d_name, "%d", &tid);
 
@@ -198,8 +198,6 @@
         ALOGE("%s: Failed to readdir from %s: %s",
               __FUNCTION__, PATH_SELF_TASK, strerror(code));
     }
-
-    closedir(dp);
 }
 
 void ProcessCallStack::log(const char* logtag, android_LogPriority priority,
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index 02907ad..ea1e4db 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -190,17 +190,22 @@
         {
             Mutex::Autolock _l(mMutex);
             char buf[128];
-            sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this);
+            snprintf(buf, sizeof(buf),
+                     "Strong references on RefBase %p (weakref_type %p):\n",
+                     mBase, this);
             text.append(buf);
             printRefsLocked(&text, mStrongRefs);
-            sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this);
+            snprintf(buf, sizeof(buf),
+                     "Weak references on RefBase %p (weakref_type %p):\n",
+                     mBase, this);
             text.append(buf);
             printRefsLocked(&text, mWeakRefs);
         }
 
         {
             char name[100];
-            snprintf(name, 100, DEBUG_REFS_CALLSTACK_PATH "/%p.stack", this);
+            snprintf(name, sizeof(name), DEBUG_REFS_CALLSTACK_PATH "/%p.stack",
+                     this);
             int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 644);
             if (rc >= 0) {
                 write(rc, text.string(), text.length());
@@ -293,8 +298,8 @@
         char buf[128];
         while (refs) {
             char inc = refs->ref >= 0 ? '+' : '-';
-            sprintf(buf, "\t%c ID %p (ref %d):\n", 
-                    inc, refs->id, refs->ref);
+            snprintf(buf, sizeof(buf), "\t%c ID %p (ref %d):\n",
+                     inc, refs->id, refs->ref);
             out->append(buf);
 #if DEBUG_REFS_CALLSTACK_ENABLED
             out->append(refs->stack.toString("\t\t"));
diff --git a/libutils/String16.cpp b/libutils/String16.cpp
index 6a5273f..87eda1b 100644
--- a/libutils/String16.cpp
+++ b/libutils/String16.cpp
@@ -18,7 +18,6 @@
 
 #include <utils/Log.h>
 #include <utils/Unicode.h>
-#include <utils/String8.h>
 #include <utils/threads.h>
 
 #include <memory.h>
@@ -77,7 +76,7 @@
         //printf("Created UTF-16 string from UTF-8 \"%s\":", in);
         //printHexData(1, str, buf->size(), 16, 1);
         //printf("\n");
-        
+
         return u16str;
     }
 
@@ -127,7 +126,7 @@
         mString = str;
         return;
     }
-    
+
     mString = getEmptyString();
 }
 
@@ -142,7 +141,7 @@
         mString = str;
         return;
     }
-    
+
     mString = getEmptyString();
 }
 
@@ -228,7 +227,7 @@
     } else if (otherLen == 0) {
         return NO_ERROR;
     }
-    
+
     SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
         ->editResize((myLen+otherLen+1)*sizeof(char16_t));
     if (buf) {
@@ -249,7 +248,7 @@
     } else if (otherLen == 0) {
         return NO_ERROR;
     }
-    
+
     SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
         ->editResize((myLen+otherLen+1)*sizeof(char16_t));
     if (buf) {
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index 771d312..ad45282 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -362,7 +362,7 @@
 status_t String8::real_append(const char* other, size_t otherLen)
 {
     const size_t myLen = bytes();
-    
+
     SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
         ->editResize(myLen+otherLen+1);
     if (buf) {
diff --git a/libutils/SystemClock.cpp b/libutils/SystemClock.cpp
index 1fca2b2..c5ae327 100644
--- a/libutils/SystemClock.cpp
+++ b/libutils/SystemClock.cpp
@@ -56,66 +56,12 @@
 	return nanoseconds_to_milliseconds(elapsedRealtimeNano());
 }
 
-#define METHOD_CLOCK_GETTIME    0
-#define METHOD_IOCTL            1
-#define METHOD_SYSTEMTIME       2
-
-/*
- * To debug/verify the timestamps returned by the kernel, change
- * DEBUG_TIMESTAMP to 1 and call the timestamp routine from a single thread
- * in the test program. b/10899829
- */
-#define DEBUG_TIMESTAMP         0
-
-#if DEBUG_TIMESTAMP && defined(__arm__)
-static inline void checkTimeStamps(int64_t timestamp,
-                                   int64_t volatile *prevTimestampPtr,
-                                   int volatile *prevMethodPtr,
-                                   int curMethod)
-{
-    /*
-     * Disable the check for SDK since the prebuilt toolchain doesn't contain
-     * gettid, and int64_t is different on the ARM platform
-     * (ie long vs long long).
-     */
-    int64_t prevTimestamp = *prevTimestampPtr;
-    int prevMethod = *prevMethodPtr;
-
-    if (timestamp < prevTimestamp) {
-        static const char *gettime_method_names[] = {
-            "clock_gettime",
-            "ioctl",
-            "systemTime",
-        };
-
-        ALOGW("time going backwards: prev %lld(%s) vs now %lld(%s), tid=%d",
-              prevTimestamp, gettime_method_names[prevMethod],
-              timestamp, gettime_method_names[curMethod],
-              gettid());
-    }
-    // NOTE - not atomic and may generate spurious warnings if the 64-bit
-    // write is interrupted or not observed as a whole.
-    *prevTimestampPtr = timestamp;
-    *prevMethodPtr = curMethod;
-}
-#else
-#define checkTimeStamps(timestamp, prevTimestampPtr, prevMethodPtr, curMethod)
-#endif
-
 /*
  * native public static long elapsedRealtimeNano();
  */
 int64_t elapsedRealtimeNano()
 {
 #if defined(__ANDROID__)
-    struct timespec ts;
-    int result;
-    int64_t timestamp;
-#if DEBUG_TIMESTAMP
-    static volatile int64_t prevTimestamp;
-    static volatile int prevMethod;
-#endif
-
     static int s_fd = -1;
 
     if (s_fd == -1) {
@@ -125,31 +71,20 @@
         }
     }
 
-    result = ioctl(s_fd,
-            ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts);
-
-    if (result == 0) {
-        timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
-        checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, METHOD_IOCTL);
-        return timestamp;
+    struct timespec ts;
+    if (ioctl(s_fd, ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts) == 0) {
+        return seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
     }
 
     // /dev/alarm doesn't exist, fallback to CLOCK_BOOTTIME
-    result = clock_gettime(CLOCK_BOOTTIME, &ts);
-    if (result == 0) {
-        timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
-        checkTimeStamps(timestamp, &prevTimestamp, &prevMethod,
-                        METHOD_CLOCK_GETTIME);
-        return timestamp;
+    if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0) {
+        return seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
     }
 
     // XXX: there was an error, probably because the driver didn't
     // exist ... this should return
     // a real error, like an exception!
-    timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
-    checkTimeStamps(timestamp, &prevTimestamp, &prevMethod,
-                    METHOD_SYSTEMTIME);
-    return timestamp;
+    return systemTime(SYSTEM_TIME_MONOTONIC);
 #else
     return systemTime(SYSTEM_TIME_MONOTONIC);
 #endif
diff --git a/libutils/tests/Vector_test.cpp b/libutils/tests/Vector_test.cpp
index d9b32f9..24ecf86 100644
--- a/libutils/tests/Vector_test.cpp
+++ b/libutils/tests/Vector_test.cpp
@@ -89,9 +89,9 @@
   vector.add(4);
 
   vector.setCapacity(8);
-  ASSERT_EQ(8, vector.capacity());
+  ASSERT_EQ(8U, vector.capacity());
   vector.setCapacity(2);
-  ASSERT_EQ(8, vector.capacity());
+  ASSERT_EQ(8U, vector.capacity());
 }
 
 // NOTE: All of the tests below are useless because of the "TODO" above.
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 37f4f4f..e65469a 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -35,7 +35,7 @@
 #include <log/logd.h>
 #include <log/logger.h>
 #include <log/logprint.h>
-#include <utils/threads.h>
+#include <system/thread_defs.h>
 
 #include <pcrecpp.h>
 
diff --git a/logcat/logpersist b/logcat/logpersist
index dab466d..8762ff1 100755
--- a/logcat/logpersist
+++ b/logcat/logpersist
@@ -1,8 +1,8 @@
 #! /system/bin/sh
 # logpersist cat start and stop handlers
 progname="${0##*/}"
-case `getprop ro.build.type` in
-userdebug|eng) ;;
+case `getprop ro.debuggable` in
+1) ;;
 *) echo "${progname} - Permission denied"
    exit 1
    ;;
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 921a461..a606b6f 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -23,6 +23,8 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
+#include <memory>
+
 #include <gtest/gtest.h>
 #include <log/log.h>
 #include <log/logger.h>
@@ -153,23 +155,29 @@
         return;
     }
 
-    FILE *fp;
+    int tries = 3; // in case run too soon after system start or buffer clear
+    int count;
 
-    ASSERT_TRUE(NULL != (fp = popen(
-      "logcat -v long -v America/Los_Angeles -b all -t 3 2>/dev/null",
-      "r")));
+    do {
+        FILE *fp;
 
-    char buffer[5120];
+        ASSERT_TRUE(NULL != (fp = popen(
+          "logcat -v long -v America/Los_Angeles -b all -t 3 2>/dev/null",
+          "r")));
 
-    int count = 0;
+        char buffer[5120];
 
-    while (fgetLongTime(buffer, sizeof(buffer), fp)) {
-        if (strstr(buffer, " -0700") || strstr(buffer, " -0800")) {
-            ++count;
+        count = 0;
+
+        while (fgetLongTime(buffer, sizeof(buffer), fp)) {
+            if (strstr(buffer, " -0700") || strstr(buffer, " -0800")) {
+                ++count;
+            }
         }
-    }
 
-    pclose(fp);
+        pclose(fp);
+
+    } while ((count < 3) && --tries && (sleep(1), true));
 
     ASSERT_EQ(3, count);
 }
@@ -196,84 +204,47 @@
     ASSERT_EQ(0, count);
 }
 
+void do_tail(int num) {
+    int tries = 3; // in case run too soon after system start or buffer clear
+    int count;
+
+    do {
+        char buffer[5120];
+
+        snprintf(buffer, sizeof(buffer),
+          "logcat -v long -b radio -b events -b system -b main -t %d 2>/dev/null",
+          num);
+
+        FILE *fp;
+        ASSERT_TRUE(NULL != (fp = popen(buffer, "r")));
+
+        count = 0;
+
+        while (fgetLongTime(buffer, sizeof(buffer), fp)) {
+            ++count;
+        }
+
+        pclose(fp);
+
+    } while ((count < num) && --tries && (sleep(1), true));
+
+    ASSERT_EQ(num, count);
+}
+
 TEST(logcat, tail_3) {
-    FILE *fp;
-
-    ASSERT_TRUE(NULL != (fp = popen(
-      "logcat -v long -b radio -b events -b system -b main -t 3 2>/dev/null",
-      "r")));
-
-    char buffer[5120];
-
-    int count = 0;
-
-    while (fgetLongTime(buffer, sizeof(buffer), fp)) {
-        ++count;
-    }
-
-    pclose(fp);
-
-    ASSERT_EQ(3, count);
+    do_tail(3);
 }
 
 TEST(logcat, tail_10) {
-    FILE *fp;
-
-    ASSERT_TRUE(NULL != (fp = popen(
-      "logcat -v long -b radio -b events -b system -b main -t 10 2>/dev/null",
-      "r")));
-
-    char buffer[5120];
-
-    int count = 0;
-
-    while (fgetLongTime(buffer, sizeof(buffer), fp)) {
-        ++count;
-    }
-
-    pclose(fp);
-
-    ASSERT_EQ(10, count);
+    do_tail(10);
 }
 
 TEST(logcat, tail_100) {
-    FILE *fp;
-
-    ASSERT_TRUE(NULL != (fp = popen(
-      "logcat -v long -b radio -b events -b system -b main -t 100 2>/dev/null",
-      "r")));
-
-    char buffer[5120];
-
-    int count = 0;
-
-    while (fgetLongTime(buffer, sizeof(buffer), fp)) {
-        ++count;
-    }
-
-    pclose(fp);
-
-    ASSERT_EQ(100, count);
+    do_tail(100);
 }
 
 TEST(logcat, tail_1000) {
-    FILE *fp;
-
-    ASSERT_TRUE(NULL != (fp = popen(
-      "logcat -v long -b radio -b events -b system -b main -t 1000 2>/dev/null",
-      "r")));
-
-    char buffer[5120];
-
-    int count = 0;
-
-    while (fgetLongTime(buffer, sizeof(buffer), fp)) {
-        ++count;
-    }
-
-    pclose(fp);
-
-    ASSERT_EQ(1000, count);
+    do_tail(1000);
 }
 
 TEST(logcat, tail_time) {
@@ -735,8 +706,8 @@
         EXPECT_FALSE(system(command));
         return;
     }
-    DIR *dir;
-    EXPECT_TRUE(NULL != (dir = opendir(tmp_out_dir)));
+    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir);
+    EXPECT_NE(nullptr, dir);
     if (!dir) {
         snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
         EXPECT_FALSE(system(command));
@@ -744,7 +715,7 @@
     }
     struct dirent *entry;
     unsigned count = 0;
-    while ((entry = readdir(dir))) {
+    while ((entry = readdir(dir.get()))) {
         if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
             continue;
         }
@@ -767,7 +738,6 @@
         free(line);
         unlink(command);
     }
-    closedir(dir);
     if (count > 1) {
         char *brk = strpbrk(second_last_line, "\r\n");
         if (!brk) {
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 9124bfd..4eb5e83 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -164,6 +164,10 @@
         }
     }
 
+    // Note: The audit log can include untrusted strings, but those containing
+    // "a control character, unprintable character, double quote mark, or a
+    // space" are hex encoded. The space character before the search term is
+    // therefore needed to prevent denial of service. Do not remove the space.
     bool permissive = strstr(str, " enforcing=0") ||
                       strstr(str, " permissive=1");
 
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index fd4800e..aa4b6e1 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -17,6 +17,7 @@
 #ifndef _LOGD_LOG_UTILS_H__
 #define _LOGD_LOG_UTILS_H__
 
+#include <sys/cdefs.h>
 #include <sys/types.h>
 
 #include <log/log.h>
@@ -29,6 +30,7 @@
 
 // Furnished in main.cpp. Caller must own and free returned value
 char *uidToName(uid_t uid);
+void prdebug(const char *fmt, ...) __printflike(1, 2);
 
 // Furnished in LogStatistics.cpp. Caller must own and free returned value
 char *pidToName(pid_t pid);
diff --git a/logd/README.property b/logd/README.property
index 6c84b25..4bc5541 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -7,7 +7,7 @@
 ro.device_owner            bool   false  Override persist.logd.security to false
 ro.logd.kernel             bool+ svelte+ Enable klogd daemon
 ro.logd.statistics         bool+ svelte+ Enable logcat -S statistics.
-ro.build.type              string        if user, logd.statistics &
+ro.debuggable              number        if not "1", logd.statistics &
                                          ro.logd.kernel default false.
 persist.logd.logpersistd   string        Enable logpersist daemon, "logcatd"
                                          turns on logcat -f in logd context
@@ -45,10 +45,10 @@
 
 NB:
 - bool+ - "true", "false" and comma separated list of "eng" (forced false if
-  ro.build.type is "user") or "svelte" (forced false if ro.config.low_ram is
+  ro.debuggable is not "1") or "svelte" (forced false if ro.config.low_ram is
   true).
 - svelte - see ro.config.low_ram for details.
-- svelte+ - see ro.config.low_ram and ro.build.type for details.
+- svelte+ - see ro.config.low_ram and ro.debuggable for details.
 - ro - <base property> temporary override, ro.<base property> platform default.
 - persist - <base property> override, persist.<base property> platform default.
 - build - VERBOSE for native, DEBUG for jvm isLoggable, or developer option.
diff --git a/logd/main.cpp b/logd/main.cpp
index 11c9372..3095f7f 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -202,8 +202,8 @@
         return false;
     }
     if (flag & BOOL_DEFAULT_FLAG_ENG) {
-        property_get("ro.build.type", property, "");
-        if (!strcmp(property, "user")) {
+        property_get("ro.debuggable", property, "");
+        if (strcmp(property, "1")) {
             return false;
         }
     }
@@ -211,10 +211,32 @@
     return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
 }
 
-// Remove the static, and use this variable
-// globally for debugging if necessary. eg:
-//   write(fdDmesg, "I am here\n", 10);
 static int fdDmesg = -1;
+void inline android::prdebug(const char *fmt, ...) {
+    if (fdDmesg < 0) {
+        return;
+    }
+
+    static const char message[] = {
+        KMSG_PRIORITY(LOG_DEBUG), 'l', 'o', 'g', 'd', ':', ' '
+    };
+    char buffer[256];
+    memcpy(buffer, message, sizeof(message));
+
+    va_list ap;
+    va_start(ap, fmt);
+    int n = vsnprintf(buffer + sizeof(message),
+                      sizeof(buffer) - sizeof(message), fmt, ap);
+    va_end(ap);
+    if (n > 0) {
+        buffer[sizeof(buffer) - 1] = '\0';
+        if (!strchr(buffer, '\n')) {
+            buffer[sizeof(buffer) - 2] = '\0';
+            strlcat(buffer, "\n", sizeof(buffer));
+        }
+        write(fdDmesg, buffer, strlen(buffer));
+    }
+}
 
 static sem_t uidName;
 static uid_t uid;
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c
index 28d6de7..ccbe0bf 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.c
@@ -408,7 +408,7 @@
         if (poll_fds[0].revents & POLLHUP) {
             int ret;
 
-            ret = waitpid(pid, &status, WNOHANG);
+            ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
             if (ret < 0) {
                 rc = errno;
                 ALOG(LOG_ERROR, "logwrap", "waitpid failed with %s\n", strerror(errno));
diff --git a/metricsd/.clang-format b/metricsd/.clang-format
deleted file mode 100644
index c98efc2..0000000
--- a/metricsd/.clang-format
+++ /dev/null
@@ -1,10 +0,0 @@
-BasedOnStyle: Google
-AllowShortFunctionsOnASingleLine: Inline
-AllowShortIfStatementsOnASingleLine: false
-AllowShortLoopsOnASingleLine: false
-BinPackArguments: false
-BinPackParameters: false
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-PointerAlignment: Left
-TabWidth: 2
diff --git a/metricsd/.clang-format b/metricsd/.clang-format
new file mode 120000
index 0000000..f9066d4
--- /dev/null
+++ b/metricsd/.clang-format
@@ -0,0 +1 @@
+../../../build/tools/brillo-clang-format
\ No newline at end of file
diff --git a/metricsd/timer_test.cc b/metricsd/timer_test.cc
index 7a67e11..cfbcd8a 100644
--- a/metricsd/timer_test.cc
+++ b/metricsd/timer_test.cc
@@ -69,7 +69,7 @@
   EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
       .WillOnce(Return(stime))
       .WillOnce(Return(etime));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   ASSERT_TRUE(timer_.Start());
   ASSERT_TRUE(timer_.start_time_ == stime);
   ASSERT_TRUE(timer_.HasStarted());
@@ -88,7 +88,7 @@
   EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
       .WillOnce(Return(stime))
       .WillOnce(Return(etime));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   timer_.Start();
   base::TimeTicks buffer = timer_.start_time_;
   timer_.Start();
@@ -98,7 +98,7 @@
 TEST_F(TimerTest, Reset) {
   EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
       .WillOnce(Return(stime));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   timer_.Start();
   ASSERT_TRUE(timer_.Reset());
   ASSERT_FALSE(timer_.HasStarted());
@@ -110,7 +110,7 @@
       .WillOnce(Return(etime))
       .WillOnce(Return(stime2))
       .WillOnce(Return(etime2));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   ASSERT_TRUE(timer_.Start());
   ASSERT_TRUE(timer_.Stop());
   ASSERT_EQ(timer_.elapsed_time_.InMilliseconds(), kDelta1MSec);
@@ -130,7 +130,7 @@
   EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
       .WillOnce(Return(stime))
       .WillOnce(Return(etime));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   ASSERT_FALSE(timer_.Stop());
   // Now we try it again, but after a valid start/stop.
   timer_.Start();
@@ -152,7 +152,7 @@
       .WillOnce(Return(etime2))
       .WillOnce(Return(stime3))
       .WillOnce(Return(etime3));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   ASSERT_TRUE(timer_.Pause());  // Starts timer paused.
   ASSERT_TRUE(timer_.start_time_ == stime);
   ASSERT_TRUE(timer_.HasStarted());
@@ -181,7 +181,7 @@
       .WillOnce(Return(stime2))
       .WillOnce(Return(etime2))
       .WillOnce(Return(stime3));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   ASSERT_TRUE(timer_.Resume());
   ASSERT_TRUE(timer_.start_time_ == stime);
   ASSERT_TRUE(timer_.HasStarted());
@@ -208,7 +208,7 @@
   EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
       .WillOnce(Return(stime))
       .WillOnce(Return(etime));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   ASSERT_TRUE(timer_.Start());
   ASSERT_TRUE(timer_.start_time_ == stime);
   ASSERT_TRUE(timer_.HasStarted());
@@ -230,7 +230,7 @@
   EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
       .WillOnce(Return(stime))
       .WillOnce(Return(etime));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   ASSERT_TRUE(timer_.Start());
   ASSERT_TRUE(timer_.start_time_ == stime);
   ASSERT_TRUE(timer_.HasStarted());
@@ -257,7 +257,7 @@
       .WillOnce(Return(etime))
       .WillOnce(Return(stime2))
       .WillOnce(Return(etime2));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   ASSERT_TRUE(timer_.Start());
   ASSERT_TRUE(timer_.start_time_ == stime);
   ASSERT_TRUE(timer_.HasStarted());
@@ -284,7 +284,7 @@
 TEST_F(TimerTest, PauseStop) {
   EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
       .WillOnce(Return(stime));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   ASSERT_TRUE(timer_.Pause());
   ASSERT_TRUE(timer_.start_time_ == stime);
   ASSERT_TRUE(timer_.HasStarted());
@@ -304,7 +304,7 @@
       .WillOnce(Return(stime))
       .WillOnce(Return(stime2))
       .WillOnce(Return(etime2));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   ASSERT_TRUE(timer_.Pause());
   ASSERT_TRUE(timer_.start_time_ == stime);
   ASSERT_TRUE(timer_.HasStarted());
@@ -328,7 +328,7 @@
       .WillOnce(Return(stime2))
       .WillOnce(Return(stime3))
       .WillOnce(Return(etime3));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   ASSERT_TRUE(timer_.Start());
   ASSERT_TRUE(timer_.start_time_ == stime);
   ASSERT_TRUE(timer_.HasStarted());
@@ -373,7 +373,7 @@
       .WillOnce(Return(etime2))
       .WillOnce(Return(stime3))
       .WillOnce(Return(etime3));
-  timer_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   ASSERT_TRUE(timer_.Start());
   ASSERT_TRUE(timer_.start_time_ == stime);
   ASSERT_TRUE(timer_.HasStarted());
@@ -444,7 +444,7 @@
   EXPECT_CALL(*clock_wrapper_mock_, GetCurrentTime())
       .WillOnce(Return(stime))
       .WillOnce(Return(etime));
-  timer_reporter_.clock_wrapper_.reset(clock_wrapper_mock_.release());
+  timer_reporter_.clock_wrapper_ = std::move(clock_wrapper_mock_);
   EXPECT_CALL(lib_, SendToUMA(kMetricName, kDelta1MSec, kMinSample, kMaxSample,
                               kNumBuckets)).WillOnce(Return(true));
   ASSERT_TRUE(timer_reporter_.Start());
diff --git a/metricsd/uploader/upload_service.cc b/metricsd/uploader/upload_service.cc
index 0dc59a4..333a7e6 100644
--- a/metricsd/uploader/upload_service.cc
+++ b/metricsd/uploader/upload_service.cc
@@ -183,6 +183,7 @@
   base::StatisticsRecorder::GetHistograms(&histograms);
 
   histogram_snapshot_manager_.PrepareDeltas(
+      histograms.begin(), histograms.end(),
       base::Histogram::kNoFlags, base::Histogram::kUmaTargetedHistogramFlag);
 
   // Gather and reset the crash counters, shared with the binder threads.
diff --git a/metricsd/uploader/upload_service_test.cc b/metricsd/uploader/upload_service_test.cc
index 70112f4..0f77fe4 100644
--- a/metricsd/uploader/upload_service_test.cc
+++ b/metricsd/uploader/upload_service_test.cc
@@ -304,6 +304,8 @@
   upload_service_->PersistToDisk();
   EXPECT_EQ(
       1, upload_service_->current_log_->uma_proto()->histogram_event().size());
+  // Destroy the old service before creating a new one.
+  upload_service_.reset();
   upload_service_.reset(new UploadService(
       "", base::TimeDelta(), base::TimeDelta(), private_dir_, shared_dir_));
   upload_service_->InitForTest(nullptr);
@@ -325,6 +327,8 @@
   // Write a bogus saved log.
   EXPECT_EQ(5, base::WriteFile(upload_service_->saved_log_path_, "hello", 5));
 
+  // Destroy the old service before creating a new one.
+  upload_service_.reset();
   upload_service_.reset(new UploadService(
       "", base::TimeDelta(), base::TimeDelta(), private_dir_, shared_dir_));
 
diff --git a/rootdir/init-debug.rc b/rootdir/init-debug.rc
index 435d4cb..44d34d8 100644
--- a/rootdir/init-debug.rc
+++ b/rootdir/init-debug.rc
@@ -6,3 +6,6 @@
 
 on property:persist.mmc.cache_size=*
     write /sys/block/mmcblk0/cache_size ${persist.mmc.cache_size}
+
+on early-init
+    mount debugfs debugfs /sys/kernel/debug
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 3e2f0a5..511b998 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -417,9 +417,6 @@
     rm /data/bugreports
     symlink /data/user_de/0/com.android.shell/files/bugreports /data/bugreports
 
-    # Separate location for storing security policy files on data
-    mkdir /data/security 0711 system system
-
     # Create all remaining /data root dirs so that they are made through init
     # and get proper encryption policy installed
     mkdir /data/backup 0700 system system
@@ -443,9 +440,6 @@
 
     init_user0
 
-    # Reload policy from /data/security if present.
-    setprop selinux.reload_policy 1
-
     # Set SELinux security contexts on upgrade or policy update.
     restorecon_recursive /data
 
diff --git a/sdcard/Android.mk b/sdcard/Android.mk
index c5f3d1d..2d04a7f 100644
--- a/sdcard/Android.mk
+++ b/sdcard/Android.mk
@@ -5,6 +5,6 @@
 LOCAL_SRC_FILES := sdcard.c
 LOCAL_MODULE := sdcard
 LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
-LOCAL_SHARED_LIBRARIES := libcutils libpackagelistparser
+LOCAL_SHARED_LIBRARIES := liblog libcutils libpackagelistparser
 
 include $(BUILD_EXECUTABLE)
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 9ade759..8b32418 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -38,7 +38,6 @@
     nandread \
     newfs_msdos \
     ps \
-    prlimit \
     sendevent \
     start \
     stop \
@@ -55,6 +54,7 @@
 LOCAL_CONLYFLAGS += -std=gnu99
 
 LOCAL_SHARED_LIBRARIES := \
+    liblog \
     libcutils \
     libselinux \
 
@@ -72,7 +72,7 @@
 $(LOCAL_PATH)/toolbox.c: $(intermediates)/tools.h
 
 TOOLS_H := $(intermediates)/tools.h
-$(TOOLS_H): PRIVATE_TOOLS := $(ALL_TOOLS)
+$(TOOLS_H): PRIVATE_TOOLS := toolbox $(ALL_TOOLS)
 $(TOOLS_H): PRIVATE_CUSTOM_TOOL = echo "/* file generated automatically */" > $@ ; for t in $(PRIVATE_TOOLS) ; do echo "TOOL($$t)" >> $@ ; done
 $(TOOLS_H): $(LOCAL_PATH)/Android.mk
 $(TOOLS_H):
diff --git a/toolbox/newfs_msdos.c b/toolbox/newfs_msdos.c
index 5b98a01..27ea9e8 100644
--- a/toolbox/newfs_msdos.c
+++ b/toolbox/newfs_msdos.c
@@ -695,7 +695,7 @@
                                                     (u_int)tm->tm_min));
                 mk4(bsx->volid, x);
                 mklabel(bsx->label, opt_L ? opt_L : "NO NAME");
-                sprintf(buf, "FAT%u", fat);
+                snprintf(buf, sizeof(buf), "FAT%u", fat);
                 setstr(bsx->type, buf, sizeof(bsx->type));
                 if (!opt_B) {
                     x1 += sizeof(struct bsx);
diff --git a/toolbox/prlimit.c b/toolbox/prlimit.c
deleted file mode 100644
index 8cf202a..0000000
--- a/toolbox/prlimit.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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/ps.c b/toolbox/ps.c
index 7e70c71..d366f3e 100644
--- a/toolbox/ps.c
+++ b/toolbox/ps.c
@@ -57,16 +57,16 @@
     int prio, nice, rtprio, sched, psr;
     struct passwd *pw;
 
-    sprintf(statline, "/proc/%d", tid ? tid : pid);
+    snprintf(statline, sizeof(statline), "/proc/%d", tid ? tid : pid);
     stat(statline, &stats);
 
     if(tid) {
-        sprintf(statline, "/proc/%d/task/%d/stat", pid, tid);
+        snprintf(statline, sizeof(statline), "/proc/%d/task/%d/stat", pid, tid);
         cmdline[0] = 0;
         snprintf(macline, sizeof(macline), "/proc/%d/task/%d/attr/current", pid, tid);
     } else {
-        sprintf(statline, "/proc/%d/stat", pid);
-        sprintf(cmdline, "/proc/%d/cmdline", pid);
+        snprintf(statline, sizeof(statline), "/proc/%d/stat", pid);
+        snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid);
         snprintf(macline, sizeof(macline), "/proc/%d/attr/current", pid);
         int fd = open(cmdline, O_RDONLY);
         if(fd == 0) {
@@ -149,7 +149,7 @@
 
     pw = getpwuid(stats.st_uid);
     if(pw == 0 || (display_flags & SHOW_NUMERIC_UID)) {
-        sprintf(user,"%d",(int)stats.st_uid);
+        snprintf(user,sizeof(user),"%d",(int)stats.st_uid);
     } else {
         strcpy(user,pw->pw_name);
     }
@@ -208,7 +208,7 @@
     int fd, r;
     char exeline[1024];
 
-    sprintf(exeline, "/proc/%d/exe", pid);
+    snprintf(exeline, sizeof(exeline), "/proc/%d/exe", pid);
     fd = open(exeline, O_RDONLY);
     if(fd == 0) {
         printf("    ");
@@ -243,7 +243,7 @@
     DIR *d;
     struct dirent *de;
 
-    sprintf(tmp,"/proc/%d/task",pid);
+    snprintf(tmp,sizeof(tmp),"/proc/%d/task",pid);
     d = opendir(tmp);
     if(d == 0) return;
 
diff --git a/toolbox/toolbox.c b/toolbox/toolbox.c
index 915da44..b5a942c 100644
--- a/toolbox/toolbox.c
+++ b/toolbox/toolbox.c
@@ -4,29 +4,14 @@
 #include <string.h>
 #include <unistd.h>
 
-int main(int, char **);
-
-static int toolbox_main(int argc, char **argv)
-{
-    // "toolbox foo ..." is equivalent to "foo ..."
-    if (argc > 1) {
-        return main(argc - 1, argv + 1);
-    } else {
-        printf("Toolbox!\n");
-        return 0;
-    }
-}
-
 #define TOOL(name) int name##_main(int, char**);
 #include "tools.h"
 #undef TOOL
 
-static struct 
-{
-    const char *name;
+static struct {
+    const char* name;
     int (*func)(int, char**);
 } tools[] = {
-    { "toolbox", toolbox_main },
 #define TOOL(name) { #name, name##_main },
 #include "tools.h"
 #undef TOOL
@@ -40,33 +25,35 @@
     _exit(0);
 }
 
-int main(int argc, char **argv)
-{
-    int i;
-    char *name = argv[0];
-
+int main(int argc, char** argv) {
     // Let's assume that none of this code handles broken pipes. At least ls,
     // ps, and top were broken (though I'd previously added this fix locally
     // to top). We exit rather than use SIG_IGN because tools like top will
     // just keep on writing to nowhere forever if we don't stop them.
     signal(SIGPIPE, SIGPIPE_handler);
 
-    if((argc > 1) && (argv[1][0] == '@')) {
-        name = argv[1] + 1;
-        argc--;
-        argv++;
-    } else {
-        char *cmd = strrchr(argv[0], '/');
-        if (cmd)
-            name = cmd + 1;
-    }
+    char* cmd = strrchr(argv[0], '/');
+    char* name = cmd ? (cmd + 1) : argv[0];
 
-    for(i = 0; tools[i].name; i++){
-        if(!strcmp(tools[i].name, name)){
+    for (size_t i = 0; tools[i].name; i++) {
+        if (!strcmp(tools[i].name, name)) {
             return tools[i].func(argc, argv);
         }
     }
 
     printf("%s: no such tool\n", argv[0]);
-    return -1;
+    return 127;
+}
+
+int toolbox_main(int argc, char** argv) {
+    // "toolbox foo ..." is equivalent to "foo ..."
+    if (argc > 1) {
+        return main(argc - 1, argv + 1);
+    }
+
+    // Plain "toolbox" lists the tools.
+    for (size_t i = 1; tools[i].name; i++) {
+        printf("%s%c", tools[i].name, tools[i+1].name ? ' ' : '\n');
+    }
+    return 0;
 }
diff --git a/toolbox/top.c b/toolbox/top.c
index 6fda132..003f4c9 100644
--- a/toolbox/top.c
+++ b/toolbox/top.c
@@ -258,29 +258,29 @@
 
             proc->pid = proc->tid = pid;
 
-            sprintf(filename, "/proc/%d/stat", pid);
+            snprintf(filename, sizeof(filename), "/proc/%d/stat", pid);
             read_stat(filename, proc);
 
-            sprintf(filename, "/proc/%d/cmdline", pid);
+            snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid);
             read_cmdline(filename, proc);
 
-            sprintf(filename, "/proc/%d/status", pid);
+            snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
             read_status(filename, proc);
 
             read_policy(pid, proc);
 
             proc->num_threads = 0;
         } else {
-            sprintf(filename, "/proc/%d/cmdline", pid);
+            snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid);
             read_cmdline(filename, &cur_proc);
 
-            sprintf(filename, "/proc/%d/status", pid);
+            snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
             read_status(filename, &cur_proc);
 
             proc = NULL;
         }
 
-        sprintf(filename, "/proc/%d/task", pid);
+        snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
         task_dir = opendir(filename);
         if (!task_dir) continue;
 
@@ -295,7 +295,7 @@
 
                 proc->pid = pid; proc->tid = tid;
 
-                sprintf(filename, "/proc/%d/task/%d/stat", pid, tid);
+                snprintf(filename, sizeof(filename), "/proc/%d/task/%d/stat", pid, tid);
                 read_stat(filename, proc);
 
                 read_policy(tid, proc);
@@ -484,7 +484,7 @@
         if (user && user->pw_name) {
             user_str = user->pw_name;
         } else {
-            snprintf(user_buf, 20, "%d", proc->uid);
+            snprintf(user_buf, sizeof(user_buf), "%d", proc->uid);
             user_str = user_buf;
         }
         if (!threads) {
diff --git a/trusty/libtrusty/tipc-test/tipc_test.c b/trusty/libtrusty/tipc-test/tipc_test.c
index 55d5ee6..1fb34c9 100644
--- a/trusty/libtrusty/tipc-test/tipc_test.c
+++ b/trusty/libtrusty/tipc-test/tipc_test.c
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <getopt.h>
+#include <sys/uio.h>
 
 #include <trusty/tipc.h>
 
@@ -80,6 +81,8 @@
 "   ta2ta-ipc    - execute TA to TA unittest\n"
 "   dev-uuid     - print device uuid\n"
 "   ta-access    - test ta-access flags\n"
+"   writev       - writev test\n"
+"   readv        - readv test\n"
 "\n"
 ;
 
@@ -93,7 +96,7 @@
 {
 	fprintf (stderr, usage, prog);
 	if (verbose)
-		fprintf (stderr, usage_long);
+		fprintf (stderr, "%s", usage_long);
 	exit(code);
 }
 
@@ -692,6 +695,171 @@
 }
 
 
+static int writev_test(uint repeat, uint msgsz, bool var)
+{
+	uint i;
+	ssize_t rc;
+	size_t  msg_len;
+	int  echo_fd = -1;
+	char tx0_buf[msgsz];
+	char tx1_buf[msgsz];
+	char rx_buf [msgsz];
+	struct iovec iovs[2]= {{tx0_buf, 0}, {tx1_buf, 0}};
+
+	if (!opt_silent) {
+		printf("%s: repeat %u: msgsz %u: variable %s\n",
+			__func__, repeat, msgsz, var ? "true" : "false");
+	}
+
+	echo_fd = tipc_connect(dev_name, echo_name);
+	if (echo_fd < 0) {
+		fprintf(stderr, "Failed to connect to service\n");
+		return echo_fd;
+	}
+
+	for (i = 0; i < repeat; i++) {
+
+		msg_len = msgsz;
+		if (opt_variable && msgsz) {
+			msg_len = rand() % msgsz;
+		}
+
+		iovs[0].iov_len = msg_len / 3;
+		iovs[1].iov_len = msg_len - iovs[0].iov_len;
+
+		memset(tx0_buf, i + 1, iovs[0].iov_len);
+		memset(tx1_buf, i + 2, iovs[1].iov_len);
+		memset(rx_buf,  i + 3, sizeof(rx_buf));
+
+		rc = writev(echo_fd, iovs, 2);
+		if (rc < 0) {
+			perror("writev_test: writev");
+			break;
+		}
+
+		if ((size_t)rc != msg_len) {
+			fprintf(stderr,
+				"%s: %s: data size mismatch (%zd vs. %zd)\n",
+				__func__, "writev", (size_t)rc, msg_len);
+			break;
+		}
+
+		rc = read(echo_fd, rx_buf, sizeof(rx_buf));
+		if (rc < 0) {
+			perror("writev_test: read");
+			break;
+		}
+
+		if ((size_t)rc != msg_len) {
+			fprintf(stderr,
+				"%s: %s: data size mismatch (%zd vs. %zd)\n",
+				__func__, "read", (size_t)rc, msg_len);
+			break;
+		}
+
+		if (memcmp(tx0_buf, rx_buf, iovs[0].iov_len)) {
+			fprintf(stderr, "%s: data mismatch: buf 0\n", __func__);
+			break;
+		}
+
+		if (memcmp(tx1_buf, rx_buf + iovs[0].iov_len, iovs[1].iov_len)) {
+			fprintf(stderr, "%s: data mismatch, buf 1\n", __func__);
+			break;
+		}
+	}
+
+	tipc_close(echo_fd);
+
+	if (!opt_silent) {
+		printf("%s: done\n",__func__);
+	}
+
+	return 0;
+}
+
+static int readv_test(uint repeat, uint msgsz, bool var)
+{
+	uint i;
+	ssize_t rc;
+	size_t  msg_len;
+	int  echo_fd = -1;
+	char tx_buf [msgsz];
+	char rx0_buf[msgsz];
+	char rx1_buf[msgsz];
+	struct iovec iovs[2]= {{rx0_buf, 0}, {rx1_buf, 0}};
+
+	if (!opt_silent) {
+		printf("%s: repeat %u: msgsz %u: variable %s\n",
+			__func__, repeat, msgsz, var ? "true" : "false");
+	}
+
+	echo_fd = tipc_connect(dev_name, echo_name);
+	if (echo_fd < 0) {
+		fprintf(stderr, "Failed to connect to service\n");
+		return echo_fd;
+	}
+
+	for (i = 0; i < repeat; i++) {
+
+		msg_len = msgsz;
+		if (opt_variable && msgsz) {
+			msg_len = rand() % msgsz;
+		}
+
+		iovs[0].iov_len = msg_len / 3;
+		iovs[1].iov_len = msg_len - iovs[0].iov_len;
+
+		memset(tx_buf,  i + 1, sizeof(tx_buf));
+		memset(rx0_buf, i + 2, iovs[0].iov_len);
+		memset(rx1_buf, i + 3, iovs[1].iov_len);
+
+		rc = write(echo_fd, tx_buf, msg_len);
+		if (rc < 0) {
+			perror("readv_test: write");
+			break;
+		}
+
+		if ((size_t)rc != msg_len) {
+			fprintf(stderr,
+				"%s: %s: data size mismatch (%zd vs. %zd)\n",
+				__func__, "write", (size_t)rc, msg_len);
+			break;
+		}
+
+		rc = readv(echo_fd, iovs, 2);
+		if (rc < 0) {
+			perror("readv_test: readv");
+			break;
+		}
+
+		if ((size_t)rc != msg_len) {
+			fprintf(stderr,
+				"%s: %s: data size mismatch (%zd vs. %zd)\n",
+				__func__, "write", (size_t)rc, msg_len);
+			break;
+		}
+
+		if (memcmp(rx0_buf, tx_buf, iovs[0].iov_len)) {
+			fprintf(stderr, "%s: data mismatch: buf 0\n", __func__);
+			break;
+		}
+
+		if (memcmp(rx1_buf, tx_buf + iovs[0].iov_len, iovs[1].iov_len)) {
+			fprintf(stderr, "%s: data mismatch, buf 1\n", __func__);
+			break;
+		}
+	}
+
+	tipc_close(echo_fd);
+
+	if (!opt_silent) {
+		printf("%s: done\n",__func__);
+	}
+
+	return 0;
+}
+
+
 int main(int argc, char **argv)
 {
 	int rc = 0;
@@ -735,6 +903,10 @@
 		rc = dev_uuid_test();
 	} else if (strcmp(test_name, "ta-access") == 0) {
 		rc = ta_access_test();
+	} else if (strcmp(test_name, "writev") == 0) {
+		rc = writev_test(opt_repeat, opt_msgsize, opt_variable);
+	} else if (strcmp(test_name, "readv") == 0) {
+		rc = readv_test(opt_repeat, opt_msgsize, opt_variable);
 	} else {
 		fprintf(stderr, "Unrecognized test name '%s'\n", test_name);
 		print_usage_and_exit(argv[0], EXIT_FAILURE, true);
diff --git a/trusty/nvram/Android.mk b/trusty/nvram/Android.mk
new file mode 100644
index 0000000..18c54d5
--- /dev/null
+++ b/trusty/nvram/Android.mk
@@ -0,0 +1,30 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# nvram.trusty is the Trusty NVRAM HAL module.
+include $(CLEAR_VARS)
+LOCAL_MODULE := nvram.trusty
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+	module.c \
+	trusty_nvram_implementation.cpp
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -Wall -Werror -Wextra -fvisibility=hidden
+LOCAL_STATIC_LIBRARIES := libnvram-hal
+LOCAL_SHARED_LIBRARIES := libtrusty libnvram-messages liblog
+include $(BUILD_SHARED_LIBRARY)
diff --git a/trusty/nvram/module.c b/trusty/nvram/module.c
new file mode 100644
index 0000000..06819c0
--- /dev/null
+++ b/trusty/nvram/module.c
@@ -0,0 +1,39 @@
+/*
+ * 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 <hardware/nvram.h>
+
+// This function is defined in trusty_nvram_implementation.cpp.
+int trusty_nvram_open(const hw_module_t* module,
+                      const char* device_id,
+                      hw_device_t** device_ptr);
+
+static struct hw_module_methods_t nvram_module_methods = {
+    .open = trusty_nvram_open,
+};
+
+struct nvram_module HAL_MODULE_INFO_SYM
+    __attribute__((visibility("default"))) = {
+        .common = {.tag = HARDWARE_MODULE_TAG,
+                   .module_api_version = NVRAM_MODULE_API_VERSION_0_1,
+                   .hal_api_version = HARDWARE_HAL_API_VERSION,
+                   .id = NVRAM_HARDWARE_MODULE_ID,
+                   .name = "Trusty NVRAM HAL",
+                   .author = "The Android Open Source Project",
+                   .methods = &nvram_module_methods,
+                   .dso = 0,
+                   .reserved = {}},
+};
diff --git a/trusty/nvram/trusty_nvram_implementation.cpp b/trusty/nvram/trusty_nvram_implementation.cpp
new file mode 100644
index 0000000..39496b4
--- /dev/null
+++ b/trusty/nvram/trusty_nvram_implementation.cpp
@@ -0,0 +1,152 @@
+/*
+ * 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 <errno.h>
+#include <string.h>
+
+#include <hardware/nvram.h>
+#include <trusty/tipc.h>
+
+#define LOG_TAG "TrustyNVRAM"
+#include <log/log.h>
+
+#include <nvram/hal/nvram_device_adapter.h>
+#include <nvram/messages/blob.h>
+#include <nvram/messages/nvram_messages.h>
+
+namespace {
+
+// Character device to open for Trusty IPC connections.
+const char kTrustyDeviceName[] = "/dev/trusty-ipc-dev0";
+
+// App identifier of the NVRAM app.
+const char kTrustyNvramAppId[] = "com.android.trusty.nvram";
+
+// |TrustyNvramImplementation| proxies requests to the Trusty NVRAM app. It
+// serializes the request objects, sends it to the Trusty app and finally reads
+// back the result and decodes it.
+class TrustyNvramImplementation : public nvram::NvramImplementation {
+ public:
+  ~TrustyNvramImplementation() override;
+
+  void Execute(const nvram::Request& request,
+               nvram::Response* response) override;
+
+ private:
+  // Connects the IPC channel to the Trusty app if it is not already open.
+  // Returns true if the channel is open, false on errors.
+  bool Connect();
+
+  // Dispatches a command to the trust app. Returns true if successful (note
+  // that the response may still indicate an error on the Trusty side), false if
+  // there are any I/O or encoding/decoding errors.
+  bool SendRequest(const nvram::Request& request,
+                   nvram::Response* response);
+
+  // The file descriptor for the IPC connection to the Trusty app.
+  int tipc_nvram_fd_ = -1;
+
+  // Response buffer. This puts a hard size limit on the responses from the
+  // Trusty app. 4096 matches the maximum IPC message size currently supported
+  // by Trusty.
+  uint8_t response_buffer_[4096];
+};
+
+TrustyNvramImplementation::~TrustyNvramImplementation() {
+  if (tipc_nvram_fd_ != -1) {
+    tipc_close(tipc_nvram_fd_);
+    tipc_nvram_fd_ = -1;
+  }
+}
+
+void TrustyNvramImplementation::Execute(const nvram::Request& request,
+                                        nvram::Response* response) {
+  if (!SendRequest(request, response)) {
+    response->result = NV_RESULT_INTERNAL_ERROR;
+  }
+}
+
+bool TrustyNvramImplementation::Connect() {
+  if (tipc_nvram_fd_ != -1) {
+    return true;
+  }
+
+  int rc = tipc_connect(kTrustyDeviceName, kTrustyNvramAppId);
+  if (rc < 0) {
+    ALOGE("Failed to connect to Trusty NVRAM app: %s\n", strerror(-rc));
+    return false;
+  }
+
+  tipc_nvram_fd_ = rc;
+  return true;
+}
+
+bool TrustyNvramImplementation::SendRequest(const nvram::Request& request,
+                                            nvram::Response* response) {
+  if (!Connect()) {
+    return false;
+  }
+
+  nvram::Blob request_buffer;
+  if (!nvram::Encode(request, &request_buffer)) {
+    ALOGE("Failed to encode NVRAM request.\n");
+    return false;
+  }
+
+  ssize_t rc =
+      write(tipc_nvram_fd_, request_buffer.data(), request_buffer.size());
+  if (rc < 0) {
+    ALOGE("Failed to send NVRAM request: %s\n", strerror(-rc));
+    return false;
+  }
+  if (static_cast<size_t>(rc) != request_buffer.size()) {
+    ALOGE("Failed to send full request buffer: %zd\n", rc);
+    return false;
+  }
+
+  rc = read(tipc_nvram_fd_, response_buffer_, sizeof(response_buffer_));
+  if (rc < 0) {
+    ALOGE("Failed to read NVRAM response: %s\n", strerror(-rc));
+    return false;
+  }
+
+  if (static_cast<size_t>(rc) >= sizeof(response_buffer_)) {
+    ALOGE("NVRAM response exceeds response buffer size.\n");
+    return false;
+  }
+
+  if (!nvram::Decode(response_buffer_, static_cast<size_t>(rc), response)) {
+    ALOGE("Failed to decode NVRAM response.\n");
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+extern "C" int trusty_nvram_open(const hw_module_t* module,
+                                 const char* device_id,
+                                 hw_device_t** device_ptr) {
+  if (strcmp(NVRAM_HARDWARE_DEVICE_ID, device_id) != 0) {
+    return -EINVAL;
+  }
+
+  nvram::NvramDeviceAdapter* adapter =
+      new nvram::NvramDeviceAdapter(module, new TrustyNvramImplementation);
+  *device_ptr = adapter->as_device();
+  return 0;
+}