adb: use the actual wMaxPacketSize for usb endpoints.
Previously, adb was assuming a fixed maximum packet size of 1024 bytes
(the value for an endpoint connected via USB 3.0). When connected to an
endpoint that has an actual maximum packet size of 512 bytes (i.e.
every single device over USB 2.0), the following could occur:
device sends amessage with 512 byte payload
client reads amessage
client tries to read payload with a length of 1024
In this scenario, the kernel will block, waiting for an additional
packet which won't arrive until something else gets sent across the
wire, which will result in the previous read failing, and the new
packet being dropped.
Bug: http://b/37783561
Test: python test_device.py on linux/darwin, with native/libusb
Change-Id: I556f5344945e22dd1533b076f662a97eea24628e
diff --git a/adb/test_device.py b/adb/test_device.py
index a30972e..e44cc83 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -1259,6 +1259,26 @@
self.assertEqual(self._get_device_state(serialno), 'device')
+ def test_packet_size_regression(self):
+ """Test for http://b/37783561
+
+ Receiving packets of a length divisible by 512 but not 1024 resulted in
+ the adb client waiting indefinitely for more input.
+ """
+ # The values that trigger things are 507 (512 - 5 bytes from shell protocol) + 1024*n
+ # Probe some surrounding values as well, for the hell of it.
+ for length in [506, 507, 508, 1018, 1019, 1020, 1530, 1531, 1532]:
+ cmd = ['dd', 'if=/dev/zero', 'bs={}'.format(length), 'count=1', '2>/dev/null;'
+ 'echo', 'foo']
+ rc, stdout, _ = self.device.shell_nocheck(cmd)
+
+ self.assertEqual(0, rc)
+
+ # Output should be '\0' * length, followed by "foo\n"
+ self.assertEqual(length, len(stdout) - 4)
+ self.assertEqual(stdout, "\0" * length + "foo\n")
+
+
def main():
random.seed(0)
if len(adb.get_devices()) > 0: