@yume-chan/android-bin 0.0.20 → 0.0.22
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 +54 -0
- package/CHANGELOG.md +25 -1
- package/LICENSE +21 -0
- package/README.md +40 -14
- package/esm/am.d.ts +17 -0
- package/esm/am.d.ts.map +1 -0
- package/esm/am.js +42 -0
- package/esm/am.js.map +1 -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 +39 -0
- package/esm/dumpsys.d.ts.map +1 -1
- package/esm/dumpsys.js +111 -0
- package/esm/dumpsys.js.map +1 -1
- package/esm/index.d.ts +6 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +6 -0
- package/esm/index.js.map +1 -1
- package/esm/intent.d.ts +10 -0
- package/esm/intent.d.ts.map +1 -0
- package/esm/intent.js +51 -0
- package/esm/intent.js.map +1 -0
- package/esm/logcat.d.ts +1 -0
- package/esm/logcat.d.ts.map +1 -1
- package/esm/logcat.js +20 -18
- 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 +42 -5
- package/esm/pm.d.ts.map +1 -1
- package/esm/pm.js +164 -46
- package/esm/pm.js.map +1 -1
- package/esm/settings.d.ts +22 -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/esm/utils.d.ts +4 -0
- package/esm/utils.d.ts.map +1 -0
- package/esm/utils.js +23 -0
- package/esm/utils.js.map +1 -0
- package/package.json +13 -8
- package/src/am.ts +69 -0
- 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 +129 -0
- package/src/index.ts +6 -0
- package/src/intent.ts +63 -0
- package/src/logcat.ts +45 -42
- package/src/overlay-display.ts +82 -85
- package/src/pm.ts +274 -61
- package/src/settings.ts +94 -43
- package/src/string-format.ts +199 -0
- package/src/utils.ts +29 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/src/demo-mode.ts
CHANGED
|
@@ -52,57 +52,65 @@ export const DemoModeStatusBarModes = [
|
|
|
52
52
|
export type DemoModeStatusBarMode = (typeof DemoModeStatusBarModes)[number];
|
|
53
53
|
|
|
54
54
|
export class DemoMode extends AdbCommandBase {
|
|
55
|
-
|
|
55
|
+
#settings: Settings;
|
|
56
56
|
|
|
57
57
|
constructor(adb: Adb) {
|
|
58
58
|
super(adb);
|
|
59
|
-
this
|
|
59
|
+
this.#settings = new Settings(adb);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
static readonly ALLOWED_SETTING_KEY = "sysui_demo_allowed";
|
|
63
63
|
|
|
64
64
|
// Demo Mode actually doesn't have a setting indicates its enablement
|
|
65
65
|
// However Developer Mode menu uses this key
|
|
66
66
|
// So we can only try our best to guess if it's enabled
|
|
67
|
-
|
|
67
|
+
static readonly ENABLED_SETTING_KEY = "sysui_tuner_demo_on";
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
const output = await this
|
|
69
|
+
async getAllowed(): Promise<boolean> {
|
|
70
|
+
const output = await this.#settings.get(
|
|
71
71
|
"global",
|
|
72
|
-
DemoMode.
|
|
72
|
+
DemoMode.ALLOWED_SETTING_KEY,
|
|
73
73
|
);
|
|
74
|
-
return output
|
|
74
|
+
return output === "1";
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
async setAllowed(value: boolean): Promise<void> {
|
|
78
78
|
if (value) {
|
|
79
|
-
await this
|
|
79
|
+
await this.#settings.put(
|
|
80
|
+
"global",
|
|
81
|
+
DemoMode.ALLOWED_SETTING_KEY,
|
|
82
|
+
"1",
|
|
83
|
+
);
|
|
80
84
|
} else {
|
|
81
85
|
await this.setEnabled(false);
|
|
82
|
-
await this
|
|
86
|
+
await this.#settings.delete("global", DemoMode.ALLOWED_SETTING_KEY);
|
|
83
87
|
}
|
|
84
88
|
}
|
|
85
89
|
|
|
86
|
-
|
|
87
|
-
const result = await this
|
|
90
|
+
async getEnabled(): Promise<boolean> {
|
|
91
|
+
const result = await this.#settings.get(
|
|
88
92
|
"global",
|
|
89
|
-
DemoMode.
|
|
93
|
+
DemoMode.ENABLED_SETTING_KEY,
|
|
90
94
|
);
|
|
91
|
-
return result
|
|
95
|
+
return result === "1";
|
|
92
96
|
}
|
|
93
97
|
|
|
94
|
-
|
|
98
|
+
async setEnabled(value: boolean): Promise<void> {
|
|
95
99
|
if (value) {
|
|
96
|
-
await this
|
|
100
|
+
await this.#settings.put(
|
|
101
|
+
"global",
|
|
102
|
+
DemoMode.ENABLED_SETTING_KEY,
|
|
103
|
+
"1",
|
|
104
|
+
);
|
|
97
105
|
} else {
|
|
98
|
-
await this
|
|
106
|
+
await this.#settings.delete("global", DemoMode.ENABLED_SETTING_KEY);
|
|
99
107
|
await this.broadcast("exit");
|
|
100
108
|
}
|
|
101
109
|
}
|
|
102
110
|
|
|
103
|
-
|
|
111
|
+
async broadcast(
|
|
104
112
|
command: string,
|
|
105
|
-
extra?: Record<string, string
|
|
113
|
+
extra?: Record<string, string>,
|
|
106
114
|
): Promise<void> {
|
|
107
115
|
await this.adb.subprocess.spawnAndWaitLegacy([
|
|
108
116
|
"am",
|
|
@@ -122,31 +130,27 @@ export class DemoMode extends AdbCommandBase {
|
|
|
122
130
|
]);
|
|
123
131
|
}
|
|
124
132
|
|
|
125
|
-
|
|
133
|
+
async setBatteryLevel(level: number): Promise<void> {
|
|
126
134
|
await this.broadcast("battery", { level: level.toString() });
|
|
127
135
|
}
|
|
128
136
|
|
|
129
|
-
|
|
137
|
+
async setBatteryCharging(value: boolean): Promise<void> {
|
|
130
138
|
await this.broadcast("battery", { plugged: value.toString() });
|
|
131
139
|
}
|
|
132
140
|
|
|
133
|
-
|
|
141
|
+
async setPowerSaveMode(value: boolean): Promise<void> {
|
|
134
142
|
await this.broadcast("battery", { powersave: value.toString() });
|
|
135
143
|
}
|
|
136
144
|
|
|
137
|
-
|
|
145
|
+
async setAirplaneMode(show: boolean): Promise<void> {
|
|
138
146
|
await this.broadcast("network", { airplane: show ? "show" : "hide" });
|
|
139
147
|
}
|
|
140
148
|
|
|
141
|
-
|
|
142
|
-
value: DemoModeSignalStrength
|
|
143
|
-
): Promise<void> {
|
|
149
|
+
async setWifiSignalStrength(value: DemoModeSignalStrength): Promise<void> {
|
|
144
150
|
await this.broadcast("network", { wifi: "show", level: value });
|
|
145
151
|
}
|
|
146
152
|
|
|
147
|
-
|
|
148
|
-
value: DemoModeMobileDataType
|
|
149
|
-
): Promise<void> {
|
|
153
|
+
async setMobileDataType(value: DemoModeMobileDataType): Promise<void> {
|
|
150
154
|
for (let i = 0; i < 2; i += 1) {
|
|
151
155
|
await this.broadcast("network", {
|
|
152
156
|
mobile: "show",
|
|
@@ -164,60 +168,60 @@ export class DemoMode extends AdbCommandBase {
|
|
|
164
168
|
}
|
|
165
169
|
}
|
|
166
170
|
|
|
167
|
-
|
|
168
|
-
value: DemoModeSignalStrength
|
|
171
|
+
async setMobileSignalStrength(
|
|
172
|
+
value: DemoModeSignalStrength,
|
|
169
173
|
): Promise<void> {
|
|
170
174
|
await this.broadcast("network", { mobile: "show", level: value });
|
|
171
175
|
}
|
|
172
176
|
|
|
173
|
-
|
|
177
|
+
async setNoSimCardIcon(show: boolean): Promise<void> {
|
|
174
178
|
await this.broadcast("network", { nosim: show ? "show" : "hide" });
|
|
175
179
|
}
|
|
176
180
|
|
|
177
|
-
|
|
181
|
+
async setStatusBarMode(mode: DemoModeStatusBarMode): Promise<void> {
|
|
178
182
|
await this.broadcast("bars", { mode });
|
|
179
183
|
}
|
|
180
184
|
|
|
181
|
-
|
|
185
|
+
async setVibrateModeEnabled(value: boolean): Promise<void> {
|
|
182
186
|
// https://cs.android.com/android/platform/superproject/+/master:frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java;l=103
|
|
183
187
|
await this.broadcast("status", { volume: value ? "vibrate" : "hide" });
|
|
184
188
|
}
|
|
185
189
|
|
|
186
|
-
|
|
190
|
+
async setBluetoothConnected(value: boolean): Promise<void> {
|
|
187
191
|
// https://cs.android.com/android/platform/superproject/+/master:frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java;l=114
|
|
188
192
|
await this.broadcast("status", {
|
|
189
193
|
bluetooth: value ? "connected" : "hide",
|
|
190
194
|
});
|
|
191
195
|
}
|
|
192
196
|
|
|
193
|
-
|
|
197
|
+
async setLocatingIcon(show: boolean): Promise<void> {
|
|
194
198
|
await this.broadcast("status", { location: show ? "show" : "hide" });
|
|
195
199
|
}
|
|
196
200
|
|
|
197
|
-
|
|
201
|
+
async setAlarmIcon(show: boolean): Promise<void> {
|
|
198
202
|
await this.broadcast("status", { alarm: show ? "show" : "hide" });
|
|
199
203
|
}
|
|
200
204
|
|
|
201
|
-
|
|
205
|
+
async setSyncingIcon(show: boolean): Promise<void> {
|
|
202
206
|
await this.broadcast("status", { sync: show ? "show" : "hide" });
|
|
203
207
|
}
|
|
204
208
|
|
|
205
|
-
|
|
209
|
+
async setMuteIcon(show: boolean): Promise<void> {
|
|
206
210
|
await this.broadcast("status", { mute: show ? "show" : "hide" });
|
|
207
211
|
}
|
|
208
212
|
|
|
209
|
-
|
|
213
|
+
async setSpeakerPhoneIcon(show: boolean): Promise<void> {
|
|
210
214
|
await this.broadcast("status", {
|
|
211
215
|
speakerphone: show ? "show" : "hide",
|
|
212
216
|
});
|
|
213
217
|
}
|
|
214
218
|
|
|
215
|
-
|
|
219
|
+
async setNotificationsVisibility(show: boolean): Promise<void> {
|
|
216
220
|
// https://cs.android.com/android/platform/superproject/+/master:frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java;l=3131
|
|
217
221
|
await this.broadcast("notifications", { visible: show.toString() });
|
|
218
222
|
}
|
|
219
223
|
|
|
220
|
-
|
|
224
|
+
async setTime(hour: number, minute: number): Promise<void> {
|
|
221
225
|
await this.broadcast("clock", {
|
|
222
226
|
// cspell: disable-next-line
|
|
223
227
|
hhmm:
|
package/src/dumpsys.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { AdbCommandBase } from "@yume-chan/adb";
|
|
2
|
+
|
|
3
|
+
export class DumpSys extends AdbCommandBase {
|
|
4
|
+
async diskStats() {
|
|
5
|
+
const output = await this.adb.subprocess.spawnAndWaitLegacy([
|
|
6
|
+
"dumpsys",
|
|
7
|
+
"diskstats",
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
function getSize(name: string) {
|
|
11
|
+
const match = output.match(
|
|
12
|
+
new RegExp(`${name}-Free: (\\d+)K / (\\d+)K`),
|
|
13
|
+
);
|
|
14
|
+
if (!match) {
|
|
15
|
+
return [0, 0];
|
|
16
|
+
}
|
|
17
|
+
return [
|
|
18
|
+
Number.parseInt(match[1]!, 10) * 1024,
|
|
19
|
+
Number.parseInt(match[2]!, 10) * 1024,
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const [dataFree, dataTotal] = getSize("Data");
|
|
24
|
+
const [cacheFree, cacheTotal] = getSize("Cache");
|
|
25
|
+
const [systemFree, systemTotal] = getSize("System");
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
dataFree,
|
|
29
|
+
dataTotal,
|
|
30
|
+
cacheFree,
|
|
31
|
+
cacheTotal,
|
|
32
|
+
systemFree,
|
|
33
|
+
systemTotal,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async battery() {
|
|
38
|
+
const output = await this.adb.subprocess.spawnAndWaitLegacy([
|
|
39
|
+
"dumpsys",
|
|
40
|
+
"battery",
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
let acPowered = false;
|
|
44
|
+
let usbPowered = false;
|
|
45
|
+
let wirelessPowered = false;
|
|
46
|
+
let level: number | undefined;
|
|
47
|
+
let scale: number | undefined;
|
|
48
|
+
let voltage: number | undefined;
|
|
49
|
+
let current: number | undefined;
|
|
50
|
+
let status: DumpSys.Battery.Status | undefined;
|
|
51
|
+
let health: DumpSys.Battery.Health | undefined;
|
|
52
|
+
for (const line of output.split("\n")) {
|
|
53
|
+
const parts = line.split(":");
|
|
54
|
+
if (parts.length !== 2) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
switch (parts[0]!.trim()) {
|
|
59
|
+
case "AC powered":
|
|
60
|
+
acPowered = parts[1]!.trim() === "true";
|
|
61
|
+
break;
|
|
62
|
+
case "USB powered":
|
|
63
|
+
usbPowered = parts[1]!.trim() === "true";
|
|
64
|
+
break;
|
|
65
|
+
case "Wireless powered":
|
|
66
|
+
wirelessPowered = parts[1]!.trim() === "true";
|
|
67
|
+
break;
|
|
68
|
+
case "level":
|
|
69
|
+
level = Number.parseInt(parts[1]!.trim(), 10);
|
|
70
|
+
break;
|
|
71
|
+
case "scale":
|
|
72
|
+
scale = Number.parseInt(parts[1]!.trim(), 10);
|
|
73
|
+
break;
|
|
74
|
+
case "voltage":
|
|
75
|
+
voltage = Number.parseInt(parts[1]!.trim(), 10);
|
|
76
|
+
break;
|
|
77
|
+
case "current now":
|
|
78
|
+
current = Number.parseInt(parts[1]!.trim(), 10);
|
|
79
|
+
break;
|
|
80
|
+
case "status":
|
|
81
|
+
status = Number.parseInt(
|
|
82
|
+
parts[1]!.trim(),
|
|
83
|
+
10,
|
|
84
|
+
) as DumpSys.Battery.Status;
|
|
85
|
+
break;
|
|
86
|
+
case "health":
|
|
87
|
+
health = Number.parseInt(
|
|
88
|
+
parts[1]!.trim(),
|
|
89
|
+
10,
|
|
90
|
+
) as DumpSys.Battery.Health;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
acPowered,
|
|
97
|
+
usbPowered,
|
|
98
|
+
wirelessPowered,
|
|
99
|
+
level,
|
|
100
|
+
scale,
|
|
101
|
+
voltage,
|
|
102
|
+
current,
|
|
103
|
+
status,
|
|
104
|
+
health,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export namespace DumpSys {
|
|
110
|
+
export namespace Battery {
|
|
111
|
+
export enum Status {
|
|
112
|
+
Unknown = 1,
|
|
113
|
+
Charging,
|
|
114
|
+
Discharging,
|
|
115
|
+
NotCharging,
|
|
116
|
+
Full,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export enum Health {
|
|
120
|
+
Unknown = 1,
|
|
121
|
+
Good,
|
|
122
|
+
Overheat,
|
|
123
|
+
Dead,
|
|
124
|
+
OverVoltage,
|
|
125
|
+
UnspecifiedFailure,
|
|
126
|
+
Cold,
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
// cspell: ignore logcat
|
|
2
2
|
|
|
3
|
+
export * from "./am.js";
|
|
4
|
+
export * from "./bu.js";
|
|
3
5
|
export * from "./bug-report.js";
|
|
4
6
|
export * from "./cmd.js";
|
|
5
7
|
export * from "./demo-mode.js";
|
|
8
|
+
export * from "./dumpsys.js";
|
|
9
|
+
export * from "./intent.js";
|
|
6
10
|
export * from "./logcat.js";
|
|
11
|
+
export * from "./overlay-display.js";
|
|
7
12
|
export * from "./pm.js";
|
|
8
13
|
export * from "./settings.js";
|
|
14
|
+
export * from "./string-format.js";
|
package/src/intent.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export class IntentBuilder {
|
|
2
|
+
#action: string | undefined;
|
|
3
|
+
#categories: string[] = [];
|
|
4
|
+
#packageName: string | undefined;
|
|
5
|
+
#component: string | undefined;
|
|
6
|
+
#data: string | undefined;
|
|
7
|
+
#type: string | undefined;
|
|
8
|
+
|
|
9
|
+
setAction(action: string): this {
|
|
10
|
+
this.#action = action;
|
|
11
|
+
return this;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
addCategory(category: string): this {
|
|
15
|
+
this.#categories.push(category);
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
setPackage(packageName: string): this {
|
|
20
|
+
this.#packageName = packageName;
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
setComponent(component: string): this {
|
|
25
|
+
this.#component = component;
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setData(data: string): this {
|
|
30
|
+
this.#data = data;
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
build(): string[] {
|
|
35
|
+
const result: string[] = [];
|
|
36
|
+
|
|
37
|
+
if (this.#action) {
|
|
38
|
+
result.push("-a", this.#action);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const category of this.#categories) {
|
|
42
|
+
result.push("-c", category);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (this.#packageName) {
|
|
46
|
+
result.push("-p", this.#packageName);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (this.#component) {
|
|
50
|
+
result.push("-n", this.#component);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (this.#data) {
|
|
54
|
+
result.push("-d", this.#data);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (this.#type) {
|
|
58
|
+
result.push("-t", this.#type);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
}
|
package/src/logcat.ts
CHANGED
|
@@ -80,6 +80,7 @@ export interface LogcatFormatModifiers {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
export interface LogcatOptions {
|
|
83
|
+
dump?: boolean;
|
|
83
84
|
pid?: number;
|
|
84
85
|
ids?: LogId[];
|
|
85
86
|
}
|
|
@@ -148,7 +149,7 @@ function formatSeconds(seconds: number, modifiers: LogcatFormatModifiers) {
|
|
|
148
149
|
|
|
149
150
|
function formatNanoseconds(
|
|
150
151
|
nanoseconds: number,
|
|
151
|
-
modifiers: LogcatFormatModifiers
|
|
152
|
+
modifiers: LogcatFormatModifiers,
|
|
152
153
|
) {
|
|
153
154
|
if (modifiers.nanoseconds) {
|
|
154
155
|
return padZero(nanoseconds, 9);
|
|
@@ -186,7 +187,7 @@ function formatTimezone(seconds: number, modifiers: LogcatFormatModifiers) {
|
|
|
186
187
|
function formatTime(
|
|
187
188
|
seconds: number,
|
|
188
189
|
nanoseconds: number,
|
|
189
|
-
modifiers: LogcatFormatModifiers
|
|
190
|
+
modifiers: LogcatFormatModifiers,
|
|
190
191
|
) {
|
|
191
192
|
const secondsString = formatSeconds(seconds, modifiers);
|
|
192
193
|
const nanosecondsString = formatNanoseconds(nanoseconds, modifiers);
|
|
@@ -197,7 +198,7 @@ function formatTime(
|
|
|
197
198
|
function formatUid(
|
|
198
199
|
uid: number,
|
|
199
200
|
modifiers: LogcatFormatModifiers,
|
|
200
|
-
suffix: string
|
|
201
|
+
suffix: string,
|
|
201
202
|
) {
|
|
202
203
|
return modifiers.uid ? `${uid.toString().padStart(5)}${suffix}` : "";
|
|
203
204
|
}
|
|
@@ -205,7 +206,7 @@ function formatUid(
|
|
|
205
206
|
function getFormatPrefix(
|
|
206
207
|
entry: AndroidLogEntry,
|
|
207
208
|
format: LogcatFormat,
|
|
208
|
-
modifiers: LogcatFormatModifiers
|
|
209
|
+
modifiers: LogcatFormatModifiers,
|
|
209
210
|
) {
|
|
210
211
|
// https://cs.android.com/android/platform/superproject/+/master:system/logging/liblog/logprint.cpp;l=1415;drc=8dbf3b2bb6b6d1652d9797e477b9abd03278bb79
|
|
211
212
|
switch (format) {
|
|
@@ -294,7 +295,7 @@ function getFormatSuffix(entry: AndroidLogEntry, format: LogcatFormat) {
|
|
|
294
295
|
function formatEntryWrapLine(
|
|
295
296
|
entry: AndroidLogEntry,
|
|
296
297
|
format: LogcatFormat,
|
|
297
|
-
modifiers: LogcatFormatModifiers
|
|
298
|
+
modifiers: LogcatFormatModifiers,
|
|
298
299
|
) {
|
|
299
300
|
const prefix = getFormatPrefix(entry, format, modifiers);
|
|
300
301
|
const suffix = getFormatSuffix(entry, format);
|
|
@@ -306,7 +307,7 @@ function formatEntryWrapLine(
|
|
|
306
307
|
function AndroidLogEntryToString(
|
|
307
308
|
this: AndroidLogEntry,
|
|
308
309
|
format: LogcatFormat = LogcatFormat.ThreadTime,
|
|
309
|
-
modifiers: LogcatFormatModifiers = {}
|
|
310
|
+
modifiers: LogcatFormatModifiers = {},
|
|
310
311
|
) {
|
|
311
312
|
switch (format) {
|
|
312
313
|
case LogcatFormat.Long:
|
|
@@ -348,7 +349,7 @@ function findTagEnd(payload: Uint8Array) {
|
|
|
348
349
|
}
|
|
349
350
|
|
|
350
351
|
export async function deserializeAndroidLogEntry(
|
|
351
|
-
stream: AsyncExactReadable
|
|
352
|
+
stream: AsyncExactReadable,
|
|
352
353
|
): Promise<AndroidLogEntry> {
|
|
353
354
|
const entry = (await LoggerEntry.deserialize(stream)) as AndroidLogEntry;
|
|
354
355
|
if (entry.headerSize !== LoggerEntry.size) {
|
|
@@ -382,35 +383,35 @@ export interface LogSize {
|
|
|
382
383
|
}
|
|
383
384
|
|
|
384
385
|
export class Logcat extends AdbCommandBase {
|
|
385
|
-
|
|
386
|
+
static logIdToName(id: LogId): string {
|
|
386
387
|
return LogId[id]!;
|
|
387
388
|
}
|
|
388
389
|
|
|
389
|
-
|
|
390
|
+
static logNameToId(name: string): LogId {
|
|
390
391
|
const key = name[0]!.toUpperCase() + name.substring(1);
|
|
391
392
|
return LogId[key as keyof typeof LogId];
|
|
392
393
|
}
|
|
393
394
|
|
|
394
|
-
|
|
395
|
+
static joinLogId(ids: LogId[]): string {
|
|
395
396
|
return ids.map((id) => Logcat.logIdToName(id)).join(",");
|
|
396
397
|
}
|
|
397
398
|
|
|
398
|
-
|
|
399
|
+
static parseSize(value: number, multiplier: string): number {
|
|
399
400
|
const MULTIPLIERS = ["", "Ki", "Mi", "Gi"];
|
|
400
401
|
return value * 1024 ** (MULTIPLIERS.indexOf(multiplier) || 0);
|
|
401
402
|
}
|
|
402
403
|
|
|
403
404
|
// TODO: logcat: Support output format before Android 10
|
|
404
405
|
// ref https://android-review.googlesource.com/c/platform/system/core/+/748128
|
|
405
|
-
|
|
406
|
+
static readonly LOG_SIZE_REGEX_10 =
|
|
406
407
|
/(.*): ring buffer is (.*) (.*)B \((.*) (.*)B consumed\), max entry is (.*) B, max payload is (.*) B/;
|
|
407
408
|
|
|
408
409
|
// Android 11 added `readable` part
|
|
409
410
|
// ref https://android-review.googlesource.com/c/platform/system/core/+/1390940
|
|
410
|
-
|
|
411
|
+
static readonly LOG_SIZE_REGEX_11 =
|
|
411
412
|
/(.*): ring buffer is (.*) (.*)B \((.*) (.*)B consumed, (.*) (.*)B readable\), max entry is (.*) B, max payload is (.*) B/;
|
|
412
413
|
|
|
413
|
-
|
|
414
|
+
async getLogSize(ids?: LogId[]): Promise<LogSize[]> {
|
|
414
415
|
const { stdout } = await this.adb.subprocess.spawn([
|
|
415
416
|
"logcat",
|
|
416
417
|
"-g",
|
|
@@ -430,15 +431,15 @@ export class Logcat extends AdbCommandBase {
|
|
|
430
431
|
id: Logcat.logNameToId(match[1]!),
|
|
431
432
|
size: Logcat.parseSize(
|
|
432
433
|
Number.parseInt(match[2]!, 10),
|
|
433
|
-
match[3]
|
|
434
|
+
match[3]!,
|
|
434
435
|
),
|
|
435
436
|
readable: Logcat.parseSize(
|
|
436
437
|
Number.parseInt(match[6]!, 10),
|
|
437
|
-
match[7]
|
|
438
|
+
match[7]!,
|
|
438
439
|
),
|
|
439
440
|
consumed: Logcat.parseSize(
|
|
440
441
|
Number.parseInt(match[4]!, 10),
|
|
441
|
-
match[5]
|
|
442
|
+
match[5]!,
|
|
442
443
|
),
|
|
443
444
|
maxEntrySize: parseInt(match[8]!, 10),
|
|
444
445
|
maxPayloadSize: parseInt(match[9]!, 10),
|
|
@@ -452,54 +453,56 @@ export class Logcat extends AdbCommandBase {
|
|
|
452
453
|
id: Logcat.logNameToId(match[1]!),
|
|
453
454
|
size: Logcat.parseSize(
|
|
454
455
|
Number.parseInt(match[2]!, 10),
|
|
455
|
-
match[3]
|
|
456
|
+
match[3]!,
|
|
456
457
|
),
|
|
457
458
|
consumed: Logcat.parseSize(
|
|
458
459
|
Number.parseInt(match[4]!, 10),
|
|
459
|
-
match[5]
|
|
460
|
+
match[5]!,
|
|
460
461
|
),
|
|
461
462
|
maxEntrySize: parseInt(match[6]!, 10),
|
|
462
463
|
maxPayloadSize: parseInt(match[7]!, 10),
|
|
463
464
|
});
|
|
464
465
|
}
|
|
465
466
|
},
|
|
466
|
-
})
|
|
467
|
+
}),
|
|
467
468
|
);
|
|
468
469
|
|
|
469
470
|
return result;
|
|
470
471
|
}
|
|
471
472
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
"-
|
|
476
|
-
|
|
477
|
-
|
|
473
|
+
async clear(ids?: LogId[]) {
|
|
474
|
+
const args = ["logcat", "-c"];
|
|
475
|
+
if (ids && ids.length > 0) {
|
|
476
|
+
args.push("-b", Logcat.joinLogId(ids));
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
await this.adb.subprocess.spawnAndWait(args);
|
|
478
480
|
}
|
|
479
481
|
|
|
480
|
-
|
|
482
|
+
binary(options?: LogcatOptions): ReadableStream<AndroidLogEntry> {
|
|
481
483
|
return new WrapReadableStream(async () => {
|
|
484
|
+
const args = ["logcat", "-B"];
|
|
485
|
+
if (options?.dump) {
|
|
486
|
+
args.push("-d");
|
|
487
|
+
}
|
|
488
|
+
if (options?.pid) {
|
|
489
|
+
args.push("--pid", options.pid.toString());
|
|
490
|
+
}
|
|
491
|
+
if (options?.ids) {
|
|
492
|
+
args.push("-b", Logcat.joinLogId(options.ids));
|
|
493
|
+
}
|
|
494
|
+
|
|
482
495
|
// TODO: make `spawn` return synchronously with streams pending
|
|
483
496
|
// so it's easier to chain them.
|
|
484
|
-
const { stdout } = await this.adb.subprocess.spawn(
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
...(options?.pid ? ["--pid", options.pid.toString()] : []),
|
|
489
|
-
...(options?.ids
|
|
490
|
-
? ["-b", Logcat.joinLogId(options.ids)]
|
|
491
|
-
: []),
|
|
492
|
-
],
|
|
493
|
-
{
|
|
494
|
-
// PERF: None protocol is 150% faster then Shell protocol
|
|
495
|
-
protocols: [AdbSubprocessNoneProtocol],
|
|
496
|
-
}
|
|
497
|
-
);
|
|
497
|
+
const { stdout } = await this.adb.subprocess.spawn(args, {
|
|
498
|
+
// PERF: None protocol is 150% faster then Shell protocol
|
|
499
|
+
protocols: [AdbSubprocessNoneProtocol],
|
|
500
|
+
});
|
|
498
501
|
return stdout;
|
|
499
502
|
}).pipeThrough(
|
|
500
503
|
new BufferedTransformStream((stream) => {
|
|
501
504
|
return deserializeAndroidLogEntry(stream);
|
|
502
|
-
})
|
|
505
|
+
}),
|
|
503
506
|
);
|
|
504
507
|
}
|
|
505
508
|
}
|