Merge "native_loader: Use ANDROID_ROOT environment variable"
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index d8b1654..45c6142 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -1613,6 +1613,11 @@
     else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
         int exec_in = !strcmp(argv[0], "exec-in");
 
+        if (argc < 2) {
+            fprintf(stderr, "Usage: adb %s command\n", argv[0]);
+            return 1;
+        }
+
         std::string cmd = "exec:";
         cmd += argv[1];
         argc -= 2;
diff --git a/adb/fdevent_test.h b/adb/fdevent_test.h
index c853bce..ef65b74 100644
--- a/adb/fdevent_test.h
+++ b/adb/fdevent_test.h
@@ -49,6 +49,16 @@
         dummy = dummy_fds[0];
     }
 
+    size_t GetAdditionalLocalSocketCount() {
+#if ADB_HOST
+        // dummy socket installed in PrepareThread()
+        return 1;
+#else
+        // dummy socket and one more socket installed in fdevent_subproc_setup()
+        return 2;
+#endif
+    }
+
     void TerminateThread(adb_thread_t thread) {
         fdevent_terminate_loop();
         ASSERT_TRUE(WriteFdExactly(dummy, "", 1));
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index 20a3bbb..d2ce2d8 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -44,6 +44,8 @@
     fdevent_loop();
 }
 
+const size_t SLEEP_FOR_FDEVENT_IN_MS = 100;
+
 TEST_F(LocalSocketTest, smoke) {
     // Join two socketpairs with a chain of intermediate socketpairs.
     int first[2];
@@ -99,7 +101,8 @@
     ASSERT_EQ(0, adb_close(last[1]));
 
     // Wait until the local sockets are closed.
-    adb_sleep_ms(100);
+    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
     TerminateThread(thread);
 }
 
@@ -151,12 +154,13 @@
     ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
                                   &arg, &thread));
     // Wait until the fdevent_loop() starts.
-    adb_sleep_ms(100);
+    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
     ASSERT_EQ(0, adb_close(cause_close_fd[0]));
-    adb_sleep_ms(100);
-    EXPECT_EQ(2u, fdevent_installed_count());
+    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
     ASSERT_EQ(0, adb_close(socket_fd[0]));
-
+    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
     TerminateThread(thread);
 }
 
@@ -175,10 +179,10 @@
     ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc),
                                   &arg, &thread));
     // Wait until the fdevent_loop() starts.
-    adb_sleep_ms(100);
+    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
     ASSERT_EQ(0, adb_close(cause_close_fd[0]));
-    adb_sleep_ms(100);
-    EXPECT_EQ(2u, fdevent_installed_count());
+    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
 
     // Verify if we can read successfully.
     std::vector<char> buf(arg.bytes_written);
@@ -186,6 +190,8 @@
     ASSERT_EQ(true, ReadFdExactly(socket_fd[0], buf.data(), buf.size()));
     ASSERT_EQ(0, adb_close(socket_fd[0]));
 
+    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
     TerminateThread(thread);
 }
 
@@ -208,10 +214,12 @@
                                   &arg, &thread));
 
     // Wait until the fdevent_loop() starts.
-    adb_sleep_ms(100);
-    EXPECT_EQ(3u, fdevent_installed_count());
+    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    EXPECT_EQ(2u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
     ASSERT_EQ(0, adb_close(socket_fd[0]));
 
+    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
     TerminateThread(thread);
 }
 
@@ -260,12 +268,14 @@
                                   &arg, &thread));
 
     // Wait until the fdevent_loop() starts.
-    adb_sleep_ms(100);
-    EXPECT_EQ(2u, fdevent_installed_count());
+    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count());
 
     // Wait until the client closes its socket.
     ASSERT_TRUE(adb_thread_join(client_thread));
 
