Merge "libcrypto_utils: convert to Soong."
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index fbca770..3368b7f 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -28,8 +28,11 @@
 #include <unistd.h>
 #include <utime.h>
 
+#include <chrono>
 #include <functional>
 #include <memory>
+#include <sstream>
+#include <string>
 #include <vector>
 
 #include "sysdeps.h"
@@ -94,14 +97,112 @@
     }
 };
 
+enum class TransferDirection {
+    push,
+    pull,
+};
+
+struct TransferLedger {
+    std::chrono::steady_clock::time_point start_time;
+    uint64_t files_transferred;
+    uint64_t files_skipped;
+    uint64_t bytes_transferred;
+    uint64_t bytes_expected;
+    bool expect_multiple_files;
+
+    TransferLedger() {
+        Reset();
+    }
+
+    bool operator==(const TransferLedger& other) const {
+        return files_transferred == other.files_transferred &&
+               files_skipped == other.files_skipped && bytes_transferred == other.bytes_transferred;
+    }
+
+    bool operator!=(const TransferLedger& other) const {
+        return !(*this == other);
+    }
+
+    void Reset() {
+        start_time = std::chrono::steady_clock::now();
+        files_transferred = 0;
+        files_skipped = 0;
+        bytes_transferred = 0;
+        bytes_expected = 0;
+    }
+
+    std::string TransferRate() {
+        if (bytes_transferred == 0) return "";
+
+        std::chrono::duration<double> duration;
+        duration = std::chrono::steady_clock::now() - start_time;
+
+        double s = duration.count();
+        if (s == 0) {
+            return "";
+        }
+        double rate = (static_cast<double>(bytes_transferred) / s) / (1024 * 1024);
+        return android::base::StringPrintf(" %.1f MB/s (%" PRIu64 " bytes in %.3fs)", rate,
+                                           bytes_transferred, s);
+    }
+
+    void ReportProgress(LinePrinter& lp, const std::string& file, uint64_t file_copied_bytes,
+                        uint64_t file_total_bytes) {
+        char overall_percentage_str[5] = "?";
+        if (bytes_expected != 0) {
+            int overall_percentage = static_cast<int>(bytes_transferred * 100 / bytes_expected);
+            // If we're pulling symbolic links, we'll pull the target of the link rather than
+            // just create a local link, and that will cause us to go over 100%.
+            if (overall_percentage <= 100) {
+                snprintf(overall_percentage_str, sizeof(overall_percentage_str), "%d%%",
+                         overall_percentage);
+            }
+        }
+
+        std::string output;
+        if (file_copied_bytes > file_total_bytes || file_total_bytes == 0) {
+            // This case can happen if we're racing against something that wrote to the file
+            // between our stat and our read, or if we're reading a magic file that lies about
+            // its size. Just show how much we've copied.
+            output = android::base::StringPrintf("[%4s] %s: %" PRId64 "/?", overall_percentage_str,
+                                                 file.c_str(), file_copied_bytes);
+        } else {
+            // If we're transferring multiple files, we want to know how far through the current
+            // file we are, as well as the overall percentage.
+            if (expect_multiple_files) {
+                int file_percentage = static_cast<int>(file_copied_bytes * 100 / file_total_bytes);
+                output = android::base::StringPrintf("[%4s] %s: %d%%", overall_percentage_str,
+                                                     file.c_str(), file_percentage);
+            } else {
+                output =
+                    android::base::StringPrintf("[%4s] %s", overall_percentage_str, file.c_str());
+            }
+        }
+        lp.Print(output, LinePrinter::LineType::INFO);
+    }
+
+    void ReportTransferRate(LinePrinter& lp, const std::string& name, TransferDirection direction) {
+        const char* direction_str = (direction == TransferDirection::push) ? "pushed" : "pulled";
+        std::stringstream ss;
+        if (!name.empty()) {
+            ss << name << ": ";
+        }
+        ss << files_transferred << " file" << ((files_transferred == 1) ? "" : "s") << " "
+           << direction_str << ".";
+        if (files_skipped > 0) {
+            ss << " " << files_skipped << " file" << ((files_skipped == 1) ? "" : "s")
+               << " skipped.";
+        }
+        ss << TransferRate();
+
+        lp.Print(ss.str(), LinePrinter::LineType::INFO);
+        lp.KeepInfoLine();
+    }
+};
+
 class SyncConnection {
   public:
-    SyncConnection()
-            : total_bytes_(0),
-              start_time_ms_(CurrentTimeMs()),
-              expected_total_bytes_(0),
-              expect_multiple_files_(false),
-              expect_done_(false) {
+    SyncConnection() : expect_done_(false) {
         max = SYNC_DATA_MAX; // TODO: decide at runtime.
 
         std::string error;
@@ -140,6 +241,40 @@
         return rc != 0;
     }
 
+    void NewTransfer() {
+        current_ledger_.Reset();
+    }
+
+    void RecordBytesTransferred(size_t bytes) {
+        current_ledger_.bytes_transferred += bytes;
+        global_ledger_.bytes_transferred += bytes;
+    }
+
+    void RecordFilesTransferred(size_t files) {
+        current_ledger_.files_transferred += files;
+        global_ledger_.files_transferred += files;
+    }
+
+    void RecordFilesSkipped(size_t files) {
+        current_ledger_.files_skipped += files;
+        global_ledger_.files_skipped += files;
+    }
+
+    void ReportProgress(const std::string& file, uint64_t file_copied_bytes,
+                        uint64_t file_total_bytes) {
+        current_ledger_.ReportProgress(line_printer_, file, file_copied_bytes, file_total_bytes);
+    }
+
+    void ReportTransferRate(const std::string& file, TransferDirection direction) {
+        current_ledger_.ReportTransferRate(line_printer_, file, direction);
+    }
+
+    void ReportOverallTransferRate(TransferDirection direction) {
+        if (current_ledger_ != global_ledger_) {
+            global_ledger_.ReportTransferRate(line_printer_, "", direction);
+        }
+    }
+
     bool SendRequest(int id, const char* path_and_mode) {
         size_t path_length = strlen(path_and_mode);
         if (path_length > 1024) {
@@ -199,7 +334,9 @@
 
         WriteOrDie(lpath, rpath, &buf[0], (p - &buf[0]));
         expect_done_ = true;
-        total_bytes_ += data_length;
+
+        // RecordFilesTransferred gets called in CopyDone.
+        RecordBytesTransferred(data_length);
         ReportProgress(rpath, data_length, data_length);
         return true;
     }
@@ -242,7 +379,7 @@
             sbuf.size = bytes_read;
             WriteOrDie(lpath, rpath, &sbuf, sizeof(SyncRequest) + bytes_read);
 
-            total_bytes_ += bytes_read;
+            RecordBytesTransferred(bytes_read);
             bytes_copied += bytes_read;
 
             // Check to see if we've received an error from the other side.
@@ -259,6 +396,8 @@
         msg.data.id = ID_DONE;
         msg.data.size = mtime;
         expect_done_ = true;
+
+        // RecordFilesTransferred gets called in CopyDone.
         return WriteOrDie(lpath, rpath, &msg.data, sizeof(msg.data));
     }
 
@@ -271,6 +410,7 @@
         if (msg.status.id == ID_OKAY) {
             if (expect_done_) {
                 expect_done_ = false;
+                RecordFilesTransferred(1);
                 return true;
             } else {
                 Error("failed to copy '%s' to '%s': received premature success", from, to);
@@ -296,44 +436,6 @@
         return false;
     }
 
-    std::string TransferRate() {
-        uint64_t ms = CurrentTimeMs() - start_time_ms_;
-        if (total_bytes_ == 0 || ms == 0) return "";
-
-        double s = static_cast<double>(ms) / 1000LL;
-        double rate = (static_cast<double>(total_bytes_) / s) / (1024*1024);
-        return android::base::StringPrintf(" %.1f MB/s (%" PRId64 " bytes in %.3fs)",
-                                           rate, total_bytes_, s);
-    }
-
-    void ReportProgress(const char* file, uint64_t file_copied_bytes, uint64_t file_total_bytes) {
-        char overall_percentage_str[5] = "?";
-        if (expected_total_bytes_ != 0) {
-            int overall_percentage = static_cast<int>(total_bytes_ * 100 / expected_total_bytes_);
-            // If we're pulling symbolic links, we'll pull the target of the link rather than
-            // just create a local link, and that will cause us to go over 100%.
-            if (overall_percentage <= 100) {
-                snprintf(overall_percentage_str, sizeof(overall_percentage_str), "%d%%",
-                         overall_percentage);
-            }
-        }
-
-        if (file_copied_bytes > file_total_bytes || file_total_bytes == 0) {
-            // This case can happen if we're racing against something that wrote to the file
-            // between our stat and our read, or if we're reading a magic file that lies about
-            // its size. Just show how much we've copied.
-            Printf("[%4s] %s: %" PRId64 "/?", overall_percentage_str, file, file_copied_bytes);
-        } else {
-            // If we're transferring multiple files, we want to know how far through the current
-            // file we are, as well as the overall percentage.
-            if (expect_multiple_files_) {
-                int file_percentage = static_cast<int>(file_copied_bytes * 100 / file_total_bytes);
-                Printf("[%4s] %s: %d%%", overall_percentage_str, file, file_percentage);
-            } else {
-                Printf("[%4s] %s", overall_percentage_str, file);
-            }
-        }
-    }
 
     void Printf(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
         std::string s;
@@ -346,6 +448,18 @@
         line_printer_.Print(s, LinePrinter::INFO);
     }
 
+    void Println(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
+        std::string s;
+
+        va_list ap;
+        va_start(ap, fmt);
+        android::base::StringAppendV(&s, fmt, ap);
+        va_end(ap);
+
+        line_printer_.Print(s, LinePrinter::INFO);
+        line_printer_.KeepInfoLine();
+    }
+
     void Error(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
         std::string s = "adb: error: ";
 
@@ -369,33 +483,29 @@
     }
 
     void ComputeExpectedTotalBytes(const std::vector<copyinfo>& file_list) {
-        expected_total_bytes_ = 0;
+        current_ledger_.bytes_expected = 0;
         for (const copyinfo& ci : file_list) {
             // Unfortunately, this doesn't work for symbolic links, because we'll copy the
             // target of the link rather than just creating a link. (But ci.size is the link size.)
-            if (!ci.skip) expected_total_bytes_ += ci.size;
+            if (!ci.skip) current_ledger_.bytes_expected += ci.size;
         }
-        expect_multiple_files_ = true;
+        current_ledger_.expect_multiple_files = true;
     }
 
     void SetExpectedTotalBytes(uint64_t expected_total_bytes) {
-        expected_total_bytes_ = expected_total_bytes;
-        expect_multiple_files_ = false;
+        current_ledger_.bytes_expected = expected_total_bytes;
+        current_ledger_.expect_multiple_files = false;
     }
 
-    uint64_t total_bytes_;
-
     // TODO: add a char[max] buffer here, to replace syncsendbuf...
     int fd;
     size_t max;
 
   private:
-    uint64_t start_time_ms_;
-
-    uint64_t expected_total_bytes_;
-    bool expect_multiple_files_;
     bool expect_done_;
 
+    TransferLedger global_ledger_;
+    TransferLedger current_ledger_;
     LinePrinter line_printer_;
 
     bool SendQuit() {
@@ -422,12 +532,6 @@
         }
         return true;
     }
-
-    static uint64_t CurrentTimeMs() {
-        struct timeval tv;
-        gettimeofday(&tv, 0); // (Not clock_gettime because of Mac/Windows.)
-        return static_cast<uint64_t>(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
-    }
 };
 
 typedef void (sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char* name);
@@ -570,13 +674,12 @@
             return false;
         }
 
-        sc.total_bytes_ += msg.data.size;
-
         bytes_copied += msg.data.size;
-
+        sc.RecordBytesTransferred(msg.data.size);
         sc.ReportProgress(rpath, bytes_copied, size);
     }
 
