@yume-chan/adb 0.0.17 → 0.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/CHANGELOG.json +27 -0
  2. package/CHANGELOG.md +16 -1
  3. package/LICENSE +1 -1
  4. package/esm/adb.d.ts +63 -60
  5. package/esm/adb.d.ts.map +1 -1
  6. package/esm/adb.js +257 -229
  7. package/esm/adb.js.map +1 -1
  8. package/esm/auth.d.ts +51 -51
  9. package/esm/auth.d.ts.map +1 -1
  10. package/esm/auth.js +95 -96
  11. package/esm/auth.js.map +1 -1
  12. package/esm/backend.d.ts +8 -8
  13. package/esm/backend.d.ts.map +1 -1
  14. package/esm/backend.js +1 -1
  15. package/esm/commands/base.d.ts +6 -6
  16. package/esm/commands/base.js +8 -8
  17. package/esm/commands/framebuffer.d.ts +53 -53
  18. package/esm/commands/framebuffer.d.ts.map +1 -1
  19. package/esm/commands/framebuffer.js +46 -47
  20. package/esm/commands/framebuffer.js.map +1 -1
  21. package/esm/commands/index.d.ts +7 -8
  22. package/esm/commands/index.d.ts.map +1 -1
  23. package/esm/commands/index.js +7 -8
  24. package/esm/commands/index.js.map +1 -1
  25. package/esm/commands/install.d.ts +9 -3
  26. package/esm/commands/install.d.ts.map +1 -1
  27. package/esm/commands/install.js +27 -21
  28. package/esm/commands/install.js.map +1 -1
  29. package/esm/commands/power.d.ts +22 -22
  30. package/esm/commands/power.d.ts.map +1 -1
  31. package/esm/commands/power.js +48 -44
  32. package/esm/commands/power.js.map +1 -1
  33. package/esm/commands/reverse.d.ts +41 -28
  34. package/esm/commands/reverse.d.ts.map +1 -1
  35. package/esm/commands/reverse.js +125 -98
  36. package/esm/commands/reverse.js.map +1 -1
  37. package/esm/commands/subprocess/command.d.ts +57 -51
  38. package/esm/commands/subprocess/command.d.ts.map +1 -1
  39. package/esm/commands/subprocess/command.js +86 -82
  40. package/esm/commands/subprocess/command.js.map +1 -1
  41. package/esm/commands/subprocess/index.d.ts +3 -3
  42. package/esm/commands/subprocess/index.js +3 -3
  43. package/esm/commands/subprocess/protocols/index.d.ts +3 -3
  44. package/esm/commands/subprocess/protocols/index.js +3 -3
  45. package/esm/commands/subprocess/protocols/none.d.ts +35 -35
  46. package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
  47. package/esm/commands/subprocess/protocols/none.js +65 -55
  48. package/esm/commands/subprocess/protocols/none.js.map +1 -1
  49. package/esm/commands/subprocess/protocols/shell.d.ts +39 -38
  50. package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
  51. package/esm/commands/subprocess/protocols/shell.js +166 -154
  52. package/esm/commands/subprocess/protocols/shell.js.map +1 -1
  53. package/esm/commands/subprocess/protocols/types.d.ts +49 -49
  54. package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
  55. package/esm/commands/subprocess/protocols/types.js +1 -1
  56. package/esm/commands/subprocess/utils.d.ts +1 -1
  57. package/esm/commands/subprocess/utils.js +18 -18
  58. package/esm/commands/sync/index.d.ts +8 -7
  59. package/esm/commands/sync/index.d.ts.map +1 -1
  60. package/esm/commands/sync/index.js +8 -7
  61. package/esm/commands/sync/index.js.map +1 -1
  62. package/esm/commands/sync/list.d.ts +42 -40
  63. package/esm/commands/sync/list.d.ts.map +1 -1
  64. package/esm/commands/sync/list.js +67 -35
  65. package/esm/commands/sync/list.js.map +1 -1
  66. package/esm/commands/sync/pull.d.ts +13 -11
  67. package/esm/commands/sync/pull.d.ts.map +1 -1
  68. package/esm/commands/sync/pull.js +35 -36
  69. package/esm/commands/sync/pull.js.map +1 -1
  70. package/esm/commands/sync/push.d.ts +46 -7
  71. package/esm/commands/sync/push.d.ts.map +1 -1
  72. package/esm/commands/sync/push.js +89 -23
  73. package/esm/commands/sync/push.js.map +1 -1
  74. package/esm/commands/sync/request.d.ts +26 -23
  75. package/esm/commands/sync/request.d.ts.map +1 -1
  76. package/esm/commands/sync/request.js +40 -42
  77. package/esm/commands/sync/request.js.map +1 -1
  78. package/esm/commands/sync/response.d.ts +19 -19
  79. package/esm/commands/sync/response.d.ts.map +1 -1
  80. package/esm/commands/sync/response.js +54 -54
  81. package/esm/commands/sync/response.js.map +1 -1
  82. package/esm/commands/sync/socket.d.ts +27 -0
  83. package/esm/commands/sync/socket.d.ts.map +1 -0
  84. package/esm/commands/sync/socket.js +66 -0
  85. package/esm/commands/sync/socket.js.map +1 -0
  86. package/esm/commands/sync/stat.d.ts +72 -72
  87. package/esm/commands/sync/stat.d.ts.map +1 -1
  88. package/esm/commands/sync/stat.js +116 -94
  89. package/esm/commands/sync/stat.js.map +1 -1
  90. package/esm/commands/sync/sync.d.ts +72 -60
  91. package/esm/commands/sync/sync.d.ts.map +1 -1
  92. package/esm/commands/sync/sync.js +127 -148
  93. package/esm/commands/sync/sync.js.map +1 -1
  94. package/esm/commands/tcpip.d.ts +5 -5
  95. package/esm/commands/tcpip.js +18 -18
  96. package/esm/crypto.d.ts +36 -36
  97. package/esm/crypto.d.ts.map +1 -1
  98. package/esm/crypto.js +248 -238
  99. package/esm/crypto.js.map +1 -1
  100. package/esm/features.d.ts +10 -7
  101. package/esm/features.d.ts.map +1 -1
  102. package/esm/features.js +13 -10
  103. package/esm/features.js.map +1 -1
  104. package/esm/index.d.ts +9 -9
  105. package/esm/index.d.ts.map +1 -1
  106. package/esm/index.js +9 -9
  107. package/esm/index.js.map +1 -1
  108. package/esm/packet.d.ts +45 -46
  109. package/esm/packet.d.ts.map +1 -1
  110. package/esm/packet.js +43 -46
  111. package/esm/packet.js.map +1 -1
  112. package/esm/socket/dispatcher.d.ts +59 -59
  113. package/esm/socket/dispatcher.d.ts.map +1 -1
  114. package/esm/socket/dispatcher.js +223 -231
  115. package/esm/socket/dispatcher.js.map +1 -1
  116. package/esm/socket/index.d.ts +2 -2
  117. package/esm/socket/index.js +2 -2
  118. package/esm/socket/socket.d.ts +59 -59
  119. package/esm/socket/socket.d.ts.map +1 -1
  120. package/esm/socket/socket.js +118 -98
  121. package/esm/socket/socket.js.map +1 -1
  122. package/esm/utils/auto-reset-event.d.ts +9 -9
  123. package/esm/utils/auto-reset-event.d.ts.map +1 -1
  124. package/esm/utils/auto-reset-event.js +33 -33
  125. package/esm/utils/auto-reset-event.js.map +1 -1
  126. package/esm/utils/base64.d.ts +27 -27
  127. package/esm/utils/base64.d.ts.map +1 -1
  128. package/esm/utils/base64.js +246 -245
  129. package/esm/utils/base64.js.map +1 -1
  130. package/esm/utils/conditional-variable.d.ts +9 -0
  131. package/esm/utils/conditional-variable.d.ts.map +1 -0
  132. package/esm/utils/conditional-variable.js +34 -0
  133. package/esm/utils/conditional-variable.js.map +1 -0
  134. package/esm/utils/index.d.ts +4 -3
  135. package/esm/utils/index.d.ts.map +1 -1
  136. package/esm/utils/index.js +4 -3
  137. package/esm/utils/index.js.map +1 -1
  138. package/package.json +17 -13
  139. package/src/adb.ts +160 -101
  140. package/src/auth.ts +31 -22
  141. package/src/backend.ts +6 -4
  142. package/src/commands/base.ts +2 -2
  143. package/src/commands/framebuffer.ts +37 -41
  144. package/src/commands/index.ts +7 -8
  145. package/src/commands/power.ts +15 -11
  146. package/src/commands/reverse.ts +74 -30
  147. package/src/commands/subprocess/command.ts +34 -23
  148. package/src/commands/subprocess/index.ts +3 -3
  149. package/src/commands/subprocess/protocols/index.ts +3 -3
  150. package/src/commands/subprocess/protocols/none.ts +26 -11
  151. package/src/commands/subprocess/protocols/shell.ts +110 -56
  152. package/src/commands/subprocess/protocols/types.ts +10 -6
  153. package/src/commands/subprocess/utils.ts +1 -1
  154. package/src/commands/sync/index.ts +8 -7
  155. package/src/commands/sync/list.ts +74 -28
  156. package/src/commands/sync/pull.ts +49 -37
  157. package/src/commands/sync/push.ts +153 -32
  158. package/src/commands/sync/request.ts +37 -34
  159. package/src/commands/sync/response.ts +34 -27
  160. package/src/commands/sync/socket.ts +97 -0
  161. package/src/commands/sync/stat.ts +98 -70
  162. package/src/commands/sync/sync.ts +78 -97
  163. package/src/commands/tcpip.ts +5 -5
  164. package/src/crypto.ts +60 -32
  165. package/src/features.ts +9 -6
  166. package/src/index.ts +9 -10
  167. package/src/packet.ts +41 -46
  168. package/src/socket/dispatcher.ts +130 -108
  169. package/src/socket/index.ts +2 -2
  170. package/src/socket/socket.ts +84 -34
  171. package/src/utils/auto-reset-event.ts +16 -17
  172. package/src/utils/base64.ts +51 -41
  173. package/src/utils/conditional-variable.ts +45 -0
  174. package/src/utils/index.ts +4 -3
  175. package/tsconfig.build.json +1 -1
  176. package/tsconfig.build.tsbuildinfo +1 -1
  177. package/src/commands/install.ts +0 -32
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yume-chan/adb",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "description": "TypeScript implementation of Android Debug Bridge (ADB) protocol.",
5
5
  "keywords": [
6
6
  "adb",
@@ -26,24 +26,28 @@
26
26
  "types": "esm/index.d.ts",
27
27
  "dependencies": {
28
28
  "@yume-chan/async": "^2.2.0",
29
- "@yume-chan/dataview-bigint-polyfill": "^0.0.17",
30
- "@yume-chan/event": "^0.0.17",
31
- "@yume-chan/stream-extra": "^0.0.17",
32
- "@yume-chan/struct": "^0.0.17",
33
- "tslib": "^2.4.0"
29
+ "@yume-chan/dataview-bigint-polyfill": "^0.0.19",
30
+ "@yume-chan/event": "^0.0.19",
31
+ "@yume-chan/stream-extra": "^0.0.19",
32
+ "@yume-chan/struct": "^0.0.19",
33
+ "tslib": "^2.4.1"
34
34
  },
35
35
  "devDependencies": {
36
- "@jest/globals": "^28.1.2",
37
- "@types/node": "^17.0.17",
38
- "@yume-chan/ts-package-builder": "^1.0.0",
36
+ "@jest/globals": "^29.5.0",
37
+ "@types/node": "^18.15.0",
38
+ "@yume-chan/eslint-config": "^1.0.0",
39
+ "@yume-chan/tsconfig": "^1.0.0",
39
40
  "cross-env": "^7.0.3",
40
- "jest": "^28.1.2",
41
- "ts-jest": "^28.0.5",
42
- "typescript": "^4.7.4"
41
+ "eslint": "^8.36.0",
42
+ "jest": "^29.5.0",
43
+ "prettier": "^2.8.4",
44
+ "ts-jest": "^29.0.4",
45
+ "typescript": "^4.9.4"
43
46
  },
44
47
  "scripts": {
45
48
  "build": "tsc -b tsconfig.build.json",
46
49
  "build:watch": "tsc -b tsconfig.build.json",
47
- "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage"
50
+ "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage",
51
+ "lint": "eslint src/**/*.ts --fix && prettier src/**/*.ts --write --tab-width 4"
48
52
  }
49
53
  }
