Merge "adb: bump the server version to 36."
diff --git a/adb/adb.cpp b/adb/adb.cpp
index efa18c2..49d2936 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -1135,6 +1135,13 @@
         /* we don't even need to send a reply */
         return 0;
     }
+
+    if (!strcmp(service, "reconnect")) {
+        if (s->transport != nullptr) {
+            kick_transport(s->transport);
+        }
+        return SendOkay(reply_fd, "done");
+    }
 #endif // ADB_HOST
 
     int ret = handle_forward_request(service, type, serial, reply_fd);
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index d29c08e..a27dd47 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -158,7 +158,8 @@
         }
     }
 
-    if (memcmp(&service[0],"host",4) != 0 && switch_socket_transport(fd, error)) {
+    if ((memcmp(&service[0],"host",4) != 0 || service == "host:reconnect") &&
+        switch_socket_transport(fd, error)) {
         return -1;
     }
 
@@ -168,9 +169,11 @@
         return -1;
     }
 
-    if (!adb_status(fd, error)) {
-        adb_close(fd);
-        return -1;
+    if (service != "reconnect") {
+        if (!adb_status(fd, error)) {
+            adb_close(fd);
+            return -1;
+        }
     }
 
     D("_adb_connect: return fd %d", fd);
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index f5d13c3..d8b1654 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -239,6 +239,9 @@
         "  - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
         "    is updated.\n"
         "\n"
+        "internal debugging:\n"
+        "  adb reconnect                  Kick current connection from host side and make it reconnect.\n"
+        "  adb reconnect device           Kick current connection from device side and make it reconnect.\n"
         "environment variables:\n"
         "  ADB_TRACE                    - Print debug information. A comma separated list of the following values\n"
         "                                 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
@@ -1895,6 +1898,14 @@
             }
         }
         return 0;
+    } else if (!strcmp(argv[0], "reconnect")) {
+        if (argc == 1) {
+            return adb_query_command("host:reconnect");
+        } else if (argc == 2 && !strcmp(argv[1], "device")) {
+            std::string err;
+            adb_connect("reconnect", &err);
+            return 0;
+        }
     }
 
     usage();
diff --git a/adb/services.cpp b/adb/services.cpp
index 67e8e41..3b212e9 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -184,6 +184,13 @@
     adb_close(fd);
 }
 