+    sc.RecordFilesTransferred(1);
     adb_close(lfd);
     return true;
 }
@@ -661,13 +764,14 @@
 static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath,
                                   std::string rpath, bool check_timestamps,
                                   bool list_only) {
+    sc.NewTransfer();
+
     // Make sure that both directory paths end in a slash.
     // Both paths are known to be nonempty, so we don't need to check.
     ensure_trailing_separators(lpath, rpath);
 
     // Recursively build the list of files to copy.
     std::vector<copyinfo> file_list;
-    int pushed = 0;
     int skipped = 0;
     if (!local_build_list(sc, &file_list, lpath, rpath)) {
         return false;
@@ -699,21 +803,19 @@
     for (const copyinfo& ci : file_list) {
         if (!ci.skip) {
             if (list_only) {
-                sc.Error("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
+                sc.Println("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
             } else {
                 if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time, ci.mode)) {
                     return false;
                 }
             }
-            pushed++;
         } else {
             skipped++;
         }
     }
 
-    sc.Printf("%s: %d file%s pushed. %d file%s skipped.%s", rpath.c_str(),
-              pushed, (pushed == 1) ? "" : "s", skipped,
-              (skipped == 1) ? "" : "s", sc.TransferRate().c_str());
+    sc.RecordFilesSkipped(skipped);
+    sc.ReportTransferRate(lpath, TransferDirection::push);
     return true;
 }
 
@@ -789,10 +891,14 @@
             path_holder += adb_basename(src_path);
             dst_path = path_holder.c_str();
         }
