@yume-chan/adb 0.0.18 → 0.0.20

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 (241) hide show
  1. package/CHANGELOG.json +54 -0
  2. package/CHANGELOG.md +25 -1
  3. package/README.md +220 -103
  4. package/esm/adb.d.ts +43 -60
  5. package/esm/adb.d.ts.map +1 -1
  6. package/esm/adb.js +68 -249
  7. package/esm/adb.js.map +1 -1
  8. package/esm/banner.d.ts +17 -0
  9. package/esm/banner.d.ts.map +1 -0
  10. package/esm/banner.js +67 -0
  11. package/esm/banner.js.map +1 -0
  12. package/esm/commands/base.d.ts +6 -6
  13. package/esm/commands/base.d.ts.map +1 -1
  14. package/esm/commands/base.js +8 -8
  15. package/esm/commands/framebuffer.d.ts +53 -53
  16. package/esm/commands/framebuffer.d.ts.map +1 -1
  17. package/esm/commands/framebuffer.js +46 -46
  18. package/esm/commands/framebuffer.js.map +1 -1
  19. package/esm/commands/index.d.ts +7 -8
  20. package/esm/commands/index.d.ts.map +1 -1
  21. package/esm/commands/index.js +7 -8
  22. package/esm/commands/index.js.map +1 -1
  23. package/esm/commands/power.d.ts +22 -22
  24. package/esm/commands/power.js +48 -48
  25. package/esm/commands/reverse.d.ts +40 -28
  26. package/esm/commands/reverse.d.ts.map +1 -1
  27. package/esm/commands/reverse.js +130 -100
  28. package/esm/commands/reverse.js.map +1 -1
  29. package/esm/commands/subprocess/command.d.ts +57 -51
  30. package/esm/commands/subprocess/command.d.ts.map +1 -1
  31. package/esm/commands/subprocess/command.js +86 -80
  32. package/esm/commands/subprocess/command.js.map +1 -1
  33. package/esm/commands/subprocess/index.d.ts +3 -3
  34. package/esm/commands/subprocess/index.js +3 -3
  35. package/esm/commands/subprocess/protocols/index.d.ts +3 -3
  36. package/esm/commands/subprocess/protocols/index.js +3 -3
  37. package/esm/commands/subprocess/protocols/none.d.ts +30 -35
  38. package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
  39. package/esm/commands/subprocess/protocols/none.js +65 -55
  40. package/esm/commands/subprocess/protocols/none.js.map +1 -1
  41. package/esm/commands/subprocess/protocols/shell.d.ts +33 -38
  42. package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
  43. package/esm/commands/subprocess/protocols/shell.js +172 -162
  44. package/esm/commands/subprocess/protocols/shell.js.map +1 -1
  45. package/esm/commands/subprocess/protocols/types.d.ts +48 -49
  46. package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
  47. package/esm/commands/subprocess/protocols/types.js +1 -1
  48. package/esm/commands/subprocess/utils.d.ts +1 -1
  49. package/esm/commands/subprocess/utils.js +18 -18
  50. package/esm/commands/sync/index.d.ts +8 -7
  51. package/esm/commands/sync/index.d.ts.map +1 -1
  52. package/esm/commands/sync/index.js +8 -7
  53. package/esm/commands/sync/index.js.map +1 -1
  54. package/esm/commands/sync/list.d.ts +42 -40
  55. package/esm/commands/sync/list.d.ts.map +1 -1
  56. package/esm/commands/sync/list.js +67 -47
  57. package/esm/commands/sync/list.js.map +1 -1
  58. package/esm/commands/sync/pull.d.ts +13 -11
  59. package/esm/commands/sync/pull.d.ts.map +1 -1
  60. package/esm/commands/sync/pull.js +35 -37
  61. package/esm/commands/sync/pull.js.map +1 -1
  62. package/esm/commands/sync/push.d.ts +57 -7
  63. package/esm/commands/sync/push.d.ts.map +1 -1
  64. package/esm/commands/sync/push.js +89 -22
  65. package/esm/commands/sync/push.js.map +1 -1
  66. package/esm/commands/sync/request.d.ts +26 -23
  67. package/esm/commands/sync/request.d.ts.map +1 -1
  68. package/esm/commands/sync/request.js +40 -42
  69. package/esm/commands/sync/request.js.map +1 -1
  70. package/esm/commands/sync/response.d.ts +19 -19
  71. package/esm/commands/sync/response.d.ts.map +1 -1
  72. package/esm/commands/sync/response.js +54 -54
  73. package/esm/commands/sync/response.js.map +1 -1
  74. package/esm/commands/sync/socket.d.ts +22 -0
  75. package/esm/commands/sync/socket.d.ts.map +1 -0
  76. package/esm/commands/sync/socket.js +69 -0
  77. package/esm/commands/sync/socket.js.map +1 -0
  78. package/esm/commands/sync/stat.d.ts +72 -72
  79. package/esm/commands/sync/stat.d.ts.map +1 -1
  80. package/esm/commands/sync/stat.js +116 -104
  81. package/esm/commands/sync/stat.js.map +1 -1
  82. package/esm/commands/sync/sync.d.ts +65 -60
  83. package/esm/commands/sync/sync.d.ts.map +1 -1
  84. package/esm/commands/sync/sync.js +123 -149
  85. package/esm/commands/sync/sync.js.map +1 -1
  86. package/esm/commands/tcpip.d.ts +5 -5
  87. package/esm/commands/tcpip.d.ts.map +1 -1
  88. package/esm/commands/tcpip.js +20 -18
  89. package/esm/commands/tcpip.js.map +1 -1
  90. package/esm/{auth.d.ts → daemon/auth.d.ts} +50 -51
  91. package/esm/daemon/auth.d.ts.map +1 -0
  92. package/esm/{auth.js → daemon/auth.js} +95 -96
  93. package/esm/daemon/auth.js.map +1 -0
  94. package/esm/daemon/connection.d.ts +11 -0
  95. package/esm/daemon/connection.d.ts.map +1 -0
  96. package/esm/daemon/connection.js +2 -0
  97. package/esm/daemon/connection.js.map +1 -0
  98. package/esm/{crypto.d.ts → daemon/crypto.d.ts} +36 -36
  99. package/esm/daemon/crypto.d.ts.map +1 -0
  100. package/esm/{crypto.js → daemon/crypto.js} +244 -248
  101. package/esm/daemon/crypto.js.map +1 -0
  102. package/esm/daemon/device.d.ts +9 -0
  103. package/esm/daemon/device.d.ts.map +1 -0
  104. package/esm/daemon/device.js +2 -0
  105. package/esm/daemon/device.js.map +1 -0
  106. package/esm/daemon/dispatcher.d.ts +42 -0
  107. package/esm/daemon/dispatcher.d.ts.map +1 -0
  108. package/esm/{socket → daemon}/dispatcher.js +225 -234
  109. package/esm/daemon/dispatcher.js.map +1 -0
  110. package/esm/daemon/index.d.ts +8 -0
  111. package/esm/daemon/index.d.ts.map +1 -0
  112. package/esm/daemon/index.js +8 -0
  113. package/esm/daemon/index.js.map +1 -0
  114. package/esm/{packet.d.ts → daemon/packet.d.ts} +45 -46
  115. package/esm/daemon/packet.d.ts.map +1 -0
  116. package/esm/{packet.js → daemon/packet.js} +43 -48
  117. package/esm/daemon/packet.js.map +1 -0
  118. package/esm/daemon/socket.d.ts +58 -0
  119. package/esm/daemon/socket.d.ts.map +1 -0
  120. package/esm/{socket → daemon}/socket.js +121 -118
  121. package/esm/daemon/socket.js.map +1 -0
  122. package/esm/daemon/transport.d.ts +45 -0
  123. package/esm/daemon/transport.d.ts.map +1 -0
  124. package/esm/daemon/transport.js +184 -0
  125. package/esm/daemon/transport.js.map +1 -0
  126. package/esm/features.d.ts +10 -7
  127. package/esm/features.d.ts.map +1 -1
  128. package/esm/features.js +13 -10
  129. package/esm/features.js.map +1 -1
  130. package/esm/index.d.ts +7 -9
  131. package/esm/index.d.ts.map +1 -1
  132. package/esm/index.js +7 -9
  133. package/esm/index.js.map +1 -1
  134. package/esm/server/client.d.ts +78 -0
  135. package/esm/server/client.d.ts.map +1 -0
  136. package/esm/server/client.js +329 -0
  137. package/esm/server/client.js.map +1 -0
  138. package/esm/server/index.d.ts +3 -0
  139. package/esm/server/index.d.ts.map +1 -0
  140. package/esm/server/index.js +3 -0
  141. package/esm/server/index.js.map +1 -0
  142. package/esm/server/transport.d.ts +19 -0
  143. package/esm/server/transport.d.ts.map +1 -0
  144. package/esm/server/transport.js +44 -0
  145. package/esm/server/transport.js.map +1 -0
  146. package/esm/utils/auto-reset-event.d.ts +8 -9
  147. package/esm/utils/auto-reset-event.d.ts.map +1 -1
  148. package/esm/utils/auto-reset-event.js +33 -33
  149. package/esm/utils/auto-reset-event.js.map +1 -1
  150. package/esm/utils/base64.d.ts +27 -27
  151. package/esm/utils/base64.js +246 -246
  152. package/esm/utils/base64.js.map +1 -1
  153. package/esm/utils/conditional-variable.d.ts +8 -0
  154. package/esm/utils/conditional-variable.d.ts.map +1 -0
  155. package/esm/utils/conditional-variable.js +34 -0
  156. package/esm/utils/conditional-variable.js.map +1 -0
  157. package/esm/utils/hex.d.ts +3 -0
  158. package/esm/utils/hex.d.ts.map +1 -0
  159. package/esm/utils/hex.js +55 -0
  160. package/esm/utils/hex.js.map +1 -0
  161. package/esm/utils/index.d.ts +6 -3
  162. package/esm/utils/index.d.ts.map +1 -1
  163. package/esm/utils/index.js +6 -3
  164. package/esm/utils/index.js.map +1 -1
  165. package/esm/utils/no-op.d.ts +7 -0
  166. package/esm/utils/no-op.d.ts.map +1 -0
  167. package/esm/utils/no-op.js +12 -0
  168. package/esm/utils/no-op.js.map +1 -0
  169. package/package.json +14 -12
  170. package/src/adb.ts +47 -248
  171. package/src/banner.ts +82 -0
  172. package/src/commands/base.ts +1 -1
  173. package/src/commands/framebuffer.ts +4 -4
  174. package/src/commands/index.ts +7 -8
  175. package/src/commands/power.ts +2 -2
  176. package/src/commands/reverse.ts +90 -70
  177. package/src/commands/subprocess/command.ts +12 -4
  178. package/src/commands/subprocess/index.ts +3 -3
  179. package/src/commands/subprocess/protocols/index.ts +3 -3
  180. package/src/commands/subprocess/protocols/none.ts +36 -23
  181. package/src/commands/subprocess/protocols/shell.ts +94 -74
  182. package/src/commands/subprocess/protocols/types.ts +7 -7
  183. package/src/commands/subprocess/utils.ts +1 -1
  184. package/src/commands/sync/index.ts +8 -7
  185. package/src/commands/sync/list.ts +44 -25
  186. package/src/commands/sync/pull.ts +40 -45
  187. package/src/commands/sync/push.ts +158 -39
  188. package/src/commands/sync/request.ts +21 -16
  189. package/src/commands/sync/response.ts +10 -9
  190. package/src/commands/sync/socket.ts +99 -0
  191. package/src/commands/sync/stat.ts +47 -42
  192. package/src/commands/sync/sync.ts +73 -116
  193. package/src/commands/tcpip.ts +9 -7
  194. package/src/{auth.ts → daemon/auth.ts} +24 -23
  195. package/src/{crypto.ts → daemon/crypto.ts} +25 -33
  196. package/src/daemon/device.ts +14 -0
  197. package/src/{socket → daemon}/dispatcher.ts +95 -117
  198. package/src/daemon/index.ts +7 -0
  199. package/src/daemon/packet.ts +75 -0
  200. package/src/{socket → daemon}/socket.ts +71 -56
  201. package/src/daemon/transport.ts +269 -0
  202. package/src/features.ts +9 -6
  203. package/src/index.ts +3 -5
  204. package/src/server/client.ts +476 -0
  205. package/src/server/index.ts +2 -0
  206. package/src/server/transport.ts +77 -0
  207. package/src/utils/auto-reset-event.ts +14 -15
  208. package/src/utils/conditional-variable.ts +45 -0
  209. package/src/utils/hex.ts +58 -0
  210. package/src/utils/index.ts +6 -3
  211. package/src/utils/no-op.ts +12 -0
  212. package/tsconfig.build.json +12 -1
  213. package/tsconfig.build.tsbuildinfo +1 -1
  214. package/esm/auth.d.ts.map +0 -1
  215. package/esm/auth.js.map +0 -1
  216. package/esm/backend.d.ts +0 -9
  217. package/esm/backend.d.ts.map +0 -1
  218. package/esm/backend.js +0 -2
  219. package/esm/backend.js.map +0 -1
  220. package/esm/commands/install.d.ts +0 -4
  221. package/esm/commands/install.d.ts.map +0 -1
  222. package/esm/commands/install.js +0 -29
  223. package/esm/commands/install.js.map +0 -1
  224. package/esm/crypto.d.ts.map +0 -1
  225. package/esm/crypto.js.map +0 -1
  226. package/esm/packet.d.ts.map +0 -1
  227. package/esm/packet.js.map +0 -1
  228. package/esm/socket/dispatcher.d.ts +0 -60
  229. package/esm/socket/dispatcher.d.ts.map +0 -1
  230. package/esm/socket/dispatcher.js.map +0 -1
  231. package/esm/socket/index.d.ts +0 -3
  232. package/esm/socket/index.d.ts.map +0 -1
  233. package/esm/socket/index.js +0 -3
  234. package/esm/socket/index.js.map +0 -1
  235. package/esm/socket/socket.d.ts +0 -60
  236. package/esm/socket/socket.d.ts.map +0 -1
  237. package/esm/socket/socket.js.map +0 -1
  238. package/src/backend.ts +0 -14
  239. package/src/commands/install.ts +0 -40
  240. package/src/packet.ts +0 -90
  241. package/src/socket/index.ts +0 -2
