@yume-chan/adb 0.0.21 → 0.0.23
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.
- package/CHANGELOG.json +39 -0
- package/CHANGELOG.md +20 -1
- package/README.md +46 -366
- package/esm/adb.d.ts +9 -5
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +9 -2
- package/esm/adb.js.map +1 -1
- package/esm/banner.d.ts.map +1 -1
- package/esm/banner.js +1 -0
- package/esm/banner.js.map +1 -1
- package/esm/commands/framebuffer.d.ts +1 -1
- package/esm/commands/framebuffer.d.ts.map +1 -1
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/reverse.js +1 -1
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/command.js.map +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts +2 -1
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +11 -14
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/shell.js +21 -71
- package/esm/commands/subprocess/protocols/shell.js.map +1 -1
- package/esm/commands/subprocess/utils.js +1 -1
- package/esm/commands/subprocess/utils.js.map +1 -1
- package/esm/commands/sync/list.d.ts +2 -1
- package/esm/commands/sync/list.d.ts.map +1 -1
- package/esm/commands/sync/list.js +2 -2
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +4 -0
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.js.map +1 -1
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +1 -1
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +1 -1
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/socket.d.ts +1 -0
- package/esm/commands/sync/socket.d.ts.map +1 -1
- package/esm/commands/sync/socket.js +4 -0
- package/esm/commands/sync/socket.js.map +1 -1
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +5 -6
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/commands/tcpip.d.ts +21 -0
- package/esm/commands/tcpip.d.ts.map +1 -1
- package/esm/commands/tcpip.js +18 -0
- package/esm/commands/tcpip.js.map +1 -1
- package/esm/daemon/auth.js.map +1 -1
- package/esm/daemon/crypto.js.map +1 -1
- package/esm/daemon/dispatcher.d.ts +9 -1
- package/esm/daemon/dispatcher.d.ts.map +1 -1
- package/esm/daemon/dispatcher.js +107 -51
- package/esm/daemon/dispatcher.js.map +1 -1
- package/esm/daemon/packet.d.ts +5 -5
- package/esm/daemon/packet.d.ts.map +1 -1
- package/esm/daemon/packet.js +1 -1
- package/esm/daemon/packet.js.map +1 -1
- package/esm/daemon/socket.d.ts +8 -13
- package/esm/daemon/socket.d.ts.map +1 -1
- package/esm/daemon/socket.js +80 -44
- package/esm/daemon/socket.js.map +1 -1
- package/esm/daemon/transport.d.ts +32 -4
- package/esm/daemon/transport.d.ts.map +1 -1
- package/esm/daemon/transport.js +61 -31
- package/esm/daemon/transport.js.map +1 -1
- package/esm/features.d.ts +2 -1
- package/esm/features.d.ts.map +1 -1
- package/esm/features.js +2 -1
- package/esm/features.js.map +1 -1
- package/esm/server/client.d.ts +14 -8
- package/esm/server/client.d.ts.map +1 -1
- package/esm/server/client.js +122 -70
- package/esm/server/client.js.map +1 -1
- package/esm/server/transport.d.ts +3 -0
- package/esm/server/transport.d.ts.map +1 -1
- package/esm/server/transport.js +26 -0
- package/esm/server/transport.js.map +1 -1
- package/esm/utils/auto-reset-event.js.map +1 -1
- package/esm/utils/base64.js.map +1 -1
- package/esm/utils/conditional-variable.js.map +1 -1
- package/esm/utils/hex.js.map +1 -1
- package/package.json +14 -14
- package/src/adb.ts +22 -7
- package/src/banner.ts +1 -0
- package/src/commands/framebuffer.ts +1 -1
- package/src/commands/reverse.ts +2 -2
- package/src/commands/subprocess/protocols/none.ts +15 -19
- package/src/commands/subprocess/protocols/shell.ts +28 -98
- package/src/commands/subprocess/utils.ts +1 -1
- package/src/commands/sync/list.ts +6 -2
- package/src/commands/sync/pull.ts +3 -0
- package/src/commands/sync/response.ts +2 -2
- package/src/commands/sync/socket.ts +5 -0
- package/src/commands/sync/sync.ts +5 -6
- package/src/commands/tcpip.ts +44 -0
- package/src/daemon/dispatcher.ts +156 -65
- package/src/daemon/packet.ts +1 -1
- package/src/daemon/socket.ts +104 -86
- package/src/daemon/transport.ts +104 -38
- package/src/features.ts +2 -1
- package/src/server/client.ts +141 -91
- package/src/server/transport.ts +28 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Consumable, WritableStream } from "@yume-chan/stream-extra";
|
|
2
|
+
import { ReadableStream } from "@yume-chan/stream-extra";
|
|
2
3
|
|
|
3
4
|
import type { Adb, AdbSocket } from "../../../adb.js";
|
|
5
|
+
import { unreachable } from "../../../utils/index.js";
|
|
4
6
|
|
|
5
7
|
import type { AdbSubprocessProtocol } from "./types.js";
|
|
6
8
|
|
|
@@ -33,26 +35,23 @@ export class AdbSubprocessNoneProtocol implements AdbSubprocessProtocol {
|
|
|
33
35
|
|
|
34
36
|
readonly #socket: AdbSocket;
|
|
35
37
|
|
|
36
|
-
readonly #duplex: DuplexStreamFactory<Uint8Array, Uint8Array>;
|
|
37
|
-
|
|
38
38
|
// Legacy shell forwards all data to stdin.
|
|
39
|
-
get stdin() {
|
|
39
|
+
get stdin(): WritableStream<Consumable<Uint8Array>> {
|
|
40
40
|
return this.#socket.writable;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
#stdout: ReadableStream<Uint8Array>;
|
|
44
43
|
/**
|
|
45
44
|
* Legacy shell mixes stdout and stderr.
|
|
46
45
|
*/
|
|
47
|
-
get stdout() {
|
|
48
|
-
return this.#
|
|
46
|
+
get stdout(): ReadableStream<Uint8Array> {
|
|
47
|
+
return this.#socket.readable;
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
#stderr: ReadableStream<Uint8Array>;
|
|
52
51
|
/**
|
|
53
52
|
* `stderr` will always be empty.
|
|
54
53
|
*/
|
|
55
|
-
get stderr() {
|
|
54
|
+
get stderr(): ReadableStream<Uint8Array> {
|
|
56
55
|
return this.#stderr;
|
|
57
56
|
}
|
|
58
57
|
|
|
@@ -64,24 +63,21 @@ export class AdbSubprocessNoneProtocol implements AdbSubprocessProtocol {
|
|
|
64
63
|
constructor(socket: AdbSocket) {
|
|
65
64
|
this.#socket = socket;
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
this.#stderr = new ReadableStream({
|
|
67
|
+
start: (controller) => {
|
|
68
|
+
this.#socket.closed
|
|
69
|
+
.then(() => controller.close())
|
|
70
|
+
.catch(unreachable);
|
|
72
71
|
},
|
|
73
72
|
});
|
|
74
|
-
|
|
75
|
-
this.#stdout = this.#duplex.wrapReadable(this.#socket.readable);
|
|
76
|
-
this.#stderr = this.#duplex.wrapReadable(new ReadableStream());
|
|
77
|
-
this.#exit = this.#duplex.closed.then(() => 0);
|
|
73
|
+
this.#exit = socket.closed.then(() => 0);
|
|
78
74
|
}
|
|
79
75
|
|
|
80
76
|
resize() {
|
|
81
77
|
// Not supported, but don't throw.
|
|
82
78
|
}
|
|
83
79
|
|
|
84
|
-
kill() {
|
|
85
|
-
|
|
80
|
+
async kill() {
|
|
81
|
+
await this.#socket.close();
|
|
86
82
|
}
|
|
87
83
|
}
|
|
@@ -6,12 +6,10 @@ import type {
|
|
|
6
6
|
WritableStreamDefaultWriter,
|
|
7
7
|
} from "@yume-chan/stream-extra";
|
|
8
8
|
import {
|
|
9
|
-
ConsumableTransformStream,
|
|
10
9
|
ConsumableWritableStream,
|
|
11
10
|
PushReadableStream,
|
|
12
11
|
StructDeserializeStream,
|
|
13
12
|
WritableStream,
|
|
14
|
-
pipeFrom,
|
|
15
13
|
} from "@yume-chan/stream-extra";
|
|
16
14
|
import type { StructValueType } from "@yume-chan/struct";
|
|
17
15
|
import Struct, { placeholder } from "@yume-chan/struct";
|
|
@@ -37,68 +35,8 @@ const AdbShellProtocolPacket = new Struct({ littleEndian: true })
|
|
|
37
35
|
.uint32("length")
|
|
38
36
|
.uint8Array("data", { lengthField: "length" });
|
|
39
37
|
|
|
40
|
-
type AdbShellProtocolPacketInit = (typeof AdbShellProtocolPacket)["TInit"];
|
|
41
|
-
|
|
42
38
|
type AdbShellProtocolPacket = StructValueType<typeof AdbShellProtocolPacket>;
|
|
43
39
|
|
|
44
|
-
class StdinSerializeStream extends ConsumableTransformStream<
|
|
45
|
-
Uint8Array,
|
|
46
|
-
AdbShellProtocolPacketInit
|
|
47
|
-
> {
|
|
48
|
-
constructor() {
|
|
49
|
-
super({
|
|
50
|
-
async transform(chunk, controller) {
|
|
51
|
-
await controller.enqueue({
|
|
52
|
-
id: AdbShellProtocolId.Stdin,
|
|
53
|
-
data: chunk,
|
|
54
|
-
});
|
|
55
|
-
},
|
|
56
|
-
flush() {
|
|
57
|
-
// TODO: AdbShellSubprocessProtocol: support closing stdin
|
|
58
|
-
},
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
class MultiplexStream<T> {
|
|
64
|
-
#readable: PushReadableStream<T>;
|
|
65
|
-
#readableController!: PushReadableStreamController<T>;
|
|
66
|
-
get readable() {
|
|
67
|
-
return this.#readable;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
#activeCount = 0;
|
|
71
|
-
|
|
72
|
-
constructor() {
|
|
73
|
-
this.#readable = new PushReadableStream((controller) => {
|
|
74
|
-
this.#readableController = controller;
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
createWriteable() {
|
|
79
|
-
return new WritableStream<T>({
|
|
80
|
-
start: () => {
|
|
81
|
-
this.#activeCount += 1;
|
|
82
|
-
},
|
|
83
|
-
write: async (chunk) => {
|
|
84
|
-
await this.#readableController.enqueue(chunk);
|
|
85
|
-
},
|
|
86
|
-
abort: () => {
|
|
87
|
-
this.#activeCount -= 1;
|
|
88
|
-
if (this.#activeCount === 0) {
|
|
89
|
-
this.#readableController.close();
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
close: () => {
|
|
93
|
-
this.#activeCount -= 1;
|
|
94
|
-
if (this.#activeCount === 0) {
|
|
95
|
-
this.#readableController.close();
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
40
|
/**
|
|
103
41
|
* Shell v2 a.k.a Shell Protocol
|
|
104
42
|
*
|
|
@@ -109,7 +47,7 @@ class MultiplexStream<T> {
|
|
|
109
47
|
*/
|
|
110
48
|
export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
|
|
111
49
|
static isSupported(adb: Adb) {
|
|
112
|
-
return adb.
|
|
50
|
+
return adb.canUseFeature(AdbFeature.ShellV2);
|
|
113
51
|
}
|
|
114
52
|
|
|
115
53
|
static async pty(adb: Adb, command: string) {
|
|
@@ -126,9 +64,7 @@ export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
|
|
|
126
64
|
}
|
|
127
65
|
|
|
128
66
|
readonly #socket: AdbSocket;
|
|
129
|
-
#
|
|
130
|
-
Consumable<AdbShellProtocolPacketInit>
|
|
131
|
-
>;
|
|
67
|
+
#writer: WritableStreamDefaultWriter<Consumable<Uint8Array>>;
|
|
132
68
|
|
|
133
69
|
#stdin: WritableStream<Consumable<Uint8Array>>;
|
|
134
70
|
get stdin() {
|
|
@@ -153,10 +89,6 @@ export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
|
|
|
153
89
|
constructor(socket: AdbSocket) {
|
|
154
90
|
this.#socket = socket;
|
|
155
91
|
|
|
156
|
-
// Check this image to help you understand the stream graph
|
|
157
|
-
// cspell: disable-next-line
|
|
158
|
-
// https://www.plantuml.com/plantuml/png/bL91QiCm4Bpx5SAdv90lb1JISmiw5XzaQKf5PIkiLZIqzEyLSg8ks13gYtOykpFhiOw93N6UGjVDqK7rZsxKqNw0U_NTgVAy4empOy2mm4_olC0VEVEE47GUpnGjKdgXoD76q4GIEpyFhOwP_m28hW0NNzxNUig1_JdW0bA7muFIJDco1daJ_1SAX9bgvoPJPyIkSekhNYctvIGXrCH6tIsPL5fs-s6J5yc9BpWXhKtNdF2LgVYPGM_6GlMwfhWUsIt4lbScANrwlgVVUifPSVi__t44qStnwPvZwobdSmHHlL57p2vFuHS0
|
|
159
|
-
|
|
160
92
|
let stdoutController!: PushReadableStreamController<Uint8Array>;
|
|
161
93
|
let stderrController!: PushReadableStreamController<Uint8Array>;
|
|
162
94
|
this.#stdout = new PushReadableStream<Uint8Array>((controller) => {
|
|
@@ -176,10 +108,14 @@ export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
|
|
|
176
108
|
this.#exit.resolve(chunk.data[0]!);
|
|
177
109
|
break;
|
|
178
110
|
case AdbShellProtocolId.Stdout:
|
|
179
|
-
|
|
111
|
+
if (!stdoutController.abortSignal.aborted) {
|
|
112
|
+
await stdoutController.enqueue(chunk.data);
|
|
113
|
+
}
|
|
180
114
|
break;
|
|
181
115
|
case AdbShellProtocolId.Stderr:
|
|
182
|
-
|
|
116
|
+
if (!stderrController.abortSignal.aborted) {
|
|
117
|
+
await stderrController.enqueue(chunk.data);
|
|
118
|
+
}
|
|
183
119
|
break;
|
|
184
120
|
}
|
|
185
121
|
},
|
|
@@ -202,39 +138,33 @@ export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
|
|
|
202
138
|
},
|
|
203
139
|
);
|
|
204
140
|
|
|
205
|
-
|
|
206
|
-
Consumable<AdbShellProtocolPacketInit>
|
|
207
|
-
>();
|
|
208
|
-
void multiplexer.readable
|
|
209
|
-
.pipeThrough(
|
|
210
|
-
new ConsumableTransformStream({
|
|
211
|
-
async transform(chunk, controller) {
|
|
212
|
-
await controller.enqueue(
|
|
213
|
-
AdbShellProtocolPacket.serialize(chunk),
|
|
214
|
-
);
|
|
215
|
-
},
|
|
216
|
-
}),
|
|
217
|
-
)
|
|
218
|
-
.pipeTo(socket.writable);
|
|
219
|
-
|
|
220
|
-
this.#stdin = pipeFrom(
|
|
221
|
-
multiplexer.createWriteable(),
|
|
222
|
-
new StdinSerializeStream(),
|
|
223
|
-
);
|
|
141
|
+
this.#writer = this.#socket.writable.getWriter();
|
|
224
142
|
|
|
225
|
-
this.#
|
|
143
|
+
this.#stdin = new WritableStream<Consumable<Uint8Array>>({
|
|
144
|
+
write: async (chunk) => {
|
|
145
|
+
await ConsumableWritableStream.write(
|
|
146
|
+
this.#writer,
|
|
147
|
+
AdbShellProtocolPacket.serialize({
|
|
148
|
+
id: AdbShellProtocolId.Stdin,
|
|
149
|
+
data: chunk.value,
|
|
150
|
+
}),
|
|
151
|
+
);
|
|
152
|
+
chunk.consume();
|
|
153
|
+
},
|
|
154
|
+
});
|
|
226
155
|
}
|
|
227
156
|
|
|
228
157
|
async resize(rows: number, cols: number) {
|
|
229
|
-
await ConsumableWritableStream.write(
|
|
230
|
-
|
|
231
|
-
|
|
158
|
+
await ConsumableWritableStream.write(
|
|
159
|
+
this.#writer,
|
|
160
|
+
AdbShellProtocolPacket.serialize({
|
|
161
|
+
id: AdbShellProtocolId.WindowSizeChange,
|
|
232
162
|
// The "correct" format is `${rows}x${cols},${x_pixels}x${y_pixels}`
|
|
233
163
|
// However, according to https://linux.die.net/man/4/tty_ioctl
|
|
234
164
|
// `x_pixels` and `y_pixels` are unused, so always sending `0` should be fine.
|
|
235
|
-
`${rows}x${cols},0x0\0
|
|
236
|
-
),
|
|
237
|
-
|
|
165
|
+
data: encodeUtf8(`${rows}x${cols},0x0\0`),
|
|
166
|
+
}),
|
|
167
|
+
);
|
|
238
168
|
}
|
|
239
169
|
|
|
240
170
|
kill() {
|
|
@@ -4,7 +4,11 @@ import { AdbSyncRequestId, adbSyncWriteRequest } from "./request.js";
|
|
|
4
4
|
import { AdbSyncResponseId, adbSyncReadResponses } from "./response.js";
|
|
5
5
|
import type { AdbSyncSocket } from "./socket.js";
|
|
6
6
|
import type { AdbSyncStat } from "./stat.js";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
AdbSyncLstatResponse,
|
|
9
|
+
AdbSyncStatErrorCode,
|
|
10
|
+
AdbSyncStatResponse,
|
|
11
|
+
} from "./stat.js";
|
|
8
12
|
|
|
9
13
|
export interface AdbSyncEntry extends AdbSyncStat {
|
|
10
14
|
name: string;
|
|
@@ -43,7 +47,7 @@ export async function* adbSyncOpenDirV2(
|
|
|
43
47
|
// `LST2` can return error codes for failed `lstat` calls.
|
|
44
48
|
// `LIST` just ignores them.
|
|
45
49
|
// But they only contain `name` so still pretty useless.
|
|
46
|
-
if (item.error !==
|
|
50
|
+
if (item.error !== AdbSyncStatErrorCode.SUCCESS) {
|
|
47
51
|
continue;
|
|
48
52
|
}
|
|
49
53
|
yield item;
|
|
@@ -46,7 +46,7 @@ export async function adbSyncReadResponse<T>(
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export async function* adbSyncReadResponses<
|
|
49
|
-
T extends Struct<object, PropertyKey, object,
|
|
49
|
+
T extends Struct<object, PropertyKey, object, unknown>,
|
|
50
50
|
>(
|
|
51
51
|
stream: AsyncExactReadable,
|
|
52
52
|
id: AdbSyncResponseId,
|
|
@@ -66,7 +66,7 @@ export async function* adbSyncReadResponses<
|
|
|
66
66
|
await stream.readExactly(type.size);
|
|
67
67
|
return;
|
|
68
68
|
case id:
|
|
69
|
-
yield await type.deserialize(stream)
|
|
69
|
+
yield (await type.deserialize(stream)) as StructValueType<T>;
|
|
70
70
|
break;
|
|
71
71
|
default:
|
|
72
72
|
throw new Error(
|
|
@@ -71,6 +71,10 @@ export class AdbSyncSocketLocked implements AsyncExactReadable {
|
|
|
71
71
|
this.#combiner.flush();
|
|
72
72
|
this.#socketLock.notifyOne();
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
async close() {
|
|
76
|
+
await this.#readable.cancel();
|
|
77
|
+
}
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
export class AdbSyncSocket {
|
|
@@ -94,6 +98,7 @@ export class AdbSyncSocket {
|
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
async close() {
|
|
101
|
+
await this.#locked.close();
|
|
97
102
|
await this.#socket.close();
|
|
98
103
|
}
|
|
99
104
|
}
|
|
@@ -74,16 +74,15 @@ export class AdbSync extends AutoDisposable {
|
|
|
74
74
|
this._adb = adb;
|
|
75
75
|
this._socket = new AdbSyncSocket(socket, adb.maxPayloadSize);
|
|
76
76
|
|
|
77
|
-
this.#supportsStat = adb.
|
|
78
|
-
this.#supportsListV2 = adb.
|
|
79
|
-
this.#fixedPushMkdir = adb.
|
|
80
|
-
this.#supportsSendReceiveV2 = adb.
|
|
77
|
+
this.#supportsStat = adb.canUseFeature(AdbFeature.StatV2);
|
|
78
|
+
this.#supportsListV2 = adb.canUseFeature(AdbFeature.ListV2);
|
|
79
|
+
this.#fixedPushMkdir = adb.canUseFeature(AdbFeature.FixedPushMkdir);
|
|
80
|
+
this.#supportsSendReceiveV2 = adb.canUseFeature(
|
|
81
81
|
AdbFeature.SendReceiveV2,
|
|
82
82
|
);
|
|
83
83
|
// https://android.googlesource.com/platform/packages/modules/adb/+/91768a57b7138166e0a3d11f79cd55909dda7014/client/file_sync_client.cpp#1361
|
|
84
84
|
this.#needPushMkdirWorkaround =
|
|
85
|
-
this._adb.
|
|
86
|
-
!this.fixedPushMkdir;
|
|
85
|
+
this._adb.canUseFeature(AdbFeature.ShellV2) && !this.fixedPushMkdir;
|
|
87
86
|
}
|
|
88
87
|
|
|
89
88
|
/**
|
package/src/commands/tcpip.ts
CHANGED
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
import { AdbCommandBase } from "./base.js";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* ADB daemon checks for the following properties in the order of
|
|
5
|
+
*
|
|
6
|
+
* * `serviceListenAddresses` (`service.adb.listen_addrs`)
|
|
7
|
+
* * `servicePort` (`service.adb.tcp.port`)
|
|
8
|
+
* * `persistPort` (`persist.adb.tcp.port`)
|
|
9
|
+
*
|
|
10
|
+
* Once it finds a non-empty value, it will use it and ignore the rest.
|
|
11
|
+
*
|
|
12
|
+
* `serviceListenAddresses` and `persistPort` are fixed at build time,
|
|
13
|
+
* only `servicePort` can be changed using `setPort` and `disable`.
|
|
14
|
+
* This means if either `serviceListenAddresses` or `persistPort` is non-empty,
|
|
15
|
+
* ADB over WiFi is always enabled.
|
|
16
|
+
*/
|
|
17
|
+
export interface AdbTcpIpListenAddresses {
|
|
18
|
+
serviceListenAddresses: string[];
|
|
19
|
+
servicePort: number | undefined;
|
|
20
|
+
persistPort: number | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
3
23
|
export class AdbTcpIpCommand extends AdbCommandBase {
|
|
24
|
+
#parsePort(value: string): number | undefined {
|
|
25
|
+
if (!value || value === "0") {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
return Number.parseInt(value, 10);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async getListenAddresses(): Promise<AdbTcpIpListenAddresses> {
|
|
32
|
+
const serviceListenAddresses = await this.adb.getProp(
|
|
33
|
+
"service.adb.listen_addrs",
|
|
34
|
+
);
|
|
35
|
+
const servicePort = await this.adb.getProp("service.adb.tcp.port");
|
|
36
|
+
const persistPort = await this.adb.getProp("persist.adb.tcp.port");
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
serviceListenAddresses:
|
|
40
|
+
serviceListenAddresses != ""
|
|
41
|
+
? serviceListenAddresses.split(",")
|
|
42
|
+
: [],
|
|
43
|
+
servicePort: this.#parsePort(servicePort),
|
|
44
|
+
persistPort: this.#parsePort(persistPort),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
4
48
|
async setPort(port: number): Promise<string> {
|
|
5
49
|
if (port <= 0) {
|
|
6
50
|
throw new Error(`Invalid port ${port}`);
|