+
+        sc.NewTransfer();
         sc.SetExpectedTotalBytes(st.st_size);
         success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode);
+        sc.ReportTransferRate(src_path, TransferDirection::push);
     }
 
+    sc.ReportOverallTransferRate(TransferDirection::push);
     return success;
 }
 
@@ -878,6 +984,8 @@
 
 static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath,
                                   std::string lpath, bool copy_attrs) {
+    sc.NewTransfer();
+
     // Make sure that both directory paths end in a slash.
     // Both paths are known to be nonempty, so we don't need to check.
     ensure_trailing_separators(lpath, rpath);
@@ -891,7 +999,6 @@
 
     sc.ComputeExpectedTotalBytes(file_list);
 
-    int pulled = 0;
     int skipped = 0;
     for (const copyinfo &ci : file_list) {
         if (!ci.skip) {
@@ -903,7 +1010,6 @@
                              ci.lpath.c_str(), strerror(errno));
                     return false;
                 }
-                pulled++;
                 continue;
             }
 
@@ -914,15 +1020,13 @@
             if (copy_attrs && set_time_and_mode(ci.lpath, ci.time, ci.mode)) {
                 return false;
             }
-            pulled++;
         } else {
             skipped++;
         }
     }
 
-    sc.Printf("%s: %d file%s pulled. %d file%s skipped.%s", rpath.c_str(),
-              pulled, (pulled == 1) ? "" : "s", skipped,
-              (skipped == 1) ? "" : "s", sc.TransferRate().c_str());
+    sc.RecordFilesSkipped(skipped);
+    sc.ReportTransferRate(rpath, TransferDirection::pull);
     return true;
 }
 
