Merge "Setting up a libadbd flag for shared usage across miniadbd (CL 1/2)"
diff --git a/Android.bp b/Android.bp
index 2504f0d..461abb4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -549,6 +549,7 @@
         }
     },
 
+    min_sdk_version: "30",
     apex_available: [
         "//apex_available:platform",
         "com.android.adbd",
@@ -629,6 +630,7 @@
         },
     },
 
+    min_sdk_version: "30",
     apex_available: [
         "//apex_available:platform",
         "com.android.adbd",
@@ -643,6 +645,7 @@
     name: "libadbd",
     defaults: ["adbd_defaults", "host_adbd_supported"],
     recovery_available: true,
+    min_sdk_version: "30",
     apex_available: ["com.android.adbd"],
 
     // avoid getting duplicate symbol of android::build::getbuildnumber().
@@ -701,6 +704,7 @@
     name: "adbd",
     defaults: ["adbd_defaults", "host_adbd_supported", "libadbd_binary_dependencies"],
     recovery_available: true,
+    min_sdk_version: "30",
     apex_available: ["com.android.adbd"],
 
     srcs: [
diff --git a/adb.cpp b/adb.cpp
index d0602ec..6813da0 100644
--- a/adb.cpp
+++ b/adb.cpp
@@ -726,7 +726,7 @@
     while (static_cast<size_t>(i) < lines.size()) fprintf(stderr, "%s\n", lines[i++].c_str());
 }
 
-int launch_server(const std::string& socket_spec) {
+int launch_server(const std::string& socket_spec, const char* one_device) {
 #if defined(_WIN32)
     /* we need to start the server in the background                    */
     /* we create a PIPE that will be used to wait for the server's "OK" */
@@ -828,8 +828,14 @@
     }
 
     WCHAR   args[64];
-    snwprintf(args, arraysize(args), L"adb -L %s fork-server server --reply-fd %d",
-              socket_spec.c_str(), ack_write_as_int);
+    if (one_device) {
+        snwprintf(args, arraysize(args),
+                  L"adb -L %s fork-server server --reply-fd %d --one-device %s",
+                  socket_spec.c_str(), ack_write_as_int, one_device);
+    } else {
+        snwprintf(args, arraysize(args), L"adb -L %s fork-server server --reply-fd %d",
+                  socket_spec.c_str(), ack_write_as_int);
+    }
 
     PROCESS_INFORMATION   pinfo;
     ZeroMemory(&pinfo, sizeof(pinfo));
@@ -978,8 +984,14 @@
         char reply_fd[30];
         snprintf(reply_fd, sizeof(reply_fd), "%d", pipe_write.get());
         // child process
-        int result = execl(path.c_str(), "adb", "-L", socket_spec.c_str(), "fork-server", "server",
-                           "--reply-fd", reply_fd, NULL);
+        std::vector<const char*> child_argv = {
+                "adb", "-L", socket_spec.c_str(), "fork-server", "server", "--reply-fd", reply_fd};
+        if (one_device) {
+            child_argv.push_back("--one-device");
+            child_argv.push_back(one_device);
+        }
+        child_argv.push_back(nullptr);
+        int result = execv(path.c_str(), const_cast<char* const*>(child_argv.data()));
         // this should not return
         fprintf(stderr, "adb: execl returned %d: %s\n", result, strerror(errno));
     } else {
diff --git a/adb.h b/adb.h
index 801da1d..9dfaf3e 100644
--- a/adb.h
+++ b/adb.h
@@ -135,8 +135,9 @@
 
 void handle_packet(apacket* p, atransport* t);
 
-int launch_server(const std::string& socket_spec);
-int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd);
+int launch_server(const std::string& socket_spec, const char* one_device);
+int adb_server_main(int is_daemon, const std::string& socket_spec, const char* one_device,
+                    int ack_reply_fd);
 
 /* initialize a transport object's func pointers and state */
 int init_socket_transport(atransport* t, unique_fd s, int port, int local);
diff --git a/apex/apex_manifest.json b/apex/apex_manifest.json
index e6081b0..f687f50 100644
--- a/apex/apex_manifest.json
+++ b/apex/apex_manifest.json
@@ -1,5 +1,5 @@
 {
   "name": "com.android.adbd",
   "version": 319999999,
-  "versionName": "319999999.5"
+  "versionName": "319999999.57"
 }
diff --git a/client/adb_client.cpp b/client/adb_client.cpp
index 60dd38f..2d3e61f 100644
--- a/client/adb_client.cpp
+++ b/client/adb_client.cpp
@@ -53,6 +53,7 @@
 static TransportId __adb_transport_id = 0;
 
 static const char* __adb_server_socket_spec;
+static const char* __adb_client_one_device;
 
 void adb_set_transport(TransportType type, const char* serial, TransportId transport_id) {
     __adb_transport = type;
@@ -73,6 +74,10 @@
     __adb_server_socket_spec = socket_spec;
 }
 
+void adb_set_one_device(const char* one_device) {
+    __adb_client_one_device = one_device;
+}
+
 static std::optional<TransportId> switch_socket_transport(int fd, std::string* error) {
     TransportId result;
     bool read_transport = true;
@@ -257,7 +262,7 @@
     } else if (fd == -2) {
         fprintf(stderr, "* daemon not running; starting now at %s\n", __adb_server_socket_spec);
     start_server:
-        if (launch_server(__adb_server_socket_spec)) {
+        if (launch_server(__adb_server_socket_spec, __adb_client_one_device)) {
             fprintf(stderr, "* failed to start daemon\n");
             // launch_server() has already printed detailed error info, so just
             // return a generic error string about the overall adb_connect()
diff --git a/client/adb_client.h b/client/adb_client.h
index ab559b2..8262d18 100644
--- a/client/adb_client.h
+++ b/client/adb_client.h
@@ -58,6 +58,10 @@
 void adb_get_transport(TransportType* _Nullable type, const char* _Nullable* _Nullable serial,
                        TransportId* _Nullable transport_id);
 
+// Set the server's "one device" id. This is either null, or a pointer to a serial number
+// or a pointer to a usb device path, the argument must live to the end of the process.
+void adb_set_one_device(const char* _Nullable one_device);
+
 // Set the socket specification for the adb server.
 // This function can only be called once, and the argument must live to the end of the process.
 void adb_set_socket_spec(const char* _Nonnull socket_spec);
diff --git a/client/commandline.cpp b/client/commandline.cpp
index b5dd13f..0f6148e 100644
--- a/client/commandline.cpp
+++ b/client/commandline.cpp
@@ -86,14 +86,18 @@
     // clang-format off
     fprintf(stdout,
         "global options:\n"
-        " -a         listen on all network interfaces, not just localhost\n"
-        " -d         use USB device (error if multiple devices connected)\n"
-        " -e         use TCP/IP device (error if multiple TCP/IP devices available)\n"
-        " -s SERIAL  use device with given serial (overrides $ANDROID_SERIAL)\n"
-        " -t ID      use device with given transport id\n"
-        " -H         name of adb server host [default=localhost]\n"
-        " -P         port of adb server [default=5037]\n"
-        " -L SOCKET  listen on given socket for adb server [default=tcp:localhost:5037]\n"
+        " -a                       listen on all network interfaces, not just localhost\n"
+        " -d                       use USB device (error if multiple devices connected)\n"
+        " -e                       use TCP/IP device (error if multiple TCP/IP devices available)\n"
+        " -s SERIAL                use device with given serial (overrides $ANDROID_SERIAL)\n"
+        " -t ID                    use device with given transport id\n"
+        " -H                       name of adb server host [default=localhost]\n"
+        " -P                       port of adb server [default=5037]\n"
+        " -L SOCKET                listen on given socket for adb server"
+        " [default=tcp:localhost:5037]\n"
+        " --one-device SERIAL|USB  only allowed with 'start-server' or 'server nodaemon', server"
+        " will only connect to one USB device, specified by a serial number or USB device"
+        " address.\n"
         "\n"
         "general commands:\n"
         " devices [-l]             list connected devices (-l for long output)\n"
@@ -1558,6 +1562,7 @@
     const char* server_host_str = nullptr;
     const char* server_port_str = nullptr;
     const char* server_socket_str = nullptr;
+    const char* one_device_str = nullptr;
 
     // We need to check for -d and -e before we look at $ANDROID_SERIAL.
     const char* serial = nullptr;
@@ -1574,21 +1579,26 @@
         } else if (!strcmp(argv[0], "--reply-fd")) {
             if (argc < 2) error_exit("--reply-fd requires an argument");
             const char* reply_fd_str = argv[1];
-            argc--;
-            argv++;
+            --argc;
+            ++argv;
             ack_reply_fd = strtol(reply_fd_str, nullptr, 10);
             if (!_is_valid_ack_reply_fd(ack_reply_fd)) {
                 fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
                 return 1;
             }
+        } else if (!strcmp(argv[0], "--one-device")) {
+            if (argc < 2) error_exit("--one-device requires an argument");
+            one_device_str = argv[1];
+            --argc;
+            ++argv;
         } else if (!strncmp(argv[0], "-s", 2)) {
             if (isdigit(argv[0][2])) {
                 serial = argv[0] + 2;
             } else {
                 if (argc < 2 || argv[0][2] != '\0') error_exit("-s requires an argument");
                 serial = argv[1];
-                argc--;
-                argv++;
+                --argc;
+                ++argv;
             }
         } else if (!strncmp(argv[0], "-t", 2)) {
             const char* id;
@@ -1596,8 +1606,8 @@
                 id = argv[0] + 2;
             } else {
                 id = argv[1];
-                argc--;
-                argv++;
+                --argc;
+                ++argv;
             }
             transport_id = strtoll(id, const_cast<char**>(&id), 10);
             if (*id != '\0') {
@@ -1613,8 +1623,8 @@
             if (argv[0][2] == '\0') {
                 if (argc < 2) error_exit("-H requires an argument");
                 server_host_str = argv[1];
-                argc--;
-                argv++;
+                --argc;
+                ++argv;
             } else {
                 server_host_str = argv[0] + 2;
             }
@@ -1622,22 +1632,22 @@
             if (argv[0][2] == '\0') {
                 if (argc < 2) error_exit("-P requires an argument");
                 server_port_str = argv[1];
-                argc--;
-                argv++;
+                --argc;
+                ++argv;
             } else {
                 server_port_str = argv[0] + 2;
             }
         } else if (!strcmp(argv[0], "-L")) {
             if (argc < 2) error_exit("-L requires an argument");
             server_socket_str = argv[1];
-            argc--;
-            argv++;
+            --argc;
+            ++argv;
         } else {
             /* out of recognized modifiers and flags */
             break;
         }
-        argc--;
-        argv++;
+        --argc;
+        ++argv;
     }
 
     if ((server_host_str || server_port_str) && server_socket_str) {
@@ -1678,6 +1688,12 @@
         server_socket_str = temp;
     }
 
+    bool server_start = is_daemon || is_server || strcmp(argv[0], "start-server") == 0;
+    if (one_device_str && !server_start) {
+        error_exit("--one-device is only allowed when starting a server.");
+    }
+
+    adb_set_one_device(one_device_str);
     adb_set_socket_spec(server_socket_str);
 
     // If none of -d, -e, or -s were specified, try $ANDROID_SERIAL.
@@ -1693,9 +1709,9 @@
                 fprintf(stderr, "reply fd for adb server to client communication not specified.\n");
                 return 1;
             }
-            r = adb_server_main(is_daemon, server_socket_str, ack_reply_fd);
+            r = adb_server_main(is_daemon, server_socket_str, one_device_str, ack_reply_fd);
         } else {
-            r = launch_server(server_socket_str);
+            r = launch_server(server_socket_str, one_device_str);
         }
         if (r) {
             fprintf(stderr,"* could not start server *\n");
@@ -1723,8 +1739,8 @@
         }
 
         /* Fall through */
-        argc--;
-        argv++;
+        --argc;
+        ++argv;
     }
 
     /* adb_connect() commands */
