@yume-chan/adb 0.0.15 → 0.0.17
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 +33 -0
- package/CHANGELOG.md +18 -1
- package/LICENSE +21 -21
- package/README.md +247 -247
- package/esm/adb.d.ts +15 -3
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +18 -6
- package/esm/adb.js.map +1 -1
- package/esm/auth.d.ts.map +1 -1
- package/esm/auth.js.map +1 -1
- package/esm/backend.d.ts +2 -2
- package/esm/backend.d.ts.map +1 -1
- package/esm/commands/base.d.ts.map +1 -1
- package/esm/commands/base.js.map +1 -1
- package/esm/commands/framebuffer.d.ts +17 -1
- package/esm/commands/framebuffer.d.ts.map +1 -1
- package/esm/commands/framebuffer.js +4 -15
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/install.d.ts +2 -2
- package/esm/commands/install.d.ts.map +1 -1
- package/esm/commands/install.js +3 -2
- package/esm/commands/install.js.map +1 -1
- package/esm/commands/power.d.ts +1 -1
- package/esm/commands/power.js +1 -1
- package/esm/commands/reverse.d.ts +3 -3
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js +9 -9
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/command.d.ts +52 -0
- package/esm/commands/subprocess/command.d.ts.map +1 -0
- package/esm/commands/subprocess/command.js +83 -0
- package/esm/commands/subprocess/command.js.map +1 -0
- package/esm/commands/subprocess/index.d.ts +1 -53
- package/esm/commands/subprocess/index.d.ts.map +1 -1
- package/esm/commands/subprocess/index.js +1 -85
- package/esm/commands/subprocess/index.js.map +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts +5 -4
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +11 -8
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/subprocess/protocols/shell.d.ts +4 -4
- package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/shell.js +6 -6
- package/esm/commands/subprocess/protocols/shell.js.map +1 -1
- package/esm/commands/subprocess/protocols/types.d.ts +7 -7
- package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
- package/esm/commands/sync/index.d.ts +1 -1
- package/esm/commands/sync/index.d.ts.map +1 -1
- package/esm/commands/sync/index.js +1 -1
- package/esm/commands/sync/index.js.map +1 -1
- package/esm/commands/sync/list.d.ts +2 -2
- package/esm/commands/sync/list.d.ts.map +1 -1
- package/esm/commands/sync/list.js +15 -43
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts +3 -2
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +15 -17
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.d.ts +2 -2
- package/esm/commands/sync/push.d.ts.map +1 -1
- package/esm/commands/sync/push.js +2 -5
- package/esm/commands/sync/push.js.map +1 -1
- package/esm/commands/sync/request.d.ts +1 -1
- package/esm/commands/sync/request.d.ts.map +1 -1
- package/esm/commands/sync/request.js +1 -1
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +4 -9
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +32 -23
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/stat.d.ts +3 -3
- package/esm/commands/sync/stat.d.ts.map +1 -1
- package/esm/commands/sync/stat.js +13 -30
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +2 -2
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +7 -5
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/crypto.js +1 -1
- package/esm/crypto.js.map +1 -1
- package/esm/index.d.ts +0 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +0 -1
- package/esm/index.js.map +1 -1
- package/esm/packet.d.ts +1 -1
- package/esm/packet.d.ts.map +1 -1
- package/esm/packet.js +1 -1
- package/esm/packet.js.map +1 -1
- package/esm/socket/dispatcher.d.ts +11 -3
- package/esm/socket/dispatcher.d.ts.map +1 -1
- package/esm/socket/dispatcher.js +19 -11
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/socket/index.d.ts +1 -1
- package/esm/socket/index.d.ts.map +1 -1
- package/esm/socket/index.js +1 -1
- package/esm/socket/index.js.map +1 -1
- package/esm/socket/socket.d.ts +9 -4
- package/esm/socket/socket.d.ts.map +1 -1
- package/esm/socket/socket.js +20 -10
- package/esm/socket/socket.js.map +1 -1
- package/esm/utils/base64.d.ts +23 -0
- package/esm/utils/base64.d.ts.map +1 -1
- package/esm/utils/base64.js +6 -0
- package/esm/utils/base64.js.map +1 -1
- package/package.json +13 -14
- package/src/adb.ts +285 -273
- package/src/auth.ts +174 -173
- package/src/backend.ts +12 -11
- package/src/commands/base.ts +12 -11
- package/src/commands/framebuffer.ts +78 -73
- package/src/commands/index.ts +8 -8
- package/src/commands/install.ts +32 -30
- package/src/commands/power.ts +54 -54
- package/src/commands/reverse.ts +141 -140
- package/src/commands/subprocess/command.ts +131 -0
- package/src/commands/subprocess/index.ts +3 -139
- package/src/commands/subprocess/protocols/none.ts +73 -68
- package/src/commands/subprocess/protocols/shell.ts +191 -190
- package/src/commands/subprocess/protocols/types.ts +60 -59
- package/src/commands/subprocess/utils.ts +20 -20
- package/src/commands/sync/index.ts +7 -7
- package/src/commands/sync/list.ts +54 -86
- package/src/commands/sync/pull.ts +45 -46
- package/src/commands/sync/push.ts +38 -41
- package/src/commands/sync/request.ts +51 -50
- package/src/commands/sync/response.ts +68 -64
- package/src/commands/sync/stat.ts +129 -150
- package/src/commands/sync/sync.ts +182 -181
- package/src/commands/tcpip.ts +21 -21
- package/src/crypto.ts +296 -296
- package/src/features.ts +9 -9
- package/src/index.ts +10 -11
- package/src/packet.ts +80 -80
- package/src/socket/dispatcher.ts +310 -304
- package/src/socket/index.ts +2 -2
- package/src/socket/socket.ts +156 -144
- package/src/utils/auto-reset-event.ts +41 -41
- package/src/utils/base64.ts +329 -306
- package/src/utils/index.ts +3 -3
- package/tsconfig.build.json +3 -3
- package/tsconfig.build.tsbuildinfo +1 -1
- package/esm/commands/subprocess/legacy.d.ts +0 -35
- package/esm/commands/subprocess/legacy.d.ts.map +0 -1
- package/esm/commands/subprocess/legacy.js +0 -53
- package/esm/commands/subprocess/legacy.js.map +0 -1
- package/esm/commands/subprocess/protocol.d.ts +0 -39
- package/esm/commands/subprocess/protocol.d.ts.map +0 -1
- package/esm/commands/subprocess/protocol.js +0 -157
- package/esm/commands/subprocess/protocol.js.map +0 -1
- package/esm/commands/subprocess/types.d.ts +0 -50
- package/esm/commands/subprocess/types.d.ts.map +0 -1
- package/esm/commands/subprocess/types.js +0 -2
- package/esm/commands/subprocess/types.js.map +0 -1
- package/esm/socket/controller.d.ts +0 -37
- package/esm/socket/controller.d.ts.map +0 -1
- package/esm/socket/controller.js +0 -66
- package/esm/socket/controller.js.map +0 -1
- package/esm/stream/buffered.d.ts +0 -35
- package/esm/stream/buffered.d.ts.map +0 -1
- package/esm/stream/buffered.js +0 -123
- package/esm/stream/buffered.js.map +0 -1
- package/esm/stream/detect.bak.d.ts +0 -240
- package/esm/stream/detect.bak.d.ts.map +0 -1
- package/esm/stream/detect.bak.js +0 -60
- package/esm/stream/detect.bak.js.map +0 -1
- package/esm/stream/detect.d.ts +0 -2
- package/esm/stream/detect.d.ts.map +0 -1
- package/esm/stream/detect.js +0 -5
- package/esm/stream/detect.js.map +0 -1
- package/esm/stream/detect.native.d.ts +0 -240
- package/esm/stream/detect.native.d.ts.map +0 -1
- package/esm/stream/detect.native.js +0 -60
- package/esm/stream/detect.native.js.map +0 -1
- package/esm/stream/detect.polyfill.d.ts +0 -18
- package/esm/stream/detect.polyfill.d.ts.map +0 -1
- package/esm/stream/detect.polyfill.js +0 -9
- package/esm/stream/detect.polyfill.js.map +0 -1
- package/esm/stream/index.d.ts +0 -4
- package/esm/stream/index.d.ts.map +0 -1
- package/esm/stream/index.js +0 -4
- package/esm/stream/index.js.map +0 -1
- package/esm/stream/transform.d.ts +0 -104
- package/esm/stream/transform.d.ts.map +0 -1
- package/esm/stream/transform.js +0 -373
- package/esm/stream/transform.js.map +0 -1
- package/esm/utils/encoding.d.ts +0 -3
- package/esm/utils/encoding.d.ts.map +0 -1
- package/esm/utils/encoding.js +0 -11
- package/esm/utils/encoding.js.map +0 -1
- package/src/stream/buffered.ts +0 -147
- package/src/stream/detect.native.ts +0 -362
- package/src/stream/detect.polyfill.ts +0 -28
- package/src/stream/detect.ts +0 -5
- package/src/stream/index.ts +0 -3
- package/src/stream/transform.ts +0 -447
- package/tsconfig.test.json +0 -10
|
@@ -1,68 +1,73 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import type {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* * `
|
|
12
|
-
* * `
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
public get
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
1
|
+
import { DuplexStreamFactory, ReadableStream } from '@yume-chan/stream-extra';
|
|
2
|
+
|
|
3
|
+
import type { Adb } from '../../../adb.js';
|
|
4
|
+
import type { AdbSocket } from '../../../socket/index.js';
|
|
5
|
+
import type { AdbSubprocessProtocol } from './types.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The legacy shell
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* * `stderr`: No
|
|
12
|
+
* * `exit` exit code: No
|
|
13
|
+
* * `resize`: No
|
|
14
|
+
*/
|
|
15
|
+
export class AdbSubprocessNoneProtocol implements AdbSubprocessProtocol {
|
|
16
|
+
public static isSupported() { return true; }
|
|
17
|
+
|
|
18
|
+
public static async pty(adb: Adb, command: string) {
|
|
19
|
+
return new AdbSubprocessNoneProtocol(await adb.createSocket(`shell:${command}`));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public static async raw(adb: Adb, command: string) {
|
|
23
|
+
// `shell,raw:${command}` also triggers raw mode,
|
|
24
|
+
// But is not supported on Android version <7.
|
|
25
|
+
return new AdbSubprocessNoneProtocol(await adb.createSocket(`exec:${command}`));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private readonly socket: AdbSocket;
|
|
29
|
+
|
|
30
|
+
private readonly duplex: DuplexStreamFactory<Uint8Array, Uint8Array>;
|
|
31
|
+
|
|
32
|
+
// Legacy shell forwards all data to stdin.
|
|
33
|
+
public get stdin() { return this.socket.writable; }
|
|
34
|
+
|
|
35
|
+
private _stdout: ReadableStream<Uint8Array>;
|
|
36
|
+
/**
|
|
37
|
+
* Legacy shell mixes stdout and stderr.
|
|
38
|
+
*/
|
|
39
|
+
public get stdout() { return this._stdout; }
|
|
40
|
+
|
|
41
|
+
private _stderr: ReadableStream<Uint8Array>;
|
|
42
|
+
/**
|
|
43
|
+
* `stderr` will always be empty.
|
|
44
|
+
*/
|
|
45
|
+
public get stderr() { return this._stderr; }
|
|
46
|
+
|
|
47
|
+
private _exit: Promise<number>;
|
|
48
|
+
public get exit() { return this._exit; }
|
|
49
|
+
|
|
50
|
+
public constructor(socket: AdbSocket) {
|
|
51
|
+
this.socket = socket;
|
|
52
|
+
|
|
53
|
+
// Link `stdout`, `stderr` and `stdin` together,
|
|
54
|
+
// so closing any of them will close the others.
|
|
55
|
+
this.duplex = new DuplexStreamFactory<Uint8Array, Uint8Array>({
|
|
56
|
+
close: async () => {
|
|
57
|
+
await this.socket.close();
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
this._stdout = this.duplex.wrapReadable(this.socket.readable);
|
|
62
|
+
this._stderr = this.duplex.wrapReadable(new ReadableStream());
|
|
63
|
+
this._exit = this.duplex.closed.then(() => 0);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public resize() {
|
|
67
|
+
// Not supported, but don't throw.
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public kill() {
|
|
71
|
+
return this.duplex.close();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -1,190 +1,191 @@
|
|
|
1
|
-
import { PromiseResolver } from
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
import type {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
.
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
private
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* * `
|
|
101
|
-
* * `
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
private
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
//
|
|
137
|
-
//
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
.pipeThrough(new
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
multiplexer
|
|
164
|
-
|
|
165
|
-
.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
1
|
+
import { PromiseResolver } from '@yume-chan/async';
|
|
2
|
+
import { pipeFrom, PushReadableStream, StructDeserializeStream, StructSerializeStream, TransformStream, WritableStream, type PushReadableStreamController, type ReadableStream, type WritableStreamDefaultWriter } from '@yume-chan/stream-extra';
|
|
3
|
+
import Struct, { placeholder, type StructValueType } from '@yume-chan/struct';
|
|
4
|
+
|
|
5
|
+
import type { Adb } from '../../../adb.js';
|
|
6
|
+
import { AdbFeatures } from '../../../features.js';
|
|
7
|
+
import type { AdbSocket } from '../../../socket/index.js';
|
|
8
|
+
import { encodeUtf8 } from '../../../utils/index.js';
|
|
9
|
+
import type { AdbSubprocessProtocol } from './types.js';
|
|
10
|
+
|
|
11
|
+
export enum AdbShellProtocolId {
|
|
12
|
+
Stdin,
|
|
13
|
+
Stdout,
|
|
14
|
+
Stderr,
|
|
15
|
+
Exit,
|
|
16
|
+
CloseStdin,
|
|
17
|
+
WindowSizeChange,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// This packet format is used in both direction.
|
|
21
|
+
const AdbShellProtocolPacket =
|
|
22
|
+
new Struct({ littleEndian: true })
|
|
23
|
+
.uint8('id', placeholder<AdbShellProtocolId>())
|
|
24
|
+
.uint32('length')
|
|
25
|
+
.uint8Array('data', { lengthField: 'length' });
|
|
26
|
+
|
|
27
|
+
type AdbShellProtocolPacketInit = typeof AdbShellProtocolPacket['TInit'];
|
|
28
|
+
|
|
29
|
+
type AdbShellProtocolPacket = StructValueType<typeof AdbShellProtocolPacket>;
|
|
30
|
+
|
|
31
|
+
class StdinSerializeStream extends TransformStream<Uint8Array, AdbShellProtocolPacketInit>{
|
|
32
|
+
constructor() {
|
|
33
|
+
super({
|
|
34
|
+
transform(chunk, controller) {
|
|
35
|
+
controller.enqueue({
|
|
36
|
+
id: AdbShellProtocolId.Stdin,
|
|
37
|
+
data: chunk,
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
flush() {
|
|
41
|
+
// TODO: AdbShellSubprocessProtocol: support closing stdin
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class StdoutDeserializeStream extends TransformStream<AdbShellProtocolPacket, Uint8Array>{
|
|
48
|
+
constructor(type: AdbShellProtocolId.Stdout | AdbShellProtocolId.Stderr) {
|
|
49
|
+
super({
|
|
50
|
+
transform(chunk, controller) {
|
|
51
|
+
if (chunk.id === type) {
|
|
52
|
+
controller.enqueue(chunk.data);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
class MultiplexStream<T>{
|
|
60
|
+
private _readable: PushReadableStream<T>;
|
|
61
|
+
private _readableController!: PushReadableStreamController<T>;
|
|
62
|
+
public get readable() { return this._readable; }
|
|
63
|
+
|
|
64
|
+
private _activeCount = 0;
|
|
65
|
+
|
|
66
|
+
constructor() {
|
|
67
|
+
this._readable = new PushReadableStream(controller => {
|
|
68
|
+
this._readableController = controller;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public createWriteable() {
|
|
73
|
+
return new WritableStream<T>({
|
|
74
|
+
start: () => {
|
|
75
|
+
this._activeCount += 1;
|
|
76
|
+
},
|
|
77
|
+
write: async (chunk) => {
|
|
78
|
+
await this._readableController.enqueue(chunk);
|
|
79
|
+
},
|
|
80
|
+
abort: async (e) => {
|
|
81
|
+
this._activeCount -= 1;
|
|
82
|
+
if (this._activeCount === 0) {
|
|
83
|
+
this._readableController.close();
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
close: async () => {
|
|
87
|
+
this._activeCount -= 1;
|
|
88
|
+
if (this._activeCount === 0) {
|
|
89
|
+
this._readableController.close();
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Shell v2 a.k.a Shell Protocol
|
|
98
|
+
*
|
|
99
|
+
* Features:
|
|
100
|
+
* * `stderr`: Yes
|
|
101
|
+
* * `exit` exit code: Yes
|
|
102
|
+
* * `resize`: Yes
|
|
103
|
+
*/
|
|
104
|
+
export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
|
|
105
|
+
public static isSupported(adb: Adb) {
|
|
106
|
+
return adb.features.includes(AdbFeatures.ShellV2);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public static async pty(adb: Adb, command: string) {
|
|
110
|
+
// TODO: AdbShellSubprocessProtocol: Support setting `XTERM` environment variable
|
|
111
|
+
return new AdbSubprocessShellProtocol(await adb.createSocket(`shell,v2,pty:${command}`));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public static async raw(adb: Adb, command: string) {
|
|
115
|
+
return new AdbSubprocessShellProtocol(await adb.createSocket(`shell,v2,raw:${command}`));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private readonly _socket: AdbSocket;
|
|
119
|
+
private _socketWriter: WritableStreamDefaultWriter<AdbShellProtocolPacketInit>;
|
|
120
|
+
|
|
121
|
+
private _stdin: WritableStream<Uint8Array>;
|
|
122
|
+
public get stdin() { return this._stdin; }
|
|
123
|
+
|
|
124
|
+
private _stdout: ReadableStream<Uint8Array>;
|
|
125
|
+
public get stdout() { return this._stdout; }
|
|
126
|
+
|
|
127
|
+
private _stderr: ReadableStream<Uint8Array>;
|
|
128
|
+
public get stderr() { return this._stderr; }
|
|
129
|
+
|
|
130
|
+
private readonly _exit = new PromiseResolver<number>();
|
|
131
|
+
public get exit() { return this._exit.promise; }
|
|
132
|
+
|
|
133
|
+
public constructor(socket: AdbSocket) {
|
|
134
|
+
this._socket = socket;
|
|
135
|
+
|
|
136
|
+
// Check this image to help you understand the stream graph
|
|
137
|
+
// cspell: disable-next-line
|
|
138
|
+
// https://www.plantuml.com/plantuml/png/bL91QiCm4Bpx5SAdv90lb1JISmiw5XzaQKf5PIkiLZIqzEyLSg8ks13gYtOykpFhiOw93N6UGjVDqK7rZsxKqNw0U_NTgVAy4empOy2mm4_olC0VEVEE47GUpnGjKdgXoD76q4GIEpyFhOwP_m28hW0NNzxNUig1_JdW0bA7muFIJDco1daJ_1SAX9bgvoPJPyIkSekhNYctvIGXrCH6tIsPL5fs-s6J5yc9BpWXhKtNdF2LgVYPGM_6GlMwfhWUsIt4lbScANrwlgVVUifPSVi__t44qStnwPvZwobdSmHHlL57p2vFuHS0
|
|
139
|
+
|
|
140
|
+
// TODO: AdbShellSubprocessProtocol: Optimize stream graph
|
|
141
|
+
|
|
142
|
+
const [stdout, stderr] = socket.readable
|
|
143
|
+
.pipeThrough(new StructDeserializeStream(AdbShellProtocolPacket))
|
|
144
|
+
.pipeThrough(new TransformStream<AdbShellProtocolPacket, AdbShellProtocolPacket>({
|
|
145
|
+
transform: (chunk, controller) => {
|
|
146
|
+
if (chunk.id === AdbShellProtocolId.Exit) {
|
|
147
|
+
this._exit.resolve(new Uint8Array(chunk.data)[0]!);
|
|
148
|
+
// We can let `StdoutDeserializeStream` to process `AdbShellProtocolId.Exit`,
|
|
149
|
+
// but since we need this `TransformStream` to capture the exit code anyway,
|
|
150
|
+
// terminating child streams here is killing two birds with one stone.
|
|
151
|
+
controller.terminate();
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
controller.enqueue(chunk);
|
|
155
|
+
}
|
|
156
|
+
}))
|
|
157
|
+
.tee();
|
|
158
|
+
this._stdout = stdout
|
|
159
|
+
.pipeThrough(new StdoutDeserializeStream(AdbShellProtocolId.Stdout));
|
|
160
|
+
this._stderr = stderr
|
|
161
|
+
.pipeThrough(new StdoutDeserializeStream(AdbShellProtocolId.Stderr));
|
|
162
|
+
|
|
163
|
+
const multiplexer = new MultiplexStream<AdbShellProtocolPacketInit>();
|
|
164
|
+
multiplexer.readable
|
|
165
|
+
.pipeThrough(new StructSerializeStream(AdbShellProtocolPacket))
|
|
166
|
+
.pipeTo(socket.writable);
|
|
167
|
+
|
|
168
|
+
this._stdin = pipeFrom(
|
|
169
|
+
multiplexer.createWriteable(),
|
|
170
|
+
new StdinSerializeStream()
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
this._socketWriter = multiplexer.createWriteable().getWriter();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
public async resize(rows: number, cols: number) {
|
|
177
|
+
await this._socketWriter.write({
|
|
178
|
+
id: AdbShellProtocolId.WindowSizeChange,
|
|
179
|
+
data: encodeUtf8(
|
|
180
|
+
// The "correct" format is `${rows}x${cols},${x_pixels}x${y_pixels}`
|
|
181
|
+
// However, according to https://linux.die.net/man/4/tty_ioctl
|
|
182
|
+
// `x_pixels` and `y_pixels` are unused, so always sending `0` should be fine.
|
|
183
|
+
`${rows}x${cols},0x0\0`
|
|
184
|
+
),
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
public kill() {
|
|
189
|
+
return this._socket.close();
|
|
190
|
+
}
|
|
191
|
+
}
|