@@ -1021,6 +1125,7 @@
             dst_path = path_holder.c_str();
         }
 
+        sc.NewTransfer();
         sc.SetExpectedTotalBytes(src_size);
         if (!sync_recv(sc, src_path, dst_path)) {
             success = false;
@@ -1031,8 +1136,10 @@
             success = false;
             continue;
         }
+        sc.ReportTransferRate(src_path, TransferDirection::pull);
     }
 
+    sc.ReportOverallTransferRate(TransferDirection::pull);
     return success;
 }
 
@@ -1040,5 +1147,9 @@
     SyncConnection sc;
     if (!sc.IsValid()) return false;
 
-    return copy_local_dir_remote(sc, lpath, rpath, true, list_only);
+    bool success = copy_local_dir_remote(sc, lpath, rpath, true, list_only);
+    if (!list_only) {
+        sc.ReportOverallTransferRate(TransferDirection::push);
+    }
+    return success;
 }
diff --git a/adb/line_printer.cpp b/adb/line_printer.cpp
index 4ec8979..64d10b6 100644
--- a/adb/line_printer.cpp
+++ b/adb/line_printer.cpp
@@ -124,4 +124,5 @@
 
 void LinePrinter::KeepInfoLine() {
   if (!have_blank_line_) Out("\n");
+  have_blank_line_ = true;
 }
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index 56e2dde..66d60c9 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -53,8 +53,8 @@
 typedef std::function<void(LogId, LogSeverity, const char*, const char*,
                            unsigned int, const char*)> LogFunction;
 
