@yume-chan/android-bin 2.0.1 → 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 +5 -2
- 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 +8 -6
- 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/string-format.d.ts +2 -2
- package/esm/string-format.d.ts.map +1 -1
- package/esm/string-format.js.map +1 -1
- package/esm/utils.d.ts +4 -1
- package/esm/utils.d.ts.map +1 -1
- package/esm/utils.js +25 -14
- package/esm/utils.js.map +1 -1
- package/package.json +8 -8
- 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 +16 -10
- package/src/overlay-display.ts +21 -19
- package/src/pm.ts +375 -302
- package/src/settings.ts +11 -10
- package/src/string-format.ts +3 -3
- package/src/utils.ts +32 -15
- package/tsconfig.build.json +0 -11
- package/CHANGELOG.md +0 -171
- package/esm/cmd.d.ts +0 -23
- package/esm/cmd.d.ts.map +0 -1
- package/esm/cmd.js +0 -102
- package/esm/cmd.js.map +0 -1
- package/src/cmd.ts +0 -164
- package/tsconfig.build.tsbuildinfo +0 -1
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
|
+
}
|
package/src/cmd/shell.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Adb } from "@yume-chan/adb";
|
|
2
|
+
import {
|
|
3
|
+
AdbFeature,
|
|
4
|
+
AdbShellProtocolProcessImpl,
|
|
5
|
+
adbShellProtocolSpawner,
|
|
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 createShellProtocol(
|
|
13
|
+
adb: Adb,
|
|
14
|
+
fallback: NonNullable<Cmd.Fallback>,
|
|
15
|
+
): Cmd.ShellProtocolService;
|
|
16
|
+
export function createShellProtocol(
|
|
17
|
+
adb: Adb,
|
|
18
|
+
fallback?: Cmd.Fallback,
|
|
19
|
+
): Cmd.ShellProtocolService | undefined;
|
|
20
|
+
export function createShellProtocol(
|
|
21
|
+
adb: Adb,
|
|
22
|
+
fallback?: Cmd.Fallback,
|
|
23
|
+
): Cmd.ShellProtocolService | undefined {
|
|
24
|
+
if (adb.canUseFeature(AdbFeature.Abb)) {
|
|
25
|
+
return {
|
|
26
|
+
mode: Cmd.Mode.Abb,
|
|
27
|
+
spawn: adbShellProtocolSpawner(async (command, signal) => {
|
|
28
|
+
const service = serializeAbbService("abb", command);
|
|
29
|
+
const socket = await adb.createSocket(service);
|
|
30
|
+
return new AdbShellProtocolProcessImpl(socket, signal);
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const shellProtocolService = adb.subprocess.shellProtocol;
|
|
36
|
+
if (!shellProtocolService) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (adb.canUseFeature(AdbFeature.Cmd)) {
|
|
41
|
+
return {
|
|
42
|
+
mode: Cmd.Mode.Cmd,
|
|
43
|
+
spawn: adbShellProtocolSpawner(async (command, signal) => {
|
|
44
|
+
checkCommand(command);
|
|
45
|
+
|
|
46
|
+
const newCommand = command.map(escapeArg);
|
|
47
|
+
newCommand.unshift("cmd");
|
|
48
|
+
return shellProtocolService.spawn(newCommand, signal);
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (fallback) {
|
|
54
|
+
return {
|
|
55
|
+
mode: Cmd.Mode.Fallback,
|
|
56
|
+
spawn: adbShellProtocolSpawner(async (command, signal) => {
|
|
57
|
+
checkCommand(command);
|
|
58
|
+
|
|
59
|
+
const newCommand = command.map(escapeArg);
|
|
60
|
+
newCommand[0] = resolveFallback(fallback, command[0]!);
|
|
61
|
+
return shellProtocolService.spawn(newCommand, signal);
|
|
62
|
+
}),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
package/src/cmd/utils.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Cmd } from "./service.js";
|
|
2
|
+
|
|
3
|
+
export function resolveFallback(
|
|
4
|
+
fallback: Cmd.Fallback,
|
|
5
|
+
command: string,
|
|
6
|
+
): string {
|
|
7
|
+
if (typeof fallback === "function") {
|
|
8
|
+
fallback = fallback(command);
|
|
9
|
+
} else if (typeof fallback === "object" && fallback !== null) {
|
|
10
|
+
fallback = fallback[command];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (!fallback) {
|
|
14
|
+
throw new Error(`No fallback configured for command "${command}"`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return fallback;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function checkCommand(command: readonly string[]) {
|
|
21
|
+
if (!command.length) {
|
|
22
|
+
throw new TypeError("Command is empty");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function serializeAbbService(
|
|
27
|
+
prefix: string,
|
|
28
|
+
command: readonly string[],
|
|
29
|
+
): string {
|
|
30
|
+
checkCommand(command);
|
|
31
|
+
|
|
32
|
+
// `abb` mode uses `\0` as the separator, allowing space in arguments.
|
|
33
|
+
// The last `\0` is required for older versions of `adb`.
|
|
34
|
+
return `${prefix}:${command.join("\0")}\0`;
|
|
35
|
+
}
|
package/src/demo-mode.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// cspell: ignore sysui
|
|
6
6
|
|
|
7
7
|
import type { Adb } from "@yume-chan/adb";
|
|
8
|
-
import { AdbServiceBase } from "@yume-chan/adb";
|
|
9
8
|
|
|
9
|
+
import { ActivityManager } from "./am.js";
|
|
10
10
|
import { Settings } from "./settings.js";
|
|
11
11
|
|
|
12
12
|
export enum DemoModeSignalStrength {
|
|
@@ -51,11 +51,12 @@ export const DemoModeStatusBarModes = [
|
|
|
51
51
|
|
|
52
52
|
export type DemoModeStatusBarMode = (typeof DemoModeStatusBarModes)[number];
|
|
53
53
|
|
|
54
|
-
export class DemoMode
|
|
54
|
+
export class DemoMode {
|
|
55
|
+
#am: ActivityManager;
|
|
55
56
|
#settings: Settings;
|
|
56
57
|
|
|
57
|
-
constructor(adb: Adb) {
|
|
58
|
-
|
|
58
|
+
constructor(adb: Adb, apiLevel?: number) {
|
|
59
|
+
this.#am = new ActivityManager(adb, apiLevel);
|
|
59
60
|
this.#settings = new Settings(adb);
|
|
60
61
|
}
|
|
61
62
|
|
|
@@ -108,26 +109,14 @@ export class DemoMode extends AdbServiceBase {
|
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
111
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
"com.android.systemui.demo",
|
|
120
|
-
"-e",
|
|
121
|
-
"command",
|
|
122
|
-
command,
|
|
123
|
-
...(extra
|
|
124
|
-
? Object.entries(extra).flatMap(([key, value]) => [
|
|
125
|
-
"-e",
|
|
126
|
-
key,
|
|
127
|
-
value,
|
|
128
|
-
])
|
|
129
|
-
: []),
|
|
130
|
-
]);
|
|
112
|
+
broadcast(command: string, extras?: Record<string, string>): Promise<void> {
|
|
113
|
+
return this.#am.broadcast({
|
|
114
|
+
action: "com.android.systemui.demo",
|
|
115
|
+
extras: {
|
|
116
|
+
command,
|
|
117
|
+
...extras,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
131
120
|
}
|
|
132
121
|
|
|
133
122
|
async setBatteryLevel(level: number): Promise<void> {
|
package/src/dumpsys.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Adb } from "@yume-chan/adb";
|
|
2
2
|
|
|
3
3
|
const BatteryDumpFields: Record<
|
|
4
4
|
string,
|
|
@@ -54,14 +54,20 @@ const Battery = {
|
|
|
54
54
|
Health,
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
export class DumpSys
|
|
57
|
+
export class DumpSys {
|
|
58
58
|
static readonly Battery = Battery;
|
|
59
59
|
|
|
60
|
+
readonly #adb: Adb;
|
|
61
|
+
|
|
62
|
+
constructor(adb: Adb) {
|
|
63
|
+
this.#adb = adb;
|
|
64
|
+
}
|
|
65
|
+
|
|
60
66
|
async diskStats() {
|
|
61
|
-
const result = await this
|
|
62
|
-
"dumpsys",
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
const result = await this.#adb.subprocess.noneProtocol
|
|
68
|
+
.spawn(["dumpsys", "diskstats"])
|
|
69
|
+
.wait()
|
|
70
|
+
.toString();
|
|
65
71
|
|
|
66
72
|
function getSize(name: string) {
|
|
67
73
|
const match = result.match(
|
|
@@ -91,10 +97,10 @@ export class DumpSys extends AdbServiceBase {
|
|
|
91
97
|
}
|
|
92
98
|
|
|
93
99
|
async battery(): Promise<DumpSys.Battery.Info> {
|
|
94
|
-
const result = await this
|
|
95
|
-
"dumpsys",
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
const result = await this.#adb.subprocess.noneProtocol
|
|
101
|
+
.spawn(["dumpsys", "battery"])
|
|
102
|
+
.wait()
|
|
103
|
+
.toString();
|
|
98
104
|
|
|
99
105
|
const info: DumpSys.Battery.Info = {
|
|
100
106
|
acPowered: false,
|
package/src/index.ts
CHANGED
package/src/intent.ts
CHANGED
|
@@ -1,73 +1,211 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
// cspell: ignore eial
|
|
2
|
+
// cspell: ignore elal
|
|
3
|
+
// cspell: ignore efal
|
|
4
|
+
// cspell: ignore esal
|
|
5
|
+
// cspell: ignore edal
|
|
6
|
+
|
|
7
|
+
export interface ComponentName {
|
|
8
|
+
packageName: string;
|
|
9
|
+
className: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface Intent {
|
|
13
|
+
action?: string | undefined;
|
|
14
|
+
data?: string | undefined;
|
|
15
|
+
type?: string | undefined;
|
|
16
|
+
identifier?: string | undefined;
|
|
17
|
+
categories?: string[] | undefined;
|
|
18
|
+
extras?:
|
|
19
|
+
| Record<
|
|
20
|
+
string,
|
|
21
|
+
| string
|
|
22
|
+
| null
|
|
23
|
+
| number
|
|
24
|
+
| bigint
|
|
25
|
+
| Intent.Extra.String
|
|
26
|
+
| ComponentName
|
|
27
|
+
| Intent.Extra.NumberArray
|
|
28
|
+
| Intent.Extra.StringArray
|
|
29
|
+
| Intent.Extra.Number
|
|
30
|
+
| boolean
|
|
31
|
+
>
|
|
32
|
+
| undefined;
|
|
33
|
+
flags?: number | undefined;
|
|
34
|
+
package?: string | undefined;
|
|
35
|
+
component?: ComponentName | undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export namespace Intent {
|
|
39
|
+
export namespace Extra {
|
|
40
|
+
export interface Number {
|
|
41
|
+
type: "long" | "float" | "double";
|
|
42
|
+
value: number;
|
|
43
|
+
}
|
|
14
44
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
45
|
+
export interface String {
|
|
46
|
+
type: "uri";
|
|
47
|
+
value: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface NumberArray {
|
|
51
|
+
type: "array" | "arrayList";
|
|
52
|
+
itemType: "int" | Number["type"];
|
|
53
|
+
value: number[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface StringArray {
|
|
57
|
+
type: "array" | "arrayList";
|
|
58
|
+
itemType: "string";
|
|
59
|
+
value: string[];
|
|
60
|
+
}
|
|
18
61
|
}
|
|
62
|
+
}
|
|
19
63
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
64
|
+
function getNumberType(type: "int" | Intent.Extra.Number["type"]) {
|
|
65
|
+
switch (type) {
|
|
66
|
+
case "int":
|
|
67
|
+
return "--ei";
|
|
68
|
+
case "long":
|
|
69
|
+
return "--el";
|
|
70
|
+
case "float":
|
|
71
|
+
return "--ef";
|
|
72
|
+
case "double":
|
|
73
|
+
return "--ed";
|
|
74
|
+
default:
|
|
75
|
+
throw new Error(`Unknown number type: ${type as string}`);
|
|
23
76
|
}
|
|
77
|
+
}
|
|
24
78
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
79
|
+
function serializeExtraArray(
|
|
80
|
+
array: Intent.Extra.NumberArray | Intent.Extra.StringArray,
|
|
81
|
+
): [type: string, value: string] {
|
|
82
|
+
let type: string;
|
|
83
|
+
let value: string;
|
|
84
|
+
|
|
85
|
+
if (array.itemType === "string") {
|
|
86
|
+
type = "--es";
|
|
87
|
+
value = array.value
|
|
88
|
+
.map((item) => item.replaceAll(",", "\\,"))
|
|
89
|
+
.join(",");
|
|
90
|
+
} else {
|
|
91
|
+
type = getNumberType(array.itemType);
|
|
92
|
+
value = array.value.join(",");
|
|
28
93
|
}
|
|
29
94
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
95
|
+
if (array.type === "array") {
|
|
96
|
+
type += "a";
|
|
97
|
+
} else {
|
|
98
|
+
type += "al";
|
|
33
99
|
}
|
|
34
100
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
101
|
+
return [type, value];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function serializeString(
|
|
105
|
+
result: string[],
|
|
106
|
+
key: string,
|
|
107
|
+
value: string | undefined,
|
|
108
|
+
) {
|
|
109
|
+
// Treat empty string as not set
|
|
110
|
+
if (value) {
|
|
111
|
+
result.push(key, value);
|
|
38
112
|
}
|
|
113
|
+
}
|
|
39
114
|
|
|
40
|
-
|
|
41
|
-
|
|
115
|
+
export function serializeIntent(intent: Intent) {
|
|
116
|
+
const result: string[] = [];
|
|
42
117
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
118
|
+
serializeString(result, "-a", intent.action);
|
|
119
|
+
serializeString(result, "-d", intent.data);
|
|
120
|
+
serializeString(result, "-t", intent.type);
|
|
121
|
+
serializeString(result, "-i", intent.identifier);
|
|
46
122
|
|
|
47
|
-
|
|
123
|
+
if (intent.categories) {
|
|
124
|
+
for (const category of intent.categories) {
|
|
48
125
|
result.push("-c", category);
|
|
49
126
|
}
|
|
127
|
+
}
|
|
50
128
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
129
|
+
if (intent.extras) {
|
|
130
|
+
for (const [key, value] of Object.entries(intent.extras)) {
|
|
131
|
+
switch (typeof value) {
|
|
132
|
+
case "string":
|
|
133
|
+
result.push("--es", key, value);
|
|
134
|
+
break;
|
|
135
|
+
case "object":
|
|
136
|
+
if (value === null) {
|
|
137
|
+
result.push("--esn", key);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
54
140
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
141
|
+
// `ComponentName`
|
|
142
|
+
if ("packageName" in value) {
|
|
143
|
+
result.push(
|
|
144
|
+
"--ecn",
|
|
145
|
+
key,
|
|
146
|
+
value.packageName + "/" + value.className,
|
|
147
|
+
);
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
58
150
|
|
|
59
|
-
|
|
60
|
-
|
|
151
|
+
switch (value.type) {
|
|
152
|
+
case "uri":
|
|
153
|
+
result.push("--eu", key, value.value);
|
|
154
|
+
break;
|
|
155
|
+
case "array":
|
|
156
|
+
case "arrayList":
|
|
157
|
+
{
|
|
158
|
+
const [type, valueString] =
|
|
159
|
+
serializeExtraArray(value);
|
|
160
|
+
result.push(type, key, valueString);
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
default:
|
|
164
|
+
result.push(
|
|
165
|
+
getNumberType(value.type),
|
|
166
|
+
key,
|
|
167
|
+
value.value.toString(),
|
|
168
|
+
);
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
break;
|
|
172
|
+
case "number":
|
|
173
|
+
if (value % 1 !== 0) {
|
|
174
|
+
throw new Error(
|
|
175
|
+
`Extra \`${key}\` is not an integer, must use \`Intent.Extra.Number\` type instead`,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
// Infer type from value
|
|
179
|
+
if (value < -2147483648 || value > 2147483647) {
|
|
180
|
+
result.push("--el", key, value.toString());
|
|
181
|
+
} else {
|
|
182
|
+
result.push("--ei", key, value.toString());
|
|
183
|
+
}
|
|
184
|
+
break;
|
|
185
|
+
case "bigint":
|
|
186
|
+
result.push("--el", key, value.toString());
|
|
187
|
+
break;
|
|
188
|
+
case "boolean":
|
|
189
|
+
result.push("--ez", key, value ? "true" : "false");
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
61
192
|
}
|
|
193
|
+
}
|
|
62
194
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
195
|
+
if (intent.component) {
|
|
196
|
+
result.push(
|
|
197
|
+
"-n",
|
|
198
|
+
intent.component.packageName + "/" + intent.component.className,
|
|
199
|
+
);
|
|
200
|
+
}
|
|
66
201
|
|
|
67
|
-
|
|
68
|
-
result.push("--es", key, value);
|
|
69
|
-
}
|
|
202
|
+
serializeString(result, "-p", intent.package);
|
|
70
203
|
|
|
71
|
-
|
|
204
|
+
// `0` is the default value for `flags` when deserializing
|
|
205
|
+
// so it can be omitted if it's either `undefined` or `0`
|
|
206
|
+
if (intent.flags) {
|
|
207
|
+
result.push("-f", intent.flags.toString());
|
|
72
208
|
}
|
|
209
|
+
|
|
210
|
+
return result;
|
|
73
211
|
}
|
package/src/logcat.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// cspell: ignore logcat
|
|
2
2
|
// cspell: ignore usec
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import type { Adb } from "@yume-chan/adb";
|
|
5
5
|
import type { ReadableStream } from "@yume-chan/stream-extra";
|
|
6
6
|
import {
|
|
7
7
|
BufferedTransformStream,
|
|
@@ -90,7 +90,7 @@ export interface LogcatFormatModifiers {
|
|
|
90
90
|
export interface LogcatOptions {
|
|
91
91
|
dump?: boolean | undefined;
|
|
92
92
|
pid?: number | undefined;
|
|
93
|
-
ids?: LogId[] | undefined;
|
|
93
|
+
ids?: readonly LogId[] | undefined;
|
|
94
94
|
tail?: number | Date | undefined;
|
|
95
95
|
}
|
|
96
96
|
|
|
@@ -405,7 +405,7 @@ export interface LogSize {
|
|
|
405
405
|
maxPayloadSize: number;
|
|
406
406
|
}
|
|
407
407
|
|
|
408
|
-
export class Logcat
|
|
408
|
+
export class Logcat {
|
|
409
409
|
static logIdToName(id: LogId): string {
|
|
410
410
|
return LogIdName[id]!;
|
|
411
411
|
}
|
|
@@ -415,7 +415,7 @@ export class Logcat extends AdbServiceBase {
|
|
|
415
415
|
return LogId[key as keyof typeof LogId];
|
|
416
416
|
}
|
|
417
417
|
|
|
418
|
-
static joinLogId(ids: LogId[]): string {
|
|
418
|
+
static joinLogId(ids: readonly LogId[]): string {
|
|
419
419
|
return ids.map((id) => Logcat.logIdToName(id)).join(",");
|
|
420
420
|
}
|
|
421
421
|
|
|
@@ -434,8 +434,14 @@ export class Logcat extends AdbServiceBase {
|
|
|
434
434
|
static readonly LOG_SIZE_REGEX_11: RegExp =
|
|
435
435
|
/(.*): ring buffer is (.*) (.*)B \((.*) (.*)B consumed, (.*) (.*)B readable\), max entry is (.*) B, max payload is (.*) B/;
|
|
436
436
|
|
|
437
|
-
|
|
438
|
-
|
|
437
|
+
readonly #adb: Adb;
|
|
438
|
+
|
|
439
|
+
constructor(adb: Adb) {
|
|
440
|
+
this.#adb = adb;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
async getLogSize(ids?: readonly LogId[]): Promise<LogSize[]> {
|
|
444
|
+
const process = await this.#adb.subprocess.noneProtocol.spawn([
|
|
439
445
|
"logcat",
|
|
440
446
|
"-g",
|
|
441
447
|
...(ids ? ["-b", Logcat.joinLogId(ids)] : []),
|
|
@@ -444,7 +450,7 @@ export class Logcat extends AdbServiceBase {
|
|
|
444
450
|
const result: LogSize[] = [];
|
|
445
451
|
for await (const line of process.output
|
|
446
452
|
.pipeThrough(new TextDecoderStream())
|
|
447
|
-
.pipeThrough(new SplitStringStream("\n"))) {
|
|
453
|
+
.pipeThrough(new SplitStringStream("\n", { trim: true }))) {
|
|
448
454
|
let match = line.match(Logcat.LOG_SIZE_REGEX_11);
|
|
449
455
|
if (match) {
|
|
450
456
|
result.push({
|
|
@@ -488,13 +494,13 @@ export class Logcat extends AdbServiceBase {
|
|
|
488
494
|
return result;
|
|
489
495
|
}
|
|
490
496
|
|
|
491
|
-
async clear(ids?: LogId[]): Promise<void> {
|
|
497
|
+
async clear(ids?: readonly LogId[]): Promise<void> {
|
|
492
498
|
const args = ["logcat", "-c"];
|
|
493
499
|
if (ids && ids.length > 0) {
|
|
494
500
|
args.push("-b", Logcat.joinLogId(ids));
|
|
495
501
|
}
|
|
496
502
|
|
|
497
|
-
await this
|
|
503
|
+
await this.#adb.subprocess.noneProtocol.spawn(args).wait();
|
|
498
504
|
}
|
|
499
505
|
|
|
500
506
|
binary(options?: LogcatOptions): ReadableStream<AndroidLogEntry> {
|
|
@@ -520,7 +526,7 @@ export class Logcat extends AdbServiceBase {
|
|
|
520
526
|
|
|
521
527
|
// TODO: make `spawn` return synchronously with streams pending
|
|
522
528
|
// so it's easier to chain them.
|
|
523
|
-
const process = await this
|
|
529
|
+
const process = await this.#adb.subprocess.noneProtocol.spawn(args);
|
|
524
530
|
return process.output;
|
|
525
531
|
}).pipeThrough(
|
|
526
532
|
new BufferedTransformStream((stream) => {
|