Merge \"Fix clang-tidy performance warnings in syste/core.\"
am: 4efbce14b5

Change-Id: I84f6b0134fae6e9f40710f243f4825e3f31fa15f
diff --git a/commandline.cpp b/commandline.cpp
index 193b929..8aab389 100644
--- a/commandline.cpp
+++ b/commandline.cpp
@@ -66,6 +66,9 @@
 static auto& gProductOutPath = *new std::string();
 extern int gListenAll;
 
+static constexpr char BUGZ_OK_PREFIX[] = "OK:";
+static constexpr char BUGZ_FAIL_PREFIX[] = "FAIL:";
+
 static std::string product_file(const char *extra) {
     if (gProductOutPath.empty()) {
         fprintf(stderr, "adb: Product directory not specified; "
@@ -158,7 +161,7 @@
         "                                 (-r: replace existing application)\n"
         "                                 (-t: allow test packages)\n"
         "                                 (-s: install application on sdcard)\n"
-        "                                 (-d: allow version code downgrade)\n"
+        "                                 (-d: allow version code downgrade (debuggable packages only))\n"
         "                                 (-g: grant all runtime permissions)\n"
         "  adb install-multiple [-lrtsdpg] <file...>\n"
         "                               - push this package file to the device and install it\n"
@@ -166,12 +169,12 @@
         "                                 (-r: replace existing application)\n"
         "                                 (-t: allow test packages)\n"
         "                                 (-s: install application on sdcard)\n"
-        "                                 (-d: allow version code downgrade)\n"
+        "                                 (-d: allow version code downgrade (debuggable packages only))\n"
         "                                 (-p: partial application install)\n"
         "                                 (-g: grant all runtime permissions)\n"
         "  adb uninstall [-k] <package> - remove this app package from the device\n"
         "                                 ('-k' means keep the data and cache directories)\n"
-        "  adb bugreport                - return all information from the device\n"
+        "  adb bugreport [<zip_file>]   - return all information from the device\n"
         "                                 that should be included in a bug report.\n"
         "\n"
         "  adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
@@ -289,11 +292,17 @@
 // this expects that incoming data will use the shell protocol, in which case
 // stdout/stderr are routed independently and the remote exit code will be
 // returned.
-static int read_and_dump(int fd, bool use_shell_protocol=false) {
+// if |output| is non-null, stdout will be appended to it instead.
+// if |err| is non-null, stderr will be appended to it instead.
+static int read_and_dump(int fd, bool use_shell_protocol=false, std::string* output=nullptr,
+                         std::string* err=nullptr) {
     int exit_code = 0;
+    if (fd < 0) return exit_code;
+
     std::unique_ptr<ShellProtocol> protocol;
     int length = 0;
     FILE* outfile = stdout;
+    std::string* outstring = output;
 
     char raw_buffer[BUFSIZ];
     char* buffer_ptr = raw_buffer;
@@ -306,7 +315,7 @@
         buffer_ptr = protocol->data();
     }
 
-    while (fd >= 0) {
+    while (true) {
         if (use_shell_protocol) {
             if (!protocol->Read()) {
                 break;
@@ -314,9 +323,11 @@
             switch (protocol->id()) {
                 case ShellProtocol::kIdStdout:
                     outfile = stdout;
+                    outstring = output;
                     break;
                 case ShellProtocol::kIdStderr:
                     outfile = stderr;
+                    outstring = err;
                     break;
                 case ShellProtocol::kIdExit:
                     exit_code = protocol->data()[0];
@@ -334,8 +345,12 @@
             }
         }
 
-        fwrite(buffer_ptr, 1, length, outfile);
-        fflush(outfile);
+        if (outstring == nullptr) {
+            fwrite(buffer_ptr, 1, length, outfile);
+            fflush(outfile);
+        } else {
+            outstring->append(buffer_ptr, length);
+        }
     }
 
     return exit_code;
@@ -1102,7 +1117,9 @@
 // resulting output.
 static int send_shell_command(TransportType transport_type, const char* serial,
                               const std::string& command,
-                              bool disable_shell_protocol) {
+                              bool disable_shell_protocol,
+                              std::string* output=nullptr,
+                              std::string* err=nullptr) {
     int fd;
     bool use_shell_protocol = false;
 
@@ -1137,7 +1154,7 @@
         }
     }
 
-    int exit_code = read_and_dump(fd, use_shell_protocol);
+    int exit_code = read_and_dump(fd, use_shell_protocol, output, err);
 
     if (adb_close(fd) < 0) {
         PLOG(ERROR) << "failure closing FD " << fd;
@@ -1146,6 +1163,45 @@
     return exit_code;
 }
 
+static int bugreport(TransportType transport_type, const char* serial, int argc,
+                     const char** argv) {
+    if (argc == 1) return send_shell_command(transport_type, serial, "bugreport", false);
+    if (argc != 2) return usage();
+
+    // Zipped bugreport option - will call 'bugreportz', which prints the location of the generated
+    // file, then pull it to the destination file provided by the user.
+    std::string dest_file = argv[1];
+    if (!android::base::EndsWith(argv[1], ".zip")) {
+        // TODO: use a case-insensitive comparison (like EndsWithIgnoreCase
+        dest_file += ".zip";
+    }
+    std::string output;
+
+    fprintf(stderr, "Bugreport is in progress and it could take minutes to complete.\n"
+            "Please be patient and do not cancel or disconnect your device until it completes.\n");
+    int status = send_shell_command(transport_type, serial, "bugreportz", false, &output, nullptr);
+    if (status != 0 || output.empty()) return status;
+    output = android::base::Trim(output);
+
+    if (android::base::StartsWith(output, BUGZ_OK_PREFIX)) {
+        const char* zip_file = &output[strlen(BUGZ_OK_PREFIX)];
+        std::vector<const char*> srcs{zip_file};
+        status = do_sync_pull(srcs, dest_file.c_str(), true, dest_file.c_str()) ? 0 : 1;
+        if (status != 0) {
+            fprintf(stderr, "Could not copy file '%s' to '%s'\n", zip_file, dest_file.c_str());
+        }
+        return status;
+    }
+    if (android::base::StartsWith(output, BUGZ_FAIL_PREFIX)) {
+        const char* error_message = &output[strlen(BUGZ_FAIL_PREFIX)];
+        fprintf(stderr, "Device failed to take a zipped bugreport: %s\n", error_message);
+        return -1;
+    }
+    fprintf(stderr, "Unexpected string (%s) returned by bugreportz, "
+            "device probably does not support -z option\n", output.c_str());
+    return -1;
+}
+
 static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
     char* log_tags = getenv("ANDROID_LOG_TAGS");
     std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
@@ -1681,12 +1737,8 @@
     } else if (!strcmp(argv[0], "root") || !strcmp(argv[0], "unroot")) {
         return adb_root(argv[0]) ? 0 : 1;
     } else if (!strcmp(argv[0], "bugreport")) {
-        if (argc != 1) return usage();
-        // No need for shell protocol with bugreport, always disable for
-        // simplicity.
-        return send_shell_command(transport_type, serial, "bugreport", true);
-    }
-    else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
+        return bugreport(transport_type, serial, argc, argv);
+    } else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
         bool reverse = !strcmp(argv[0], "reverse");
         ++argv;
         --argc;
diff --git a/file_sync_client.cpp b/file_sync_client.cpp
index fbca770..6302eb7 100644
--- a/file_sync_client.cpp
+++ b/file_sync_client.cpp
@@ -518,7 +518,8 @@
     return sc.CopyDone(lpath, rpath);
 }
 
-static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath) {
+static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath,
+                      const char* name=nullptr) {
     unsigned size = 0;
     if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false;
 
@@ -574,7 +575,7 @@
 
         bytes_copied += msg.data.size;
 
-        sc.ReportProgress(rpath, bytes_copied, size);
+        sc.ReportProgress(name != nullptr ? name : rpath, bytes_copied, size);
     }
 
     adb_close(lfd);
@@ -927,7 +928,7 @@
 }
 
 bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