+    adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS);
+    ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count());
     TerminateThread(thread);
 }
 
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index f0c334e..fde344a 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -218,7 +218,7 @@
 
 TEST_F(sysdeps_poll, fd_count) {
     // https://code.google.com/p/android/issues/detail?id=12141
-    static constexpr int num_sockets = 512;
+    static constexpr int num_sockets = 256;
     std::vector<int> sockets;
     std::vector<adb_pollfd> pfds;
     sockets.resize(num_sockets * 2);
diff --git a/adb/test_device.py b/adb/test_device.py
index 9dab3ae..2a3be88 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -279,7 +279,7 @@
         Raises:
           unittest.SkipTest: The device doesn't support exit codes.
         """
-        if self.device.SHELL_PROTOCOL_FEATURE not in self.device.features:
+        if not self.device.has_shell_protocol():
             raise unittest.SkipTest('exit codes are unavailable on this device')
 
         proc = subprocess.Popen(
@@ -342,7 +342,7 @@
         a terminal stdin to test so this test will be skipped if stdin
         is not a terminal.
         """
-        if self.device.SHELL_PROTOCOL_FEATURE not in self.device.features:
+        if not self.device.has_shell_protocol():
             raise unittest.SkipTest('PTY arguments unsupported on this device')
         if not os.isatty(sys.stdin.fileno()):
             raise unittest.SkipTest('PTY tests require stdin terminal')
@@ -394,7 +394,7 @@
 
         Bug: http://b/19734861
         """
-        if self.device.SHELL_PROTOCOL_FEATURE not in self.device.features:
+        if not self.device.has_shell_protocol():
             raise unittest.SkipTest('shell protocol unsupported on this device')
 
         # Shell protocol should be used by default.
@@ -424,7 +424,7 @@
 
         Bug: http://b/23825725
         """
-        if self.device.SHELL_PROTOCOL_FEATURE not in self.device.features:
+        if not self.device.has_shell_protocol():
             raise unittest.SkipTest('shell protocol unsupported on this device')
 
         # Start a long-running process.
@@ -445,7 +445,7 @@
 
     def test_non_interactive_stdin(self):
         """Tests that non-interactive shells send stdin."""
-        if self.device.SHELL_PROTOCOL_FEATURE not in self.device.features:
+        if not self.device.has_shell_protocol():
             raise unittest.SkipTest('non-interactive stdin unsupported '
                                     'on this device')
 
diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp
index c863ed2..0ba6b4b 100644
--- a/adb/usb_linux_client.cpp
+++ b/adb/usb_linux_client.cpp
@@ -31,6 +31,9 @@
 #include <unistd.h>
 
 #include <algorithm>
+#include <atomic>
+
+#include <android-base/logging.h>
 
 #include "adb.h"
 #include "transport.h"
@@ -49,14 +52,19 @@
 #define cpu_to_le16(x)  htole16(x)
 #define cpu_to_le32(x)  htole32(x)
 
+static int dummy_fd = -1;
+
 struct usb_handle
 {
     adb_cond_t notify;
     adb_mutex_t lock;
+    bool open_new_connection;
+    std::atomic<bool> kicked;
 
     int (*write)(usb_handle *h, const void *data, int len);
     int (*read)(usb_handle *h, void *data, int len);
     void (*kick)(usb_handle *h);
+    void (*close)(usb_handle *h);
 
     // Legacy f_adb
     int fd;
@@ -241,8 +249,10 @@
     while (true) {
         // wait until the USB device needs opening
         adb_mutex_lock(&usb->lock);
-        while (usb->fd != -1)
+        while (!usb->open_new_connection) {
             adb_cond_wait(&usb->notify, &usb->lock);
+        }
+        usb->open_new_connection = false;
         adb_mutex_unlock(&usb->lock);
 
         D("[ usb_thread - opening device ]");
@@ -281,6 +291,10 @@
             h->fd, n, errno, strerror(errno));
         return -1;
     }
+    if (h->kicked) {
+        D("usb_adb_write finished due to kicked");
+        return -1;
+    }
     D("[ done fd=%d ]", h->fd);
     return 0;
 }
@@ -299,6 +313,10 @@
                 h->fd, n, errno, strerror(errno));
             return -1;
         }
+        if (h->kicked) {
+            D("usb_adb_read finished due to kicked");
+            return -1;
+        }
         len -= n;
         data = ((char*)data) + n;
     }