package/src/adb.ts CHANGED
@@ -1,20 +1,44 @@
1
- // cspell: ignore libusb
2
-
3
- import { PromiseResolver } from '@yume-chan/async';
4
- import { AbortController, DecodeUtf8Stream, GatherStringStream, WritableStream, type ReadableWritablePair } from '@yume-chan/stream-extra';
5
-
6
- import { AdbAuthenticationProcessor, ADB_DEFAULT_AUTHENTICATORS, type AdbCredentialStore } from './auth.js';
7
- import { AdbPower, AdbReverseCommand, AdbSubprocess, AdbSync, AdbTcpIpCommand, escapeArg, framebuffer, install, type AdbFrameBuffer } from './commands/index.js';
8
- import { AdbFeatures } from './features.js';
9
- import { AdbCommand, calculateChecksum, type AdbPacketData, type AdbPacketInit } from './packet.js';
10
- import { AdbIncomingSocketHandler, AdbPacketDispatcher, type AdbSocket, type Closeable } from './socket/index.js';
11
- import { decodeUtf8, encodeUtf8 } from './utils/index.js';
1
+ import { PromiseResolver } from "@yume-chan/async";
2
+ import type { Consumable, ReadableWritablePair } from "@yume-chan/stream-extra";
3
+ import {
4
+ AbortController,
5
+ ConsumableWritableStream,
6
+ DecodeUtf8Stream,
7
+ GatherStringStream,
8
+ WritableStream,
9
+ } from "@yume-chan/stream-extra";
10
+
11
+ import type { AdbCredentialStore } from "./auth.js";
12
+ import {
13
+ ADB_DEFAULT_AUTHENTICATORS,
14
+ AdbAuthenticationProcessor,
15
+ } from "./auth.js";
16
+ import type { AdbFrameBuffer } from "./commands/index.js";
17
+ import {
18
+ AdbPower,
19
+ AdbReverseCommand,
20
+ AdbSubprocess,
21
+ AdbSync,
22
+ AdbTcpIpCommand,
23
+ escapeArg,
24
+ framebuffer,
25
+ } from "./commands/index.js";
26
+ import { AdbFeature } from "./features.js";
27
+ import type { AdbPacketData, AdbPacketInit } from "./packet.js";
28
+ import { AdbCommand, calculateChecksum } from "./packet.js";
29
+ import type {
30
+ AdbIncomingSocketHandler,
31
+ AdbSocket,
32
+ Closeable,
33
+ } from "./socket/index.js";
34
+ import { AdbPacketDispatcher } from "./socket/index.js";
35
+ import { decodeUtf8, encodeUtf8 } from "./utils/index.js";
12
36
 
