From 33823dfd546ef99e46bd432ee2e0f59100348646 Mon Sep 17 00:00:00 2001 From: Simon Chan <1330321+yume-chan@users.noreply.github.com> Date: Mon, 12 Aug 2024 12:03:07 +0800 Subject: [PATCH] feat(webusb): add unique error type for device busy --- libraries/adb-daemon-webusb/src/device.ts | 24 +++++++++++++++++++---- libraries/adb-daemon-webusb/src/utils.ts | 2 +- libraries/adb/src/daemon/transport.ts | 12 +++++++----- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/libraries/adb-daemon-webusb/src/device.ts b/libraries/adb-daemon-webusb/src/device.ts index ca34f69c9..6595bdf93 100644 --- a/libraries/adb-daemon-webusb/src/device.ts +++ b/libraries/adb-daemon-webusb/src/device.ts @@ -242,7 +242,7 @@ export class AdbDaemonWebUsbConnection } catch (e) { // On Windows, disconnecting the device will cause `NetworkError` to be thrown, // even before the `disconnect` event is fired. - // We need to wait a little bit and check if the device is still connected. + // Wait a little while and check if the device is still connected. // https://github.com/WICG/webusb/issues/219 if (isErrorName(e, "NetworkError")) { await new Promise((resolve) => { @@ -253,8 +253,6 @@ export class AdbDaemonWebUsbConnection if (closed) { return undefined; - } else { - throw e; } } @@ -318,7 +316,15 @@ export class AdbDaemonWebUsbDevice implements AdbDaemonDevice { } if (!interface_.claimed) { - await this.#raw.claimInterface(interface_.interfaceNumber); + try { + await this.#raw.claimInterface(interface_.interfaceNumber); + } catch (e) { + if (isErrorName(e, "NetworkError")) { + throw new AdbDaemonWebUsbDevice.DeviceBusyError(e); + } + + throw e; + } } if ( @@ -350,3 +356,13 @@ export class AdbDaemonWebUsbDevice implements AdbDaemonDevice { ); } } + +export namespace AdbDaemonWebUsbDevice { + export class DeviceBusyError extends Error { + constructor(cause?: Error) { + super("The device is already in used by another program", { + cause, + }); + } + } +} diff --git a/libraries/adb-daemon-webusb/src/utils.ts b/libraries/adb-daemon-webusb/src/utils.ts index 81c177d6e..96a7212bf 100644 --- a/libraries/adb-daemon-webusb/src/utils.ts +++ b/libraries/adb-daemon-webusb/src/utils.ts @@ -1,4 +1,4 @@ -export function isErrorName(e: unknown, name: string): boolean { +export function isErrorName(e: unknown, name: string): e is Error { // node-usb package doesn't use `DOMException`, // so use a looser check // https://github.com/node-usb/node-usb/issues/573 diff --git a/libraries/adb/src/daemon/transport.ts b/libraries/adb/src/daemon/transport.ts index 989dd904f..433060019 100644 --- a/libraries/adb/src/daemon/transport.ts +++ b/libraries/adb/src/daemon/transport.ts @@ -114,13 +114,15 @@ interface AdbDaemonSocketConnectorConstructionOptions { /** * The number of bytes the device can send before receiving an ack packet. - * Using delayed ack can improve the throughput, - * especially when the device is connected over Wi-Fi (so the latency is higher). + * + * On Android 14 and newer, the Delayed Acknowledgement feature is added to + * improve performance, especially for high-latency connections like ADB over Wi-Fi. * * When `features` doesn't include `AdbFeature.DelayedAck`, it must be set to 0. Otherwise, - * the value must be in the range of unsigned 32-bit integer. If the device enabled - * delayed ack but the client didn't, the device will throw an error when the client sends - * the first data packet. And vice versa. + * the value must be in the range of unsigned 32-bit integer. + * + * If the device enabled delayed ack but the client didn't, the device will throw an error + * when the client sends the first data packet. And vice versa. */ initialDelayedAckBytes: number;