Merge "crash_reporter: Mark the euid parameter as __unused."
diff --git a/adb/Android.mk b/adb/Android.mk
index 4777883..2dba41d 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -79,10 +79,12 @@
 
 LIBADB_darwin_SRC_FILES := \
     get_my_path_darwin.cpp \
+    sysdeps_unix.cpp \
     usb_osx.cpp \
 
 LIBADB_linux_SRC_FILES := \
     get_my_path_linux.cpp \
+    sysdeps_unix.cpp \
     usb_linux.cpp \
 
 LIBADB_windows_SRC_FILES := \
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 85aaa61..3a81ce6 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -517,12 +517,6 @@
     if (!sc.SendRequest(ID_RECV, rpath)) return false;
 
     adb_unlink(lpath);
-    const std::string dirpath = adb_dirname(lpath);
-    if (!mkdirs(dirpath.c_str())) {
-        sc.Error("failed to create parent directory '%s': %s", dirpath.c_str(), strerror(errno));
-        return false;
-    }
-
     int lfd = adb_creat(lpath, 0644);
     if (lfd < 0) {
         sc.Error("cannot create '%s': %s", lpath, strerror(errno));
@@ -803,13 +797,14 @@
     return S_ISDIR(mode);
 }
 
-static bool remote_build_list(SyncConnection& sc,
-                              std::vector<copyinfo>* file_list,
-                              const std::string& rpath,
-                              const std::string& lpath) {
+static bool remote_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
+                              const std::string& rpath, const std::string& lpath) {
     std::vector<copyinfo> dirlist;
     std::vector<copyinfo> linklist;
-    bool empty_dir = true;
+
+    // Add an entry for the current directory to ensure it gets created before pulling its contents.
+    copyinfo ci(adb_dirname(lpath), adb_dirname(rpath), adb_basename(rpath), S_IFDIR);
+    file_list->push_back(ci);
 
     // Put the files/dirs in rpath on the lists.
     auto callback = [&](unsigned mode, unsigned size, unsigned time, const char* name) {
@@ -817,9 +812,6 @@
             return;
         }
 
-        // We found a child that isn't '.' or '..'.
-        empty_dir = false;
-
         copyinfo ci(lpath, rpath, name, mode);
         if (S_ISDIR(mode)) {
             dirlist.push_back(ci);
@@ -836,13 +828,6 @@
         return false;
     }
 
-    // Add the current directory to the list if it was empty, to ensure that it gets created.
-    if (empty_dir) {
-        copyinfo ci(adb_dirname(lpath), adb_dirname(rpath), adb_basename(rpath), S_IFDIR);
-        file_list->push_back(ci);
-        return true;
-    }
-
     // Check each symlink we found to see whether it's a file or directory.
     for (copyinfo& link_ci : linklist) {
         if (remote_symlink_isdir(sc, link_ci.rpath)) {
diff --git a/adb/services.cpp b/adb/services.cpp
index 2eef1c2..d5e963b 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -421,6 +421,11 @@
     close_on_exec(fd);
     disable_tcp_nagle(fd);
 
+    // Send a TCP keepalive ping to the device every second so we can detect disconnects.
+    if (!set_tcp_keepalive(fd, 1)) {
+        D("warning: failed to configure TCP keepalives (%s)", strerror(errno));
+    }
+
     int ret = register_socket_transport(fd, serial.c_str(), port, 0);
     if (ret < 0) {
         adb_close(fd);
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 7af2979..ce0f289 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -841,4 +841,9 @@
     adb_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &off, sizeof(off));
 }
 
+// Sets TCP socket |fd| to send a keepalive TCP message every |interval_sec| seconds. Set
+// |interval_sec| to 0 to disable keepalives. If keepalives are enabled, the connection will be
+// configured to drop after 10 missed keepalives. Returns true on success.
+bool set_tcp_keepalive(int fd, int interval_sec);
+
 #endif /* _ADB_SYSDEPS_H */
diff --git a/adb/sysdeps_unix.cpp b/adb/sysdeps_unix.cpp
new file mode 100644
index 0000000..4445a44
--- /dev/null
+++ b/adb/sysdeps_unix.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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 "sysdeps.h"
+
+bool set_tcp_keepalive(int fd, int interval_sec) {
+    int enable = (interval_sec > 0);
+    if (adb_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable))) {
+        return false;
+    }
+
+    if (!enable) {
+        return true;
+    }
+
+    // Idle time before sending the first keepalive is TCP_KEEPIDLE on Linux, TCP_KEEPALIVE on Mac.
+#if defined(TCP_KEEPIDLE)
+    if (adb_setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &interval_sec, sizeof(interval_sec))) {
+        return false;
+    }
+#elif defined(TCP_KEEPALIVE)
+    if (adb_setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &interval_sec, sizeof(interval_sec))) {
+        return false;
+    }
+#endif
+
+    // TCP_KEEPINTVL and TCP_KEEPCNT are available on Linux 2.4+ and OS X 10.8+ (Mountain Lion).
+#if defined(TCP_KEEPINTVL)
+    if (adb_setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval_sec, sizeof(interval_sec))) {
+        return false;
+    }
+#endif
+
+#if defined(TCP_KEEPCNT)
+    // On Windows this value is hardcoded to 10. This is a reasonable value, so we do the same here
+    // to match behavior. See SO_KEEPALIVE documentation at
+    // https://msdn.microsoft.com/en-us/library/windows/desktop/ee470551(v=vs.85).aspx.
+    const int keepcnt = 10;
+    if (adb_setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt))) {
+        return false;
+    }
+#endif
+
+    return true;
+}
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 7eae186..a2f34fb 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -1228,6 +1228,33 @@
     }
 }
 
