@yume-chan/android-bin 0.0.20 → 0.0.21
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 +30 -0
- package/CHANGELOG.md +14 -1
- package/LICENSE +21 -0
- package/esm/bu.d.ts +20 -7
- package/esm/bu.d.ts.map +1 -1
- package/esm/bu.js +47 -8
- package/esm/bu.js.map +1 -1
- package/esm/bug-report.d.ts +82 -21
- package/esm/bug-report.d.ts.map +1 -1
- package/esm/bug-report.js +187 -53
- package/esm/bug-report.js.map +1 -1
- package/esm/cmd.d.ts +4 -6
- package/esm/cmd.d.ts.map +1 -1
- package/esm/cmd.js +36 -21
- package/esm/cmd.js.map +1 -1
- package/esm/demo-mode.d.ts +3 -3
- package/esm/demo-mode.d.ts.map +1 -1
- package/esm/demo-mode.js +14 -15
- package/esm/demo-mode.js.map +1 -1
- package/esm/dumpsys.d.ts +17 -0
- package/esm/dumpsys.d.ts.map +1 -1
- package/esm/dumpsys.js +78 -0
- package/esm/dumpsys.js.map +1 -1
- package/esm/index.d.ts +3 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +3 -0
- package/esm/index.js.map +1 -1
- package/esm/logcat.d.ts +1 -0
- package/esm/logcat.d.ts.map +1 -1
- package/esm/logcat.js +15 -13
- package/esm/logcat.js.map +1 -1
- package/esm/overlay-display.d.ts +20 -3
- package/esm/overlay-display.d.ts.map +1 -1
- package/esm/overlay-display.js +34 -61
- package/esm/overlay-display.js.map +1 -1
- package/esm/pm.d.ts +25 -2
- package/esm/pm.d.ts.map +1 -1
- package/esm/pm.js +88 -17
- package/esm/pm.js.map +1 -1
- package/esm/settings.d.ts +21 -8
- package/esm/settings.d.ts.map +1 -1
- package/esm/settings.js +50 -25
- package/esm/settings.js.map +1 -1
- package/esm/string-format.d.ts +40 -0
- package/esm/string-format.d.ts.map +1 -0
- package/esm/string-format.js +153 -0
- package/esm/string-format.js.map +1 -0
- package/package.json +13 -8
- package/src/bu.ts +68 -14
- package/src/bug-report.ts +234 -68
- package/src/cmd.ts +64 -30
- package/src/demo-mode.ts +47 -43
- package/src/dumpsys.ts +91 -0
- package/src/index.ts +3 -0
- package/src/logcat.ts +39 -37
- package/src/overlay-display.ts +82 -85
- package/src/pm.ts +149 -27
- package/src/settings.ts +93 -43
- package/src/string-format.ts +199 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/src/bug-report.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// cspell: ignore bugreport
|
|
2
2
|
// cspell: ignore bugreportz
|
|
3
3
|
|
|
4
|
+
import type { Adb, AdbSync } from "@yume-chan/adb";
|
|
4
5
|
import { AdbCommandBase, AdbSubprocessShellProtocol } from "@yume-chan/adb";
|
|
5
|
-
import type { ReadableStream } from "@yume-chan/stream-extra";
|
|
6
|
+
import type { AbortSignal, ReadableStream } from "@yume-chan/stream-extra";
|
|
6
7
|
import {
|
|
8
|
+
AbortController,
|
|
7
9
|
DecodeUtf8Stream,
|
|
8
10
|
PushReadableStream,
|
|
9
11
|
SplitStringStream,
|
|
@@ -11,80 +13,200 @@ import {
|
|
|
11
13
|
WritableStream,
|
|
12
14
|
} from "@yume-chan/stream-extra";
|
|
13
15
|
|
|
14
|
-
export interface
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
export interface BugReportCapabilities {
|
|
17
|
+
supportsBugReport: boolean;
|
|
18
|
+
bugReportZVersion?: string | undefined;
|
|
19
|
+
supportsBugReportZ: boolean;
|
|
20
|
+
supportsBugReportZProgress: boolean;
|
|
21
|
+
supportsBugReportZStream: boolean;
|
|
22
|
+
}
|
|
17
23
|
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
export interface BugReportZOptions {
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
/**
|
|
27
|
+
* A callback that will be called when progress is updated.
|
|
28
|
+
*
|
|
29
|
+
* Specify `onProgress` when `supportsBugReportZProgress` is `false` will throw an error.
|
|
30
|
+
*/
|
|
31
|
+
onProgress?: ((completed: string, total: string) => void) | undefined;
|
|
20
32
|
}
|
|
21
33
|
|
|
22
|
-
export class
|
|
23
|
-
|
|
34
|
+
export class BugReport extends AdbCommandBase {
|
|
35
|
+
static VERSION_REGEX = /(\d+)\.(\d+)/;
|
|
24
36
|
|
|
25
|
-
|
|
37
|
+
static BEGIN_REGEX = /BEGIN:(.*)/;
|
|
26
38
|
|
|
27
|
-
|
|
39
|
+
static PROGRESS_REGEX = /PROGRESS:(.*)\/(.*)/;
|
|
28
40
|
|
|
29
|
-
|
|
41
|
+
static OK_REGEX = /OK:(.*)/;
|
|
30
42
|
|
|
31
|
-
|
|
43
|
+
static FAIL_REGEX = /FAIL:(.*)/;
|
|
32
44
|
|
|
33
45
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* @returns a `BugReportVersion` object, or `undefined` if `bugreportz` is not available.
|
|
46
|
+
* Queries the device's bugreport capabilities.
|
|
37
47
|
*/
|
|
38
|
-
|
|
48
|
+
static async queryCapabilities(adb: Adb): Promise<BugReport> {
|
|
39
49
|
// bugreportz requires shell protocol
|
|
40
|
-
if (!AdbSubprocessShellProtocol.isSupported(
|
|
41
|
-
return
|
|
50
|
+
if (!AdbSubprocessShellProtocol.isSupported(adb)) {
|
|
51
|
+
return new BugReport(adb, {
|
|
52
|
+
supportsBugReport: true,
|
|
53
|
+
bugReportZVersion: undefined,
|
|
54
|
+
supportsBugReportZ: false,
|
|
55
|
+
supportsBugReportZProgress: false,
|
|
56
|
+
supportsBugReportZStream: false,
|
|
57
|
+
});
|
|
42
58
|
}
|
|
43
59
|
|
|
44
|
-
const { stderr, exitCode } = await
|
|
60
|
+
const { stderr, exitCode } = await adb.subprocess.spawnAndWait([
|
|
45
61
|
"bugreportz",
|
|
46
62
|
"-v",
|
|
47
63
|
]);
|
|
48
64
|
if (exitCode !== 0 || stderr === "") {
|
|
49
|
-
return
|
|
65
|
+
return new BugReport(adb, {
|
|
66
|
+
supportsBugReport: true,
|
|
67
|
+
bugReportZVersion: undefined,
|
|
68
|
+
supportsBugReportZ: false,
|
|
69
|
+
supportsBugReportZProgress: false,
|
|
70
|
+
supportsBugReportZStream: false,
|
|
71
|
+
});
|
|
50
72
|
}
|
|
51
73
|
|
|
52
|
-
const match = stderr.match(
|
|
74
|
+
const match = stderr.match(BugReport.VERSION_REGEX);
|
|
53
75
|
if (!match) {
|
|
54
|
-
return
|
|
76
|
+
return new BugReport(adb, {
|
|
77
|
+
supportsBugReport: true,
|
|
78
|
+
bugReportZVersion: undefined,
|
|
79
|
+
supportsBugReportZ: false,
|
|
80
|
+
supportsBugReportZProgress: false,
|
|
81
|
+
supportsBugReportZStream: false,
|
|
82
|
+
});
|
|
55
83
|
}
|
|
56
84
|
|
|
57
|
-
const major =
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
85
|
+
const [major, minor] = match[0]
|
|
86
|
+
.split(".")
|
|
87
|
+
.map((x) => parseInt(x, 10)) as [number, number];
|
|
88
|
+
return new BugReport(adb, {
|
|
89
|
+
// Before BugReportZ version 1.2 (Android 12), BugReport was deprecated but still works.
|
|
90
|
+
supportsBugReport: major === 1 && minor <= 1,
|
|
91
|
+
bugReportZVersion: match[0],
|
|
92
|
+
supportsBugReportZ: true,
|
|
93
|
+
supportsBugReportZProgress: major > 1 || minor >= 1,
|
|
94
|
+
supportsBugReportZStream: major > 1 || minor >= 2,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#supportsBugReport: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Gets whether the device supports flat (text file, non-zipped) bugreport.
|
|
101
|
+
*
|
|
102
|
+
* Should be `true` for Android version <= 11.
|
|
103
|
+
*/
|
|
104
|
+
get supportsBugReport() {
|
|
105
|
+
return this.#supportsBugReport;
|
|
106
|
+
}
|
|
62
107
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
108
|
+
#bugReportZVersion: string | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* Gets the version of BugReportZ.
|
|
111
|
+
*
|
|
112
|
+
* Will be `undefined` if BugReportZ is not supported.
|
|
113
|
+
*/
|
|
114
|
+
get bugReportZVersion() {
|
|
115
|
+
return this.#bugReportZVersion;
|
|
66
116
|
}
|
|
67
117
|
|
|
68
|
-
|
|
69
|
-
|
|
118
|
+
#supportsBugReportZ: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Gets whether the device supports zipped bugreport.
|
|
121
|
+
*
|
|
122
|
+
* Should be `true` for Android version >= 7.
|
|
123
|
+
*/
|
|
124
|
+
get supportsBugReportZ() {
|
|
125
|
+
return this.#supportsBugReportZ;
|
|
70
126
|
}
|
|
71
127
|
|
|
128
|
+
#supportsBugReportZProgress: boolean;
|
|
72
129
|
/**
|
|
73
|
-
*
|
|
130
|
+
* Gets whether the device supports progress report for zipped bugreport.
|
|
74
131
|
*
|
|
75
|
-
*
|
|
132
|
+
* Should be `true` for Android version >= 8.
|
|
133
|
+
*/
|
|
134
|
+
get supportsBugReportZProgress() {
|
|
135
|
+
return this.#supportsBugReportZProgress;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
#supportsBugReportZStream: boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Gets whether the device supports streaming zipped bugreport.
|
|
141
|
+
*
|
|
142
|
+
* Should be `true` for Android version >= 12.
|
|
143
|
+
*/
|
|
144
|
+
get supportsBugReportZStream() {
|
|
145
|
+
return this.#supportsBugReportZStream;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
constructor(adb: Adb, capabilities: BugReportCapabilities) {
|
|
149
|
+
super(adb);
|
|
150
|
+
|
|
151
|
+
this.#supportsBugReport = capabilities.supportsBugReport;
|
|
152
|
+
this.#bugReportZVersion = capabilities.bugReportZVersion;
|
|
153
|
+
this.#supportsBugReportZ = capabilities.supportsBugReportZ;
|
|
154
|
+
this.#supportsBugReportZProgress =
|
|
155
|
+
capabilities.supportsBugReportZProgress;
|
|
156
|
+
this.#supportsBugReportZStream = capabilities.supportsBugReportZStream;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Creates a legacy, non-zipped bugreport file, or throws an error if `supportsBugReport` is `false`.
|
|
161
|
+
*
|
|
162
|
+
* @returns A flat (text file, non-zipped) bugreport.
|
|
163
|
+
*/
|
|
164
|
+
bugReport(): ReadableStream<Uint8Array> {
|
|
165
|
+
if (!this.#supportsBugReport) {
|
|
166
|
+
throw new Error(
|
|
167
|
+
"Flat (text file, non-zipped) bugreport is not supported.",
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return new WrapReadableStream(async () => {
|
|
172
|
+
// https://cs.android.com/android/platform/superproject/+/master:frameworks/native/cmds/bugreport/bugreport.cpp;drc=9b73bf07d73dbab5b792632e1e233edbad77f5fd;bpv=0;bpt=0
|
|
173
|
+
const process = await this.adb.subprocess.spawn(["bugreport"]);
|
|
174
|
+
return process.stdout;
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Creates a zipped bugreport file, or throws an error if `supportsBugReportZ` is `false`.
|
|
180
|
+
*
|
|
181
|
+
* Compare to `bugReportZStream`, this method will write the output to a file on device.
|
|
76
182
|
* You can pull it later using sync protocol.
|
|
77
183
|
*
|
|
78
|
-
* @
|
|
79
|
-
* @returns The path of the bugreport file.
|
|
184
|
+
* @returns The path to the generated bugreport file on device filesystem.
|
|
80
185
|
*/
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
186
|
+
async bugReportZ(options?: BugReportZOptions): Promise<string> {
|
|
187
|
+
if (options?.signal?.aborted) {
|
|
188
|
+
throw options?.signal.reason ?? new Error("Aborted");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (!this.#supportsBugReportZ) {
|
|
192
|
+
throw new Error("bugreportz is not supported");
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const args = ["bugreportz"];
|
|
196
|
+
if (options?.onProgress) {
|
|
197
|
+
if (!this.#supportsBugReportZProgress) {
|
|
198
|
+
throw new Error("bugreportz progress is not supported");
|
|
199
|
+
}
|
|
200
|
+
args.push("-p");
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const process = await this.adb.subprocess.spawn(args, {
|
|
204
|
+
protocols: [AdbSubprocessShellProtocol],
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
options?.signal?.addEventListener("abort", () => {
|
|
208
|
+
void process.kill();
|
|
209
|
+
});
|
|
88
210
|
|
|
89
211
|
let filename: string | undefined;
|
|
90
212
|
let error: string | undefined;
|
|
@@ -96,29 +218,29 @@ export class BugReportZ extends AdbCommandBase {
|
|
|
96
218
|
new WritableStream<string>({
|
|
97
219
|
write(line) {
|
|
98
220
|
// `BEGIN:` and `PROGRESS:` only appear when `-p` is specified.
|
|
99
|
-
let match = line.match(
|
|
221
|
+
let match = line.match(BugReport.PROGRESS_REGEX);
|
|
100
222
|
if (match) {
|
|
101
|
-
onProgress?.(match[1]!, match[2]!);
|
|
223
|
+
options?.onProgress?.(match[1]!, match[2]!);
|
|
102
224
|
}
|
|
103
225
|
|
|
104
|
-
match = line.match(
|
|
226
|
+
match = line.match(BugReport.BEGIN_REGEX);
|
|
105
227
|
if (match) {
|
|
106
228
|
filename = match[1]!;
|
|
107
229
|
}
|
|
108
230
|
|
|
109
|
-
match = line.match(
|
|
231
|
+
match = line.match(BugReport.OK_REGEX);
|
|
110
232
|
if (match) {
|
|
111
233
|
filename = match[1];
|
|
112
234
|
}
|
|
113
235
|
|
|
114
|
-
match = line.match(
|
|
236
|
+
match = line.match(BugReport.FAIL_REGEX);
|
|
115
237
|
if (match) {
|
|
116
238
|
// Don't report error now
|
|
117
239
|
// We want to gather all output.
|
|
118
240
|
error = match[1];
|
|
119
241
|
}
|
|
120
242
|
},
|
|
121
|
-
})
|
|
243
|
+
}),
|
|
122
244
|
);
|
|
123
245
|
|
|
124
246
|
if (error) {
|
|
@@ -133,23 +255,24 @@ export class BugReportZ extends AdbCommandBase {
|
|
|
133
255
|
return filename;
|
|
134
256
|
}
|
|
135
257
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
258
|
+
/**
|
|
259
|
+
* Creates a zipped bugreport file, or throws an error if `supportsBugReportZStream` is `false`.
|
|
260
|
+
*
|
|
261
|
+
* @returns The content of the generated bugreport file.
|
|
262
|
+
*/
|
|
263
|
+
bugReportZStream(): ReadableStream<Uint8Array> {
|
|
141
264
|
return new PushReadableStream(async (controller) => {
|
|
142
|
-
const process = await this.adb.subprocess.spawn(
|
|
143
|
-
"bugreportz",
|
|
144
|
-
|
|
145
|
-
|
|
265
|
+
const process = await this.adb.subprocess.spawn(
|
|
266
|
+
["bugreportz", "-s"],
|
|
267
|
+
{ protocols: [AdbSubprocessShellProtocol] },
|
|
268
|
+
);
|
|
146
269
|
process.stdout
|
|
147
270
|
.pipeTo(
|
|
148
271
|
new WritableStream({
|
|
149
272
|
async write(chunk) {
|
|
150
273
|
await controller.enqueue(chunk);
|
|
151
274
|
},
|
|
152
|
-
})
|
|
275
|
+
}),
|
|
153
276
|
)
|
|
154
277
|
.catch((e) => {
|
|
155
278
|
controller.error(e);
|
|
@@ -161,7 +284,7 @@ export class BugReportZ extends AdbCommandBase {
|
|
|
161
284
|
write(chunk) {
|
|
162
285
|
controller.error(new Error(chunk));
|
|
163
286
|
},
|
|
164
|
-
})
|
|
287
|
+
}),
|
|
165
288
|
)
|
|
166
289
|
.catch((e) => {
|
|
167
290
|
controller.error(e);
|
|
@@ -169,14 +292,57 @@ export class BugReportZ extends AdbCommandBase {
|
|
|
169
292
|
await process.exit;
|
|
170
293
|
});
|
|
171
294
|
}
|
|
172
|
-
}
|
|
173
295
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
296
|
+
/**
|
|
297
|
+
* Automatically choose the best bugreport method.
|
|
298
|
+
*
|
|
299
|
+
* * If `supportsBugReportZStream` is `true`, this method will return a stream of zipped bugreport.
|
|
300
|
+
* * If `supportsBugReportZ` is `true`, this method will return a stream of zipped bugreport, and will delete the file on device after the stream is closed.
|
|
301
|
+
* * If `supportsBugReport` is `true`, this method will return a stream of flat bugreport.
|
|
302
|
+
*
|
|
303
|
+
* @param onProgress
|
|
304
|
+
* If `supportsBugReportZStream` is `false` and `supportsBugReportZProgress` is `true`,
|
|
305
|
+
* this callback will be called when progress is updated.
|
|
306
|
+
*/
|
|
307
|
+
automatic(onProgress?: (completed: string, total: string) => void): {
|
|
308
|
+
type: "bugreport" | "bugreportz";
|
|
309
|
+
stream: ReadableStream<Uint8Array>;
|
|
310
|
+
} {
|
|
311
|
+
if (this.#supportsBugReportZStream) {
|
|
312
|
+
return { type: "bugreportz", stream: this.bugReportZStream() };
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (this.#supportsBugReportZ) {
|
|
316
|
+
let path: string | undefined;
|
|
317
|
+
let sync: AdbSync | undefined;
|
|
318
|
+
const controller = new AbortController();
|
|
319
|
+
const cleanup = async () => {
|
|
320
|
+
controller.abort();
|
|
321
|
+
await sync?.dispose();
|
|
322
|
+
if (path) {
|
|
323
|
+
await this.adb.rm(path);
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
return {
|
|
328
|
+
type: "bugreportz",
|
|
329
|
+
stream: new WrapReadableStream({
|
|
330
|
+
start: async () => {
|
|
331
|
+
path = await this.bugReportZ({
|
|
332
|
+
signal: controller.signal,
|
|
333
|
+
onProgress: this.#supportsBugReportZProgress
|
|
334
|
+
? onProgress
|
|
335
|
+
: undefined,
|
|
336
|
+
});
|
|
337
|
+
sync = await this.adb.sync();
|
|
338
|
+
return sync.read(path);
|
|
339
|
+
},
|
|
340
|
+
cancel: cleanup,
|
|
341
|
+
close: cleanup,
|
|
342
|
+
}),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return { type: "bugreport", stream: this.bugReport() };
|
|
181
347
|
}
|
|
182
348
|
}
|
package/src/cmd.ts
CHANGED
|
@@ -1,67 +1,101 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
Adb,
|
|
3
|
+
AdbSubprocessProtocol,
|
|
4
|
+
AdbSubprocessProtocolConstructor,
|
|
5
|
+
AdbSubprocessWaitResult,
|
|
6
|
+
} from "@yume-chan/adb";
|
|
2
7
|
import {
|
|
3
8
|
AdbCommandBase,
|
|
4
9
|
AdbFeature,
|
|
5
10
|
AdbSubprocessNoneProtocol,
|
|
6
11
|
AdbSubprocessShellProtocol,
|
|
7
12
|
} from "@yume-chan/adb";
|
|
13
|
+
import { ConcatStringStream, DecodeUtf8Stream } from "@yume-chan/stream-extra";
|
|
8
14
|
|
|
9
15
|
export class Cmd extends AdbCommandBase {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
private _supportsAbbExec: boolean;
|
|
14
|
-
|
|
15
|
-
public get supportsShellV2() {
|
|
16
|
-
return this._supportsShellV2;
|
|
16
|
+
#supportsShellV2: boolean;
|
|
17
|
+
get supportsShellV2() {
|
|
18
|
+
return this.#supportsShellV2;
|
|
17
19
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
|
|
21
|
+
#supportsCmd: boolean;
|
|
22
|
+
get supportsCmd() {
|
|
23
|
+
return this.#supportsCmd;
|
|
20
24
|
}
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
|
|
26
|
+
#supportsAbb: boolean;
|
|
27
|
+
get supportsAbb() {
|
|
28
|
+
return this.#supportsAbb;
|
|
23
29
|
}
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
|
|
31
|
+
#supportsAbbExec: boolean;
|
|
32
|
+
get supportsAbbExec() {
|
|
33
|
+
return this.#supportsAbbExec;
|
|
26
34
|
}
|
|
27
35
|
|
|
28
|
-
|
|
36
|
+
constructor(adb: Adb) {
|
|
29
37
|
super(adb);
|
|
30
|
-
this
|
|
31
|
-
this
|
|
32
|
-
this
|
|
33
|
-
this
|
|
38
|
+
this.#supportsShellV2 = adb.supportsFeature(AdbFeature.ShellV2);
|
|
39
|
+
this.#supportsCmd = adb.supportsFeature(AdbFeature.Cmd);
|
|
40
|
+
this.#supportsAbb = adb.supportsFeature(AdbFeature.Abb);
|
|
41
|
+
this.#supportsAbbExec = adb.supportsFeature(AdbFeature.AbbExec);
|
|
34
42
|
}
|
|
35
43
|
|
|
36
|
-
|
|
44
|
+
async spawn(
|
|
37
45
|
shellProtocol: boolean,
|
|
38
46
|
command: string,
|
|
39
47
|
...args: string[]
|
|
40
|
-
) {
|
|
48
|
+
): Promise<AdbSubprocessProtocol> {
|
|
41
49
|
let supportsAbb: boolean;
|
|
42
|
-
let supportsCmd: boolean = this
|
|
50
|
+
let supportsCmd: boolean = this.#supportsCmd;
|
|
43
51
|
let service: string;
|
|
44
52
|
let Protocol: AdbSubprocessProtocolConstructor;
|
|
45
53
|
if (shellProtocol) {
|
|
46
|
-
supportsAbb = this
|
|
54
|
+
supportsAbb = this.#supportsAbb;
|
|
47
55
|
supportsCmd &&= this.supportsShellV2;
|
|
48
56
|
service = "abb";
|
|
49
57
|
Protocol = AdbSubprocessShellProtocol;
|
|
50
58
|
} else {
|
|
51
|
-
supportsAbb = this
|
|
59
|
+
supportsAbb = this.#supportsAbbExec;
|
|
52
60
|
service = "abb_exec";
|
|
53
61
|
Protocol = AdbSubprocessNoneProtocol;
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
if (supportsAbb) {
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
return new Protocol(
|
|
66
|
+
await this.adb.createSocket(
|
|
67
|
+
`${service}:${command}\0${args.join("\0")}\0`,
|
|
68
|
+
),
|
|
59
69
|
);
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (supportsCmd) {
|
|
62
73
|
return Protocol.raw(this.adb, `cmd ${command} ${args.join(" ")}`);
|
|
63
|
-
} else {
|
|
64
|
-
throw new Error("Not supported");
|
|
65
74
|
}
|
|
75
|
+
|
|
76
|
+
throw new Error("Not supported");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async spawnAndWait(
|
|
80
|
+
command: string,
|
|
81
|
+
...args: string[]
|
|
82
|
+
): Promise<AdbSubprocessWaitResult> {
|
|
83
|
+
const process = await this.spawn(true, command, ...args);
|
|
84
|
+
|
|
85
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
86
|
+
process.stdout
|
|
87
|
+
.pipeThrough(new DecodeUtf8Stream())
|
|
88
|
+
.pipeThrough(new ConcatStringStream()),
|
|
89
|
+
process.stderr
|
|
90
|
+
.pipeThrough(new DecodeUtf8Stream())
|
|
91
|
+
.pipeThrough(new ConcatStringStream()),
|
|
92
|
+
process.exit,
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
stdout,
|
|
97
|
+
stderr,
|
|
98
|
+
exitCode,
|
|
99
|
+
};
|
|
66
100
|
}
|
|
67
101
|
}
|