@@ -306,14 +324,23 @@
     return 0;
 }
 
-static void usb_adb_kick(usb_handle *h)
-{
+static void usb_adb_kick(usb_handle *h) {
     D("usb_kick");
-    adb_mutex_lock(&h->lock);
-    unix_close(h->fd);
-    h->fd = -1;
+    // Other threads may be calling usb_adb_read/usb_adb_write at the same time.
+    // If we close h->fd, the file descriptor will be reused to open other files,
+    // and the read/write thread may operate on the wrong file. So instead
+    // we set the kicked flag and reopen h->fd to a dummy file here. After read/write
+    // threads finish, we close h->fd in usb_adb_close().
+    h->kicked = true;
+    TEMP_FAILURE_RETRY(dup2(dummy_fd, h->fd));
+}
 
-    // notify usb_adb_open_thread that we are disconnected
+static void usb_adb_close(usb_handle *h) {
+    h->kicked = false;
+    adb_close(h->fd);
+    // Notify usb_adb_open_thread to open a new connection.
+    adb_mutex_lock(&h->lock);
+    h->open_new_connection = true;
     adb_cond_signal(&h->notify);
     adb_mutex_unlock(&h->lock);
 }
@@ -326,8 +353,11 @@
     h->write = usb_adb_write;
     h->read = usb_adb_read;
     h->kick = usb_adb_kick;
+    h->close = usb_adb_close;
+    h->kicked = false;
     h->fd = -1;
 
+    h->open_new_connection = true;
     adb_cond_init(&h->notify, 0);
     adb_mutex_init(&h->lock, 0);
 
@@ -350,7 +380,7 @@
 }
 
 
-static void init_functionfs(struct usb_handle *h)
+static bool init_functionfs(struct usb_handle *h)
 {
     ssize_t ret;
     struct desc_v1 v1_descriptor;
@@ -413,7 +443,7 @@
         goto err;
     }
 
-    return;
+    return true;
 
 err:
     if (h->bulk_in > 0) {
@@ -428,7 +458,7 @@
         adb_close(h->control);
         h->control = -1;
     }
-    return;
+    return false;
 }
 
 static void usb_ffs_open_thread(void* x) {
@@ -439,16 +469,16 @@
     while (true) {
         // wait until the USB device needs opening
         adb_mutex_lock(&usb->lock);
-        while (usb->control != -1 && usb->bulk_in != -1 && usb->bulk_out != -1)
+        while (!usb->open_new_connection) {
             adb_cond_wait(&usb->notify, &usb->lock);
+        }
+        usb->open_new_connection = false;
         adb_mutex_unlock(&usb->lock);
 
         while (true) {
-            init_functionfs(usb);
-
-            if (usb->control >= 0 && usb->bulk_in >= 0 && usb->bulk_out >= 0)
+            if (init_functionfs(usb)) {
                 break;
-
+            }
             adb_sleep_ms(1000);
         }
         property_set("sys.usb.ffs.ready", "1");
@@ -513,16 +543,22 @@
         D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out, errno);
     }
 
-    adb_mutex_lock(&h->lock);
-
     // don't close ep0 here, since we may not need to reinitialize it with
     // the same descriptors again. if however ep1/ep2 fail to re-open in
     // init_functionfs, only then would we close and open ep0 again.
+    // Ditto the comment in usb_adb_kick.
+    h->kicked = true;
+    TEMP_FAILURE_RETRY(dup2(dummy_fd, h->bulk_out));
+    TEMP_FAILURE_RETRY(dup2(dummy_fd, h->bulk_in));
+}
+
+static void usb_ffs_close(usb_handle *h) {
+    h->kicked = false;
     adb_close(h->bulk_out);
     adb_close(h->bulk_in);
-    h->bulk_out = h->bulk_in = -1;
-
-    // notify usb_ffs_open_thread that we are disconnected
+    // Notify usb_adb_open_thread to open a new connection.
+    adb_mutex_lock(&h->lock);
+    h->open_new_connection = true;
     adb_cond_signal(&h->notify);
     adb_mutex_unlock(&h->lock);
 }
