@yume-chan/android-bin 2.1.0 → 3.0.0-beta.0
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/LICENSE +1 -1
- package/README.md +4 -1
- package/esm/am.d.ts +20 -15
- package/esm/am.d.ts.map +1 -1
- package/esm/am.js +60 -13
- package/esm/am.js.map +1 -1
- package/esm/bu.d.ts +22 -18
- package/esm/bu.d.ts.map +1 -1
- package/esm/bu.js +10 -4
- package/esm/bu.js.map +1 -1
- package/esm/bug-report.d.ts +21 -20
- package/esm/bug-report.d.ts.map +1 -1
- package/esm/bug-report.js +15 -21
- package/esm/bug-report.js.map +1 -1
- package/esm/cmd/index.d.ts +2 -0
- package/esm/cmd/index.d.ts.map +1 -0
- package/esm/cmd/index.js +2 -0
- package/esm/cmd/index.js.map +1 -0
- package/esm/cmd/none.d.ts +5 -0
- package/esm/cmd/none.d.ts.map +1 -0
- package/esm/cmd/none.js +39 -0
- package/esm/cmd/none.js.map +1 -0
- package/esm/cmd/service.d.ts +29 -0
- package/esm/cmd/service.d.ts.map +1 -0
- package/esm/cmd/service.js +24 -0
- package/esm/cmd/service.js.map +1 -0
- package/esm/cmd/shell.d.ts +5 -0
- package/esm/cmd/shell.d.ts.map +1 -0
- package/esm/cmd/shell.js +43 -0
- package/esm/cmd/shell.js.map +1 -0
- package/esm/cmd/utils.d.ts +5 -0
- package/esm/cmd/utils.d.ts.map +1 -0
- package/esm/cmd/utils.js +24 -0
- package/esm/cmd/utils.js.map +1 -0
- package/esm/demo-mode.d.ts +3 -4
- package/esm/demo-mode.d.ts.map +1 -1
- package/esm/demo-mode.js +13 -21
- package/esm/demo-mode.js.map +1 -1
- package/esm/dumpsys.d.ts +4 -2
- package/esm/dumpsys.d.ts.map +1 -1
- package/esm/dumpsys.js +13 -10
- package/esm/dumpsys.js.map +1 -1
- package/esm/index.d.ts +1 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/esm/intent.d.ts +37 -9
- package/esm/intent.d.ts.map +1 -1
- package/esm/intent.js +116 -53
- package/esm/intent.js.map +1 -1
- package/esm/logcat.d.ts +4 -2
- package/esm/logcat.d.ts.map +1 -1
- package/esm/logcat.js +9 -6
- package/esm/logcat.js.map +1 -1
- package/esm/overlay-display.d.ts +17 -14
- package/esm/overlay-display.d.ts.map +1 -1
- package/esm/overlay-display.js +2 -4
- package/esm/overlay-display.js.map +1 -1
- package/esm/pm.d.ts +131 -168
- package/esm/pm.d.ts.map +1 -1
- package/esm/pm.js +229 -112
- package/esm/pm.js.map +1 -1
- package/esm/settings.d.ts +1 -2
- package/esm/settings.d.ts.map +1 -1
- package/esm/settings.js +9 -9
- package/esm/settings.js.map +1 -1
- package/esm/utils.d.ts +4 -1
- package/esm/utils.d.ts.map +1 -1
- package/esm/utils.js +24 -13
- package/esm/utils.js.map +1 -1
- package/package.json +9 -9
- package/src/am.ts +94 -34
- package/src/bu.ts +31 -20
- package/src/bug-report.ts +42 -42
- package/src/cmd/index.ts +1 -0
- package/src/cmd/none.ts +62 -0
- package/src/cmd/service.ts +54 -0
- package/src/cmd/shell.ts +67 -0
- package/src/cmd/utils.ts +35 -0
- package/src/demo-mode.ts +13 -24
- package/src/dumpsys.ts +16 -10
- package/src/index.ts +1 -1
- package/src/intent.ts +187 -49
- package/src/logcat.ts +12 -6
- package/src/overlay-display.ts +21 -19
- package/src/pm.ts +374 -301
- package/src/settings.ts +11 -10
- package/src/utils.ts +30 -13
- package/tsconfig.build.json +0 -11
- package/CHANGELOG.md +0 -181
- package/esm/cmd.d.ts +0 -23
- package/esm/cmd.d.ts.map +0 -1
- package/esm/cmd.js +0 -104
- package/esm/cmd.js.map +0 -1
- package/src/cmd.ts +0 -166
- package/tsconfig.build.tsbuildinfo +0 -1
package/esm/settings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
|
package/esm/utils.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export declare function
|
|
1
|
+
export declare function buildCommand<T>(commands: readonly string[], options: Partial<T> | undefined, map: Partial<Record<keyof T, string>>): string[];
|
|
2
2
|
export type SingleUser = number | "current";
|
|
3
3
|
export type SingleUserOrAll = SingleUser | "all";
|
|
4
|
+
export type Optional<T extends object> = {
|
|
5
|
+
[K in keyof T]?: T[K] | undefined;
|
|
6
|
+
};
|
|
4
7
|
//# sourceMappingURL=utils.d.ts.map
|
package/esm/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,CAAC,EAC1B,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,EAC/B,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,GACtC,MAAM,EAAE,CAoCV;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;AAC5C,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,KAAK,CAAC;AAEjD,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS;CAAE,CAAC"}
|
package/esm/utils.js
CHANGED
|
@@ -1,20 +1,31 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function buildCommand(commands, options, map) {
|
|
2
2
|
const args = commands.slice();
|
|
3
3
|
if (options) {
|
|
4
4
|
for (const [key, value] of Object.entries(options)) {
|
|
5
|
-
if (value) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
if (value === undefined || value === null) {
|
|
6
|
+
continue;
|
|
7
|
+
}
|
|
8
|
+
const option = map[key];
|
|
9
|
+
// Empty string means positional argument,
|
|
10
|
+
// they must be added at the end,
|
|
11
|
+
// so let the caller handle it.
|
|
12
|
+
if (option === undefined || option === "") {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
switch (typeof value) {
|
|
16
|
+
case "boolean":
|
|
17
|
+
if (value) {
|
|
18
|
+
args.push(option);
|
|
16
19
|
}
|
|
17
|
-
|
|
20
|
+
break;
|
|
21
|
+
case "number":
|
|
22
|
+
args.push(option, value.toString());
|
|
23
|
+
break;
|
|
24
|
+
case "string":
|
|
25
|
+
args.push(option, value);
|
|
26
|
+
break;
|
|
27
|
+
default:
|
|
28
|
+
throw new Error(`Unsupported type for option ${key}: ${typeof value}`);
|
|
18
29
|
}
|
|
19
30
|
}
|
|
20
31
|
}
|
package/esm/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CACxB,QAA2B,EAC3B,OAA+B,EAC/B,GAAqC;IAErC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC;IAC9B,IAAI,OAAO,EAAE,CAAC;QACV,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACjD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACxC,SAAS;YACb,CAAC;YAED,MAAM,MAAM,GAAG,GAAG,CAAC,GAAc,CAAC,CAAC;YACnC,0CAA0C;YAC1C,iCAAiC;YACjC,+BAA+B;YAC/B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;gBACxC,SAAS;YACb,CAAC;YAED,QAAQ,OAAO,KAAK,EAAE,CAAC;gBACnB,KAAK,SAAS;oBACV,IAAI,KAAK,EAAE,CAAC;wBACR,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBACtB,CAAC;oBACD,MAAM;gBACV,KAAK,QAAQ;oBACT,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;oBACpC,MAAM;gBACV,KAAK,QAAQ;oBACT,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;oBACzB,MAAM;gBACV;oBACI,MAAM,IAAI,KAAK,CACX,+BAA+B,GAAG,KAAK,OAAO,KAAK,EAAE,CACxD,CAAC;YACV,CAAC;QACL,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yume-chan/android-bin",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-beta.0",
|
|
4
4
|
"description": "Wrappers for Android built-in executables.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adb",
|
|
@@ -26,20 +26,20 @@
|
|
|
26
26
|
"types": "esm/index.d.ts",
|
|
27
27
|
"sideEffects": false,
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@yume-chan/
|
|
30
|
-
"@yume-chan/
|
|
31
|
-
"@yume-chan/
|
|
29
|
+
"@yume-chan/adb": "3.0.0-beta.0",
|
|
30
|
+
"@yume-chan/stream-extra": "3.0.0-beta.0",
|
|
31
|
+
"@yume-chan/struct": "3.0.0-beta.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@types/node": "^
|
|
35
|
-
"prettier": "^3.
|
|
36
|
-
"typescript": "^
|
|
37
|
-
"@yume-chan/test-runner": "^1.0.0",
|
|
34
|
+
"@types/node": "^26.0.0",
|
|
35
|
+
"prettier": "^3.8.4",
|
|
36
|
+
"typescript": "^6.0.3",
|
|
38
37
|
"@yume-chan/eslint-config": "^1.0.0",
|
|
38
|
+
"@yume-chan/test-runner": "^1.0.0",
|
|
39
39
|
"@yume-chan/tsconfig": "^1.0.0"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
|
-
"build": "tsc -
|
|
42
|
+
"build": "tsc -p tsconfig.build.json",
|
|
43
43
|
"lint": "run-eslint && prettier src/**/*.ts --write --tab-width 4",
|
|
44
44
|
"test": "run-test"
|
|
45
45
|
}
|
package/src/am.ts
CHANGED
|
@@ -1,21 +1,15 @@
|
|
|
1
|
-
import type { Adb } from "@yume-chan/adb";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import type {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
displayId?: number;
|
|
11
|
-
windowingMode?: number;
|
|
12
|
-
forceStop?: boolean;
|
|
13
|
-
user?: SingleUser;
|
|
14
|
-
intent: IntentBuilder;
|
|
15
|
-
}
|
|
1
|
+
import type { Adb, AdbNoneProtocolProcess } from "@yume-chan/adb";
|
|
2
|
+
import { escapeArg } from "@yume-chan/adb";
|
|
3
|
+
import { SplitStringStream, TextDecoderStream } from "@yume-chan/stream-extra";
|
|
4
|
+
|
|
5
|
+
import { Cmd } from "./cmd/index.js";
|
|
6
|
+
import type { Intent } from "./intent.js";
|
|
7
|
+
import { serializeIntent } from "./intent.js";
|
|
8
|
+
import type { SingleUser, SingleUserOrAll } from "./utils.js";
|
|
9
|
+
import { buildCommand } from "./utils.js";
|
|
16
10
|
|
|
17
11
|
const START_ACTIVITY_OPTIONS_MAP: Partial<
|
|
18
|
-
Record<keyof
|
|
12
|
+
Record<keyof ActivityManager.StartActivityOptions, string>
|
|
19
13
|
> = {
|
|
20
14
|
displayId: "--display",
|
|
21
15
|
windowingMode: "--windowingMode",
|
|
@@ -23,42 +17,108 @@ const START_ACTIVITY_OPTIONS_MAP: Partial<
|
|
|
23
17
|
user: "--user",
|
|
24
18
|
};
|
|
25
19
|
|
|
26
|
-
export class ActivityManager
|
|
27
|
-
static ServiceName = "activity";
|
|
28
|
-
static CommandName = "am";
|
|
20
|
+
export class ActivityManager {
|
|
21
|
+
static readonly ServiceName = "activity";
|
|
22
|
+
static readonly CommandName = "am";
|
|
29
23
|
|
|
30
|
-
#
|
|
24
|
+
readonly #adb: Adb;
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
26
|
+
#apiLevel: number | undefined;
|
|
27
|
+
#cmd: Cmd.NoneProtocolService;
|
|
28
|
+
|
|
29
|
+
constructor(adb: Adb, apiLevel?: number) {
|
|
30
|
+
this.#adb = adb;
|
|
31
|
+
this.#apiLevel = apiLevel;
|
|
32
|
+
this.#cmd = Cmd.createNoneProtocol(adb, ActivityManager.CommandName);
|
|
38
33
|
}
|
|
39
34
|
|
|
40
35
|
async startActivity(
|
|
41
|
-
options:
|
|
36
|
+
options: ActivityManager.StartActivityOptions,
|
|
42
37
|
): Promise<void> {
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
// Android 8 added "start-activity" alias to "start"
|
|
39
|
+
// but we want to use the most compatible one.
|
|
40
|
+
const command = buildCommand(
|
|
41
|
+
[ActivityManager.ServiceName, "start", "-W"],
|
|
45
42
|
options,
|
|
46
43
|
START_ACTIVITY_OPTIONS_MAP,
|
|
47
44
|
);
|
|
48
45
|
|
|
49
|
-
|
|
46
|
+
for (const arg of serializeIntent(options.intent)) {
|
|
47
|
+
command.push(arg);
|
|
48
|
+
}
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
// Android 7 supports `cmd activity` but not `cmd activity start` command
|
|
51
|
+
let process: AdbNoneProtocolProcess;
|
|
52
|
+
if (this.#apiLevel !== undefined && this.#apiLevel <= 25) {
|
|
53
|
+
command[0] = ActivityManager.CommandName;
|
|
54
|
+
process = await this.#adb.subprocess.noneProtocol.spawn(
|
|
55
|
+
command.map(escapeArg),
|
|
56
|
+
);
|
|
57
|
+
} else {
|
|
58
|
+
process = await this.#cmd.spawn(command);
|
|
59
|
+
}
|
|
54
60
|
|
|
55
|
-
|
|
61
|
+
const lines = process.output
|
|
62
|
+
.pipeThrough(new TextDecoderStream())
|
|
63
|
+
.pipeThrough(new SplitStringStream("\n", { trim: true }));
|
|
64
|
+
|
|
65
|
+
for await (const line of lines) {
|
|
56
66
|
if (line.startsWith("Error:")) {
|
|
67
|
+
// Exit from the `for await` loop will cancel `lines`,
|
|
68
|
+
// and subsequently, `process`, which is fine, as the work is already done
|
|
57
69
|
throw new Error(line.substring("Error:".length).trim());
|
|
58
70
|
}
|
|
71
|
+
|
|
59
72
|
if (line === "Complete") {
|
|
73
|
+
// Same as above
|
|
60
74
|
return;
|
|
61
75
|
}
|
|
62
76
|
}
|
|
77
|
+
|
|
78
|
+
// Ensure the subprocess exits before returning
|
|
79
|
+
await process.exited;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async broadcast(
|
|
83
|
+
intent: Intent,
|
|
84
|
+
options?: { user?: SingleUserOrAll; receiverPermission?: string },
|
|
85
|
+
) {
|
|
86
|
+
const command = [ActivityManager.ServiceName, "broadcast"];
|
|
87
|
+
|
|
88
|
+
if (options) {
|
|
89
|
+
if (options.user !== undefined) {
|
|
90
|
+
command.push("--user", options.user.toString());
|
|
91
|
+
}
|
|
92
|
+
if (options.receiverPermission) {
|
|
93
|
+
command.push(
|
|
94
|
+
"--receiver-permission",
|
|
95
|
+
options.receiverPermission,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
for (const arg of serializeIntent(intent)) {
|
|
101
|
+
command.push(arg);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Android 7 supports `cmd activity` but not `cmd activity broadcast` command
|
|
105
|
+
if (this.#apiLevel !== undefined && this.#apiLevel <= 25) {
|
|
106
|
+
command[0] = ActivityManager.CommandName;
|
|
107
|
+
await this.#adb.subprocess.noneProtocol
|
|
108
|
+
.spawn(command.map(escapeArg))
|
|
109
|
+
.wait();
|
|
110
|
+
} else {
|
|
111
|
+
await this.#cmd.spawn(command).wait();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export namespace ActivityManager {
|
|
117
|
+
export interface StartActivityOptions {
|
|
118
|
+
displayId?: number;
|
|
119
|
+
windowingMode?: number;
|
|
120
|
+
forceStop?: boolean;
|
|
121
|
+
user?: SingleUser;
|
|
122
|
+
intent: Intent;
|
|
63
123
|
}
|
|
64
124
|
}
|
package/src/bu.ts
CHANGED
|
@@ -1,28 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Adb } from "@yume-chan/adb";
|
|
2
2
|
import type { MaybeConsumable, ReadableStream } from "@yume-chan/stream-extra";
|
|
3
3
|
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
saveSharedStorage?: boolean;
|
|
7
|
-
saveWidgets?: boolean;
|
|
8
|
-
packages: readonly string[] | "user" | "all";
|
|
9
|
-
savePackageApk: boolean;
|
|
10
|
-
savePackageObb: boolean;
|
|
11
|
-
savePackageKeyValue: boolean;
|
|
12
|
-
compress: boolean;
|
|
13
|
-
}
|
|
4
|
+
export class AdbBackup {
|
|
5
|
+
readonly #adb: Adb;
|
|
14
6
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
7
|
+
constructor(adb: Adb) {
|
|
8
|
+
this.#adb = adb;
|
|
9
|
+
}
|
|
19
10
|
|
|
20
|
-
export class AdbBackup extends AdbServiceBase {
|
|
21
11
|
/**
|
|
22
12
|
* User must confirm backup on device within 60 seconds.
|
|
23
13
|
*/
|
|
24
14
|
async backup(
|
|
25
|
-
options:
|
|
15
|
+
options: AdbBackup.BackupOptions,
|
|
26
16
|
): Promise<ReadableStream<Uint8Array>> {
|
|
27
17
|
const args = ["bu", "backup"];
|
|
28
18
|
|
|
@@ -54,7 +44,7 @@ export class AdbBackup extends AdbServiceBase {
|
|
|
54
44
|
args.push(...options.packages);
|
|
55
45
|
}
|
|
56
46
|
|
|
57
|
-
const process = await this
|
|
47
|
+
const process = await this.#adb.subprocess.noneProtocol.spawn(args);
|
|
58
48
|
return process.output;
|
|
59
49
|
}
|
|
60
50
|
|
|
@@ -62,11 +52,32 @@ export class AdbBackup extends AdbServiceBase {
|
|
|
62
52
|
* User must enter the password (if any) and
|
|
63
53
|
* confirm restore on device within 60 seconds.
|
|
64
54
|
*/
|
|
65
|
-
restore(options:
|
|
55
|
+
restore(options: AdbBackup.RestoreOptions): Promise<string> {
|
|
66
56
|
const args = ["bu", "restore"];
|
|
67
57
|
if (options.user !== undefined) {
|
|
68
58
|
args.push("--user", options.user.toString());
|
|
69
59
|
}
|
|
70
|
-
return this
|
|
60
|
+
return this.#adb.subprocess.noneProtocol
|
|
61
|
+
.spawn(args)
|
|
62
|
+
.wait({ stdin: options.file })
|
|
63
|
+
.toString();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export namespace AdbBackup {
|
|
68
|
+
export interface BackupOptions {
|
|
69
|
+
user?: number | undefined;
|
|
70
|
+
saveSharedStorage?: boolean | undefined;
|
|
71
|
+
saveWidgets?: boolean | undefined;
|
|
72
|
+
packages: readonly string[] | "user" | "all";
|
|
73
|
+
savePackageApk: boolean;
|
|
74
|
+
savePackageObb: boolean;
|
|
75
|
+
savePackageKeyValue: boolean;
|
|
76
|
+
compress: boolean;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface RestoreOptions {
|
|
80
|
+
user?: number | undefined;
|
|
81
|
+
file: ReadableStream<MaybeConsumable<Uint8Array>>;
|
|
71
82
|
}
|
|
72
83
|
}
|
package/src/bug-report.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
// cspell: ignore bugreport
|
|
2
2
|
// cspell: ignore bugreportz
|
|
3
3
|
|
|
4
|
-
import type { Adb
|
|
5
|
-
import { AdbServiceBase } from "@yume-chan/adb";
|
|
4
|
+
import type { Adb } from "@yume-chan/adb";
|
|
6
5
|
import type { AbortSignal, ReadableStream } from "@yume-chan/stream-extra";
|
|
7
6
|
import {
|
|
8
7
|
AbortController,
|
|
@@ -13,25 +12,7 @@ import {
|
|
|
13
12
|
WritableStream,
|
|
14
13
|
} from "@yume-chan/stream-extra";
|
|
15
14
|
|
|
16
|
-
export
|
|
17
|
-
supportsBugReport: boolean;
|
|
18
|
-
bugReportZVersion?: string | undefined;
|
|
19
|
-
supportsBugReportZ: boolean;
|
|
20
|
-
supportsBugReportZProgress: boolean;
|
|
21
|
-
supportsBugReportZStream: boolean;
|
|
22
|
-
}
|
|
23
|
-
|
|
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;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class BugReport extends AdbServiceBase {
|
|
15
|
+
export class BugReport {
|
|
35
16
|
static VERSION_REGEX: RegExp = /(\d+)\.(\d+)/;
|
|
36
17
|
|
|
37
18
|
static BEGIN_REGEX: RegExp = /BEGIN:(.*)/;
|
|
@@ -57,10 +38,10 @@ export class BugReport extends AdbServiceBase {
|
|
|
57
38
|
});
|
|
58
39
|
}
|
|
59
40
|
|
|
60
|
-
const result = await adb.subprocess.shellProtocol
|
|
61
|
-
"bugreportz",
|
|
62
|
-
|
|
63
|
-
|
|
41
|
+
const result = await adb.subprocess.shellProtocol
|
|
42
|
+
.spawn(["bugreportz", "-v"])
|
|
43
|
+
.wait()
|
|
44
|
+
.toString();
|
|
64
45
|
if (result.exitCode !== 0 || result.stderr === "") {
|
|
65
46
|
return new BugReport(adb, {
|
|
66
47
|
supportsBugReport: true,
|
|
@@ -95,6 +76,8 @@ export class BugReport extends AdbServiceBase {
|
|
|
95
76
|
});
|
|
96
77
|
}
|
|
97
78
|
|
|
79
|
+
readonly #adb: Adb;
|
|
80
|
+
|
|
98
81
|
#supportsBugReport: boolean;
|
|
99
82
|
/**
|
|
100
83
|
* Gets whether the device supports flat (text file, non-zipped) bugreport.
|
|
@@ -145,8 +128,8 @@ export class BugReport extends AdbServiceBase {
|
|
|
145
128
|
return this.#supportsBugReportZStream;
|
|
146
129
|
}
|
|
147
130
|
|
|
148
|
-
constructor(adb: Adb, capabilities:
|
|
149
|
-
|
|
131
|
+
constructor(adb: Adb, capabilities: BugReport.Capabilities) {
|
|
132
|
+
this.#adb = adb;
|
|
150
133
|
|
|
151
134
|
this.#supportsBugReport = capabilities.supportsBugReport;
|
|
152
135
|
this.#bugReportZVersion = capabilities.bugReportZVersion;
|
|
@@ -171,7 +154,7 @@ export class BugReport extends AdbServiceBase {
|
|
|
171
154
|
return new WrapReadableStream(async () => {
|
|
172
155
|
// https://cs.android.com/android/platform/superproject/+/master:frameworks/native/cmds/bugreport/bugreport.cpp;drc=9b73bf07d73dbab5b792632e1e233edbad77f5fd;bpv=0;bpt=0
|
|
173
156
|
const process =
|
|
174
|
-
await this
|
|
157
|
+
await this.#adb.subprocess.noneProtocol.spawn("bugreport");
|
|
175
158
|
return process.output;
|
|
176
159
|
});
|
|
177
160
|
}
|
|
@@ -184,7 +167,7 @@ export class BugReport extends AdbServiceBase {
|
|
|
184
167
|
*
|
|
185
168
|
* @returns The path to the generated bugreport file on device filesystem.
|
|
186
169
|
*/
|
|
187
|
-
async bugReportZ(options?: BugReportZOptions): Promise<string> {
|
|
170
|
+
async bugReportZ(options?: BugReport.BugReportZOptions): Promise<string> {
|
|
188
171
|
if (options?.signal?.aborted) {
|
|
189
172
|
throw options?.signal.reason as Error;
|
|
190
173
|
}
|
|
@@ -202,7 +185,7 @@ export class BugReport extends AdbServiceBase {
|
|
|
202
185
|
}
|
|
203
186
|
|
|
204
187
|
// `subprocess.shellProtocol` must be defined when `this.#supportsBugReportZ` is `true`
|
|
205
|
-
const process = await this
|
|
188
|
+
const process = await this.#adb.subprocess.shellProtocol!.spawn(args);
|
|
206
189
|
|
|
207
190
|
options?.signal?.addEventListener("abort", () => {
|
|
208
191
|
void process.kill();
|
|
@@ -211,10 +194,10 @@ export class BugReport extends AdbServiceBase {
|
|
|
211
194
|
let filename: string | undefined;
|
|
212
195
|
let error: string | undefined;
|
|
213
196
|
|
|
214
|
-
|
|
197
|
+
const lines = process.stdout
|
|
215
198
|
.pipeThrough(new TextDecoderStream())
|
|
216
|
-
|
|
217
|
-
|
|
199
|
+
.pipeThrough(new SplitStringStream("\n", { trim: true }));
|
|
200
|
+
for await (const line of lines) {
|
|
218
201
|
// `BEGIN:` and `PROGRESS:` only appear when `-p` is specified.
|
|
219
202
|
let match = line.match(BugReport.PROGRESS_REGEX);
|
|
220
203
|
if (match) {
|
|
@@ -258,10 +241,10 @@ export class BugReport extends AdbServiceBase {
|
|
|
258
241
|
*/
|
|
259
242
|
bugReportZStream(): ReadableStream<Uint8Array> {
|
|
260
243
|
return new PushReadableStream(async (controller) => {
|
|
261
|
-
const process = await this
|
|
262
|
-
"bugreportz",
|
|
263
|
-
|
|
264
|
-
|
|
244
|
+
const process = await this.#adb.subprocess.shellProtocol!.spawn(
|
|
245
|
+
["bugreportz", "-s"],
|
|
246
|
+
controller.abortSignal,
|
|
247
|
+
);
|
|
265
248
|
process.stdout
|
|
266
249
|
.pipeTo(
|
|
267
250
|
new WritableStream({
|
|
@@ -310,13 +293,11 @@ export class BugReport extends AdbServiceBase {
|
|
|
310
293
|
|
|
311
294
|
if (this.#supportsBugReportZ) {
|
|
312
295
|
let path: string | undefined;
|
|
313
|
-
let sync: AdbSync | undefined;
|
|
314
296
|
const controller = new AbortController();
|
|
315
297
|
const cleanup = async () => {
|
|
316
298
|
controller.abort();
|
|
317
|
-
await sync?.dispose();
|
|
318
299
|
if (path) {
|
|
319
|
-
await this
|
|
300
|
+
await this.#adb.rm(path);
|
|
320
301
|
}
|
|
321
302
|
};
|
|
322
303
|
|
|
@@ -330,8 +311,7 @@ export class BugReport extends AdbServiceBase {
|
|
|
330
311
|
? onProgress
|
|
331
312
|
: undefined,
|
|
332
313
|
});
|
|
333
|
-
|
|
334
|
-
return sync.read(path);
|
|
314
|
+
return this.#adb.sync.read(path);
|
|
335
315
|
},
|
|
336
316
|
cancel: cleanup,
|
|
337
317
|
close: cleanup,
|
|
@@ -342,3 +322,23 @@ export class BugReport extends AdbServiceBase {
|
|
|
342
322
|
return { type: "bugreport", stream: this.bugReport() };
|
|
343
323
|
}
|
|
344
324
|
}
|
|
325
|
+
|
|
326
|
+
export namespace BugReport {
|
|
327
|
+
export interface Capabilities {
|
|
328
|
+
supportsBugReport: boolean;
|
|
329
|
+
bugReportZVersion?: string | undefined;
|
|
330
|
+
supportsBugReportZ: boolean;
|
|
331
|
+
supportsBugReportZProgress: boolean;
|
|
332
|
+
supportsBugReportZStream: boolean;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export interface BugReportZOptions {
|
|
336
|
+
signal?: AbortSignal;
|
|
337
|
+
/**
|
|
338
|
+
* A callback that will be called when progress is updated.
|
|
339
|
+
*
|
|
340
|
+
* Specify `onProgress` when `supportsBugReportZProgress` is `false` will throw an error.
|
|
341
|
+
*/
|
|
342
|
+
onProgress?: ((completed: string, total: string) => void) | undefined;
|
|
343
|
+
}
|
|
344
|
+
}
|
package/src/cmd/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./service.js";
|
package/src/cmd/none.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Adb } from "@yume-chan/adb";
|
|
2
|
+
import {
|
|
3
|
+
AdbFeature,
|
|
4
|
+
AdbNoneProtocolProcessImpl,
|
|
5
|
+
adbNoneProtocolSpawner,
|
|
6
|
+
escapeArg,
|
|
7
|
+
} from "@yume-chan/adb";
|
|
8
|
+
|
|
9
|
+
import { Cmd } from "./service.js";
|
|
10
|
+
import { checkCommand, resolveFallback, serializeAbbService } from "./utils.js";
|
|
11
|
+
|
|
12
|
+
export function createNoneProtocol(
|
|
13
|
+
adb: Adb,
|
|
14
|
+
fallback: NonNullable<Cmd.Fallback>,
|
|
15
|
+
): Cmd.NoneProtocolService;
|
|
16
|
+
export function createNoneProtocol(
|
|
17
|
+
adb: Adb,
|
|
18
|
+
fallback?: Cmd.Fallback,
|
|
19
|
+
): Cmd.NoneProtocolService | undefined;
|
|
20
|
+
export function createNoneProtocol(
|
|
21
|
+
adb: Adb,
|
|
22
|
+
fallback?: Cmd.Fallback,
|
|
23
|
+
): Cmd.NoneProtocolService | undefined {
|
|
24
|
+
if (adb.canUseFeature(AdbFeature.AbbExec)) {
|
|
25
|
+
return {
|
|
26
|
+
mode: Cmd.Mode.Abb,
|
|
27
|
+
spawn: adbNoneProtocolSpawner(async (command, signal) => {
|
|
28
|
+
const service = serializeAbbService("abb_exec", command);
|
|
29
|
+
const socket = await adb.createSocket(service);
|
|
30
|
+
return new AdbNoneProtocolProcessImpl(socket, signal);
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (adb.canUseFeature(AdbFeature.Cmd)) {
|
|
36
|
+
return {
|
|
37
|
+
mode: Cmd.Mode.Cmd,
|
|
38
|
+
spawn: adbNoneProtocolSpawner(async (command, signal) => {
|
|
39
|
+
checkCommand(command);
|
|
40
|
+
|
|
41
|
+
const newCommand = command.map(escapeArg);
|
|
42
|
+
newCommand.unshift("cmd");
|
|
43
|
+
return adb.subprocess.noneProtocol.spawn(newCommand, signal);
|
|
44
|
+
}),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (fallback) {
|
|
49
|
+
return {
|
|
50
|
+
mode: Cmd.Mode.Fallback,
|
|
51
|
+
spawn: adbNoneProtocolSpawner(async (command, signal) => {
|
|
52
|
+
checkCommand(command);
|
|
53
|
+
|
|
54
|
+
const newCommand = command.map(escapeArg);
|
|
55
|
+
newCommand[0] = resolveFallback(fallback, command[0]!);
|
|
56
|
+
return adb.subprocess.noneProtocol.spawn(newCommand, signal);
|
|
57
|
+
}),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Adb,
|
|
3
|
+
AdbNoneProtocolSpawner,
|
|
4
|
+
AdbShellProtocolSpawner,
|
|
5
|
+
} from "@yume-chan/adb";
|
|
6
|
+
|
|
7
|
+
import { createNoneProtocol } from "./none.js";
|
|
8
|
+
import { createShellProtocol } from "./shell.js";
|
|
9
|
+
|
|
10
|
+
export class Cmd {
|
|
11
|
+
static readonly Mode = {
|
|
12
|
+
Abb: 0,
|
|
13
|
+
Cmd: 1,
|
|
14
|
+
Fallback: 2,
|
|
15
|
+
} as const;
|
|
16
|
+
|
|
17
|
+
static readonly createNoneProtocol = createNoneProtocol;
|
|
18
|
+
static readonly createShellProtocol = createShellProtocol;
|
|
19
|
+
|
|
20
|
+
#noneProtocol: Cmd.NoneProtocolService | undefined;
|
|
21
|
+
get noneProtocol() {
|
|
22
|
+
return this.#noneProtocol;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
#shellProtocol: Cmd.ShellProtocolService | undefined;
|
|
26
|
+
get shellProtocol() {
|
|
27
|
+
return this.#shellProtocol;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
constructor(adb: Adb, fallback?: Cmd.Fallback) {
|
|
31
|
+
this.#noneProtocol = createNoneProtocol(adb, fallback);
|
|
32
|
+
this.#shellProtocol = createShellProtocol(adb, fallback);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export namespace Cmd {
|
|
37
|
+
export type Fallback =
|
|
38
|
+
| string
|
|
39
|
+
| Record<string, string>
|
|
40
|
+
| ((service: string) => string)
|
|
41
|
+
| undefined;
|
|
42
|
+
|
|
43
|
+
export type Mode = (typeof Cmd.Mode)[keyof typeof Cmd.Mode];
|
|
44
|
+
|
|
45
|
+
export interface NoneProtocolService {
|
|
46
|
+
mode: Mode;
|
|
47
|
+
spawn: AdbNoneProtocolSpawner;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface ShellProtocolService {
|
|
51
|
+
mode: Mode;
|
|
52
|
+
spawn: AdbShellProtocolSpawner;
|
|
53
|
+
}
|
|
54
|
+
}
|