-extern void StderrLogger(LogId, LogSeverity, const char*, const char*,
-                         unsigned int, const char*);
+void KernelLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
+void StderrLogger(LogId, LogSeverity, const char*, const char*, unsigned int, const char*);
 
 #ifdef __ANDROID__
 // We expose this even though it is the default because a user that wants to
@@ -79,17 +79,14 @@
 // The tag (or '*' for the global level) comes first, followed by a colon and a
 // letter indicating the minimum priority level we're expected to log.  This can
 // be used to reveal or conceal logs with specific tags.
-extern void InitLogging(char* argv[], LogFunction&& logger);
+void InitLogging(char* argv[], LogFunction&& logger);
 
 // Configures logging using the default logger (logd for the device, stderr for
 // the host).
-extern void InitLogging(char* argv[]);
+void InitLogging(char* argv[]);
 
 // Replace the current logger.
-extern void SetLogger(LogFunction&& logger);
-
-// Get the minimum severity level for logging.
-extern LogSeverity GetMinimumLogSeverity();
+void SetLogger(LogFunction&& logger);
 
 class ErrnoRestorer {
  public:
@@ -334,6 +331,12 @@
   DISALLOW_COPY_AND_ASSIGN(LogMessage);
 };
 
+// Get the minimum severity level for logging.
+LogSeverity GetMinimumLogSeverity();
+
+// Set the minimum severity level for logging, returning the old severity.
+LogSeverity SetMinimumLogSeverity(LogSeverity new_severity);
+
 // Allows to temporarily change the minimum severity level for logging.
 class ScopedLogSeverity {
  public:
diff --git a/base/logging.cpp b/base/logging.cpp
index 959bb8b..1f47a9f 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-#ifdef _WIN32
+#if defined(_WIN32)
 #include <windows.h>
 #endif
 
 #include "android-base/logging.h"
 
+#include <fcntl.h>
 #include <libgen.h>
 #include <time.h>
 
@@ -30,6 +31,10 @@
 #include <errno.h>
 #endif
 
+#if defined(__linux__)
+#include <sys/uio.h>
+#endif
+
 #include <iostream>
 #include <limits>
 #include <sstream>
@@ -172,10 +177,6 @@
 static LogSeverity gMinimumLogSeverity = INFO;
 static auto& gProgramInvocationName = *new std::unique_ptr<std::string>();
 
-LogSeverity GetMinimumLogSeverity() {
-  return gMinimumLogSeverity;
-}
-
 static const char* ProgramInvocationName() {
   if (gProgramInvocationName == nullptr) {
     gProgramInvocationName.reset(new std::string(getprogname()));
@@ -184,6 +185,42 @@
   return gProgramInvocationName->c_str();
 }
 
+#if defined(__linux__)
+void KernelLogger(android::base::LogId, android::base::LogSeverity severity,
+                  const char* tag, const char*, unsigned int, const char* msg) {
+  static constexpr int kLogSeverityToKernelLogLevel[] = {
+    [android::base::VERBOSE] = 7, // KERN_DEBUG (there is no verbose kernel log level)
+    [android::base::DEBUG]   = 7, // KERN_DEBUG
+    [android::base::INFO]    = 6, // KERN_INFO
+    [android::base::WARNING] = 4, // KERN_WARNING
+    [android::base::ERROR]   = 3, // KERN_ERROR
+    [android::base::FATAL]   = 2, // KERN_CRIT
+  };
+  static_assert(arraysize(kLogSeverityToKernelLogLevel) == android::base::FATAL + 1,
+                "Mismatch in size of kLogSeverityToKernelLogLevel and values in LogSeverity");
+
+  static int klog_fd = TEMP_FAILURE_RETRY(open("/dev/kmsg", O_WRONLY | O_CLOEXEC));
+  if (klog_fd == -1) return;
+
+  int level = kLogSeverityToKernelLogLevel[severity];
+
+  // The kernel's printk buffer is only 1024 bytes.
+  // TODO: should we automatically break up long lines into multiple lines?
+  // Or we could log but with something like "..." at the end?
+  char buf[1024];
+  size_t size = snprintf(buf, sizeof(buf), "<%d>%s: %s\n", level, tag, msg);
+  if (size > sizeof(buf)) {
+    size = snprintf(buf, sizeof(buf), "<%d>%s: %zu-byte message too long for printk\n",
+                    level, tag, size);
+  }
+
+  iovec iov[1];
+  iov[0].iov_base = buf;
+  iov[0].iov_len = size;
+  TEMP_FAILURE_RETRY(writev(klog_fd, iov, 1));
+}
+#endif
+
 void StderrLogger(LogId, LogSeverity severity, const char*, const char* file,
                   unsigned int line, const char* message) {
   struct tm now;
@@ -211,28 +248,26 @@
 LogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) {
 }
 
-static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
-    ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
-    ANDROID_LOG_WARN,    ANDROID_LOG_ERROR, ANDROID_LOG_FATAL,
-};
-static_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1,
-              "Mismatch in size of kLogSeverityToAndroidLogPriority and values "
-              "in LogSeverity");
-
-static const log_id kLogIdToAndroidLogId[] = {
-    LOG_ID_MAX, LOG_ID_MAIN, LOG_ID_SYSTEM,
-};
-static_assert(arraysize(kLogIdToAndroidLogId) == SYSTEM + 1,
-              "Mismatch in size of kLogIdToAndroidLogId and values in LogId");
-
 void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag,
                             const char* file, unsigned int line,
                             const char* message) {
+  static constexpr android_LogPriority kLogSeverityToAndroidLogPriority[] = {
+    ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
+    ANDROID_LOG_WARN,    ANDROID_LOG_ERROR, ANDROID_LOG_FATAL,
+  };
+  static_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1,
+                "Mismatch in size of kLogSeverityToAndroidLogPriority and values in LogSeverity");
+
   int priority = kLogSeverityToAndroidLogPriority[severity];
   if (id == DEFAULT) {
     id = default_log_id_;
   }
 