diff --git a/client/main.cpp b/client/main.cpp
index 4fa58fa..cc89734 100644
--- a/client/main.cpp
+++ b/client/main.cpp
@@ -81,7 +81,10 @@
     LOG(INFO) << "leaking pointer " << p;
 }
 
-int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd) {
+// one_device: if null, server owns all devices, else server owns only
+//     device where atransport::MatchesTarget(one_device) is true.
+int adb_server_main(int is_daemon, const std::string& socket_spec, const char* one_device,
+                    int ack_reply_fd) {
 #if defined(_WIN32)
     // adb start-server starts us up with stdout and stderr hooked up to
     // anonymous pipes. When the C Runtime sees this, it makes stderr and
@@ -108,6 +111,10 @@
         fdevent_run_on_main_thread([]() { exit(0); });
     });
 
+    if (one_device) {
+        transport_set_one_device(one_device);
+    }
+
     const char* reject_kill_server = getenv("ADB_REJECT_KILL_SERVER");
     if (reject_kill_server && strcmp(reject_kill_server, "1") == 0) {
         adb_set_reject_kill_server(true);
diff --git a/client/usb_libusb.cpp b/client/usb_libusb.cpp
index 2564c26..e0b0104 100644
--- a/client/usb_libusb.cpp
+++ b/client/usb_libusb.cpp
@@ -469,6 +469,8 @@
         return true;
     }
 