13
37
  export enum AdbPropKey {
14
- Product = 'ro.product.name',
15
- Model = 'ro.product.model',
16
- Device = 'ro.product.device',
17
- Features = 'features',
38
+ Product = "ro.product.name",
39
+ Model = "ro.product.model",
40
+ Device = "ro.product.device",
41
+ Features = "features",
18
42
  }
19
43
 
20
44
  export const VERSION_OMIT_CHECKSUM = 0x01000001;
@@ -26,47 +50,63 @@ export class Adb implements Closeable {
26
50
  * and starts a new authentication process.
27
51
  */
28
52
  public static async authenticate(
29
- connection: ReadableWritablePair<AdbPacketData, AdbPacketInit>,
53
+ connection: ReadableWritablePair<
54
+ AdbPacketData,
55
+ Consumable<AdbPacketInit>
56
+ >,
30
57
  credentialStore: AdbCredentialStore,
31
- authenticators = ADB_DEFAULT_AUTHENTICATORS,
58
+ authenticators = ADB_DEFAULT_AUTHENTICATORS
32
59
  ): Promise<Adb> {
33
60
  // Initially, set to highest-supported version and payload size.
34
61
  let version = 0x01000001;
35
- let maxPayloadSize = 0x100000;
62
+ // Android 4: 4K, Android 7: 256K, Android 9: 1M
63
+ let maxPayloadSize = 1024 * 1024;
36
64
 
37
65
  const resolver = new PromiseResolver<string>();
38
- const authProcessor = new AdbAuthenticationProcessor(authenticators, credentialStore);
66
+ const authProcessor = new AdbAuthenticationProcessor(
67
+ authenticators,
68
+ credentialStore
69
+ );
39
70
 
40
71
  // Here is similar to `AdbPacketDispatcher`,
41
72
  // But the received packet types and send packet processing are different.
42
73
  const abortController = new AbortController();
43
74
  const pipe = connection.readable
44
- .pipeTo(new WritableStream({
45
- async write(packet) {
46
- switch (packet.command) {
47
- case AdbCommand.Connect:
48
- version = Math.min(version, packet.arg0);
49
- maxPayloadSize = Math.min(maxPayloadSize, packet.arg1);
50
- resolver.resolve(decodeUtf8(packet.payload));
51
- break;
52
- case AdbCommand.Auth:
53
- const response = await authProcessor.process(packet);
54
- await sendPacket(response);
55
- break;
56
- default:
57
- // Maybe the previous ADB client exited without reading all packets,
58
- // so they are still waiting in OS internal buffer.
59
- // Just ignore them.
60
- // Because a `Connect` packet will reset the device,
61
- // Eventually there will be `Connect` and `Auth` response packets.
62
- break;
63
- }
75
+ .pipeTo(
76
+ new WritableStream({
77
+ async write(packet) {
78
+ switch (packet.command) {
79
+ case AdbCommand.Connect:
80
+ version = Math.min(version, packet.arg0);
81
+ maxPayloadSize = Math.min(
82
+ maxPayloadSize,
83
+ packet.arg1
84
+ );
85
+ resolver.resolve(decodeUtf8(packet.payload));
86
+ break;
87
+ case AdbCommand.Auth: {
88
+ const response = await authProcessor.process(
89
+ packet
90
+ );
91
+ await sendPacket(response);
92
+ break;
93
+ }
94
+ default:
95
+ // Maybe the previous ADB client exited without reading all packets,
96
+ // so they are still waiting in OS internal buffer.
97
+ // Just ignore them.
98
+ // Because a `Connect` packet will reset the device,
99
+ // Eventually there will be `Connect` and `Auth` response packets.
100
+ break;
101
+ }
102
+ },
103
+ }),
104
+ {
105
+ // Don't cancel the source ReadableStream on AbortSignal abort.
106
+ preventCancel: true,
107
+ signal: abortController.signal,
64
108
  }
65
- }), {
66
- // Don't cancel the source ReadableStream on AbortSignal abort.
67
- preventCancel: true,
68
- signal: abortController.signal,
69
- })
109
+ )
70
110
  .catch((e) => {
71
111
  resolver.reject(e);
72
112
  });
@@ -75,7 +115,9 @@ export class Adb implements Closeable {
75
115
  async function sendPacket(init: AdbPacketData) {
76
116
  // Always send checksum in auth steps
77
117
  // Because we don't know if the device needs it or not.
78
- await writer.write(calculateChecksum(init));
118
+ (init as AdbPacketInit).checksum = calculateChecksum(init.payload);
119
+ (init as AdbPacketInit).magic = init.command ^ 0xffffffff;
120
+ await ConsumableWritableStream.write(writer, init as AdbPacketInit);
79
121
  }
80
122
 
81
123
  let banner: string;
@@ -83,25 +125,25 @@ export class Adb implements Closeable {
83
125
  // https://android.googlesource.com/platform/packages/modules/adb/+/79010dc6d5ca7490c493df800d4421730f5466ca/transport.cpp#1252
84
126
  // There are some other feature constants, but some of them are only used by ADB server, not devices (daemons).
85
127
  const features = [
86
- AdbFeatures.ShellV2,
87
- AdbFeatures.Cmd,
88
- AdbFeatures.StatV2,
89
- AdbFeatures.ListV2,
90
- AdbFeatures.FixedPushMkdir,
91
- 'apex',
92
- 'abb',
128
+ AdbFeature.ShellV2,
129
+ AdbFeature.Cmd,
130
+ AdbFeature.StatV2,
131
+ AdbFeature.ListV2,
132
+ AdbFeature.FixedPushMkdir,
133
+ "apex",
134
+ AdbFeature.Abb,
93
135
  // only tells the client the symlink timestamp issue in `adb push --sync` has been fixed.
94
136
  // No special handling required.
95
- 'fixed_push_symlink_timestamp',
96
- 'abb_exec',
97
- 'remount_shell',
98
- 'track_app',
99
- 'sendrecv_v2',
100
- 'sendrecv_v2_brotli',
101
- 'sendrecv_v2_lz4',
102
- 'sendrecv_v2_zstd',
103
- 'sendrecv_v2_dry_run_send',
104
- ].join(',');
137
+ "fixed_push_symlink_timestamp",
138
+ AdbFeature.AbbExec,
139
+ "remount_shell",
140
+ "track_app",
141
+ "sendrecv_v2",
142
+ "sendrecv_v2_brotli",
143
+ "sendrecv_v2_lz4",
144
+ "sendrecv_v2_zstd",
145
+ "sendrecv_v2_dry_run_send",
146
+ ].join(",");
105
147
 
106
148
  await sendPacket({
107
149
  command: AdbCommand.Connect,
@@ -123,32 +165,44 @@ export class Adb implements Closeable {
123
165
  await pipe;
124
166
  }
125
167
 
126
- return new Adb(
127
- connection,
128
- version,
129
- maxPayloadSize,
130
- banner,
131
- );
168
+ return new Adb(connection, version, maxPayloadSize, banner);
132
169
  }
133
170
 
134
171
  private readonly dispatcher: AdbPacketDispatcher;
135
172
 
136
- public get disconnected() { return this.dispatcher.disconnected; }
173
+ public get disconnected() {
174
+ return this.dispatcher.disconnected;
175
+ }
137
176
 
138
- private _protocolVersion: number | undefined;
139
- public get protocolVersion() { return this._protocolVersion; }
177
+ private _protocolVersion: number;
178
+ public get protocolVersion() {
179
+ return this._protocolVersion;
180
+ }
181
+
182
+ private _maxPayloadSize: number;
183
+ public get maxPayloadSize() {
184
+ return this._maxPayloadSize;
185
+ }
140
186
 
141
187
  private _product: string | undefined;
142
- public get product() { return this._product; }
188
+ public get product() {
189
+ return this._product;
190
+ }
143
191
 
144
192
  private _model: string | undefined;
145
- public get model() { return this._model; }
193
+ public get model() {
194
+ return this._model;
195
+ }
146
196
 
147
197
  private _device: string | undefined;
148
- public get device() { return this._device; }
198
+ public get device() {
199
+ return this._device;
200
+ }
149
201
 
150
- private _features: AdbFeatures[] = [];
151
- public get features() { return this._features; }
202
+ private _features: AdbFeature[] = [];
203
+ public get features() {
204
+ return this._features;
205
+ }
152
206
 
153
207
  public readonly subprocess: AdbSubprocess;
154
208
  public readonly power: AdbPower;
@@ -156,10 +210,13 @@ export class Adb implements Closeable {
156
210
  public readonly tcpip: AdbTcpIpCommand;
157
211
 
158
212
  public constructor(
159
- connection: ReadableWritablePair<AdbPacketData, AdbPacketInit>,
213
+ connection: ReadableWritablePair<
214
+ AdbPacketData,
215
+ Consumable<AdbPacketInit>
216
+ >,
160
217
  version: number,
161
218
  maxPayloadSize: number,
162
- banner: string,
219
+ banner: string
163
220
  ) {
164
221
  this.parseBanner(banner);
165
222
 
@@ -173,16 +230,14 @@ export class Adb implements Closeable {
173
230
  appendNullToServiceString = true;
174
231
  }
175
232
 
176
- this.dispatcher = new AdbPacketDispatcher(
177
- connection,
178
- {
179
- calculateChecksum,
180
- appendNullToServiceString,
181
- maxPayloadSize,
182
- }
183
- );
233
+ this.dispatcher = new AdbPacketDispatcher(connection, {
234
+ calculateChecksum,
235
+ appendNullToServiceString,
236
+ maxPayloadSize,
237
+ });
184
238
 
185
239
  this._protocolVersion = version;
240
+ this._maxPayloadSize = maxPayloadSize;
186
241
 
187
242
  this.subprocess = new AdbSubprocess(this);
188
243
  this.power = new AdbPower(this);
@@ -191,15 +246,15 @@ export class Adb implements Closeable {
191
246
  }
192
247
 
193
248
  private parseBanner(banner: string): void {
194
- const pieces = banner.split('::');
249
+ const pieces = banner.split("::");
195
250
  if (pieces.length > 1) {
196
251
  const props = pieces[1]!;
197
- for (const prop of props.split(';')) {
252
+ for (const prop of props.split(";")) {
198
253
  if (!prop) {
199
254
  continue;
200
255
  }
201
256
 
202
- const keyValue = prop.split('=');
257
+ const keyValue = prop.split("=");
203
258
  if (keyValue.length !== 2) {
204
259
  continue;
205
260
  }
@@ -216,13 +271,17 @@ export class Adb implements Closeable {
216
271
  this._device = value;
217
272
  break;
218
273
  case AdbPropKey.Features:
219
- this._features = value!.split(',') as AdbFeatures[];
274
+ this._features = value!.split(",") as AdbFeature[];
220
275
  break;
221
276
  }
222
277
  }
223
278
  }
224
279
  }
225
280
 
281
+ public supportsFeature(feature: AdbFeature): boolean {
282
+ return this._features.includes(feature);
283
+ }
284
+
226
285
  /**
227
286
  * Add a handler for incoming socket.
228
287
  * @param handler A function to call with new incoming sockets. It must return `true` if it accepts the socket.
@@ -246,25 +305,25 @@ export class Adb implements Closeable {
246
305
  }
247
306
 
248
307
  public async getProp(key: string): Promise<string> {
249
- const stdout = await this.subprocess.spawnAndWaitLegacy(
250
- ['getprop', key]
251
- );
308
+ const stdout = await this.subprocess.spawnAndWaitLegacy([
309
+ "getprop",
310
+ key,
311
+ ]);
252
312
  return stdout.trim();
253
313
  }
254
314
 
255
315
  public async rm(...filenames: string[]): Promise<string> {
256
- const stdout = await this.subprocess.spawnAndWaitLegacy(
257
- ['rm', '-rf', ...filenames.map(arg => escapeArg(arg))],
258
- );
316
+ // https://android.googlesource.com/platform/packages/modules/adb/+/1a0fb8846d4e6b671c8aa7f137a8c21d7b248716/client/adb_install.cpp#984
317
+ const stdout = await this.subprocess.spawnAndWaitLegacy([
318
+ "rm",
319
+ ...filenames.map((arg) => escapeArg(arg)),
320
+ "</dev/null",
321
+ ]);
259
322
  return stdout;
260
323
  }
261
324
 
262
- public install() {
263
- return install(this);
264
- }
265
-
266
325
  public async sync(): Promise<AdbSync> {
267
- const socket = await this.createSocket('sync:');
326
+ const socket = await this.createSocket("sync:");
268
327
  return new AdbSync(this, socket);
269
328
  }
270
329
 
package/src/auth.ts CHANGED
@@ -1,10 +1,15 @@
1
- import { PromiseResolver } from '@yume-chan/async';
2
- import type { Disposable } from '@yume-chan/event';
3
- import type { ValueOrPromise } from '@yume-chan/struct';
4
-
5
- import { calculatePublicKey, calculatePublicKeyLength, sign } from './crypto.js';
6
- import { AdbCommand, type AdbPacketData } from './packet.js';
7
- import { calculateBase64EncodedLength, encodeBase64 } from './utils/index.js';
1
+ import { PromiseResolver } from "@yume-chan/async";
2
+ import type { Disposable } from "@yume-chan/event";
3
+ import type { ValueOrPromise } from "@yume-chan/struct";
4
+
5
+ import {
6
+ calculatePublicKey,
7
+ calculatePublicKeyLength,
8
+ sign,
9
+ } from "./crypto.js";
10
+ import type { AdbPacketData } from "./packet.js";
11
+ import { AdbCommand } from "./packet.js";
12
+ import { calculateBase64EncodedLength, encodeBase64 } from "./utils/index.js";
8
13
 
9
14
  export type AdbKeyIterable = Iterable<Uint8Array> | AsyncIterable<Uint8Array>;
10
15
 
@@ -50,7 +55,7 @@ export interface AdbAuthenticator {
50
55
 
51
56
  export const AdbSignatureAuthenticator: AdbAuthenticator = async function* (
52
57
  credentialStore: AdbCredentialStore,
53
- getNextRequest: () => Promise<AdbPacketData>,
58
+ getNextRequest: () => Promise<AdbPacketData>
54
59
  ): AsyncIterable<AdbPacketData> {
55
60
  for await (const key of credentialStore.iterateKeys()) {
56
61
  const packet = await getNextRequest();
@@ -71,7 +76,7 @@ export const AdbSignatureAuthenticator: AdbAuthenticator = async function* (
71
76
 
72
77
  export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
73
78
  credentialStore: AdbCredentialStore,
74
- getNextRequest: () => Promise<AdbPacketData>,
79
+ getNextRequest: () => Promise<AdbPacketData>
75
80
  ): AsyncIterable<AdbPacketData> {
76
81
  const packet = await getNextRequest();
77
82
 
@@ -85,23 +90,20 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
85
90
  break;
86
91
  }
87
92
 
88
-
89
93
  if (!privateKey) {
90
94
  privateKey = await credentialStore.generateKey();
91
95
  }
92
96
 
93
97
  const publicKeyLength = calculatePublicKeyLength();
94
- const [publicKeyBase64Length] = calculateBase64EncodedLength(publicKeyLength);
98
+ const [publicKeyBase64Length] =
99
+ calculateBase64EncodedLength(publicKeyLength);
95
100
 
96
- // The public key is null terminated,
97
- // So we allocate the buffer with one extra byte.
98
- const publicKeyBuffer = new Uint8Array(publicKeyBase64Length + 1);
101
+ const publicKeyBuffer = new Uint8Array(
102
+ publicKeyBase64Length + 1 // Null character
103
+ );
99
104
 
100
105
  calculatePublicKey(privateKey, publicKeyBuffer);
101
- encodeBase64(
102
- publicKeyBuffer.subarray(0, publicKeyLength),
103
- publicKeyBuffer
104
- );
106
+ encodeBase64(publicKeyBuffer.subarray(0, publicKeyLength), publicKeyBuffer);
105
107
 
106
108
  yield {
107
109
  command: AdbCommand.Auth,
@@ -137,9 +139,16 @@ export class AdbAuthenticationProcessor implements Disposable {
137
139
  return this.pendingRequest.promise;
138
140
  };
139
141
 
140
- private async* invokeAuthenticator(): AsyncGenerator<AdbPacketData, void, void> {
142
+ private async *invokeAuthenticator(): AsyncGenerator<
143
+ AdbPacketData,
144
+ void,
145
+ void
146
+ > {
141
147
  for (const authenticator of this.authenticators) {
142
- for await (const packet of authenticator(this.credentialStore, this.getNextRequest)) {
148
+ for await (const packet of authenticator(
149
+ this.credentialStore,
150
+ this.getNextRequest
151
+ )) {
143
152
  // If the authenticator yielded a response
144
153
  // Prepare `nextRequest` for next authentication request
145
154
  this.pendingRequest = new PromiseResolver();
@@ -162,13 +171,13 @@ export class AdbAuthenticationProcessor implements Disposable {
162
171
 
163
172
  const result = await this.iterator.next();
164
173
  if (result.done) {
165
- throw new Error('No authenticator can handle the request');
174
+ throw new Error("No authenticator can handle the request");
166
175
  }
167
176
 
168
177
  return result.value;
169
178
  }
170
179
 
171
180
  public dispose() {
172
- this.iterator?.return?.();
181
+ void this.iterator?.return?.();
173
182
  }
174
183
  }
package/src/backend.ts CHANGED
@@ -1,12 +1,14 @@
1
- import type { ReadableWritablePair } from '@yume-chan/stream-extra';
2
- import type { ValueOrPromise } from '@yume-chan/struct';
1
+ import type { Consumable, ReadableWritablePair } from "@yume-chan/stream-extra";
2
+ import type { ValueOrPromise } from "@yume-chan/struct";
3
3
 
4
- import type { AdbPacketData, AdbPacketInit } from './packet.js';
4
+ import type { AdbPacketData, AdbPacketInit } from "./packet.js";
5
5
 
6
6
  export interface AdbBackend {
7
7
  readonly serial: string;
8
8
 
9
9
  readonly name: string | undefined;
10
10
 
11
- connect(): ValueOrPromise<ReadableWritablePair<AdbPacketData, AdbPacketInit>>;
11
+ connect(): ValueOrPromise<
12
+ ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>
13
+ >;
12
14
  }
@@ -1,6 +1,6 @@
1
- import { AutoDisposable } from '@yume-chan/event';
1
+ import { AutoDisposable } from "@yume-chan/event";
2
2
 
3
- import type { Adb } from '../adb.js';
3
+ import type { Adb } from "../adb.js";
4
4
 
5
5
  export class AdbCommandBase extends AutoDisposable {
6
6
  protected adb: Adb;
@@ -1,48 +1,44 @@
1
- import { BufferedReadableStream } from '@yume-chan/stream-extra';
2
- import Struct from '@yume-chan/struct';
1
+ import { BufferedReadableStream } from "@yume-chan/stream-extra";
2
+ import Struct from "@yume-chan/struct";
3
3
 
4
- import type { Adb } from '../adb.js';
4
+ import type { Adb } from "../adb.js";
5
5
 
6
- const Version =
7
- new Struct({ littleEndian: true })
8
- .uint32('version');
6
+ const Version = new Struct({ littleEndian: true }).uint32("version");
9
7
 
10
- export const AdbFrameBufferV1 =
11
- new Struct({ littleEndian: true })
12
- .uint32('bpp')
13
- .uint32('size')
14
- .uint32('width')
15
- .uint32('height')
16
- .uint32('red_offset')
17
- .uint32('red_length')
18
- .uint32('blue_offset')
19
- .uint32('blue_length')
20
- .uint32('green_offset')
21
- .uint32('green_length')
22
- .uint32('alpha_offset')
23
- .uint32('alpha_length')
24
- .uint8Array('data', { lengthField: 'size' });
8
+ export const AdbFrameBufferV1 = new Struct({ littleEndian: true })
9
+ .uint32("bpp")
10
+ .uint32("size")
11
+ .uint32("width")
12
+ .uint32("height")
13
+ .uint32("red_offset")
14
+ .uint32("red_length")
15
+ .uint32("blue_offset")
16
+ .uint32("blue_length")
17
+ .uint32("green_offset")
18
+ .uint32("green_length")
19
+ .uint32("alpha_offset")
20
+ .uint32("alpha_length")
21
+ .uint8Array("data", { lengthField: "size" });
25
22
 
26
- export type AdbFrameBufferV1 = typeof AdbFrameBufferV1['TDeserializeResult'];
23
+ export type AdbFrameBufferV1 = (typeof AdbFrameBufferV1)["TDeserializeResult"];
27
24
 
28
- export const AdbFrameBufferV2 =
29
- new Struct({ littleEndian: true })
30
- .uint32('bpp')
31
- .uint32('colorSpace')
32
- .uint32('size')
33
- .uint32('width')
34
- .uint32('height')
35
- .uint32('red_offset')
36
- .uint32('red_length')
37
- .uint32('blue_offset')
38
- .uint32('blue_length')
39
- .uint32('green_offset')
40
- .uint32('green_length')
41
- .uint32('alpha_offset')
42
- .uint32('alpha_length')
43
- .uint8Array('data', { lengthField: 'size' });
25
+ export const AdbFrameBufferV2 = new Struct({ littleEndian: true })
26
+ .uint32("bpp")
27
+ .uint32("colorSpace")
28
+ .uint32("size")
29
+ .uint32("width")
30
+ .uint32("height")
31
+ .uint32("red_offset")
32
+ .uint32("red_length")
33
+ .uint32("blue_offset")
34
+ .uint32("blue_length")
35
+ .uint32("green_offset")
36
+ .uint32("green_length")
37
+ .uint32("alpha_offset")
38
+ .uint32("alpha_length")
39
+ .uint8Array("data", { lengthField: "size" });
44
40
 
45
- export type AdbFrameBufferV2 = typeof AdbFrameBufferV2['TDeserializeResult'];
41
+ export type AdbFrameBufferV2 = (typeof AdbFrameBufferV2)["TDeserializeResult"];
46
42
 
47
43
  /**
48
44
  * ADB uses 8 int32 fields to describe bit depths
@@ -63,7 +59,7 @@ export type AdbFrameBufferV2 = typeof AdbFrameBufferV2['TDeserializeResult'];
63
59
  export type AdbFrameBuffer = AdbFrameBufferV1 | AdbFrameBufferV2;
64
60
 
65
61
  export async function framebuffer(adb: Adb): Promise<AdbFrameBuffer> {
66
- const socket = await adb.createSocket('framebuffer:');
62
+ const socket = await adb.createSocket("framebuffer:");
67
63
  const stream = new BufferedReadableStream(socket.readable);
68
64
  const { version } = await Version.deserialize(stream);
69
65
  switch (version) {
@@ -73,6 +69,6 @@ export async function framebuffer(adb: Adb): Promise<AdbFrameBuffer> {
73
69
  case 2:
74
70
  return AdbFrameBufferV2.deserialize(stream);
75
71
  default:
76
- throw new Error('Unknown FrameBuffer version');
72
+ throw new Error("Unsupported FrameBuffer version");
77
73
  }
78
74
  }