+static void reconnect_service(int fd, void* arg) {
+    WriteFdExactly(fd, "done");
+    adb_close(fd);
+    atransport* t = static_cast<atransport*>(arg);
+    kick_transport(t);
+}
+
 int reverse_service(const char* command) {
     int s[2];
     if (adb_socketpair(s)) {
@@ -345,6 +352,8 @@
         ret = create_service_thread(set_verity_enabled_state_service, (void*)0);
     } else if(!strncmp(name, "enable-verity:", 15)) {
         ret = create_service_thread(set_verity_enabled_state_service, (void*)1);
+    } else if (!strcmp(name, "reconnect")) {
+        ret = create_service_thread(reconnect_service, const_cast<atransport*>(transport));
 #endif
     }
     if (ret >= 0) {
diff --git a/adb/transport.cpp b/adb/transport.cpp
index e3340af..aaab21d 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -305,7 +305,11 @@
 
 void kick_transport(atransport* t) {
     adb_mutex_lock(&transport_lock);
-    kick_transport_locked(t);
+    // As kick_transport() can be called from threads without guarantee that t is valid,
+    // check if the transport is in transport_list first.
+    if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
+        kick_transport_locked(t);
+    }
     adb_mutex_unlock(&transport_lock);
 }
 
diff --git a/healthd/Android.mk b/healthd/Android.mk
index d866887..127f39e 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -9,6 +9,7 @@
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 LOCAL_STATIC_LIBRARIES := libbinder
+LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libbinder
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
diff --git a/libcrypto_utils/android_pubkey.c b/libcrypto_utils/android_pubkey.c
index 9cd9aab..3052e52 100644
--- a/libcrypto_utils/android_pubkey.c
+++ b/libcrypto_utils/android_pubkey.c
@@ -20,6 +20,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <openssl/bn.h>
+
 // Better safe than sorry.
 #if (ANDROID_PUBKEY_MODULUS_SIZE % 4) != 0
 #error RSA modulus size must be multiple of the word size!
diff --git a/logcat/logcatd.rc b/logcat/logcatd.rc
index cf0e0d2..70d1dd4 100644
--- a/logcat/logcatd.rc
+++ b/logcat/logcatd.rc
@@ -2,10 +2,10 @@
     # all exec/services are called with umask(077), so no gain beyond 0700
     mkdir /data/misc/logd 0700 logd log
     # logd for write to /data/misc/logd, log group for read from pstore (-L)
-    exec - logd log -- /system/bin/logcat -L -b all -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n 256
+    exec - logd log -- /system/bin/logcat -L -b ${persist.logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${persist.logd.logpersistd.size:-256}
     start logcatd
 
-service logcatd /system/bin/logcat -b all -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n 256
+service logcatd /system/bin/logcat -b ${persist.logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${persist.logd.logpersistd.size:-256}
     class late_start
     disabled
     # logd for write to /data/misc/logd, log group for read from log daemon
diff --git a/logcat/logpersist b/logcat/logpersist
index 8762ff1..e448456 100755
--- a/logcat/logpersist
+++ b/logcat/logpersist
@@ -1,5 +1,5 @@
 #! /system/bin/sh
-# logpersist cat start and stop handlers
+# logpersist cat, start and stop handlers
 progname="${0##*/}"
 case `getprop ro.debuggable` in
 1) ;;
@@ -7,36 +7,134 @@
    exit 1
    ;;
 esac
+
 data=/data/misc/logd
 property=persist.logd.logpersistd
 service=logcatd
-if [ X"${1}" = X"-h" -o X"${1}" = X"--help" ]; then
-  echo "${progname%.*}.cat            - dump current ${service%d} logs"
-  echo "${progname%.*}.start          - start ${service} service"
-  echo "${progname%.*}.stop [--clear] - stop ${service} service"
-  exit 0
+size_default=256
+buffer_default=all
+args="${@}"
+
+size=${size_default}
+buffer=${buffer_default}
+clear=false
+while [ ${#} -gt 0 ]; do
+  case ${1} in
+    -c|--clear) clear=true ;;
+    --size=*) size="${1#--size=}" ;;
+    --rotate-count=*) size="${1#--rotate-count=}" ;;
+    -n|--size|--rotate-count) size="${2}" ; shift ;;
+    --buffer=*) buffer="${1#--buffer=}" ;;
+    -b|--buffer) buffer="${2}" ; shift ;;
+    -h|--help|*)
+      LEAD_SPACE_="`echo ${progname%.*} | tr '[ -~]' ' '`"
+      echo "${progname%.*}.cat             - dump current ${service%d} logs"
+      echo "${progname%.*}.start [--size=<size_in_kb>] [--buffer=<buffers>] [--clear]"
+      echo "${LEAD_SPACE_}                 - start ${service} service"
+      echo "${progname%.*}.stop [--clear]  - stop ${service} service"
+      case ${1} in
+        -h|--help) exit 0 ;;
+        *) echo ERROR: bad argument ${@} >&2 ; exit 1 ;;
+      esac
+      ;;
+  esac
+  shift
+done
+
+if [ -z "${size}" -o "${size_default}" = "${size}" ]; then
+  unset size
 fi
+if [ -n "${size}" ] &&
+  ! ( [ 0 -lt "${size}" ] && [ 2048 -ge "${size}" ] ) >/dev/null 2>&1; then
+  echo ERROR: Invalid --size ${size} >&2
+  exit 1
+fi
+if [ -z "${buffer}" -o "${buffer_default}" = "${buffer}" ]; then
+  unset buffer
+fi
+if [ -n "${buffer}" ] && ! logcat -b ${buffer} -g >/dev/null 2>&1; then
+  echo ERROR: Invalid --buffer ${buffer} >&2
+  exit 1
+fi
+
 case ${progname} in
 *.cat)