+    std::string GetUsbDeviceAddress() const { return std::string("usb:") + device_address_; }
+
     std::string GetSerial() {
         std::string serial;
 
@@ -722,10 +724,14 @@
 
         auto device_desc = connection->GetDeviceDescriptor();
         if (!device_desc) {
+            LOG(INFO) << "ignoring device " << connection->GetUsbDeviceAddress()
+                      << ": not an adb interface. (GetDeviceDescriptor)";
             return {};
         }
 
         if (!connection->FindInterface(&device_desc.value())) {
+            LOG(INFO) << "ignoring device " << connection->GetUsbDeviceAddress()
+                      << ": not an adb interface. (FindInterface)";
             return {};
         }
 
@@ -743,11 +749,19 @@
 #else
         // We need to open the device to get its serial on Windows and OS X.
         if (!connection->OpenDevice(nullptr)) {
+            LOG(INFO) << "ignoring device " << connection->GetUsbDeviceAddress()
+                      << ": not an adb interface. (OpenDevice)";
             return {};
         }
         connection->serial_ = connection->GetSerial();
         connection->CloseDevice();
 #endif
+        if (!transport_server_owns_device(connection->GetUsbDeviceAddress(), connection->serial_)) {
+            LOG(INFO) << "ignoring device " << connection->GetUsbDeviceAddress() << " serial "
+                      << connection->serial_ << ": this server owns '" << transport_get_one_device()
+                      << "'";
+            return {};
+        }
 
         return connection;
     }