@@ -1,22 +1,16 @@
1
1
  import { AutoDisposable } from "@yume-chan/event";
2
- import {
3
- BufferedReadableStream,
4
- WrapReadableStream,
5
- WrapWritableStream,
6
- type ReadableStream,
7
- type WritableStream,
8
- type WritableStreamDefaultWriter,
9
- } from "@yume-chan/stream-extra";
10
-
11
- import { type Adb } from "../../adb.js";
12
- import { AdbFeatures } from "../../features.js";
13
- import { type AdbSocket } from "../../socket/index.js";
14
- import { AutoResetEvent } from "../../utils/index.js";
2
+ import type { Consumable, ReadableStream } from "@yume-chan/stream-extra";
3
+
4
+ import type { Adb, AdbSocket } from "../../adb.js";
5
+ import { AdbFeature } from "../../features.js";
15
6
  import { escapeArg } from "../subprocess/index.js";
16
7
 
17
- import { adbSyncOpenDir, type AdbSyncEntry } from "./list.js";
8
+ import type { AdbSyncEntry } from "./list.js";
9
+ import { adbSyncOpenDir } from "./list.js";
18
10
  import { adbSyncPull } from "./pull.js";
19
11
  import { adbSyncPush } from "./push.js";
12
+ import { AdbSyncSocket } from "./socket.js";
13
+ import type { AdbSyncStat, LinuxFileType } from "./stat.js";
20
14
  import { adbSyncLstat, adbSyncStat } from "./stat.js";