-  su 1036 ls "${data}" |
+  if [ -n "${size}${buffer}" -o "true" = "${clear}" ]; then
+    echo WARNING: Can not use --clear, --size or --buffer with ${progname%.*}.cat >&2
+  fi
+  su logd ls "${data}" |
   tr -d '\r' |
   sort -ru |
   sed "s#^#${data}/#" |
-  su 1036 xargs cat
+  su logd xargs cat
   ;;
 *.start)
-  su 0 setprop ${property} ${service}
+  current_buffer="`getprop ${property}.buffer`"
+  current_size="`getprop ${property}.size`"
+  if [ "${service}" = "`getprop ${property}`" ]; then
+    if [ "true" = "${clear}" ]; then
+      su root stop ${service}
+      su root setprop ${property} ""
+      # 20ms done, guarantees content stop before rm
+      sleep 1
+    elif [ "${buffer}|${size}" != "${current_buffer}|${current_size}" ]; then
+      echo   "ERROR: Changing existing collection parameters from" >&2
+      if [ "${buffer}" != "${current_buffer}" ]; then
+        a=${current_buffer}
+        b=${buffer}
+        if [ -z "${a}" ]; then a="${default_buffer}"; fi
+        if [ -z "${b}" ]; then b="${default_buffer}"; fi
+        echo "           --buffer ${a} to ${b}" >&2
+      fi
+      if [ "${size}" != "${current_size}" ]; then
+        a=${current_size}
+        b=${size}
+        if [ -z "${a}" ]; then a="${default_size}"; fi
+        if [ -z "${b}" ]; then b="${default_size}"; fi
+        echo "           --size ${a} to ${b}" >&2
+      fi
+      echo   "       Are you sure you want to do this?" >&2
+      echo   "       Suggest add --clear to erase data and restart with new settings." >&2
+      echo   "       To blindly override and retain data, ${progname%.*}.stop first." >&2
+      exit 1
+    fi
+  fi
+  if [ "true" = "${clear}" ]; then
+    su logd,misc rm -rf "${data}"
+  fi
+  if [ -n "${buffer}${current_buffer}" ]; then
+    su root setprop ${property}.buffer "${buffer}"
+  fi
+  if [ -n "${size}${current_size}" ]; then
+    su root setprop ${property}.size "${size}"
+  fi
+  # ${service}.rc does the heavy lifting with the following trigger
+  su root setprop ${property} ${service}
   getprop ${property}
+  # 20ms done, to permit process feedback check
   sleep 1
+  # also generate an error return code if not found running, bonus
   ps -t | grep "${data##*/}.*${service%d}"
   ;;
 *.stop)
-  su 0 stop ${service}
-  su 0 setprop ${property} ""
-  [ X"${1}" != X"-c" -a X"${1}" != X"--clear" ] ||
-  ( sleep 1 ; su 1036,9998 rm -rf "${data}" )
+  if [ -n "${size}${buffer}" ]; then
+    echo "WARNING: Can not use --size or --buffer with ${progname%.*}.stop" >&2
+  fi
+  su root stop ${service}
+  su root setprop ${property} ""
+  if [ -n "`getprop ${property}.buffer`" ]; then
+    su root setprop ${property}.buffer ""
+  fi
+  if [ -n "`getprop ${property}.size`" ]; then
+    su root setprop ${property}.size ""
+  fi
+  if [ "true" = "${clear}" ]; then
+    # 20ms done, guarantees content stop before rm
+    sleep 1
+    su logd,misc rm -rf "${data}"
+  fi
   ;;
 *)
-  echo "Unexpected command ${0##*/} ${@}" >&2
+  echo "ERROR: Unexpected command ${0##*/} ${args}" >&2
   exit 1
 esac
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;
-}