-                  bool copy_attrs) {
+                  bool copy_attrs, const char* name) {
     SyncConnection sc;
     if (!sc.IsValid()) return false;
 
@@ -1022,7 +1023,7 @@
         }
 
         sc.SetExpectedTotalBytes(src_size);
-        if (!sync_recv(sc, src_path, dst_path)) {
+        if (!sync_recv(sc, src_path, dst_path, name)) {
             success = false;
             continue;
         }
diff --git a/file_sync_service.h b/file_sync_service.h
index 460e9dc..0e25974 100644
--- a/file_sync_service.h
+++ b/file_sync_service.h
@@ -67,7 +67,7 @@
 bool do_sync_ls(const char* path);
 bool do_sync_push(const std::vector<const char*>& srcs, const char* dst);
 bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
-                  bool copy_attrs);
+                  bool copy_attrs, const char* name=nullptr);
 
 bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only);
 
diff --git a/transport.cpp b/transport.cpp
index 65b05b8..ad63a6a 100644
--- a/transport.cpp
+++ b/transport.cpp
@@ -784,9 +784,7 @@
     // Local static allocation to avoid global non-POD variables.
     static const FeatureSet* features = new FeatureSet{
         kFeatureShell2,
-        // Internal master has 'cmd'. AOSP master doesn't.
-        // kFeatureCmd
-
+        kFeatureCmd
         // Increment ADB_SERVER_VERSION whenever the feature list changes to
         // make sure that the adb client and server features stay in sync
         // (http://b/24370690).
diff --git a/transport_local.cpp b/transport_local.cpp
index d918cc7..cc19785 100644
--- a/transport_local.cpp
+++ b/transport_local.cpp
@@ -41,14 +41,19 @@
 #include "adb_utils.h"
 
 #if ADB_HOST
+
+// Android Wear has been using port 5601 in all of its documentation/tooling,
+// but we search for emulators on ports [5554, 5555 + ADB_LOCAL_TRANSPORT_MAX].
+// Avoid stomping on their port by limiting the number of emulators that can be
+// connected.
+#define ADB_LOCAL_TRANSPORT_MAX 16
+
+ADB_MUTEX_DEFINE(local_transports_lock);
+
 /* we keep a list of opened transports. The atransport struct knows to which
  * local transport it is connected. The list is used to detect when we're
  * trying to connect twice to a given local transport.
  */
-#define  ADB_LOCAL_TRANSPORT_MAX  64
-
-ADB_MUTEX_DEFINE( local_transports_lock );
-
 static atransport*  local_transports[ ADB_LOCAL_TRANSPORT_MAX ];
 #endif /* ADB_HOST */
 
diff --git a/usb_linux_client.cpp b/usb_linux_client.cpp
index c10b48c..0ba6b4b 100644
--- a/usb_linux_client.cpp
+++ b/usb_linux_client.cpp
@@ -400,33 +400,35 @@
     v2_descriptor.os_header = os_desc_header;
     v2_descriptor.os_desc = os_desc_compat;
 
-    D("OPENING %s", USB_FFS_ADB_EP0);
-    h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR);
-    if (h->control < 0) {
-        D("[ %s: cannot open control endpoint: errno=%d]", USB_FFS_ADB_EP0, errno);
-        goto err;
-    }
-
-    ret = adb_write(h->control, &v2_descriptor, sizeof(v2_descriptor));
-    if (ret < 0) {
-        v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
-        v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
-        v1_descriptor.header.fs_count = 3;
-        v1_descriptor.header.hs_count = 3;
-        v1_descriptor.fs_descs = fs_descriptors;
-        v1_descriptor.hs_descs = hs_descriptors;
-        D("[ %s: Switching to V1_descriptor format errno=%d ]", USB_FFS_ADB_EP0, errno);
-        ret = adb_write(h->control, &v1_descriptor, sizeof(v1_descriptor));
-        if (ret < 0) {
-            D("[ %s: write descriptors failed: errno=%d ]", USB_FFS_ADB_EP0, errno);
+    if (h->control < 0) { // might have already done this before
+        D("OPENING %s", USB_FFS_ADB_EP0);
+        h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR);
+        if (h->control < 0) {
+            D("[ %s: cannot open control endpoint: errno=%d]", USB_FFS_ADB_EP0, errno);
             goto err;
         }
-    }
 
-    ret = adb_write(h->control, &strings, sizeof(strings));
-    if (ret < 0) {
-        D("[ %s: writing strings failed: errno=%d]", USB_FFS_ADB_EP0, errno);
-        goto err;
+        ret = adb_write(h->control, &v2_descriptor, sizeof(v2_descriptor));
+        if (ret < 0) {
+            v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
+            v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
+            v1_descriptor.header.fs_count = 3;
+            v1_descriptor.header.hs_count = 3;
+            v1_descriptor.fs_descs = fs_descriptors;
+            v1_descriptor.hs_descs = hs_descriptors;
+            D("[ %s: Switching to V1_descriptor format errno=%d ]", USB_FFS_ADB_EP0, errno);
+            ret = adb_write(h->control, &v1_descriptor, sizeof(v1_descriptor));
+            if (ret < 0) {
+                D("[ %s: write descriptors failed: errno=%d ]", USB_FFS_ADB_EP0, errno);
+                goto err;
+            }
+        }
+
+        ret = adb_write(h->control, &strings, sizeof(strings));
+        if (ret < 0) {
+            D("[ %s: writing strings failed: errno=%d]", USB_FFS_ADB_EP0, errno);
+            goto err;
+        }
     }
 
     h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR);
@@ -554,7 +556,6 @@
     h->kicked = false;
     adb_close(h->bulk_out);
     adb_close(h->bulk_in);
-    adb_close(h->control);
     // Notify usb_adb_open_thread to open a new connection.
     adb_mutex_lock(&h->lock);
     h->open_new_connection = true;