adb: allow selection of a specific transport.

Extend device selection to allow selecting a specific transport via
monotonically increasing identifier (visible in devices -l).

This is useful when using multiple devices (like hikey960...) that
have identical bogus serial numbers like 0123456789ABCDEF.

Bug: http://b/37043226
Test: adb -t {1, 2, 9999999} {get-serialno, shell, features}
Change-Id: I55e5dc5a406a4eeee0012e39b52e8cd232e608a6
diff --git a/adb/adb.cpp b/adb/adb.cpp
index ff7b71f..8c24bbb 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -956,8 +956,8 @@
 // Try to handle a network forwarding request.
 // This returns 1 on success, 0 on failure, and -1 to indicate this is not
 // a forwarding-related request.
-int handle_forward_request(const char* service, TransportType type, const char* serial, int reply_fd)
-{
+int handle_forward_request(const char* service, TransportType type, const char* serial,
+                           TransportId transport_id, int reply_fd) {
     if (!strcmp(service, "list-forward")) {
         // Create the list of forward redirections.
         std::string listeners = format_listeners();
@@ -1010,7 +1010,8 @@
         }
 
         std::string error_msg;
-        atransport* transport = acquire_one_transport(type, serial, nullptr, &error_msg);
+        atransport* transport =
+            acquire_one_transport(type, serial, transport_id, nullptr, &error_msg);
         if (!transport) {
             SendFail(reply_fd, error_msg);
             return 1;
@@ -1068,8 +1069,8 @@
     return 0;
 }
 
-int handle_host_request(const char* service, TransportType type,
-                        const char* serial, int reply_fd, asocket* s) {
+int handle_host_request(const char* service, TransportType type, const char* serial,
+                        TransportId transport_id, int reply_fd, asocket* s) {
     if (strcmp(service, "kill") == 0) {
         fprintf(stderr, "adb server killed by remote request\n");
         fflush(stdout);
@@ -1089,7 +1090,14 @@
     if (!strncmp(service, "transport", strlen("transport"))) {
         TransportType type = kTransportAny;
 
-        if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
+        if (!strncmp(service, "transport-id:", strlen("transport-id:"))) {
+            service += strlen("transport-id:");
+            transport_id = strtoll(service, const_cast<char**>(&service), 10);
+            if (*service != '\0') {
+                SendFail(reply_fd, "invalid transport id");
+                return 1;
+            }
+        } else if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
             type = kTransportUsb;
         } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
             type = kTransportLocal;
@@ -1101,7 +1109,7 @@
         }
 
         std::string error;
-        atransport* t = acquire_one_transport(type, serial, nullptr, &error);
+        atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
         if (t != nullptr) {
             s->transport = t;
             SendOkay(reply_fd);
@@ -1144,7 +1152,7 @@
 
     if (!strcmp(service, "features")) {
         std::string error;
-        atransport* t = acquire_one_transport(type, serial, nullptr, &error);
+        atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
         if (t != nullptr) {
             SendOkay(reply_fd, FeatureSetToString(t->features()));
         } else {
@@ -1197,7 +1205,7 @@
     // These always report "unknown" rather than the actual error, for scripts.
     if (!strcmp(service, "get-serialno")) {
         std::string error;
-        atransport* t = acquire_one_transport(type, serial, nullptr, &error);
+        atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
         if (t) {
             return SendOkay(reply_fd, t->serial ? t->serial : "unknown");
         } else {
@@ -1206,7 +1214,7 @@
     }
     if (!strcmp(service, "get-devpath")) {
         std::string error;
-        atransport* t = acquire_one_transport(type, serial, nullptr, &error);
+        atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
         if (t) {
             return SendOkay(reply_fd, t->devpath ? t->devpath : "unknown");
         } else {
@@ -1215,7 +1223,7 @@
     }
     if (!strcmp(service, "get-state")) {
         std::string error;
-        atransport* t = acquire_one_transport(type, serial, nullptr, &error);
+        atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
         if (t) {
             return SendOkay(reply_fd, t->connection_state_name());
         } else {
@@ -1233,7 +1241,7 @@
 
     if (!strcmp(service, "reconnect")) {
         std::string response;
-        atransport* t = acquire_one_transport(type, serial, nullptr, &response, true);
+        atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &response, true);
         if (t != nullptr) {
             kick_transport(t);
             response =
@@ -1242,7 +1250,7 @@
         return SendOkay(reply_fd, response);
     }
 
-    int ret = handle_forward_request(service, type, serial, reply_fd);
+    int ret = handle_forward_request(service, type, serial, transport_id, reply_fd);
     if (ret >= 0)
       return ret - 1;
     return -1;