Merge changes If2f3008f,Id3411479,I90df5fc1

* changes:
  adb: improve display of transfer rate.
  adb: add missing newline when printing transfer rate.
  adb: fix output of `sync -l`
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/include/utils/Condition.h b/include/utils/Condition.h
index a420185..5650598 100644
--- a/include/utils/Condition.h
+++ b/include/utils/Condition.h
@@ -54,7 +54,7 @@
     };
 
     Condition();
-    Condition(int type);
+    explicit Condition(int type);
     ~Condition();
     // Wait on the condition variable.  Lock the mutex before calling.
     status_t wait(Mutex& mutex);
diff --git a/include/utils/Mutex.h b/include/utils/Mutex.h
index f027c79..8b720b9 100644
--- a/include/utils/Mutex.h
+++ b/include/utils/Mutex.h
@@ -48,8 +48,8 @@
     };
 
                 Mutex();
-                Mutex(const char* name);
-                Mutex(int type, const char* name = NULL);
+    explicit    Mutex(const char* name);
+    explicit    Mutex(int type, const char* name = NULL);
                 ~Mutex();
 
     // lock or unlock the mutex
@@ -73,8 +73,8 @@
     // constructed and released when Autolock goes out of scope.
     class Autolock {
     public:
-        inline Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
-        inline Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
+        inline explicit Autolock(Mutex& mutex) : mLock(mutex)  { mLock.lock(); }
+        inline explicit Autolock(Mutex* mutex) : mLock(*mutex) { mLock.lock(); }
         inline ~Autolock() { mLock.unlock(); }
     private:
         Mutex& mLock;
diff --git a/include/utils/RWLock.h b/include/utils/RWLock.h
index e743b1c..d5b81d3 100644
--- a/include/utils/RWLock.h
+++ b/include/utils/RWLock.h
@@ -47,8 +47,8 @@
     };
 
                 RWLock();
-                RWLock(const char* name);
-                RWLock(int type, const char* name = NULL);
+    explicit    RWLock(const char* name);
+    explicit    RWLock(int type, const char* name = NULL);
                 ~RWLock();
 
     status_t    readLock();