+bool set_tcp_keepalive(int fd, int interval_sec) {
+    FH fh = _fh_from_int(fd, __func__);
+
+    if (!fh || fh->clazz != &_fh_socket_class) {
+        D("set_tcp_keepalive(%d) failed: invalid fd", fd);
+        errno = EBADF;
+        return false;
+    }
+
+    tcp_keepalive keepalive;
+    keepalive.onoff = (interval_sec > 0);
+    keepalive.keepalivetime = interval_sec * 1000;
+    keepalive.keepaliveinterval = interval_sec * 1000;
+
+    DWORD bytes_returned = 0;
+    if (WSAIoctl(fh->fh_socket, SIO_KEEPALIVE_VALS, &keepalive, sizeof(keepalive), nullptr, 0,
+                 &bytes_returned, nullptr, nullptr) != 0) {
+        const DWORD err = WSAGetLastError();
+        D("set_tcp_keepalive(%d) failed: %s", fd,
+          android::base::SystemErrorCodeToString(err).c_str());
+        _socket_set_errno(err);
+        return false;
+    }
+
+    return true;
+}
+
 static adb_mutex_t g_console_output_buffer_lock;
 
 void
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 6232f72..53966d5 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -91,6 +91,7 @@
 #define AID_CAMERASERVER  1047  /* cameraserver process */
 #define AID_FIREWALL      1048  /* firewalld process */
 #define AID_TRUNKS        1049  /* trunksd process (TPM daemon) */
+/* 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 */
diff --git a/liblog/Android.bp b/liblog/Android.bp
index ee883f0..607d667 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -14,15 +14,16 @@
 // limitations under the License.
 //
 