+  static constexpr log_id kLogIdToAndroidLogId[] = {
+    LOG_ID_MAX, LOG_ID_MAIN, LOG_ID_SYSTEM,
+  };
+  static_assert(arraysize(kLogIdToAndroidLogId) == SYSTEM + 1,
+                "Mismatch in size of kLogIdToAndroidLogId and values in LogId");
   log_id lg_id = kLogIdToAndroidLogId[id];
 
   if (priority == ANDROID_LOG_FATAL) {
@@ -427,13 +462,22 @@
   gLogger(id, severity, tag, file, line, message);
 }
 
-ScopedLogSeverity::ScopedLogSeverity(LogSeverity level) {
-  old_ = gMinimumLogSeverity;
-  gMinimumLogSeverity = level;
+LogSeverity GetMinimumLogSeverity() {
+    return gMinimumLogSeverity;
+}
+
+LogSeverity SetMinimumLogSeverity(LogSeverity new_severity) {
+  LogSeverity old_severity = gMinimumLogSeverity;
+  gMinimumLogSeverity = new_severity;
+  return old_severity;
+}
+
+ScopedLogSeverity::ScopedLogSeverity(LogSeverity new_severity) {
+  old_ = SetMinimumLogSeverity(new_severity);
 }
 
 ScopedLogSeverity::~ScopedLogSeverity() {
-  gMinimumLogSeverity = old_;
+  SetMinimumLogSeverity(old_);
 }
 
 }  // namespace base
diff --git a/init/action.cpp b/init/action.cpp
index f3e362e..ed88f6d 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -118,7 +118,8 @@
     Timer t;
     int result = command.InvokeFunc();
 
