Loading libraries/adb-daemon-webusb/src/device.ts +68 −37 Original line number Diff line number Diff line Loading @@ -99,6 +99,11 @@ class Uint8ArrayExactReadable implements ExactReadable { export class AdbDaemonWebUsbConnection implements ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>> { #device: AdbDaemonWebUsbDevice; get device() { return this.#device; } #readable: ReadableStream<AdbPacketData>; get readable() { return this.#readable; Loading @@ -110,11 +115,13 @@ export class AdbDaemonWebUsbConnection } constructor( device: USBDevice, device: AdbDaemonWebUsbDevice, inEndpoint: USBEndpoint, outEndpoint: USBEndpoint, usbManager: USB, ) { this.#device = device; let closed = false; const duplex = new DuplexStreamFactory< Loading @@ -124,7 +131,7 @@ export class AdbDaemonWebUsbConnection close: async () => { try { closed = true; await device.close(); await device.raw.close(); } catch { /* device may have already disconnected */ } Loading @@ -139,7 +146,7 @@ export class AdbDaemonWebUsbConnection }); function handleUsbDisconnect(e: USBConnectionEvent) { if (e.device === device) { if (e.device === device.raw) { duplex.dispose().catch(unreachable); } } Loading @@ -150,15 +157,25 @@ export class AdbDaemonWebUsbConnection new ReadableStream<AdbPacketData>({ async pull(controller) { try { while (true) { // The `length` argument in `transferIn` must not be smaller than what the device sent, // otherwise it will return `babble` status without any data. // ADB daemon sends each packet in two parts, the 24-byte header and the payload. const result = await device.transferIn( const result = await device.raw.transferIn( inEndpoint.endpointNumber, 24, ); // TODO: webusb: handle `babble` by discarding the data and receive again // Maximum payload size is 1MB, so reading 1MB data will always success, // and always discards all lingering data. // FIXME: Chrome on Windows doesn't support babble status. See the HACK below. if (result.status === "babble") { await device.raw.transferIn( inEndpoint.endpointNumber, 1024 * 1024, ); continue; } // Per spec, the `result.data` always covers the whole `buffer`. const buffer = new Uint8Array(result.data!.buffer); Loading @@ -169,7 +186,21 @@ export class AdbDaemonWebUsbConnection stream, ) as AdbPacketHeader & { payload: Uint8Array }; if (packet.payloadLength !== 0) { const result = await device.transferIn( // HACK: Chrome on Windows doesn't support babble status, // so maybe we are not actually reading an ADB packet header. // Currently the maximum payload size is 1MB, // so if the payload length is larger than that, // try to discard the data and receive again. // https://crbug.com/1314358 if (packet.payloadLength > 1024 * 1024) { await device.raw.transferIn( inEndpoint.endpointNumber, 1024 * 1024, ); continue; } const result = await device.raw.transferIn( inEndpoint.endpointNumber, packet.payloadLength, ); Loading @@ -181,6 +212,8 @@ export class AdbDaemonWebUsbConnection } controller.enqueue(packet); return; } } catch (e) { // On Windows, disconnecting the device will cause `NetworkError` to be thrown, // even before the `disconnect` event is fired. Loading Loading @@ -212,7 +245,7 @@ export class AdbDaemonWebUsbConnection new ConsumableWritableStream({ write: async (chunk) => { try { await device.transferOut( await device.raw.transferOut( outEndpoint.endpointNumber, chunk, ); Loading @@ -225,7 +258,7 @@ export class AdbDaemonWebUsbConnection zeroMask && (chunk.byteLength & zeroMask) === 0 ) { await device.transferOut( await device.raw.transferOut( outEndpoint.endpointNumber, EMPTY_UINT8_ARRAY, ); Loading Loading @@ -281,9 +314,7 @@ export class AdbDaemonWebUsbDevice implements AdbDaemonDevice { * Claim the device and create a pair of `AdbPacket` streams to the ADB interface. * @returns The pair of `AdbPacket` streams. */ async connect(): Promise< ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>> > { async connect(): Promise<AdbDaemonWebUsbConnection> { if (!this.#raw.opened) { await this.#raw.open(); } Loading Loading @@ -319,7 +350,7 @@ export class AdbDaemonWebUsbDevice implements AdbDaemonDevice { alternate.endpoints, ); return new AdbDaemonWebUsbConnection( this.#raw, this, inEndpoint, outEndpoint, this.#usbManager, Loading libraries/adb/src/daemon/transport.ts +15 −5 Original line number Diff line number Diff line Loading @@ -27,9 +27,14 @@ import { AdbCommand, calculateChecksum } from "./packet.js"; export const ADB_DAEMON_VERSION_OMIT_CHECKSUM = 0x01000001; export type AdbDaemonConnection = ReadableWritablePair< AdbPacketData, Consumable<AdbPacketInit> >; interface AdbDaemonAuthenticationOptions { serial: string; connection: ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>; connection: AdbDaemonConnection; credentialStore: AdbCredentialStore; authenticators?: AdbAuthenticator[]; /** Loading @@ -40,7 +45,7 @@ interface AdbDaemonAuthenticationOptions { interface AdbDaemonSocketConnectorConstructionOptions { serial: string; connection: ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>; connection: AdbDaemonConnection; version: number; maxPayloadSize: number; banner: string; Loading Loading @@ -94,9 +99,8 @@ export class AdbDaemonTransport implements AdbTransport { resolver.resolve(decodeUtf8(packet.payload)); break; case AdbCommand.Auth: { const response = await authProcessor.process( packet, ); const response = await authProcessor.process(packet); await sendPacket(response); break; } Loading Loading @@ -193,6 +197,11 @@ export class AdbDaemonTransport implements AdbTransport { }); } #connection: AdbDaemonConnection; get connection() { return this.#connection; } readonly #dispatcher: AdbPacketDispatcher; #serial: string; Loading Loading @@ -228,6 +237,7 @@ export class AdbDaemonTransport implements AdbTransport { preserveConnection, }: AdbDaemonSocketConnectorConstructionOptions) { this.#serial = serial; this.#connection = connection; this.#banner = AdbBanner.parse(banner); let calculateChecksum: boolean; Loading libraries/android-bin/src/index.ts +1 −0 Original line number Diff line number Diff line Loading @@ -9,3 +9,4 @@ export * from "./logcat.js"; export * from "./overlay-display.js"; export * from "./pm.js"; export * from "./settings.js"; export * from "./string-format.js"; Loading
libraries/adb-daemon-webusb/src/device.ts +68 −37 Original line number Diff line number Diff line Loading @@ -99,6 +99,11 @@ class Uint8ArrayExactReadable implements ExactReadable { export class AdbDaemonWebUsbConnection implements ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>> { #device: AdbDaemonWebUsbDevice; get device() { return this.#device; } #readable: ReadableStream<AdbPacketData>; get readable() { return this.#readable; Loading @@ -110,11 +115,13 @@ export class AdbDaemonWebUsbConnection } constructor( device: USBDevice, device: AdbDaemonWebUsbDevice, inEndpoint: USBEndpoint, outEndpoint: USBEndpoint, usbManager: USB, ) { this.#device = device; let closed = false; const duplex = new DuplexStreamFactory< Loading @@ -124,7 +131,7 @@ export class AdbDaemonWebUsbConnection close: async () => { try { closed = true; await device.close(); await device.raw.close(); } catch { /* device may have already disconnected */ } Loading @@ -139,7 +146,7 @@ export class AdbDaemonWebUsbConnection }); function handleUsbDisconnect(e: USBConnectionEvent) { if (e.device === device) { if (e.device === device.raw) { duplex.dispose().catch(unreachable); } } Loading @@ -150,15 +157,25 @@ export class AdbDaemonWebUsbConnection new ReadableStream<AdbPacketData>({ async pull(controller) { try { while (true) { // The `length` argument in `transferIn` must not be smaller than what the device sent, // otherwise it will return `babble` status without any data. // ADB daemon sends each packet in two parts, the 24-byte header and the payload. const result = await device.transferIn( const result = await device.raw.transferIn( inEndpoint.endpointNumber, 24, ); // TODO: webusb: handle `babble` by discarding the data and receive again // Maximum payload size is 1MB, so reading 1MB data will always success, // and always discards all lingering data. // FIXME: Chrome on Windows doesn't support babble status. See the HACK below. if (result.status === "babble") { await device.raw.transferIn( inEndpoint.endpointNumber, 1024 * 1024, ); continue; } // Per spec, the `result.data` always covers the whole `buffer`. const buffer = new Uint8Array(result.data!.buffer); Loading @@ -169,7 +186,21 @@ export class AdbDaemonWebUsbConnection stream, ) as AdbPacketHeader & { payload: Uint8Array }; if (packet.payloadLength !== 0) { const result = await device.transferIn( // HACK: Chrome on Windows doesn't support babble status, // so maybe we are not actually reading an ADB packet header. // Currently the maximum payload size is 1MB, // so if the payload length is larger than that, // try to discard the data and receive again. // https://crbug.com/1314358 if (packet.payloadLength > 1024 * 1024) { await device.raw.transferIn( inEndpoint.endpointNumber, 1024 * 1024, ); continue; } const result = await device.raw.transferIn( inEndpoint.endpointNumber, packet.payloadLength, ); Loading @@ -181,6 +212,8 @@ export class AdbDaemonWebUsbConnection } controller.enqueue(packet); return; } } catch (e) { // On Windows, disconnecting the device will cause `NetworkError` to be thrown, // even before the `disconnect` event is fired. Loading Loading @@ -212,7 +245,7 @@ export class AdbDaemonWebUsbConnection new ConsumableWritableStream({ write: async (chunk) => { try { await device.transferOut( await device.raw.transferOut( outEndpoint.endpointNumber, chunk, ); Loading @@ -225,7 +258,7 @@ export class AdbDaemonWebUsbConnection zeroMask && (chunk.byteLength & zeroMask) === 0 ) { await device.transferOut( await device.raw.transferOut( outEndpoint.endpointNumber, EMPTY_UINT8_ARRAY, ); Loading Loading @@ -281,9 +314,7 @@ export class AdbDaemonWebUsbDevice implements AdbDaemonDevice { * Claim the device and create a pair of `AdbPacket` streams to the ADB interface. * @returns The pair of `AdbPacket` streams. */ async connect(): Promise< ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>> > { async connect(): Promise<AdbDaemonWebUsbConnection> { if (!this.#raw.opened) { await this.#raw.open(); } Loading Loading @@ -319,7 +350,7 @@ export class AdbDaemonWebUsbDevice implements AdbDaemonDevice { alternate.endpoints, ); return new AdbDaemonWebUsbConnection( this.#raw, this, inEndpoint, outEndpoint, this.#usbManager, Loading
libraries/adb/src/daemon/transport.ts +15 −5 Original line number Diff line number Diff line Loading @@ -27,9 +27,14 @@ import { AdbCommand, calculateChecksum } from "./packet.js"; export const ADB_DAEMON_VERSION_OMIT_CHECKSUM = 0x01000001; export type AdbDaemonConnection = ReadableWritablePair< AdbPacketData, Consumable<AdbPacketInit> >; interface AdbDaemonAuthenticationOptions { serial: string; connection: ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>; connection: AdbDaemonConnection; credentialStore: AdbCredentialStore; authenticators?: AdbAuthenticator[]; /** Loading @@ -40,7 +45,7 @@ interface AdbDaemonAuthenticationOptions { interface AdbDaemonSocketConnectorConstructionOptions { serial: string; connection: ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>; connection: AdbDaemonConnection; version: number; maxPayloadSize: number; banner: string; Loading Loading @@ -94,9 +99,8 @@ export class AdbDaemonTransport implements AdbTransport { resolver.resolve(decodeUtf8(packet.payload)); break; case AdbCommand.Auth: { const response = await authProcessor.process( packet, ); const response = await authProcessor.process(packet); await sendPacket(response); break; } Loading Loading @@ -193,6 +197,11 @@ export class AdbDaemonTransport implements AdbTransport { }); } #connection: AdbDaemonConnection; get connection() { return this.#connection; } readonly #dispatcher: AdbPacketDispatcher; #serial: string; Loading Loading @@ -228,6 +237,7 @@ export class AdbDaemonTransport implements AdbTransport { preserveConnection, }: AdbDaemonSocketConnectorConstructionOptions) { this.#serial = serial; this.#connection = connection; this.#banner = AdbBanner.parse(banner); let calculateChecksum: boolean; Loading
libraries/android-bin/src/index.ts +1 −0 Original line number Diff line number Diff line Loading @@ -9,3 +9,4 @@ export * from "./logcat.js"; export * from "./overlay-display.js"; export * from "./pm.js"; export * from "./settings.js"; export * from "./string-format.js";