@@ -792,7 +806,6 @@
     unique_device device(libusb_ref_device(device_raw));
     auto connection_opt = LibusbConnection::Create(std::move(device));
     if (!connection_opt) {
-        LOG(INFO) << "ignoring device: not an adb interface";
         return;
     }
 
diff --git a/client/usb_linux.cpp b/client/usb_linux.cpp
index f75232f..7f92626 100644
--- a/client/usb_linux.cpp
+++ b/client/usb_linux.cpp
@@ -531,6 +531,24 @@
 static void register_device(const char* dev_name, const char* dev_path, unsigned char ep_in,
                             unsigned char ep_out, int interface, int serial_index,
                             unsigned zero_mask, size_t max_packet_size) {
+    // Read the device's serial number.
+    std::string serial_path =
+            android::base::StringPrintf("/sys/bus/usb/devices/%s/serial", dev_path + 4);
+    std::string serial;
+    if (!android::base::ReadFileToString(serial_path, &serial)) {
+        D("[ usb read %s failed: %s ]", serial_path.c_str(), strerror(errno));
+        // We don't actually want to treat an unknown serial as an error because
+        // devices aren't able to communicate a serial number in early bringup.
+        // http://b/20883914
+        serial = "";
+    }
+    serial = android::base::Trim(serial);
+
+    if (!transport_server_owns_device(dev_path, serial)) {
+        // We aren't allowed to communicate with this device. Don't open this device.
+        return;
+    }
+
     // Since Linux will not reassign the device ID (and dev_name) as long as the
     // device is open, we can add to the list here once we open it and remove
     // from the list when we're finally closed and everything will work out
@@ -579,19 +597,6 @@
         }
     }
 