-    if (klog_get_level() >= KLOG_DEBUG_LEVEL) {
+    // TODO: this should probably be changed to "if (failed || took a long time)"...
+    if (android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
         std::string trigger_name = BuildTriggersString();
         std::string cmd_str = command.BuildCommandString();
         std::string source = command.BuildSourceString();
diff --git a/init/builtins.cpp b/init/builtins.cpp
index d64c3d2..3d220c5 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -482,11 +482,7 @@
  * not return.
  */
 static int do_mount_all(const std::vector<std::string>& args) {
-    pid_t pid;
     int ret = -1;
-    int child_ret = -1;
-    int status;
-    struct fstab *fstab;
 
     const char* fstabfile = args[1].c_str();
     /*
@@ -495,9 +491,10 @@
      * process if anything goes wrong (crash or memory leak), and wait for
      * the child to finish in the parent.
      */
-    pid = fork();
+    pid_t pid = fork();
     if (pid > 0) {
         /* Parent.  Wait for the child to return */
+        int status;
         int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
         if (wp_ret == -1) {
             // Unexpected error code. We will continue anyway.
@@ -511,9 +508,13 @@
         }
     } else if (pid == 0) {
         /* child, call fs_mgr_mount_all() */
-        klog_set_level(6);  /* So we can see what fs_mgr_mount_all() does */
-        fstab = fs_mgr_read_fstab(fstabfile);
-        child_ret = fs_mgr_mount_all(fstab);
+
+        // So we can always see what fs_mgr_mount_all() does.
+        // Only needed if someone explicitly changes the default log level in their init.rc.
+        android::base::ScopedLogSeverity info(android::base::INFO);
+
+        struct fstab* fstab = fs_mgr_read_fstab(fstabfile);
+        int child_ret = fs_mgr_mount_all(fstab);
         fs_mgr_free_fstab(fstab);
         if (child_ret == -1) {
             PLOG(ERROR) << "fs_mgr_mount_all returned an error";
@@ -866,12 +867,23 @@
 }
 
 static int do_loglevel(const std::vector<std::string>& args) {
+    // TODO: support names instead/as well?
     int log_level = std::stoi(args[1]);
-    if (log_level < KLOG_ERROR_LEVEL || log_level > KLOG_DEBUG_LEVEL) {
-        LOG(ERROR) << "loglevel: invalid log level " << log_level;
-        return -EINVAL;
+    android::base::LogSeverity severity;
+    switch (log_level) {
+        case 7: severity = android::base::DEBUG; break;
+        case 6: severity = android::base::INFO; break;
+        case 5:
+        case 4: severity = android::base::WARNING; break;
+        case 3: severity = android::base::ERROR; break;
+        case 2:
+        case 1:
+        case 0: severity = android::base::FATAL; break;
+        default:
+            LOG(ERROR) << "loglevel: invalid log level " << log_level;
+            return -EINVAL;
     }
-    klog_set_level(log_level);
+    android::base::SetMinimumLogSeverity(severity);
     return 0;
 }
 
diff --git a/init/log.cpp b/init/log.cpp
index 379141a..8618340 100644
--- a/init/log.cpp
+++ b/init/log.cpp
@@ -17,52 +17,16 @@
 #include "log.h"
 
 #include <fcntl.h>
-#include <stdlib.h>
 #include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/uio.h>
 
 #include <selinux/selinux.h>
 
-static const int kLogSeverityToKLogLevel[] = {
-    [android::base::VERBOSE] = KLOG_DEBUG_LEVEL,
-    [android::base::DEBUG] = KLOG_DEBUG_LEVEL,
-    [android::base::INFO] = KLOG_INFO_LEVEL,
-    [android::base::WARNING] = KLOG_WARNING_LEVEL,
-    [android::base::ERROR] = KLOG_ERROR_LEVEL,
-    [android::base::FATAL] = KLOG_ERROR_LEVEL,
-};
-static_assert(arraysize(kLogSeverityToKLogLevel) == android::base::FATAL + 1,
-              "Mismatch in size of kLogSeverityToKLogLevel and values in LogSeverity");
-
-static void KernelLogger(android::base::LogId, android::base::LogSeverity severity,
-                         const char* tag, const char*, unsigned int, const char* msg) {
-    int level = kLogSeverityToKLogLevel[severity];
-    if (level > klog_get_level()) return;
-
-    // The kernel's printk buffer is only 1024 bytes.
-    // TODO: should we automatically break up long lines into multiple lines?
-    // Or we could log but with something like "..." at the end?
-    char buf[1024];
-    size_t size = snprintf(buf, sizeof(buf), "<%d>%s: %s\n", level, tag, msg);
-    if (size > sizeof(buf)) {
-        size = snprintf(buf, sizeof(buf), "<%d>%s: %zu-byte message too long for printk\n",
-                        level, tag, size);
-    }
-
-    iovec iov[1];
-    iov[0].iov_base = buf;
-    iov[0].iov_len = size;
-    klog_writev(level, iov, 1);
-}
-
 void InitKernelLogging(char* argv[]) {
     // Make stdin/stdout/stderr all point to /dev/null.
     int fd = open("/sys/fs/selinux/null", O_RDWR);
     if (fd == -1) {
         int saved_errno = errno;
-        android::base::InitLogging(argv, &KernelLogger);
+        android::base::InitLogging(argv, &android::base::KernelLogger);
         errno = saved_errno;
         PLOG(FATAL) << "Couldn't open /sys/fs/selinux/null";
     }
@@ -71,8 +35,7 @@
     dup2(fd, 2);
     if (fd > 2) close(fd);
 
-    android::base::InitLogging(argv, &KernelLogger);
-    klog_set_level(KLOG_INFO_LEVEL);
+    android::base::InitLogging(argv, &android::base::KernelLogger);
 }
 
 int selinux_klog_callback(int type, const char *fmt, ...) {
@@ -87,6 +50,6 @@
     va_start(ap, fmt);
     vsnprintf(buf, sizeof(buf), fmt, ap);
     va_end(ap);
-    KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
+    android::base::KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
     return 0;
 }
diff --git a/init/log.h b/init/log.h
index cf552a1..8fa6d74 100644
--- a/init/log.h
+++ b/init/log.h
@@ -19,8 +19,6 @@
 
 #include <android-base/logging.h>
 
-#include <cutils/klog.h>
-
 void InitKernelLogging(char* argv[]);
 
 int selinux_klog_callback(int level, const char* fmt, ...) __printflike(2, 3);
diff --git a/init/readme.txt b/init/readme.txt
index 7260775..4c04f17 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -514,6 +514,3 @@
 Alternatively, use the emulator:
 
   emulator -partition-size 1024 -verbose -show-kernel -no-window
-
-You might want to change the klog_set_level call so you see all the kernel
-logging in dmesg (or the emulator output).
diff --git a/libsync/Android.mk b/libsync/Android.mk
index fd1c88c..f407bd1 100644
--- a/libsync/Android.mk
+++ b/libsync/Android.mk
@@ -4,17 +4,27 @@
 LOCAL_SRC_FILES := sync.c
 LOCAL_MODULE := libsync
 LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 LOCAL_CFLAGS := -Werror
 include $(BUILD_SHARED_LIBRARY)
 
+# libsync_recovery is only intended for the recovery binary.
+# Future versions of the kernel WILL require an updated libsync, and will break
+# anything statically linked against the current libsync.
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := sync.c
+LOCAL_MODULE := libsync_recovery
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_CFLAGS := -Werror
+include $(BUILD_STATIC_LIBRARY)
+
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := sync.c sync_test.c
 LOCAL_MODULE := sync_test
 LOCAL_MODULE_TAGS := optional tests
-LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_CFLAGS := -Werror
 include $(BUILD_EXECUTABLE)
diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp
index f3d6d8f..dc96aef 100644
--- a/libutils/SharedBuffer.cpp
+++ b/libutils/SharedBuffer.cpp
@@ -114,8 +114,9 @@
 int32_t SharedBuffer::release(uint32_t flags) const
 {
     int32_t prev = 1;
-    if (onlyOwner() || ((prev = mRefs.fetch_sub(1, std::memory_order_release) == 1)
-            && (atomic_thread_fence(std::memory_order_acquire), true))) {
+    if (onlyOwner()
+            || (((prev = mRefs.fetch_sub(1, std::memory_order_release)) == 1)
+                && (atomic_thread_fence(std::memory_order_acquire), true))) {
         mRefs.store(0, std::memory_order_relaxed);
         if ((flags & eKeepStorage) == 0) {
             free(const_cast<SharedBuffer*>(this));
diff --git a/logcat/logpersist b/logcat/logpersist
index f0e7d42..74d99fc 100755
--- a/logcat/logpersist
+++ b/logcat/logpersist
@@ -171,6 +171,6 @@
 
 if [ X"${log_tag}" != X"`getprop ${log_tag_property}`" ] ||
    [ X"${logd_logpersistd}" != X"`getprop ${property}`" ]; then
-  echo "WARNING: killing Settings" >&2
+  echo "WARNING: killing Settings application to pull in new values" >&2
   am force-stop com.android.settings
 fi