21
15
 
22
16
  /**
@@ -35,57 +29,65 @@ export function dirname(path: string): string {
35
29
  return path.substring(0, end);
36
30
  }
37
31
 
32
+ export interface AdbSyncWriteOptions {
33
+ filename: string;
34
+ file: ReadableStream<Consumable<Uint8Array>>;
35
+ type?: LinuxFileType;
36
+ permission?: number;
37
+ mtime?: number;
38
+ dryRun?: boolean;
39
+ }
40
+
38
41
  export class AdbSync extends AutoDisposable {
39
- protected adb: Adb;
42
+ protected _adb: Adb;
43
+ protected _socket: AdbSyncSocket;
40
44
 
41
- protected stream: BufferedReadableStream;
42
- // Getting another writer on a locked WritableStream will throw.
43
- // We don't want this behavior on higher-level APIs.
44
- // So we acquire the writer early and use a blocking lock to guard it.
45
- protected writer: WritableStreamDefaultWriter<Uint8Array>;
46
- protected sendLock = this.addDisposable(new AutoResetEvent());
45
+ readonly #supportsStat: boolean;
46
+ readonly #supportsListV2: boolean;
47
+ readonly #fixedPushMkdir: boolean;
48
+ readonly #supportsSendReceiveV2: boolean;
49
+ readonly #needPushMkdirWorkaround: boolean;
47
50
 
48
51
  public get supportsStat(): boolean {
49
- return this.adb.features.includes(AdbFeatures.StatV2);
52
+ return this.#supportsStat;
50
53
  }
51
54
 
52
- public get supportsList2(): boolean {
53
- return this.adb.features.includes(AdbFeatures.ListV2);
55
+ public get supportsListV2(): boolean {
56
+ return this.#supportsListV2;
54
57
  }
55
58
 
56
59
  public get fixedPushMkdir(): boolean {
57
- return this.adb.features.includes(AdbFeatures.FixedPushMkdir);
60
+ return this.#fixedPushMkdir;
61
+ }
62
+
63
+ public get supportsSendReceiveV2(): boolean {
64
+ return this.#supportsSendReceiveV2;
58
65
  }
59
66
 
60
67
  public get needPushMkdirWorkaround(): boolean {
61
- // https://android.googlesource.com/platform/packages/modules/adb/+/91768a57b7138166e0a3d11f79cd55909dda7014/client/file_sync_client.cpp#1361
62
- return (
63
- this.adb.features.includes(AdbFeatures.ShellV2) &&
64
- !this.fixedPushMkdir
65
- );
68
+ return this.#needPushMkdirWorkaround;
66
69
  }
67
70
 
68
71
  public constructor(adb: Adb, socket: AdbSocket) {
69
72
  super();
70
73
 
71
- this.adb = adb;
72
- this.stream = new BufferedReadableStream(socket.readable);
73
- this.writer = socket.writable.getWriter();
74
- }
74
+ this._adb = adb;
75
+ this._socket = new AdbSyncSocket(socket, adb.maxPayloadSize);
75
76
 
76
- public async lstat(path: string) {
77
- await this.sendLock.wait();
77
+ this.#supportsStat = adb.supportsFeature(AdbFeature.StatV2);
78
+ this.#supportsListV2 = adb.supportsFeature(AdbFeature.ListV2);
79
+ this.#fixedPushMkdir = adb.supportsFeature(AdbFeature.FixedPushMkdir);
80
+ this.#supportsSendReceiveV2 = adb.supportsFeature(
81
+ AdbFeature.SendReceiveV2
82
+ );
83
+ // https://android.googlesource.com/platform/packages/modules/adb/+/91768a57b7138166e0a3d11f79cd55909dda7014/client/file_sync_client.cpp#1361
84
+ this.#needPushMkdirWorkaround =
85
+ this._adb.supportsFeature(AdbFeature.ShellV2) &&
86
+ !this.fixedPushMkdir;
87
+ }
78
88
 
79
- try {
80
- return adbSyncLstat(
81
- this.stream,
82
- this.writer,
83
- path,
84
- this.supportsStat
85
- );
86
- } finally {
87
- this.sendLock.notify();
88
- }
89
+ public async lstat(path: string): Promise<AdbSyncStat> {
90
+ return await adbSyncLstat(this._socket, path, this.supportsStat);
89
91
  }
90
92
 
91
93
  public async stat(path: string) {
@@ -93,13 +95,7 @@ export class AdbSync extends AutoDisposable {
93
95
  throw new Error("Not supported");
94
96
  }
95
97
 
96
- await this.sendLock.wait();
97
-
98
- try {
99
- return adbSyncStat(this.stream, this.writer, path);
100
- } finally {
101
- this.sendLock.notify();
102
- }
98
+ return await adbSyncStat(this._socket, path);
103
99
  }
104
100
 
105
101
  public async isDirectory(path: string): Promise<boolean> {
@@ -111,21 +107,8 @@ export class AdbSync extends AutoDisposable {
111
107
  }
112
108
  }
113
109
 
114
- public async *opendir(
115
- path: string
116
- ): AsyncGenerator<AdbSyncEntry, void, void> {
117
- await this.sendLock.wait();
118
-
119
- try {
120
- yield* adbSyncOpenDir(
121
- this.stream,
122
- this.writer,
123
- path,
124
- this.supportsList2
125
- );
126
- } finally {
127
- this.sendLock.notify();
128
- }
110
+ public opendir(path: string): AsyncGenerator<AdbSyncEntry, void, void> {
111
+ return adbSyncOpenDir(this._socket, path, this.supportsListV2);
129
112
  }
130
113
 
131
114
  public async readdir(path: string) {
@@ -137,67 +120,41 @@ export class AdbSync extends AutoDisposable {
137
120
  }
138
121
 
139
122
  /**
140
- * Read the content of a file on device.
123
+ * Reads the content of a file on device.
141
124
  *
142
125
  * @param filename The full path of the file on device to read.
143
- * @returns A `ReadableStream` that reads from the file.
126
+ * @returns A `ReadableStream` that contains the file content.
144
127
  */