-    // Read the device's serial number.
-    std::string serial_path = android::base::StringPrintf(
-        "/sys/bus/usb/devices/%s/serial", dev_path + 4);
-    std::string serial;
-    if (!android::base::ReadFileToString(serial_path, &serial)) {
-        D("[ usb read %s failed: %s ]", serial_path.c_str(), strerror(errno));
-        // We don't actually want to treat an unknown serial as an error because
-        // devices aren't able to communicate a serial number in early bringup.
-        // http://b/20883914
-        serial = "";
-    }
-    serial = android::base::Trim(serial);
-
     // Add to the end of the active handles.
     usb_handle* done_usb = usb.release();
     {
diff --git a/client/usb_osx.cpp b/client/usb_osx.cpp
index 42ba812..e72d719 100644
--- a/client/usb_osx.cpp
+++ b/client/usb_osx.cpp
@@ -296,6 +296,13 @@
             continue;
         }
 
+        if (!transport_server_owns_device(devpath, serial)) {
+            // We aren't allowed to communicate with this device. Don't open this device.
+            D("ignoring device: not owned by this server dev_path: '%s', serial: '%s'",
+              devpath.c_str(), serial);
+            continue;
+        }
+
         std::unique_ptr<usb_handle> handle =
             CheckInterface((IOUSBInterfaceInterface550**)iface, vendor, product);
         if (handle == nullptr) {
diff --git a/client/usb_windows.cpp b/client/usb_windows.cpp
index 0ffcc09..6581928 100644
--- a/client/usb_windows.cpp
+++ b/client/usb_windows.cpp
@@ -574,6 +574,15 @@
                     unsigned long serial_number_len = sizeof(serial_number);
                     if (AdbGetSerialNumber(handle->adb_interface, serial_number, &serial_number_len,
                                            true)) {
+                        if (!transport_server_owns_device(serial_number)) {
+                            // We aren't allowed to communicate with this device. Don't open this
+                            // device.
+                            D("ignoring device: not owned by this server serial: '%s'",
+                              serial_number);
+                            usb_cleanup_handle(handle);
+                            free(handle);
+                            return;
+                        }
                         // Lets make sure that we don't duplicate this device
                         if (register_new_device(handle)) {
                             register_usb_transport(handle, serial_number, nullptr, 1);
diff --git a/crypto/Android.bp b/crypto/Android.bp
index 8fdce89..9628348 100644
--- a/crypto/Android.bp
+++ b/crypto/Android.bp
@@ -69,6 +69,7 @@
     name: "libadb_crypto",
     defaults: ["libadb_crypto_defaults"],
 
+    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
         "test_com.android.adbd",
diff --git a/libs/adbconnection/Android.bp b/libs/adbconnection/Android.bp
index da0b5b6..0698a98 100644
--- a/libs/adbconnection/Android.bp
+++ b/libs/adbconnection/Android.bp
@@ -27,6 +27,7 @@
     use_version_lib: false,
 
     recovery_available: true,
+    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
         // TODO(b/151398197) remove the below
@@ -50,6 +51,7 @@
         "//art:__subpackages__",
         "//packages/modules/adb/apex:__subpackages__",
     ],
+    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
         "test_com.android.adbd",
diff --git a/pairing_auth/Android.bp b/pairing_auth/Android.bp
index e2e9fc4..1d6dd98 100644
--- a/pairing_auth/Android.bp
+++ b/pairing_auth/Android.bp
@@ -71,6 +71,7 @@
     name: "libadb_pairing_auth",
     defaults: ["libadb_pairing_auth_defaults"],
 
+    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
     ],
diff --git a/pairing_connection/Android.bp b/pairing_connection/Android.bp
index 3c5b0a3..3557810 100644
--- a/pairing_connection/Android.bp
+++ b/pairing_connection/Android.bp
@@ -81,6 +81,7 @@
     name: "libadb_pairing_connection",
     defaults: ["libadb_pairing_connection_defaults"],
 
+    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
     ],