@@ -537,10 +573,13 @@
     h->write = usb_ffs_write;
     h->read = usb_ffs_read;
     h->kick = usb_ffs_kick;
+    h->close = usb_ffs_close;
+    h->kicked = false;
     h->control = -1;
     h->bulk_out = -1;
     h->bulk_out = -1;
 
+    h->open_new_connection = true;
     adb_cond_init(&h->notify, 0);
     adb_mutex_init(&h->lock, 0);
 
@@ -552,6 +591,8 @@
 
 void usb_init()
 {
+    dummy_fd = adb_open("/dev/null", O_WRONLY);
+    CHECK_NE(dummy_fd, -1);
     if (access(USB_FFS_ADB_EP0, F_OK) == 0)
         usb_ffs_init();
     else
@@ -569,6 +610,7 @@
 }
 int usb_close(usb_handle *h)
 {
+    h->close(h);
     return 0;
 }
 
diff --git a/bootstat/Android.mk b/bootstat/Android.mk
index 6300941..bdd680d 100644
--- a/bootstat/Android.mk
+++ b/bootstat/Android.mk
@@ -16,8 +16,6 @@
 
 LOCAL_PATH := $(call my-dir)
 
-bootstat_c_includes := external/gtest/include
-
 bootstat_lib_src_files := \
         boot_event_record_store.cpp \
         event_log_list_builder.cpp \
@@ -57,7 +55,7 @@
 
 LOCAL_MODULE := libbootstat
 LOCAL_CFLAGS := $(bootstat_cflags)
-LOCAL_C_INCLUDES := $(bootstat_c_includes)
+LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_prod
 LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
 LOCAL_SRC_FILES := $(bootstat_lib_src_files)
 # Clang is required because of C++14
@@ -72,7 +70,7 @@
 
 LOCAL_MODULE := libbootstat_debug
 LOCAL_CFLAGS := $(bootstat_cflags)
-LOCAL_C_INCLUDES := $(bootstat_c_includes)
+LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_prod
 LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
 LOCAL_SRC_FILES := $(bootstat_lib_src_files)
 # Clang is required because of C++14
@@ -87,7 +85,7 @@
 
 LOCAL_MODULE := libbootstat_host_debug
 LOCAL_CFLAGS := $(bootstat_debug_cflags)
-LOCAL_C_INCLUDES := $(bootstat_c_includes)
+LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_prod
 LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
 LOCAL_SRC_FILES := $(bootstat_lib_src_files)
 # Clang is required because of C++14
@@ -102,7 +100,7 @@
 
 LOCAL_MODULE := bootstat
 LOCAL_CFLAGS := $(bootstat_cflags)
-LOCAL_C_INCLUDES := $(bootstat_c_includes)
+LOCAL_WHOLE_STATIC_LIBRARIES := libgtest_prod
 LOCAL_SHARED_LIBRARIES := $(bootstat_shared_libs)
 LOCAL_STATIC_LIBRARIES := libbootstat
 LOCAL_INIT_RC := bootstat.rc