145
128
  public read(filename: string): ReadableStream<Uint8Array> {
146
- return new WrapReadableStream({
147
- start: async () => {
148
- await this.sendLock.wait();
149
- return adbSyncPull(this.stream, this.writer, filename);
150
- },
151
- close: () => {
152
- this.sendLock.notify();
153
- },
154
- });
129
+ return adbSyncPull(this._socket, filename);
155
130
  }
156
131
 
157
132
  /**
158
- * Write (or overwrite) a file on device.
133
+ * Writes a file on device. If the file name already exists, it will be overwritten.
159
134
  *
160
- * @param filename The full path of the file on device to write.
161
- * @param mode The unix permissions of the file.
162
- * @param mtime The modified time of the file.
163
- * @returns A `WritableStream` that writes to the file.
135
+ * @param options The content and options of the file to write.
164
136
  */
165
- public write(
166
- filename: string,
167
- mode?: number,
168
- mtime?: number
169
- ): WritableStream<Uint8Array> {
170
- return new WrapWritableStream({
171
- start: async () => {
172
- await this.sendLock.wait();
173
-
174
- if (this.needPushMkdirWorkaround) {
175
- // It may fail if the path is already existed.
176
- // Ignore the result.
177
- // TODO: sync: test push mkdir workaround (need an Android 8 device)
178
- await this.adb.subprocess.spawnAndWait([
179
- "mkdir",
180
- "-p",
181
- escapeArg(dirname(filename)),
182
- ]);
183
- }
184
-
185
- return adbSyncPush(
186
- this.stream,
187
- this.writer,
188
- filename,
189
- mode,
190
- mtime
191
- );
192
- },
193
- close: () => {
194
- this.sendLock.notify();
195
- },
137
+ public async write(options: AdbSyncWriteOptions): Promise<void> {
138
+ if (this.needPushMkdirWorkaround) {
139
+ // It may fail if the path is already existed.
140
+ // Ignore the result.
141
+ // TODO: sync: test push mkdir workaround (need an Android 8 device)
142
+ await this._adb.subprocess.spawnAndWait([
143
+ "mkdir",
144
+ "-p",
145
+ escapeArg(dirname(options.filename)),
146
+ ]);
147
+ }
148
+
149
+ await adbSyncPush({
150
+ v2: this.supportsSendReceiveV2,
151
+ socket: this._socket,
152
+ ...options,
196
153
  });
197
154
  }
198
155
 
199
156
  public override async dispose() {
200
157
  super.dispose();
201
- await this.writer.close();
158
+ await this._socket.close();
202
159
  }
203
160
  }
@@ -1,21 +1,23 @@
1
- import { AdbCommandBase } from './base.js';
1
+ import { AdbCommandBase } from "./base.js";
2
2
 
3
3
  export class AdbTcpIpCommand extends AdbCommandBase {
4
- public async setPort(port: number): Promise<void> {
4
+ public async setPort(port: number): Promise<string> {
5
5
  if (port <= 0) {
6
6
  throw new Error(`Invalid port ${port}`);
7
7
  }
8
8
 
9
9
  const output = await this.adb.createSocketAndWait(`tcpip:${port}`);
10
10
  if (output !== `restarting in TCP mode port: ${port}\n`) {
11
- throw new Error('Invalid response');
11
+ throw new Error(output);
12
12
  }
13
+ return output;
13
14
  }
14
15
 
15
- public async disable(): Promise<void> {
16
- const output = await this.adb.createSocketAndWait('usb:');
17
- if (output !== 'restarting in USB mode\n') {
18
- throw new Error('Invalid response');
16
+ public async disable(): Promise<string> {
17
+ const output = await this.adb.createSocketAndWait("usb:");
18
+ if (output !== "restarting in USB mode\n") {
19
+ throw new Error(output);
19
20
  }
21
+ return output;
20
22
  }
21
23
  }
@@ -1,14 +1,16 @@
1
1
  import { PromiseResolver } from "@yume-chan/async";
2
- import { type Disposable } from "@yume-chan/event";
3
- import { type ValueOrPromise } from "@yume-chan/struct";
2
+ import type { Disposable } from "@yume-chan/event";
3
+ import type { ValueOrPromise } from "@yume-chan/struct";
4
+
5
+ import { calculateBase64EncodedLength, encodeBase64 } from "../utils/index.js";
4
6
 
5
7
  import {
6
- calculatePublicKey,
7
- calculatePublicKeyLength,
8
- sign,
8
+ adbGeneratePublicKey,
9
+ adbGetPublicKeySize,
10
+ rsaSign,
9
11
  } from "./crypto.js";
10
- import { AdbCommand, type AdbPacketData } from "./packet.js";
11
- import { calculateBase64EncodedLength, encodeBase64 } from "./utils/index.js";
12
+ import type { AdbPacketData } from "./packet.js";
13
+ import { AdbCommand } from "./packet.js";
12
14
 
13
15
  export type AdbKeyIterable = Iterable<Uint8Array> | AsyncIterable<Uint8Array>;
14
16
 
@@ -63,7 +65,7 @@ export const AdbSignatureAuthenticator: AdbAuthenticator = async function* (
63
65
  return;
64
66
  }
65
67
 
66
- const signature = sign(key, packet.payload);
68
+ const signature = rsaSign(key, packet.payload);
67
69
  yield {
68
70
  command: AdbCommand.Auth,
69
71
  arg0: AdbAuthType.Signature,
@@ -93,15 +95,15 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
93
95
  privateKey = await credentialStore.generateKey();
94
96
  }
95
97
 
96
- const publicKeyLength = calculatePublicKeyLength();
98
+ const publicKeyLength = adbGetPublicKeySize();
97
99
  const [publicKeyBase64Length] =
98
100
  calculateBase64EncodedLength(publicKeyLength);
99
101
 
100
- // The public key is null terminated,
101
- // So we allocate the buffer with one extra byte.
102
- const publicKeyBuffer = new Uint8Array(publicKeyBase64Length + 1);
102
+ const publicKeyBuffer = new Uint8Array(
103
+ publicKeyBase64Length + 1 // Null character
104
+ );
103
105
 
104
- calculatePublicKey(privateKey, publicKeyBuffer);
106
+ adbGeneratePublicKey(privateKey, publicKeyBuffer);
105
107
  encodeBase64(publicKeyBuffer.subarray(0, publicKeyLength), publicKeyBuffer);
106
108
 
107
109
  yield {
@@ -122,9 +124,8 @@ export class AdbAuthenticationProcessor implements Disposable {
122
124
 
123
125
  private readonly credentialStore: AdbCredentialStore;
124
126
 
125
- private pendingRequest = new PromiseResolver<AdbPacketData>();
126
-
127
- private iterator: AsyncIterator<AdbPacketData, void, void> | undefined;
127
+ #pendingRequest = new PromiseResolver<AdbPacketData>();
128
+ #iterator: AsyncIterator<AdbPacketData, void, void> | undefined;
128
129
 
129
130
  public constructor(
130
131
  authenticators: readonly AdbAuthenticator[],
@@ -135,7 +136,7 @@ export class AdbAuthenticationProcessor implements Disposable {
135
136
  }
136
137
 
137
138
  private getNextRequest = (): Promise<AdbPacketData> => {
138
- return this.pendingRequest.promise;
139
+ return this.#pendingRequest.promise;
139
140
  };
140
141
 
141
142
  private async *invokeAuthenticator(): AsyncGenerator<
@@ -150,7 +151,7 @@ export class AdbAuthenticationProcessor implements Disposable {
150
151
  )) {
151
152
  // If the authenticator yielded a response
152
153
  // Prepare `nextRequest` for next authentication request
153
- this.pendingRequest = new PromiseResolver();
154
+ this.#pendingRequest = new PromiseResolver();
154
155
 
155
156
  // Yield the response to outer layer
156
157
  yield packet;
@@ -162,13 +163,13 @@ export class AdbAuthenticationProcessor implements Disposable {
162
163
  }
163
164
 
164
165
  public async process(packet: AdbPacketData): Promise<AdbPacketData> {
165
- if (!this.iterator) {
166
- this.iterator = this.invokeAuthenticator();
166
+ if (!this.#iterator) {
167
+ this.#iterator = this.invokeAuthenticator();
167
168
  }
168
169
 
169
- this.pendingRequest.resolve(packet);
170
+ this.#pendingRequest.resolve(packet);
170
171
 
171
- const result = await this.iterator.next();
172
+ const result = await this.#iterator.next();
172
173
  if (result.done) {
173
174
  throw new Error("No authenticator can handle the request");
174
175
  }
@@ -177,6 +178,6 @@ export class AdbAuthenticationProcessor implements Disposable {
177
178
  }
178
179
 
179
180
  public dispose() {
180
- void this.iterator?.return?.();
181
+ void this.#iterator?.return?.();
181
182
  }
182
183
  }
@@ -3,11 +3,6 @@ import {
3
3
  setBigUint64,
4
4
  } from "@yume-chan/dataview-bigint-polyfill/esm/fallback.js";
5
5
 
6
- const BigInt0 = BigInt(0);
7
- const BigInt1 = BigInt(1);
8
- const BigInt2 = BigInt(2);
9
- const BigInt64 = BigInt(64);
10
-
11
6
  /**
12
7
  * Gets the `BigInt` value at the specified byte offset and length from the start of the view. There is
13
8
  * no alignment constraint; multi-byte values may be fetched from any offset.
@@ -20,13 +15,13 @@ export function getBigUint(
20
15
  byteOffset: number,
21
16
  length: number
22
17
  ): bigint {
23
- let result = BigInt0;
18
+ let result = 0n;
24
19
 
25
20
  // Currently `length` must be a multiplication of 8
26
21
  // Support for arbitrary length can be easily added
27
22
 
28
23
  for (let i = byteOffset; i < byteOffset + length; i += 8) {
29
- result <<= BigInt64;
24
+ result <<= 64n;
30
25
  const value = getBigUint64(dataView, i, false);
31
26
  result += value;
32
27
  }
@@ -50,18 +45,18 @@ export function setBigUint(
50
45
  const start = byteOffset;
51
46
 
52
47
  if (littleEndian) {
53
- while (value > BigInt0) {
48
+ while (value > 0n) {
54
49
  setBigUint64(dataView, byteOffset, value, true);
55
50
  byteOffset += 8;
56
- value >>= BigInt64;
51
+ value >>= 64n;
57
52
  }
58
53
  } else {
59
54
  // Because we don't know how long (in bits) the `value` is,
60
55
  // Convert it to an array of `uint64` first.
61
56
  const uint64Array: bigint[] = [];
62
- while (value > BigInt0) {
57
+ while (value > 0n) {
63
58
  uint64Array.push(BigInt.asUintN(64, value));
64
- value >>= BigInt64;
59
+ value >>= 64n;
65
60
  }
66
61
 
67
62
  for (let i = uint64Array.length - 1; i >= 0; i -= 1) {
@@ -99,7 +94,7 @@ const RsaPrivateKeyNLength = 2048 / 8;
99
94
  const RsaPrivateKeyDOffset = 303;
100
95
  const RsaPrivateKeyDLength = 2048 / 8;
101
96
 
102
- export function parsePrivateKey(key: Uint8Array): [n: bigint, d: bigint] {
97
+ export function rsaParsePrivateKey(key: Uint8Array): [n: bigint, d: bigint] {
103
98
  const view = new DataView(key.buffer, key.byteOffset, key.byteLength);
104
99
  const n = getBigUint(view, RsaPrivateKeyNOffset, RsaPrivateKeyNLength);
105
100
  const d = getBigUint(view, RsaPrivateKeyDOffset, RsaPrivateKeyDLength);
@@ -133,16 +128,16 @@ export function modInverse(a: number, m: number) {
133
128
  return ((y % m) + m) % m;
134
129
  }
135
130
 
136
- export function calculatePublicKeyLength() {
131
+ export function adbGetPublicKeySize() {
137
132
  return 4 + 4 + 2048 / 8 + 2048 / 8 + 4;
138
133
  }
139
134
 
140
- export function calculatePublicKey(privateKey: Uint8Array): Uint8Array;
141
- export function calculatePublicKey(
135
+ export function adbGeneratePublicKey(privateKey: Uint8Array): Uint8Array;
136
+ export function adbGeneratePublicKey(
142
137
  privateKey: Uint8Array,
143
138
  output: Uint8Array
144
139
  ): number;
145
- export function calculatePublicKey(
140
+ export function adbGeneratePublicKey(
146
141
  privateKey: Uint8Array,
147
142
  output?: Uint8Array
148
143
  ): Uint8Array | number {
@@ -164,10 +159,10 @@ export function calculatePublicKey(
164
159
  // See https://android.googlesource.com/platform/system/core.git/+/91784040db2b9273687f88d8b95f729d4a61ecc2/libcrypto_utils/android_pubkey.cpp#38
165
160
 
166
161
  // extract `n` from private key
167
- const [n] = parsePrivateKey(privateKey);
162
+ const [n] = rsaParsePrivateKey(privateKey);
168
163
 
169
164
  let outputType: "Uint8Array" | "number";
170
- const outputLength = calculatePublicKeyLength();
165
+ const outputLength = adbGetPublicKeySize();
171
166
  if (!output) {
172
167
  output = new Uint8Array(outputLength);
173
168
  outputType = "Uint8Array";
@@ -191,12 +186,9 @@ export function calculatePublicKey(
191
186
  outputOffset += 4;
192
187
 
193
188
  // Calculate `n0inv`
194
- // Don't know why need to multiple -1
189
+ // Don't know why need to multiply by -1
195
190
  // Didn't exist in Android codebase
196
- const n0inv = modInverse(
197
- Number(BigInt.asUintN(32, n) * BigInt(-1)),
198
- 2 ** 32
199
- );
191
+ const n0inv = modInverse(-Number(BigInt.asUintN(32, n)), 2 ** 32);
200
192
  outputView.setUint32(outputOffset, n0inv, true);
201
193
  outputOffset += 4;
202
194
 
@@ -205,7 +197,7 @@ export function calculatePublicKey(
205
197
  outputOffset += 256;
206
198
 
207
199
  // Calculate rr = (2^(rsa_size)) ^ 2 mod n
208
- const rr = BigInt(2) ** BigInt(4096) % n;
200
+ const rr = 2n ** 4096n % n;
209
201
  outputOffset += setBigUint(outputView, outputOffset, rr, true);
210
202
 
211
203
  // exponent
@@ -231,20 +223,20 @@ export function powMod(
231
223
  exponent: bigint,
232
224
  modulus: bigint
233
225
  ): bigint {
234
- if (modulus === BigInt1) {
235
- return BigInt0;
226
+ if (modulus === 1n) {
227
+ return 0n;
236
228
  }
237
229
 
238
- let r = BigInt1;
230
+ let r = 1n;
239
231
  base = base % modulus;
240
232
 
241
- while (exponent > BigInt0) {
242
- if (BigInt.asUintN(1, exponent) === BigInt1) {
233
+ while (exponent > 0n) {
234
+ if (BigInt.asUintN(1, exponent) === 1n) {
243
235
  r = (r * base) % modulus;
244
236
  }
245
237
 
246
- exponent >>= BigInt1;
247
- base = base ** BigInt2 % modulus;
238
+ base = (base * base) % modulus;
239
+ exponent >>= 1n;
248
240
  }
249
241
 
250
242
  return r;
@@ -283,8 +275,8 @@ export const SHA1_DIGEST_INFO = new Uint8Array([
283
275
  // encrypt the given data with its private key)
284
276
  // However SubtileCrypto.encrypt() doesn't accept 'RSASSA-PKCS1-v1_5' algorithm
285
277
  // So we need to implement the encryption by ourself
286
- export function sign(privateKey: Uint8Array, data: Uint8Array): Uint8Array {
287
- const [n, d] = parsePrivateKey(privateKey);
278
+ export function rsaSign(privateKey: Uint8Array, data: Uint8Array): Uint8Array {
279
+ const [n, d] = rsaParsePrivateKey(privateKey);
288
280
 
289
281
  // PKCS#1 padding
290
282
  const padded = new Uint8Array(256);
@@ -0,0 +1,14 @@
1
+ import type { Consumable, ReadableWritablePair } from "@yume-chan/stream-extra";
2
+ import type { ValueOrPromise } from "@yume-chan/struct";
3
+
4
+ import type { AdbPacketData, AdbPacketInit } from "./packet.js";
5
+
6
+ export interface AdbDaemonDevice {
7
+ readonly serial: string;
8
+
9
+ readonly name: string | undefined;
10
+
11
+ connect(): ValueOrPromise<
12
+ ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>
13
+ >;
14
+ }