@@ -59,7 +59,7 @@
 
     class AutoRLock {
     public:
-        inline AutoRLock(RWLock& rwlock) : mLock(rwlock)  { mLock.readLock(); }
+        inline explicit AutoRLock(RWLock& rwlock) : mLock(rwlock)  { mLock.readLock(); }
         inline ~AutoRLock() { mLock.unlock(); }
     private:
         RWLock& mLock;
@@ -67,7 +67,7 @@
 
     class AutoWLock {
     public:
-        inline AutoWLock(RWLock& rwlock) : mLock(rwlock)  { mLock.writeLock(); }
+        inline explicit AutoWLock(RWLock& rwlock) : mLock(rwlock)  { mLock.writeLock(); }
         inline ~AutoWLock() { mLock.unlock(); }
     private:
         RWLock& mLock;
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index c82e7d9..950dbd0 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -222,12 +222,12 @@
     
     inline wp() : m_ptr(0) { }
 
-    wp(T* other);
+    wp(T* other);  // NOLINT(implicit)
     wp(const wp<T>& other);
-    wp(const sp<T>& other);
-    template<typename U> wp(U* other);
-    template<typename U> wp(const sp<U>& other);
-    template<typename U> wp(const wp<U>& other);
+    explicit wp(const sp<T>& other);
+    template<typename U> wp(U* other);  // NOLINT(implicit)
+    template<typename U> wp(const sp<U>& other);  // NOLINT(implicit)
+    template<typename U> wp(const wp<U>& other);  // NOLINT(implicit)
 
     ~wp();
     
diff --git a/include/utils/StrongPointer.h b/include/utils/StrongPointer.h
index 50fde35..d90b788 100644
--- a/include/utils/StrongPointer.h
+++ b/include/utils/StrongPointer.h
@@ -60,12 +60,12 @@
 public:
     inline sp() : m_ptr(0) { }
 
-    sp(T* other);
+    sp(T* other);  // NOLINT(implicit)
     sp(const sp<T>& other);
     sp(sp<T>&& other);
-    template<typename U> sp(U* other);
-    template<typename U> sp(const sp<U>& other);
-    template<typename U> sp(sp<U>&& other);
+    template<typename U> sp(U* other);  // NOLINT(implicit)
+    template<typename U> sp(const sp<U>& other);  // NOLINT(implicit)
+    template<typename U> sp(sp<U>&& other);  // NOLINT(implicit)
 
     ~sp();
 
diff --git a/include/utils/Thread.h b/include/utils/Thread.h
index 1532b7e..0f7ac9f 100644
--- a/include/utils/Thread.h
+++ b/include/utils/Thread.h
@@ -41,7 +41,7 @@
 public:
     // Create a Thread object, but doesn't create or start the associated
     // thread. See the run() method.
-                        Thread(bool canCallJava = true);
+    explicit            Thread(bool canCallJava = true);
     virtual             ~Thread();
 
     // Start the thread in threadLoop() which needs to be implemented.
diff --git a/include/utils/TypeHelpers.h b/include/utils/TypeHelpers.h
index 61d618e..64d25c5 100644
--- a/include/utils/TypeHelpers.h
+++ b/include/utils/TypeHelpers.h
@@ -240,7 +240,7 @@
     key_value_pair_t() { }
     key_value_pair_t(const key_value_pair_t& o) : key(o.key), value(o.value) { }
     key_value_pair_t(const KEY& k, const VALUE& v) : key(k), value(v)  { }
-    key_value_pair_t(const KEY& k) : key(k) { }
+    explicit key_value_pair_t(const KEY& k) : key(k) { }
     inline bool operator < (const key_value_pair_t& o) const {
         return strictly_order_type(key, o.key);
     }
diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h
index 21ad71c..4dd91fd 100644
--- a/include/utils/VectorImpl.h
+++ b/include/utils/VectorImpl.h
@@ -132,7 +132,7 @@
 {
 public:
                             SortedVectorImpl(size_t itemSize, uint32_t flags);
-                            SortedVectorImpl(const VectorImpl& rhs);
+    explicit                SortedVectorImpl(const VectorImpl& rhs);
     virtual                 ~SortedVectorImpl();
     
     SortedVectorImpl&     operator = (const SortedVectorImpl& rhs);    
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/libcutils/sched_policy.c b/libcutils/sched_policy.c
index d7b4b0b..5c68add 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -45,9 +45,6 @@
 
 #define POLICY_DEBUG 0
 
-// This prctl is only available in Android kernels.
-#define PR_SET_TIMERSLACK_PID 41
-
 // timer slack value in nS enforced when the thread moves to background
 #define TIMER_SLACK_BG 40000000
 #define TIMER_SLACK_FG 50000
@@ -293,9 +290,9 @@
 }
 
 static void set_timerslack_ns(int tid, unsigned long long slack) {
+    // v4.6+ kernels support the /proc/<tid>/timerslack_ns interface.
+    // TODO: once we've backported this, log if the open(2) fails.
     char buf[64];
-
-    /* v4.6+ kernels support the /proc/<tid>/timerslack_ns interface. */
     snprintf(buf, sizeof(buf), "/proc/%d/timerslack_ns", tid);
     int fd = open(buf, O_WRONLY | O_CLOEXEC);
     if (fd != -1) {
@@ -306,11 +303,6 @@
         close(fd);
         return;
     }
-
-    /* If the above fails, try the old common.git PR_SET_TIMERSLACK_PID. */
-    if (prctl(PR_SET_TIMERSLACK_PID, slack, tid) == -1) {
-        SLOGE("set_timerslack_ns prctl failed: %s\n", strerror(errno));
-    }
 }
 
 int set_sched_policy(int tid, SchedPolicy policy)
diff --git a/libcutils/tests/Android.bp b/libcutils/tests/Android.bp
index 530c747..ada7d5f 100644
--- a/libcutils/tests/Android.bp
+++ b/libcutils/tests/Android.bp
@@ -21,6 +21,7 @@
             srcs: [
                 "MemsetTest.cpp",
                 "PropertiesTest.cpp",
+                "sched_policy_test.cpp",
                 "trace-dev_test.cpp",
             ],
         },
diff --git a/libcutils/tests/sched_policy_test.cpp b/libcutils/tests/sched_policy_test.cpp
new file mode 100644
index 0000000..173174a
--- /dev/null
+++ b/libcutils/tests/sched_policy_test.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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 <algorithm>
+#include <chrono>
+#include <thread>
+#include <vector>
+
+#include <sys/capability.h>
+
+#include <cutils/sched_policy.h>
+
+#include <gtest/gtest.h>
+
+bool hasCapSysNice() {
+    __user_cap_header_struct header;
+    memset(&header, 0, sizeof(header));
+    header.version = _LINUX_CAPABILITY_VERSION_3;
+
+    __user_cap_data_struct caps[_LINUX_CAPABILITY_U32S_3];
+    if (capget(&header, &caps[0])) {
+        GTEST_LOG_(WARNING) << "failed to get process capabilities";
+        return false;
+    }
+
+    auto nice_idx = CAP_TO_INDEX(CAP_SYS_NICE);
+    auto nice_mask = CAP_TO_MASK(CAP_SYS_NICE);
+    return caps[nice_idx].effective & nice_mask;
+}
+
+long long medianSleepTime() {
+    std::vector<long long> sleepTimes;
+    constexpr size_t numSamples = 100;
+
+    for (size_t i = 0; i < numSamples; i++) {
+        auto start = std::chrono::steady_clock::now();
+        std::this_thread::sleep_for(std::chrono::nanoseconds(1));
+        auto end = std::chrono::steady_clock::now();
+
+        auto diff = end - start;
+        sleepTimes.push_back(diff.count());
+    }
+
+    constexpr auto median = numSamples / 2;
+    std::nth_element(sleepTimes.begin(), sleepTimes.begin() + median,
+            sleepTimes.end());
+    return sleepTimes[median];
+}
+
+TEST(SchedPolicy, set_sched_policy) {
+    if (!hasCapSysNice()) {
+        GTEST_LOG_(INFO) << "skipping test that requires CAP_SYS_NICE";
+        return;
+    }
+
+    // A measureable effect of scheduling policy is that the kernel has 800x
+    // greater slack time in waking up a sleeping background thread.
+    //
+    // Look for 100x difference in how long FB and BG threads actually sleep
+    // when trying to sleep for 1 ns.  This difference is large enough not
+    // to happen by chance, but small enough (compared to 800x) to keep inherent
+    // fuzziness in scheduler behavior from causing false negatives.
+    const unsigned int BG_FG_SLACK_FACTOR = 100;
+
+    ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
+    auto bgSleepTime = medianSleepTime();
+
+    ASSERT_EQ(0, set_sched_policy(0, SP_FOREGROUND));
+    auto fgSleepTime = medianSleepTime();
+    ASSERT_GT(bgSleepTime, fgSleepTime * BG_FG_SLACK_FACTOR);
+}
+
+TEST(SchedPolicy, get_sched_policy) {
+    SchedPolicy policy;
+    ASSERT_EQ(0, get_sched_policy(0, &policy));
+
+    const char *policyName = get_sched_policy_name(policy);
+    EXPECT_NE(nullptr, policyName);
+    EXPECT_STRNE("error", policyName);
+
+    ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
+    SchedPolicy newPolicy;
+    ASSERT_EQ(0, get_sched_policy(0, &newPolicy));
+    EXPECT_EQ(SP_BACKGROUND, newPolicy);
+}
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index 085b314..d4d7d7e 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -580,15 +580,14 @@
             // grab a strong-reference, which is always safe due to the
             // extended life-time.
             curCount = impl->mStrong.fetch_add(1, std::memory_order_relaxed);
-        }
-
-        // If the strong reference count has already been incremented by
-        // someone else, the implementor of onIncStrongAttempted() is holding
-        // an unneeded reference.  So call onLastStrongRef() here to remove it.
-        // (No, this is not pretty.)  Note that we MUST NOT do this if we
-        // are in fact acquiring the first reference.
-        if (curCount > 0 && curCount < INITIAL_STRONG_VALUE) {
-            impl->mBase->onLastStrongRef(id);
+            // If the strong reference count has already been incremented by
+            // someone else, the implementor of onIncStrongAttempted() is holding
+            // an unneeded reference.  So call onLastStrongRef() here to remove it.
+            // (No, this is not pretty.)  Note that we MUST NOT do this if we
+            // are in fact acquiring the first reference.
+            if (curCount != 0 && curCount != INITIAL_STRONG_VALUE) {
+                impl->mBase->onLastStrongRef(id);
+            }
         }
     }
     
@@ -598,7 +597,7 @@
     ALOGD("attemptIncStrong of %p from %p: cnt=%d\n", this, id, curCount);
 #endif
 
-    // curCount is the value of mStrong before we increment ed it.
+    // curCount is the value of mStrong before we incremented it.
     // Now we need to fix-up the count if it was INITIAL_STRONG_VALUE.
     // This must be done safely, i.e.: handle the case where several threads
     // were here in attemptIncStrong().