diff --git a/fastboot/protocol.cpp b/fastboot/protocol.cpp
index 4850b4a..1785b76 100644
--- a/fastboot/protocol.cpp
+++ b/fastboot/protocol.cpp
@@ -54,14 +54,14 @@
     while (true) {
         int r = transport->Read(status, 64);
         if (r < 0) {
-            sprintf(ERROR, "status read failed (%s)", strerror(errno));
+            snprintf(ERROR, sizeof(ERROR), "status read failed (%s)", strerror(errno));
             transport->Close();
             return -1;
         }
         status[r] = 0;
 
         if (r < 4) {
-            sprintf(ERROR, "status malformed (%d bytes)", r);
+            snprintf(ERROR, sizeof(ERROR), "status malformed (%d bytes)", r);
             transport->Close();
             return -1;
         }
@@ -80,7 +80,7 @@
 
         if (!memcmp(status, "FAIL", 4)) {
             if (r > 4) {
-                sprintf(ERROR, "remote: %s", status + 4);
+                snprintf(ERROR, sizeof(ERROR), "remote: %s", status + 4);
             } else {
                 strcpy(ERROR, "remote failure");
             }
@@ -108,7 +108,7 @@
 static int _command_start(Transport* transport, const char* cmd, uint32_t size, char* response) {
     size_t cmdsize = strlen(cmd);
     if (cmdsize > 64) {
-        sprintf(ERROR, "command too large");
+        snprintf(ERROR, sizeof(ERROR), "command too large");
         return -1;
     }
 
@@ -117,7 +117,7 @@
     }
 
     if (transport->Write(cmd, cmdsize) != static_cast<int>(cmdsize)) {
-        sprintf(ERROR, "command write failed (%s)", strerror(errno));
+        snprintf(ERROR, sizeof(ERROR), "command write failed (%s)", strerror(errno));
         transport->Close();
         return -1;
     }
@@ -128,12 +128,12 @@
 static int _command_data(Transport* transport, const void* data, uint32_t size) {
     int r = transport->Write(data, size);
     if (r < 0) {
-        sprintf(ERROR, "data transfer failure (%s)", strerror(errno));
+        snprintf(ERROR, sizeof(ERROR), "data transfer failure (%s)", strerror(errno));
         transport->Close();
         return -1;
     }
     if (r != ((int) size)) {
-        sprintf(ERROR, "data transfer failure (short transfer)");
+        snprintf(ERROR, sizeof(ERROR), "data transfer failure (short transfer)");
         transport->Close();
         return -1;
     }
@@ -182,7 +182,7 @@
 
 int fb_download_data(Transport* transport, const void* data, uint32_t size) {
     char cmd[64];
-    sprintf(cmd, "download:%08x", size);
+    snprintf(cmd, sizeof(cmd), "download:%08x", size);
     return _command_send(transport, cmd, data, size, 0) < 0 ? -1 : 0;
 }
 
@@ -216,7 +216,7 @@
 
     if (len > TRANSPORT_BUF_SIZE) {
         if (transport_buf_len > 0) {
-            sprintf(ERROR, "internal error: transport_buf not empty\n");
+            snprintf(ERROR, sizeof(ERROR), "internal error: transport_buf not empty\n");
             return -1;
         }
         to_write = round_down(len, TRANSPORT_BUF_SIZE);
@@ -230,7 +230,7 @@
 
     if (len > 0) {
         if (len > TRANSPORT_BUF_SIZE) {
-            sprintf(ERROR, "internal error: too much left for transport_buf\n");
+            snprintf(ERROR, sizeof(ERROR), "internal error: too much left for transport_buf\n");
             return -1;
         }
         memcpy(transport_buf, ptr, len);
@@ -257,7 +257,7 @@
     }
 
     char cmd[64];
-    sprintf(cmd, "download:%08x", size);
+    snprintf(cmd, sizeof(cmd), "download:%08x", size);
     int r = _command_start(transport, cmd, size, 0);
     if (r < 0) {
         return -1;
diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp
index a718b02..f48e1d0 100644
--- a/libpixelflinger/scanline.cpp
+++ b/libpixelflinger/scanline.cpp
@@ -965,7 +965,7 @@
  * Use only for one-to-one texture mapping.
  */
 struct horz_iterator32 {
-    horz_iterator32(context_t* c) {
+    explicit horz_iterator32(context_t* c) {
         const int x = c->iterators.xl;
         const int y = c->iterators.y;
         texture_t& tx = c->state.texture[0];
@@ -982,7 +982,7 @@
 
 /* A variant for 16-bit source textures. */
 struct horz_iterator16 {
-    horz_iterator16(context_t* c) {
+    explicit horz_iterator16(context_t* c) {
         const int x = c->iterators.xl;
         const int y = c->iterators.y;
         texture_t& tx = c->state.texture[0];
@@ -1002,7 +1002,7 @@
  * texture pixel value.
  */
 struct clamp_iterator {
-    clamp_iterator(context_t* c) {
+    explicit clamp_iterator(context_t* c) {
         const int xs = c->iterators.xl;
         texture_t& tx = c->state.texture[0];
         texture_iterators_t& ti = tx.iterators;
@@ -1112,13 +1112,13 @@
 }
 
 struct horz_clamp_iterator16 : horz_clamp_iterator {
-    horz_clamp_iterator16(const context_t* c) {
+    explicit horz_clamp_iterator16(const context_t* c) {
         init(c,1);
     };
 };
 
 struct horz_clamp_iterator32 : horz_clamp_iterator {
-    horz_clamp_iterator32(context_t* c) {
+    explicit horz_clamp_iterator32(context_t* c) {
         init(c,2);
     };
 };
@@ -1126,7 +1126,7 @@
 /* This is used to perform dithering operations.
  */
 struct ditherer {
-    ditherer(const context_t* c) {
+    explicit ditherer(const context_t* c) {
         const int x = c->iterators.xl;
         const int y = c->iterators.y;
         m_line = &c->ditherMatrix[ ((y & GGL_DITHER_MASK)<<GGL_DITHER_ORDER_SHIFT) ];
@@ -1172,7 +1172,7 @@
  *   blender.blend(<32-bit-src-pixel-value>,<ptr-to-16-bit-dest-pixel>)
  */
 struct blender_32to16 {
-    blender_32to16(context_t* /*c*/) { }
+    explicit blender_32to16(context_t* /*c*/) { }
     void write(uint32_t s, uint16_t* dst) {
         if (s == 0)
             return;
@@ -1229,7 +1229,7 @@
  * where dstFactor=srcA*(1-srcA) srcFactor=srcA
  */
 struct blender_32to16_srcA {
-    blender_32to16_srcA(const context_t* /*c*/) { }
+    explicit blender_32to16_srcA(const context_t* /*c*/) { }
     void write(uint32_t s, uint16_t* dst) {
         if (!s) {
             return;
@@ -1271,7 +1271,7 @@
 /* This blender does a normal blend after modulation.
  */
 struct blender_32to16_modulate : blender_modulate {
-    blender_32to16_modulate(const context_t* c) {
+    explicit blender_32to16_modulate(const context_t* c) {
         init(c);
     }
     void write(uint32_t s, uint16_t* dst) {
@@ -1343,7 +1343,7 @@
 
 /* same as 32to16_modulate, except that the input is xRGB, instead of ARGB */
 struct blender_x32to16_modulate : blender_modulate {
-    blender_x32to16_modulate(const context_t* c) {
+    explicit blender_x32to16_modulate(const context_t* c) {
         init(c);
     }
     void write(uint32_t s, uint16_t* dst) {
@@ -1398,7 +1398,7 @@
 
 /* Same as above, but source is 16bit rgb565 */
 struct blender_16to16_modulate : blender_modulate {
-    blender_16to16_modulate(const context_t* c) {
+    explicit blender_16to16_modulate(const context_t* c) {
         init(c);
     }
     void write(uint16_t s16, uint16_t* dst) {
@@ -1434,7 +1434,7 @@
  *   }
  */
 struct dst_iterator16 {
-    dst_iterator16(const context_t* c) {
+    explicit dst_iterator16(const context_t* c) {
         const int x = c->iterators.xl;
         const int width = c->iterators.xr - x;
         const int32_t y = c->iterators.y;
diff --git a/libziparchive/zip_archive_stream_entry.cc b/libziparchive/zip_archive_stream_entry.cc
index f618835..4b205a7 100644
--- a/libziparchive/zip_archive_stream_entry.cc
+++ b/libziparchive/zip_archive_stream_entry.cc
@@ -48,7 +48,8 @@
 
 class ZipArchiveStreamEntryUncompressed : public ZipArchiveStreamEntry {
  public:
-  ZipArchiveStreamEntryUncompressed(ZipArchiveHandle handle) : ZipArchiveStreamEntry(handle) {}
+  explicit ZipArchiveStreamEntryUncompressed(ZipArchiveHandle handle)
+      : ZipArchiveStreamEntry(handle) {}
   virtual ~ZipArchiveStreamEntryUncompressed() {}
 
   const std::vector<uint8_t>* Read() override;
@@ -110,7 +111,8 @@
 
 class ZipArchiveStreamEntryCompressed : public ZipArchiveStreamEntry {
  public:
-  ZipArchiveStreamEntryCompressed(ZipArchiveHandle handle) : ZipArchiveStreamEntry(handle) {}
+  explicit ZipArchiveStreamEntryCompressed(ZipArchiveHandle handle)
+      : ZipArchiveStreamEntry(handle) {}
   virtual ~ZipArchiveStreamEntryCompressed();
 
   const std::vector<uint8_t>* Read() override;
@@ -249,7 +251,7 @@
 
 class ZipArchiveStreamEntryRawCompressed : public ZipArchiveStreamEntryUncompressed {
  public:
-  ZipArchiveStreamEntryRawCompressed(ZipArchiveHandle handle)
+  explicit ZipArchiveStreamEntryRawCompressed(ZipArchiveHandle handle)
       : ZipArchiveStreamEntryUncompressed(handle) {}
   virtual ~ZipArchiveStreamEntryRawCompressed() {}
 
diff --git a/logcat/tests/logcat_benchmark.cpp b/logcat/tests/logcat_benchmark.cpp
index be815be..dd85164 100644
--- a/logcat/tests/logcat_benchmark.cpp
+++ b/logcat/tests/logcat_benchmark.cpp
@@ -49,7 +49,7 @@
             }
         }
 
-        timestamp(const char *buffer)
+        explicit timestamp(const char *buffer)
         {
             init(buffer);
         }
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 8c30f79..db65978 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -380,7 +380,7 @@
             tid(tid),
             padding(0) {
     }
-    LogBufferElementKey(uint64_t key):value(key) { }
+    explicit LogBufferElementKey(uint64_t key):value(key) { }
 
     uint64_t getKey() { return value; }
 };
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index f862561..f08c9d8 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -822,7 +822,8 @@
             hdr->nodeid, node ? node->name : "?");
     if (node) {
         __u64 n = req->nlookup;
-        while (n--) {
+        while (n) {
+            n--;
             release_node_locked(node);
         }
     }
diff --git a/toolbox/ps.c b/toolbox/ps.c
index d366f3e..3b3c8a1 100644
--- a/toolbox/ps.c
+++ b/toolbox/ps.c
@@ -60,7 +60,7 @@
     snprintf(statline, sizeof(statline), "/proc/%d", tid ? tid : pid);
     stat(statline, &stats);
 
-    if(tid) {
+    if (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);
@@ -69,21 +69,21 @@
         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) {
+        if (fd == 0) {
             r = 0;
         } else {
             r = read(fd, cmdline, 1023);
             close(fd);
-            if(r < 0) r = 0;
+            if (r < 0) r = 0;
         }
         cmdline[r] = 0;
     }
 
     int fd = open(statline, O_RDONLY);
-    if(fd == 0) return -1;
+    if (fd == 0) return -1;
     r = read(fd, statline, 1023);
     close(fd);
-    if(r < 0) return -1;
+    if (r < 0) return -1;
     statline[r] = 0;
 
     ptr = statline;
@@ -142,19 +142,19 @@
 
     nexttok(&ptr); // tty
 
-    if(tid != 0) {
+    if (tid != 0) {
         ppid = pid;
         pid = tid;
     }
 
     pw = getpwuid(stats.st_uid);
-    if(pw == 0 || (display_flags & SHOW_NUMERIC_UID)) {
-        snprintf(user,sizeof(user),"%d",(int)stats.st_uid);
+    if (pw == 0 || (display_flags & SHOW_NUMERIC_UID)) {
+        snprintf(user, sizeof(user), "%d", (int)stats.st_uid);
     } else {
-        strcpy(user,pw->pw_name);
+        strcpy(user, pw->pw_name);
     }
 
-    if(ppid_filter != 0 && ppid != ppid_filter) {
+    if (ppid_filter != 0 && ppid != ppid_filter) {
         return 0;
     }
 
@@ -196,7 +196,7 @@
         print_exe_abi(pid);
     }
     printf("%s", cmdline[0] ? cmdline : name);
-    if(display_flags&SHOW_TIME)
+    if (display_flags & SHOW_TIME)
         printf(" (u:%d, s:%d)", utime, stime);
 
     printf("\n");
@@ -210,13 +210,13 @@
 
     snprintf(exeline, sizeof(exeline), "/proc/%d/exe", pid);
     fd = open(exeline, O_RDONLY);
-    if(fd == 0) {
+    if (fd == 0) {
         printf("    ");
         return;
     }
     r = read(fd, exeline, 5 /* 4 byte ELFMAG + 1 byte EI_CLASS */);
     close(fd);
-    if(r < 0) {
+    if (r < 0) {
         printf("    ");
         return;
     }
@@ -245,12 +245,12 @@
 
     snprintf(tmp,sizeof(tmp),"/proc/%d/task",pid);
     d = opendir(tmp);
-    if(d == 0) return;
+    if (d == 0) return;
 
-    while((de = readdir(d)) != 0){
-        if(isdigit(de->d_name[0])){
+    while ((de = readdir(d)) != 0) {
+        if (isdigit(de->d_name[0])) {
             int tid = atoi(de->d_name);
-            if(tid == pid) continue;
+            if (tid == pid) continue;
             ps_line(pid, tid);
         }
     }
@@ -264,24 +264,31 @@
     int pidfilter = 0;
     int threads = 0;
 
-    while(argc > 1){
-        if(!strcmp(argv[1],"-t")) {
+    while (argc > 1) {
+        if (!strcmp(argv[1], "-t")) {
             threads = 1;
-        } else if(!strcmp(argv[1],"-n")) {
+        } else if (!strcmp(argv[1], "-n")) {
             display_flags |= SHOW_NUMERIC_UID;
-        } else if(!strcmp(argv[1],"-x")) {
+        } else if (!strcmp(argv[1], "-x")) {
             display_flags |= SHOW_TIME;
-        } else if(!strcmp(argv[1], "-Z")) {
+        } else if (!strcmp(argv[1], "-Z")) {
             display_flags |= SHOW_MACLABEL;
-        } else if(!strcmp(argv[1],"-P")) {
+        } else if (!strcmp(argv[1], "-P")) {
             display_flags |= SHOW_POLICY;
-        } else if(!strcmp(argv[1],"-p")) {
+        } else if (!strcmp(argv[1], "-p")) {
             display_flags |= SHOW_PRIO;
-        } else if(!strcmp(argv[1],"-c")) {
+        } else if (!strcmp(argv[1], "-c")) {
             display_flags |= SHOW_CPU;
-        } else if(!strcmp(argv[1],"--abi")) {
+        } else if (!strcmp(argv[1], "--abi")) {
             display_flags |= SHOW_ABI;
-        } else if(!strcmp(argv[1],"--ppid")) {
+        } else if (!strcmp(argv[1], "--ppid")) {
+            if (argc < 3) {
+                /* Bug 26554285: Use printf because some apps require at least
+                 * one line of output to stdout even for errors.
+                 */
+                printf("no ppid\n");
+                return 1;
+            }
             ppid_filter = atoi(argv[2]);
             if (ppid_filter == 0) {
                 /* Bug 26554285: Use printf because some apps require at least
@@ -317,18 +324,17 @@
            (display_flags&SHOW_ABI)?"ABI " : "");
 
     d = opendir("/proc");
-    if(d == 0) return -1;
+    if (d == 0) return -1;
 
-    while((de = readdir(d)) != 0){
-        if(isdigit(de->d_name[0])){
+    while ((de = readdir(d)) != 0) {
+        if (isdigit(de->d_name[0])) {
             int pid = atoi(de->d_name);
-            if(!pidfilter || (pidfilter == pid)) {
+            if (!pidfilter || (pidfilter == pid)) {
                 ps_line(pid, 0);
-                if(threads) ps_threads(pid);
+                if (threads) ps_threads(pid);
             }
         }
     }
     closedir(d);
     return 0;
 }
-