-liblog_host_sources = [
+liblog_sources = [
     "logd_write.c",
+    "log_event_list.c",
     "log_event_write.c",
+]
+liblog_host_sources = [
     "fake_log_device.c",
     //"event.logtags",
 ]
 liblog_target_sources = [
-    "logd_write.c",
-    "log_event_write.c",
     "event_tag_map.c",
     "log_time.cpp",
     "log_is_loggable.c",
@@ -36,6 +37,8 @@
     name: "liblog",
     host_supported: true,
 
+    srcs: liblog_sources,
+
     target: {
         host: {
             srcs: liblog_host_sources,
@@ -71,7 +74,6 @@
         //       $(LOCAL_PATH)/event.logtags)
         // so make sure we do not regret hard-coding it as follows:
         "-DLIBLOG_LOG_TAG=1005",
-        "-DSNET_EVENT_LOG_TAG=1397638484",
     ],
     compile_multilib: "both",
     stl: "none",
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/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/Android.mk b/libmincrypt/tools/Android.mk
deleted file mode 100644
index f403621..0000000
--- a/libmincrypt/tools/Android.mk
+++ /dev/null
@@ -1,32 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Determine whether to build dumpkey from system/core/libmincrypt or from
-# bootable/recovery/tools. The dumpkey source is temporarily present in both
-# locations during the process of moving the tool to the recovery repository.
-# TODO(mnissler): Remove the guard after the transition is complete.
-ifndef BUILD_DUMPKEY_FROM_RECOVERY
-BUILD_DUMPKEY_FROM_RECOVERY := false
-endif
-
-ifeq ($(BUILD_DUMPKEY_FROM_RECOVERY),false)
-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)
-endif
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/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 230dd11..9124bfd 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -99,11 +99,20 @@
 }
 
 void LogAudit::enforceIntegrity() {
+    static bool loggedOnce;
+    bool once = loggedOnce;
+
+    loggedOnce = true;
+
     if (!AUDITD_ENFORCE_INTEGRITY) {
-        logToDmesg("integrity enforcement suppressed; not rebooting");
+        if (!once) {
+            logToDmesg("integrity enforcement suppressed; not rebooting");
+        }
     } else if (rebootToSafeMode) {
         if (getProperty("persist.sys.safemode") == "1") {
-            logToDmesg("integrity enforcement suppressed; in safe mode");
+            if (!once) {
+                logToDmesg("integrity enforcement suppressed; in safe mode");
+            }
             return;
         }
 
diff --git a/mkbootimg/mkbootimg b/mkbootimg/mkbootimg
index aea2585..f95d703 100755
--- a/mkbootimg/mkbootimg
+++ b/mkbootimg/mkbootimg
@@ -19,6 +19,7 @@
 from os import fstat
 from struct import pack
 from hashlib import sha1
+import sys
 
 def filesize(f):
     if f is None:
@@ -133,8 +134,10 @@
     img_id = write_header(args)
     write_data(args)
     if args.id:
-        print('0x' + ''.join('{:02x}'.format(ord(c)) for c in img_id))
-
+        if isinstance(img_id, str):
+            # Python 2's struct.pack returns a string, but py3 returns bytes.
+            img_id = [ord(x) for x in img_id]
+        print('0x' + ''.join('{:02x}'.format(c) for c in img_id))
 
 if __name__ == '__main__':
     main()
diff --git a/toolbox/generate-input.h-labels.py b/toolbox/generate-input.h-labels.py
index 30485a0..a2b9111 100755
--- a/toolbox/generate-input.h-labels.py
+++ b/toolbox/generate-input.h-labels.py
@@ -16,6 +16,7 @@
 #
 # pylint: disable=bad-indentation,bad-continuation
 
+from __future__ import print_function
 import os
 import re
 import sys
@@ -72,11 +73,11 @@
         ff_list.append(name)
 
 def Dump(struct_name, values):
-  print 'static struct label %s[] = {' % (struct_name)
+  print('static struct label %s[] = {' % (struct_name))
   for value in values:
-    print '    LABEL(%s),' % (value)
-  print '    LABEL_END,'
-  print '};'
+    print('    LABEL(%s),' % (value))
+  print('    LABEL_END,')
+  print('};')
 
 Dump("input_prop_labels", input_prop_list)
 Dump("ev_labels", ev_list)