@yume-chan/adb 0.0.9 → 0.0.10
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 +23 -0
- package/CHANGELOG.md +16 -0
- package/LICENSE +21 -21
- package/README.md +227 -257
- package/dts/adb.d.ts.map +1 -1
- package/dts/auth.d.ts +11 -1
- package/dts/auth.d.ts.map +1 -1
- package/dts/backend.d.ts +3 -5
- package/dts/backend.d.ts.map +1 -1
- package/dts/commands/demo-mode.d.ts +3 -3
- package/dts/commands/demo-mode.d.ts.map +1 -1
- package/dts/commands/reverse.d.ts +2 -2
- package/dts/commands/reverse.d.ts.map +1 -1
- package/dts/commands/shell/index.d.ts +31 -5
- package/dts/commands/shell/index.d.ts.map +1 -1
- package/dts/commands/shell/legacy.d.ts +13 -2
- package/dts/commands/shell/legacy.d.ts.map +1 -1
- package/dts/commands/shell/protocol.d.ts +11 -3
- package/dts/commands/shell/protocol.d.ts.map +1 -1
- package/dts/commands/shell/types.d.ts +35 -3
- package/dts/commands/shell/types.d.ts.map +1 -1
- package/dts/commands/sync/request.d.ts +1 -1
- package/dts/commands/sync/request.d.ts.map +1 -1
- package/dts/commands/sync/response.d.ts +2 -2
- package/dts/commands/sync/response.d.ts.map +1 -1
- package/dts/commands/sync/sync.d.ts.map +1 -1
- package/dts/crypto.d.ts +7 -0
- package/dts/crypto.d.ts.map +1 -1
- package/dts/packet.d.ts.map +1 -1
- package/dts/socket/close-event-emitter.d.ts.map +1 -1
- package/dts/socket/controller.d.ts.map +1 -1
- package/dts/socket/data-event-emitter.d.ts.map +1 -1
- package/dts/socket/dispatcher.d.ts.map +1 -1
- package/dts/stream/buffered-stream.d.ts +2 -4
- package/dts/stream/buffered-stream.d.ts.map +1 -1
- package/dts/utils/encoding.d.ts +3 -0
- package/dts/utils/encoding.d.ts.map +1 -0
- package/dts/utils/index.d.ts +1 -0
- package/dts/utils/index.d.ts.map +1 -1
- package/esm/adb.js +3 -2
- package/esm/adb.js.map +1 -1
- package/esm/auth.js +2 -2
- package/esm/auth.js.map +1 -1
- package/esm/commands/demo-mode.js +9 -9
- package/esm/commands/demo-mode.js.map +1 -1
- package/esm/commands/reverse.js +3 -2
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/shell/index.js +28 -18
- package/esm/commands/shell/index.js.map +1 -1
- package/esm/commands/shell/legacy.js +16 -0
- package/esm/commands/shell/legacy.js.map +1 -1
- package/esm/commands/shell/protocol.js +36 -9
- package/esm/commands/shell/protocol.js.map +1 -1
- package/esm/commands/sync/request.js +5 -4
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.js +4 -3
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/crypto.js +7 -2
- package/esm/crypto.js.map +1 -1
- package/esm/packet.js +12 -14
- package/esm/packet.js.map +1 -1
- package/esm/socket/close-event-emitter.js.map +1 -1
- package/esm/socket/controller.js.map +1 -1
- package/esm/socket/data-event-emitter.js.map +1 -1
- package/esm/socket/dispatcher.js +7 -7
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/stream/buffered-stream.js +0 -6
- package/esm/stream/buffered-stream.js.map +1 -1
- package/esm/utils/encoding.js +11 -0
- package/esm/utils/encoding.js.map +1 -0
- package/esm/utils/index.js +1 -0
- package/esm/utils/index.js.map +1 -1
- package/package.json +44 -51
- package/src/adb.ts +243 -242
- package/src/auth.ts +166 -156
- package/src/backend.ts +20 -24
- package/src/commands/base.ts +11 -11
- package/src/commands/demo-mode.ts +160 -160
- package/src/commands/framebuffer.ts +73 -73
- package/src/commands/index.ts +8 -8
- package/src/commands/install.ts +21 -21
- package/src/commands/reverse.ts +134 -133
- package/src/commands/shell/index.ts +87 -68
- package/src/commands/shell/legacy.ts +59 -42
- package/src/commands/shell/protocol.ts +121 -94
- package/src/commands/shell/types.ts +55 -21
- package/src/commands/shell/utils.ts +20 -20
- package/src/commands/sync/index.ts +7 -7
- package/src/commands/sync/list.ts +39 -39
- package/src/commands/sync/pull.ts +34 -34
- package/src/commands/sync/push.ts +46 -46
- package/src/commands/sync/request.ts +49 -48
- package/src/commands/sync/response.ts +58 -57
- package/src/commands/sync/stat.ts +121 -121
- package/src/commands/sync/sync.ts +113 -113
- package/src/commands/tcpip.ts +21 -21
- package/src/crypto.ts +285 -280
- package/src/features.ts +5 -5
- package/src/index.ts +10 -10
- package/src/packet.ts +84 -89
- package/src/socket/close-event-emitter.ts +28 -28
- package/src/socket/controller.ts +105 -105
- package/src/socket/data-event-emitter.ts +27 -27
- package/src/socket/dispatcher.ts +269 -269
- package/src/socket/index.ts +6 -6
- package/src/socket/logger.ts +12 -12
- package/src/socket/socket.ts +28 -28
- package/src/stream/buffered-stream.ts +92 -100
- package/src/stream/index.ts +2 -2
- package/src/stream/stream.ts +50 -50
- package/src/utils/auto-reset-event.ts +41 -41
- package/src/utils/base64.ts +274 -274
- package/src/utils/chunk.ts +70 -70
- package/src/utils/encoding.ts +13 -0
- package/src/utils/event-queue.ts +145 -145
- package/src/utils/index.ts +5 -4
- package/cjs/adb.js +0 -205
- package/cjs/adb.js.map +0 -1
- package/cjs/auth.js +0 -141
- package/cjs/auth.js.map +0 -1
- package/cjs/backend.js +0 -3
- package/cjs/backend.js.map +0 -1
- package/cjs/commands/base.js +0 -12
- package/cjs/commands/base.js.map +0 -1
- package/cjs/commands/demo-mode.js +0 -174
- package/cjs/commands/demo-mode.js.map +0 -1
- package/cjs/commands/framebuffer.js +0 -66
- package/cjs/commands/framebuffer.js.map +0 -1
- package/cjs/commands/index.js +0 -12
- package/cjs/commands/index.js.map +0 -1
- package/cjs/commands/install.js +0 -20
- package/cjs/commands/install.js.map +0 -1
- package/cjs/commands/reverse.js +0 -105
- package/cjs/commands/reverse.js.map +0 -1
- package/cjs/commands/shell/index.js +0 -56
- package/cjs/commands/shell/index.js.map +0 -1
- package/cjs/commands/shell/legacy.js +0 -37
- package/cjs/commands/shell/legacy.js.map +0 -1
- package/cjs/commands/shell/protocol.js +0 -83
- package/cjs/commands/shell/protocol.js.map +0 -1
- package/cjs/commands/shell/types.js +0 -3
- package/cjs/commands/shell/types.js.map +0 -1
- package/cjs/commands/shell/utils.js +0 -23
- package/cjs/commands/shell/utils.js.map +0 -1
- package/cjs/commands/sync/index.js +0 -11
- package/cjs/commands/sync/index.js.map +0 -1
- package/cjs/commands/sync/list.js +0 -36
- package/cjs/commands/sync/list.js.map +0 -1
- package/cjs/commands/sync/pull.js +0 -34
- package/cjs/commands/sync/pull.js.map +0 -1
- package/cjs/commands/sync/push.js +0 -49
- package/cjs/commands/sync/push.js.map +0 -1
- package/cjs/commands/sync/request.js +0 -48
- package/cjs/commands/sync/request.js.map +0 -1
- package/cjs/commands/sync/response.js +0 -53
- package/cjs/commands/sync/response.js.map +0 -1
- package/cjs/commands/sync/stat.js +0 -109
- package/cjs/commands/sync/stat.js.map +0 -1
- package/cjs/commands/sync/sync.js +0 -118
- package/cjs/commands/sync/sync.js.map +0 -1
- package/cjs/commands/tcpip.js +0 -28
- package/cjs/commands/tcpip.js.map +0 -1
- package/cjs/crypto.js +0 -231
- package/cjs/crypto.js.map +0 -1
- package/cjs/features.js +0 -10
- package/cjs/features.js.map +0 -1
- package/cjs/index.js +0 -14
- package/cjs/index.js.map +0 -1
- package/cjs/packet.js +0 -77
- package/cjs/packet.js.map +0 -1
- package/cjs/socket/close-event-emitter.js +0 -32
- package/cjs/socket/close-event-emitter.js.map +0 -1
- package/cjs/socket/controller.js +0 -84
- package/cjs/socket/controller.js.map +0 -1
- package/cjs/socket/data-event-emitter.js +0 -29
- package/cjs/socket/data-event-emitter.js.map +0 -1
- package/cjs/socket/dispatcher.js +0 -219
- package/cjs/socket/dispatcher.js.map +0 -1
- package/cjs/socket/index.js +0 -10
- package/cjs/socket/index.js.map +0 -1
- package/cjs/socket/logger.js +0 -3
- package/cjs/socket/logger.js.map +0 -1
- package/cjs/socket/socket.js +0 -24
- package/cjs/socket/socket.js.map +0 -1
- package/cjs/stream/buffered-stream.js +0 -78
- package/cjs/stream/buffered-stream.js.map +0 -1
- package/cjs/stream/index.js +0 -6
- package/cjs/stream/index.js.map +0 -1
- package/cjs/stream/stream.js +0 -45
- package/cjs/stream/stream.js.map +0 -1
- package/cjs/utils/auto-reset-event.js +0 -37
- package/cjs/utils/auto-reset-event.js.map +0 -1
- package/cjs/utils/base64.js +0 -210
- package/cjs/utils/base64.js.map +0 -1
- package/cjs/utils/chunk.js +0 -75
- package/cjs/utils/chunk.js.map +0 -1
- package/cjs/utils/event-queue.js +0 -108
- package/cjs/utils/event-queue.js.map +0 -1
- package/cjs/utils/index.js +0 -8
- package/cjs/utils/index.js.map +0 -1
- package/tsconfig.cjs.json +0 -11
- package/tsconfig.esm.json +0 -28
- package/tsconfig.esm.tsbuildinfo +0 -1305
- package/tsconfig.json +0 -18
package/src/commands/reverse.ts
CHANGED
|
@@ -1,133 +1,134 @@
|
|
|
1
|
-
import { AutoDisposable } from '@yume-chan/event';
|
|
2
|
-
import Struct from '@yume-chan/struct';
|
|
3
|
-
import { AdbPacket } from '../packet';
|
|
4
|
-
import { AdbIncomingSocketEventArgs, AdbPacketDispatcher, AdbSocket } from '../socket';
|
|
5
|
-
import { AdbBufferedStream } from '../stream';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
.string('
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
this.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
e.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
* @param
|
|
90
|
-
* @param
|
|
91
|
-
* @
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
this.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
this.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
this.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
1
|
+
import { AutoDisposable } from '@yume-chan/event';
|
|
2
|
+
import Struct from '@yume-chan/struct';
|
|
3
|
+
import type { AdbPacket } from '../packet';
|
|
4
|
+
import type { AdbIncomingSocketEventArgs, AdbPacketDispatcher, AdbSocket } from '../socket';
|
|
5
|
+
import { AdbBufferedStream } from '../stream';
|
|
6
|
+
import { decodeUtf8 } from "../utils";
|
|
7
|
+
|
|
8
|
+
export interface AdbReverseHandler {
|
|
9
|
+
onSocket(packet: AdbPacket, socket: AdbSocket): void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface AdbForwardListener {
|
|
13
|
+
deviceSerial: string;
|
|
14
|
+
|
|
15
|
+
localName: string;
|
|
16
|
+
|
|
17
|
+
remoteName: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const AdbReverseStringResponse =
|
|
21
|
+
new Struct({ littleEndian: true })
|
|
22
|
+
.string('length', { length: 4 })
|
|
23
|
+
.string('content', { lengthField: 'length', lengthFieldBase: 16 });
|
|
24
|
+
|
|
25
|
+
const AdbReverseErrorResponse =
|
|
26
|
+
new Struct({ littleEndian: true })
|
|
27
|
+
.fields(AdbReverseStringResponse)
|
|
28
|
+
.postDeserialize((value) => {
|
|
29
|
+
throw new Error(value.content);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export class AdbReverseCommand extends AutoDisposable {
|
|
33
|
+
protected localPortToHandler = new Map<number, AdbReverseHandler>();
|
|
34
|
+
|
|
35
|
+
protected deviceAddressToLocalPort = new Map<string, number>();
|
|
36
|
+
|
|
37
|
+
protected dispatcher: AdbPacketDispatcher;
|
|
38
|
+
|
|
39
|
+
protected listening = false;
|
|
40
|
+
|
|
41
|
+
public constructor(dispatcher: AdbPacketDispatcher) {
|
|
42
|
+
super();
|
|
43
|
+
|
|
44
|
+
this.dispatcher = dispatcher;
|
|
45
|
+
this.addDisposable(this.dispatcher.onIncomingSocket(this.handleIncomingSocket, this));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected handleIncomingSocket(e: AdbIncomingSocketEventArgs): void {
|
|
49
|
+
if (e.handled) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const address = decodeUtf8(e.packet.payload!);
|
|
54
|
+
// tcp:1234\0
|
|
55
|
+
const port = Number.parseInt(address.substring(4));
|
|
56
|
+
if (this.localPortToHandler.has(port)) {
|
|
57
|
+
this.localPortToHandler.get(port)!.onSocket(e.packet, e.socket);
|
|
58
|
+
e.handled = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private async createBufferedStream(service: string) {
|
|
63
|
+
const socket = await this.dispatcher.createSocket(service);
|
|
64
|
+
return new AdbBufferedStream(socket);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private async sendRequest(service: string) {
|
|
68
|
+
const stream = await this.createBufferedStream(service);
|
|
69
|
+
const success = decodeUtf8(await stream.read(4)) === 'OKAY';
|
|
70
|
+
if (!success) {
|
|
71
|
+
await AdbReverseErrorResponse.deserialize(stream);
|
|
72
|
+
}
|
|
73
|
+
return stream;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public async list(): Promise<AdbForwardListener[]> {
|
|
77
|
+
const stream = await this.createBufferedStream('reverse:list-forward');
|
|
78
|
+
|
|
79
|
+
const response = await AdbReverseStringResponse.deserialize(stream);
|
|
80
|
+
return response.content!.split('\n').map(line => {
|
|
81
|
+
const [deviceSerial, localName, remoteName] = line.split(' ');
|
|
82
|
+
return { deviceSerial, localName, remoteName };
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// No need to close the stream, device will close it
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @param deviceAddress The address adbd on device is listening on. Can be `tcp:0` to let adbd choose an available TCP port by itself.
|
|
90
|
+
* @param localPort Native ADB will open a connection to localPort when reverse connection starts. In webadb, it's only used to uniquely identify a reverse registry, `handler` will be called on connection.
|
|
91
|
+
* @param handler A callback to handle incoming connections
|
|
92
|
+
* @returns If `deviceAddress` is `tcp:0`, return `tcp:{ACTUAL_LISTENING_PORT}`; otherwise, return `deviceAddress`.
|
|
93
|
+
*/
|
|
94
|
+
public async add(
|
|
95
|
+
deviceAddress: string,
|
|
96
|
+
localPort: number,
|
|
97
|
+
handler: AdbReverseHandler,
|
|
98
|
+
): Promise<string> {
|
|
99
|
+
const stream = await this.sendRequest(`reverse:forward:${deviceAddress};tcp:${localPort}`);
|
|
100
|
+
|
|
101
|
+
// `tcp:0` tells the device to pick an available port.
|
|
102
|
+
// However, device will response with the selected port for all `tcp:` requests.
|
|
103
|
+
if (deviceAddress.startsWith('tcp:')) {
|
|
104
|
+
const response = await AdbReverseStringResponse.deserialize(stream);
|
|
105
|
+
deviceAddress = `tcp:${Number.parseInt(response.content!, 10)}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
this.localPortToHandler.set(localPort, handler);
|
|
109
|
+
this.deviceAddressToLocalPort.set(deviceAddress, localPort);
|
|
110
|
+
return deviceAddress;
|
|
111
|
+
|
|
112
|
+
// No need to close the stream, device will close it
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public async remove(deviceAddress: string): Promise<void> {
|
|
116
|
+
await this.sendRequest(`reverse:killforward:${deviceAddress}`);
|
|
117
|
+
|
|
118
|
+
if (this.deviceAddressToLocalPort.has(deviceAddress)) {
|
|
119
|
+
this.localPortToHandler.delete(this.deviceAddressToLocalPort.get(deviceAddress)!);
|
|
120
|
+
this.deviceAddressToLocalPort.delete(deviceAddress);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// No need to close the stream, device will close it
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public async removeAll(): Promise<void> {
|
|
127
|
+
await this.sendRequest(`reverse:killforward-all`);
|
|
128
|
+
|
|
129
|
+
this.deviceAddressToLocalPort.clear();
|
|
130
|
+
this.localPortToHandler.clear();
|
|
131
|
+
|
|
132
|
+
// No need to close the stream, device will close it
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -1,68 +1,87 @@
|
|
|
1
|
-
import { Adb } from '../../adb';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export * from './
|
|
8
|
-
export * from './
|
|
9
|
-
export * from './
|
|
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
|
-
|
|
61
|
-
return this.createShell(
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
1
|
+
import type { Adb } from '../../adb';
|
|
2
|
+
import { AdbLegacyShell } from './legacy';
|
|
3
|
+
import { AdbShellProtocol } from './protocol';
|
|
4
|
+
import type { AdbShell, AdbShellConstructor } from './types';
|
|
5
|
+
|
|
6
|
+
export * from './legacy';
|
|
7
|
+
export * from './protocol';
|
|
8
|
+
export * from './types';
|
|
9
|
+
export * from './utils';
|
|
10
|
+
|
|
11
|
+
export interface AdbChildProcessOptions {
|
|
12
|
+
/**
|
|
13
|
+
* A list of `AdbShellConstructor`s to be used.
|
|
14
|
+
*
|
|
15
|
+
* Different `AdbShell` has different capabilities, thus requires specific adaptations.
|
|
16
|
+
* Check each `AdbShell`'s documentation for details.
|
|
17
|
+
*
|
|
18
|
+
* The first one whose `isSupported` returns `true` will be used.
|
|
19
|
+
* If no `AdbShell` is supported, an error will be thrown.
|
|
20
|
+
*
|
|
21
|
+
* The default value is `[AdbShellProtocol, AdbLegacyShell]`.
|
|
22
|
+
*/
|
|
23
|
+
shells: AdbShellConstructor[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const DefaultOptions: AdbChildProcessOptions = {
|
|
27
|
+
shells: [AdbShellProtocol, AdbLegacyShell],
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export class AdbChildProcess {
|
|
31
|
+
public readonly adb: Adb;
|
|
32
|
+
|
|
33
|
+
public constructor(adb: Adb) {
|
|
34
|
+
this.adb = adb;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private async createShell(command: string, options?: Partial<AdbChildProcessOptions>): Promise<AdbShell> {
|
|
38
|
+
let { shells } = { ...DefaultOptions, ...options };
|
|
39
|
+
|
|
40
|
+
let shell: AdbShellConstructor | undefined;
|
|
41
|
+
for (const item of shells) {
|
|
42
|
+
if (await item.isSupported(this.adb)) {
|
|
43
|
+
shell = item;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!shell) {
|
|
49
|
+
throw new Error('No specified shell is supported by the device');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return await shell.spawn(this.adb, command);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Spawns the default shell in interactive mode.
|
|
57
|
+
* @param options The options for creating the `AdbShell`
|
|
58
|
+
* @returns A new `AdbShell` instance connecting to the spawned shell process.
|
|
59
|
+
*/
|
|
60
|
+
public shell(options?: Partial<AdbChildProcessOptions>): Promise<AdbShell> {
|
|
61
|
+
return this.createShell('', options);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Spawns a new process using the given `command`.
|
|
66
|
+
* @param command The command to run, or an array of strings containing both command and args.
|
|
67
|
+
* @param options The options for creating the `AdbShell`
|
|
68
|
+
* @returns A new `AdbShell` instance connecting to the spawned process.
|
|
69
|
+
*/
|
|
70
|
+
public spawn(command: string | string[], options?: Partial<AdbChildProcessOptions>): Promise<AdbShell> {
|
|
71
|
+
if (Array.isArray(command)) {
|
|
72
|
+
command = command.join(' ');
|
|
73
|
+
}
|
|
74
|
+
return this.createShell(command, options);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Spawns a new process, waits until it exits, and returns the entire output.
|
|
79
|
+
* @param command The command to run
|
|
80
|
+
* @param args List of command arguments
|
|
81
|
+
* @returns The entire output of the command
|
|
82
|
+
*/
|
|
83
|
+
public exec(command: string, ...args: string[]): Promise<string> {
|
|
84
|
+
// `exec` only needs the entire output, use Legacy Shell is simpler.
|
|
85
|
+
return this.adb.createSocketAndReadAll(`shell:${command} ${args.join(' ')}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -1,42 +1,59 @@
|
|
|
1
|
-
import { EventEmitter } from "@yume-chan/event";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
public
|
|
16
|
-
|
|
17
|
-
public
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
private
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
1
|
+
import { EventEmitter } from "@yume-chan/event";
|
|
2
|
+
import type { Adb } from "../../adb";
|
|
3
|
+
import type { AdbSocket } from "../../socket";
|
|
4
|
+
import type { AdbShell } from "./types";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The legacy shell
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* * `onStderr`: No
|
|
11
|
+
* * `onExit` exit code: No
|
|
12
|
+
* * `resize`: No
|
|
13
|
+
*/
|
|
14
|
+
export class AdbLegacyShell implements AdbShell {
|
|
15
|
+
public static isSupported() { return true; }
|
|
16
|
+
|
|
17
|
+
public static async spawn(adb: Adb, command: string) {
|
|
18
|
+
return new AdbLegacyShell(await adb.createSocket(`shell:${command}`));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private readonly socket: AdbSocket;
|
|
22
|
+
|
|
23
|
+
private readonly stdoutEvent = new EventEmitter<ArrayBuffer>();
|
|
24
|
+
public get onStdout() { return this.stdoutEvent.event; }
|
|
25
|
+
|
|
26
|
+
private readonly stderrEvent = new EventEmitter<ArrayBuffer>();
|
|
27
|
+
public get onStderr() { return this.stderrEvent.event; }
|
|
28
|
+
|
|
29
|
+
private readonly exitEvent = new EventEmitter<number>();
|
|
30
|
+
public get onExit() { return this.exitEvent.event; }
|
|
31
|
+
|
|
32
|
+
public constructor(socket: AdbSocket) {
|
|
33
|
+
this.socket = socket;
|
|
34
|
+
this.socket.onData(this.handleData, this);
|
|
35
|
+
this.socket.onClose(this.handleExit, this);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private handleData(data: ArrayBuffer) {
|
|
39
|
+
// Legacy shell doesn't support splitting output streams.
|
|
40
|
+
this.stdoutEvent.fire(data);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private handleExit() {
|
|
44
|
+
// Legacy shell doesn't support returning exit code.
|
|
45
|
+
this.exitEvent.fire(0);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public async write(data: ArrayBuffer) {
|
|
49
|
+
this.socket.write(data);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public resize() {
|
|
53
|
+
// Not supported
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public kill() {
|
|
57
|
+
return this.socket.close();
|
|
58
|
+
}
|
|
59
|
+
}
|