@@ -163,6 +164,7 @@
     name: "libadb_pairing_server",
     defaults: ["libadb_pairing_server_defaults"],
 
+    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
     ],
diff --git a/proto/Android.bp b/proto/Android.bp
index c7271fb..fae321f 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -65,6 +65,7 @@
     name: "libadb_protos",
     defaults: ["libadb_protos_defaults"],
 
+    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
         "test_com.android.adbd",
@@ -121,6 +122,7 @@
     name: "libapp_processes_protos_lite",
     defaults: ["libapp_processes_protos_defaults"],
 
+    min_sdk_version: "30",
     apex_available: ["//apex_available:platform"],
 
     proto: {
diff --git a/tls/Android.bp b/tls/Android.bp
index 9e850ab..b45fc8d 100644
--- a/tls/Android.bp
+++ b/tls/Android.bp
@@ -64,6 +64,7 @@
     name: "libadb_tls_connection",
     defaults: ["libadb_tls_connection_defaults"],
 
+    min_sdk_version: "30",
     apex_available: [
         "com.android.adbd",
         "test_com.android.adbd",
diff --git a/transport.cpp b/transport.cpp
index 3493cc1..0dfad0e 100644
--- a/transport.cpp
+++ b/transport.cpp
@@ -96,6 +96,7 @@
 namespace {
 
 #if ADB_HOST
+
 // Tracks and handles atransport*s that are attempting reconnection.
 class ReconnectHandler {
   public:
@@ -948,6 +949,34 @@
     return !*ptr;
 }
 
+// Contains either a device serial string or a USB device address like "usb:2-6"
+const char* __transport_server_one_device = nullptr;
+
+void transport_set_one_device(const char* adb_one_device) {
+    __transport_server_one_device = adb_one_device;
+}
+
+const char* transport_get_one_device() {
+    return __transport_server_one_device;
+}
+
+bool transport_server_owns_device(std::string_view serial) {
+    if (!__transport_server_one_device) {
+        // If the server doesn't own one device, server owns all devices.
+        return true;
+    }
+    return serial.compare(__transport_server_one_device) == 0;
+}
+
+bool transport_server_owns_device(std::string_view dev_path, std::string_view serial) {
+    if (!__transport_server_one_device) {
+        // If the server doesn't own one device, server owns all devices.
+        return true;
+    }
+    return serial.compare(__transport_server_one_device) == 0 ||
+           dev_path.compare(__transport_server_one_device) == 0;
+}
+
 atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
                                   bool* is_ambiguous, std::string* error_out,
                                   bool accept_any_state) {
diff --git a/transport.h b/transport.h
index 35cecf8..8618693 100644
--- a/transport.h
+++ b/transport.h
@@ -422,6 +422,18 @@
     DISALLOW_COPY_AND_ASSIGN(atransport);
 };
 
+// --one-device command line parameter is eventually put here.
+void transport_set_one_device(const char* adb_one_device);
+
+// Returns one device owned by this server of nullptr if all devices belong to server.
+const char* transport_get_one_device();
+
+// Returns true if the adb server owns all devices, or `serial`.
+bool transport_server_owns_device(std::string_view serial);
+
+// Returns true if the adb server owns all devices, `serial`, or `dev_path`.
+bool transport_server_owns_device(std::string_view dev_path, std::string_view serial);
+
 /*
  * Obtain a transport from the available transports.
  * If serial is non-null then only the device with that serial will be chosen.