Merge "Fix kick_transport test."
diff --git a/adb/adb.h b/adb/adb.h
index 59644d4..ea20800 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -50,7 +50,7 @@
 std::string adb_version();
 
 // Increment this when we want to force users to start a new adb server.
-#define ADB_SERVER_VERSION 35
+#define ADB_SERVER_VERSION 36
 
 class atransport;
 struct usb_handle;
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
index 21a82e8..611b239 100644
--- a/adb/adb_io_test.cpp
+++ b/adb/adb_io_test.cpp
@@ -37,7 +37,13 @@
 // fds far from the range that open() returns. But all of that might defeat the
 // purpose of the tests.
 
-TEST(io, ReadFdExactly_whole) {
+#if defined(_WIN32)
+#define POSIX_TEST(x,y) TEST(DISABLED_ ## x,y)
+#else
+#define POSIX_TEST TEST
+#endif
+
+POSIX_TEST(io, ReadFdExactly_whole) {
   const char expected[] = "Foobar";
   TemporaryFile tf;
   ASSERT_NE(-1, tf.fd);
@@ -51,7 +57,7 @@
   EXPECT_STREQ(expected, buf);
 }
 
-TEST(io, ReadFdExactly_eof) {
+POSIX_TEST(io, ReadFdExactly_eof) {
   const char expected[] = "Foobar";
   TemporaryFile tf;
   ASSERT_NE(-1, tf.fd);
@@ -65,7 +71,7 @@
   EXPECT_EQ(0, errno) << strerror(errno);
 }
 
-TEST(io, ReadFdExactly_partial) {
+POSIX_TEST(io, ReadFdExactly_partial) {
   const char input[] = "Foobar";
   TemporaryFile tf;
   ASSERT_NE(-1, tf.fd);
@@ -82,7 +88,7 @@
   EXPECT_STREQ(expected.c_str(), buf);
 }
 
-TEST(io, WriteFdExactly_whole) {
+POSIX_TEST(io, WriteFdExactly_whole) {
   const char expected[] = "Foobar";
   TemporaryFile tf;
   ASSERT_NE(-1, tf.fd);
@@ -97,7 +103,7 @@
   EXPECT_STREQ(expected, s.c_str());
 }
 
-TEST(io, WriteFdExactly_partial) {
+POSIX_TEST(io, WriteFdExactly_partial) {
   const char buf[] = "Foobar";
   TemporaryFile tf;
   ASSERT_NE(-1, tf.fd);
@@ -114,7 +120,7 @@
   EXPECT_EQ(expected, s);
 }
 
-TEST(io, WriteFdExactly_ENOSPC) {
+POSIX_TEST(io, WriteFdExactly_ENOSPC) {
     int fd = open("/dev/full", O_WRONLY);
     ASSERT_NE(-1, fd);
 
@@ -123,7 +129,7 @@
     ASSERT_EQ(ENOSPC, errno);
 }
 
-TEST(io, WriteFdExactly_string) {
+POSIX_TEST(io, WriteFdExactly_string) {
   const char str[] = "Foobar";
   TemporaryFile tf;
   ASSERT_NE(-1, tf.fd);
@@ -137,7 +143,7 @@
   EXPECT_STREQ(str, s.c_str());
 }
 
-TEST(io, WriteFdFmt) {
+POSIX_TEST(io, WriteFdFmt) {
     TemporaryFile tf;
     ASSERT_NE(-1, tf.fd);
 
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index 78efea8..f0c334e 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -215,3 +215,32 @@
     // Linux returns POLLIN | POLLHUP, Windows returns just POLLHUP.
     EXPECT_EQ(POLLHUP, pfd.revents & POLLHUP);
 }
+
+TEST_F(sysdeps_poll, fd_count) {
+    // https://code.google.com/p/android/issues/detail?id=12141
+    static constexpr int num_sockets = 512;
+    std::vector<int> sockets;
+    std::vector<adb_pollfd> pfds;
+    sockets.resize(num_sockets * 2);
+    for (int32_t i = 0; i < num_sockets; ++i) {
+        ASSERT_EQ(0, adb_socketpair(&sockets[i * 2])) << strerror(errno);
+        ASSERT_TRUE(WriteFdExactly(sockets[i * 2], &i, sizeof(i)));
+        adb_pollfd pfd;
+        pfd.events = POLLIN;
+        pfd.fd = sockets[i * 2 + 1];
+        pfds.push_back(pfd);
+    }
+
+    ASSERT_EQ(num_sockets, adb_poll(pfds.data(), pfds.size(), 0));
+    for (int i = 0; i < num_sockets; ++i) {
+        ASSERT_NE(0, pfds[i].revents & POLLIN);
+
+        int32_t buf[2] = { -1, -1 };
+        ASSERT_EQ(adb_read(pfds[i].fd, buf, sizeof(buf)), static_cast<ssize_t>(sizeof(int32_t)));
+        ASSERT_EQ(i, buf[0]);
+    }
+
+    for (int fd : sockets) {
+        adb_close(fd);
+    }
+}
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index a2f34fb..bc09fdc 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -191,7 +191,7 @@
 #define  fh_socket  u.socket
 
 #define  WIN32_FH_BASE    2048
-#define  WIN32_MAX_FHS    128
+#define  WIN32_MAX_FHS    2048
 
 static adb_mutex_t   _win32_lock;
 static  FHRec        _win32_fhs[ WIN32_MAX_FHS ];
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index 79a5670..bd8d5af 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -63,7 +63,6 @@
 
 static void refresh_cache(struct cache *cache, const char *key)
 {
-    uint32_t serial;
     char buf[PROP_VALUE_MAX];
 
     if (!cache->pinfo) {
@@ -71,13 +70,8 @@
         if (!cache->pinfo) {
             return;
         }
-        cache->serial = -1;
     }
-    serial = __system_property_serial(cache->pinfo);
-    if (serial == cache->serial) {
-        return;
-    }
-    cache->serial = serial;
+    cache->serial = __system_property_serial(cache->pinfo);
     __system_property_read(cache->pinfo, 0, buf);
     switch(buf[0]) {
     case 't': case 'T':
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 456f8b3..1a7d4aa 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -1338,7 +1338,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, levels[j].level));
                 }
@@ -1347,7 +1347,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, levels[j].level));
                 }
@@ -1379,7 +1379,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1388,7 +1388,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1408,7 +1408,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1417,7 +1417,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1439,7 +1439,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1448,7 +1448,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1468,7 +1468,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1477,7 +1477,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1513,7 +1513,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1522,7 +1522,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1542,7 +1542,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_FALSE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_FALSE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
@@ -1551,7 +1551,7 @@
                     fprintf(stderr, "\n");
                 }
                 EXPECT_TRUE(android_log_is_loggable);
-                for(size_t k = 1000; k; --k) {
+                for(size_t k = 10; k; --k) {
                     EXPECT_TRUE(__android_log_is_loggable(
                         levels[i].level, tag, ANDROID_LOG_DEBUG));
                 }
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 8b32418..85f9415 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -32,7 +32,6 @@
 
 OUR_TOOLS := \
     getevent \
-    iftop \
     ioctl \
     log \
     nandread \
diff --git a/toolbox/iftop.c b/toolbox/iftop.c
deleted file mode 100644
index 800c0f0..0000000
--- a/toolbox/iftop.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (c) 2008, The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the 
- *    distribution.
- *  * Neither the name of Google, Inc. nor the names of its contributors
- *    may be used to endorse or promote products derived from this
- *    software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <net/if.h>
-
-#define PROC_NET_DEV    "/proc/net/dev"
-
-#define MAX_IF           8   /* max interfaces we can handle */
-
-#ifndef PAGE_SIZE
-# define PAGE_SIZE 4096
-#endif
-
-#define _STR(s) #s
-#define STR(s) _STR(s)
-
-struct if_stats {
-    char name[IFNAMSIZ];
-
-    unsigned int mtu;
-
-    unsigned int rx_bytes;
-    unsigned int rx_packets;
-    unsigned int rx_errors;
-    unsigned int rx_dropped;
-
-    unsigned int tx_bytes;
-    unsigned int tx_packets;
-    unsigned int tx_errors;
-    unsigned int tx_dropped;
-};
-
-static int get_mtu(const char *if_name)
-{
-    struct ifreq ifr;
-    int s, ret;
-
-    s = socket(AF_INET, SOCK_DGRAM, 0);
-    if (s < 0) {
-        perror("socket");
-        exit(EXIT_FAILURE);
-    }
-
-    memset(&ifr, 0, sizeof(struct ifreq));
-    ifr.ifr_addr.sa_family = AF_INET;
-    strcpy(ifr.ifr_name, if_name);
-
-    ret = ioctl(s, SIOCGIFMTU, &ifr);
-    if (ret < 0) {
-        perror("ioctl");
-        exit(EXIT_FAILURE);
-    }
-
-    ret = close(s);
-    if (ret < 0) {
-        perror("close");
-        exit(EXIT_FAILURE);
-    }
-
-    return ifr.ifr_mtu;
-}
-
-static int get_interfaces(struct if_stats *ifs)
-{
-    char buf[PAGE_SIZE];
-    char *p;
-    int ret, nr, fd;
-
-    fd = open(PROC_NET_DEV, O_RDONLY);
-    if (fd < 0) {
-        perror("open");
-        exit(EXIT_FAILURE);
-    }
-
-    ret = read(fd, buf, sizeof(buf) - 1);
-    if (ret < 0) {
-        perror("read");
-        exit(EXIT_FAILURE);
-    } else if (!ret) {
-        fprintf(stderr, "reading " PROC_NET_DEV " returned premature EOF\n");
-        exit(EXIT_FAILURE);
-    }
-    buf[ret] = '\0';
-
-    /* skip down to the third line */
-    p = strchr(buf, '\n');
-    if (!p) {
-        fprintf(stderr, "parsing " PROC_NET_DEV " failed unexpectedly\n");
-        exit(EXIT_FAILURE);
-    }
-    p = strchr(p + 1, '\n');
-    if (!p) {
-        fprintf(stderr, "parsing " PROC_NET_DEV " failed unexpectedly\n");
-        exit(EXIT_FAILURE);
-    }
-    p += 1;
-
-    /*
-     * Key:
-     * if: (Rx) bytes packets errs drop fifo frame compressed multicast \
-     *     (Tx) bytes packets errs drop fifo colls carrier compressed
-     */
-    for (nr = 0; nr < MAX_IF; nr++) {
-        char *c;
-
-        ret = sscanf(p, "%" STR(IFNAMSIZ) "s", ifs->name);
-        if (ret != 1) {
-            fprintf(stderr, "parsing " PROC_NET_DEV " failed unexpectedly\n");
-            exit(EXIT_FAILURE);
-        }
-
-        /*
-         * This works around a bug in the proc file where large interface names
-         * or Rx byte counts eat the delimiter, breaking sscanf.
-         */
-        c = strchr(ifs->name, ':');
-        if (c)
-            *c = '\0';
-
-        p = strchr(p, ':') + 1;
-
-        ret = sscanf(p, "%u %u %u %u %*u %*u %*u %*u %u %u %u %u %*u %*u "
-                     "%*u %*u\n", &ifs->rx_bytes, &ifs->rx_packets,
-                     &ifs->rx_errors, &ifs->rx_dropped, &ifs->tx_bytes,
-                     &ifs->tx_packets, &ifs->tx_errors, &ifs->tx_dropped);
-        if (ret != 8) {
-            fprintf(stderr, "parsing " PROC_NET_DEV " failed unexpectedly\n");
-            exit(EXIT_FAILURE);
-        }
-
-        ifs->mtu = get_mtu(ifs->name);
-
-        p = strchr(p, '\n') + 1;
-        if (*p == '\0') {
-            nr++;
-            break;
-        }
-
-        ifs++;
-    }
-
-    ret = close(fd);
-    if (ret) {
-        perror("close");
-        exit(EXIT_FAILURE);
-    }
-
-    return nr;
-}
-
-static void print_header(void)
-{
-    printf("               Rx                              Tx\n");
-    printf("%-8s %-5s %-10s %-8s %-5s %-5s %-10s %-8s %-5s %-5s\n",
-           "name", "MTU", "bytes", "packets", "errs", "drpd", "bytes",
-           "packets", "errs", "drpd");
-}
-
-static int print_interfaces(struct if_stats *old, struct if_stats *new, int nr)
-{
-    int i = 0;
-
-    while (nr--) {
-        if (old->rx_packets || old->tx_packets) {
-            printf("%-8s %-5u %-10u %-8u %-5u %-5u %-10u %-8u %-5u %-5u\n",
-                   new->name, new->mtu,
-                   new->rx_bytes - old->rx_bytes,
-                   new->rx_packets - old->rx_packets,
-                   new->rx_errors - old->rx_errors,
-                   new->rx_dropped - old->rx_dropped,
-                   new->tx_bytes - old->tx_bytes,
-                   new->tx_packets - old->tx_packets,
-                   new->tx_errors - old->tx_errors,
-                   new->tx_dropped - old->tx_dropped);
-            i++;
-        }
-        old++;
-        new++;
-    }
-
-    return i;
-}
-
-static void usage(const char *cmd)
-{
-    fprintf(stderr, "usage: %s [ -r repeats] [ -d delay ]\n", cmd);
-}
-
-int iftop_main(int argc, char *argv[])
-{
-    struct if_stats ifs[2][MAX_IF];
-    int count = 0, header_interval = 22, delay = 1, i;
-    unsigned int toggle = 0;
-
-    for (i = 1; i < argc; i++) {
-        if (!strcmp(argv[i], "-d")) {
-            if (i >= argc - 1) {
-                fprintf(stderr, "Option -d requires an argument.\n");
-                exit(EXIT_FAILURE);
-            }
-            delay = atoi(argv[i++]);
-            if (!delay)
-                delay = 1;
-            continue;
-        }
-        if (!strcmp(argv[i], "-r")) {
-            if (i >= argc - 1) {
-                fprintf(stderr, "Option -r requires an argument.\n");
-                exit(EXIT_FAILURE);
-            }
-            header_interval = atoi(argv[i++]);
-            if (header_interval < MAX_IF)
-                header_interval = MAX_IF;
-            continue;
-        }
-        if (!strcmp(argv[i], "-h")) {
-            usage(argv[0]);
-            exit(EXIT_SUCCESS);
-        }
-        usage(argv[0]);
-        exit(EXIT_FAILURE);
-    }
-
-    get_interfaces(ifs[!toggle]);
-    if (header_interval)
-        print_header();
-    while (1) {
-        int nr;
-
-        sleep(delay);
-        nr = get_interfaces(ifs[toggle]);
-        if (header_interval && count + nr > header_interval) {
-            print_header();
-            count = 0;
-        }
-        count += print_interfaces(ifs[!toggle], ifs[toggle], nr);
-        toggle = !toggle;
-    }
-
-    return 0;
-}