@yume-chan/android-bin 0.0.19 → 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 +36 -0
- package/CHANGELOG.md +19 -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 +189 -55
- 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 +39 -24
- 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 +21 -0
- package/esm/dumpsys.d.ts.map +1 -0
- package/esm/dumpsys.js +82 -0
- package/esm/dumpsys.js.map +1 -0
- 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 +3 -2
- package/esm/logcat.d.ts.map +1 -1
- package/esm/logcat.js +34 -24
- 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 +55 -19
- 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 +236 -70
- package/src/cmd.ts +67 -33
- package/src/demo-mode.ts +47 -43
- package/src/dumpsys.ts +91 -0
- package/src/index.ts +3 -0
- package/src/logcat.ts +63 -74
- package/src/overlay-display.ts +82 -85
- package/src/pm.ts +149 -27
- package/src/settings.ts +99 -50
- package/src/string-format.ts +199 -0
- package/tsconfig.build.json +11 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/src/overlay-display.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Adb } from "@yume-chan/adb";
|
|
|
2
2
|
import { AdbCommandBase } from "@yume-chan/adb";
|
|
3
3
|
|
|
4
4
|
import { Settings } from "./settings.js";
|
|
5
|
+
import { p } from "./string-format.js";
|
|
5
6
|
|
|
6
7
|
export interface OverlayDisplayDeviceMode {
|
|
7
8
|
width: number;
|
|
@@ -17,99 +18,95 @@ export interface OverlayDisplayDevice {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export class OverlayDisplay extends AdbCommandBase {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
#settings: Settings;
|
|
22
|
+
|
|
23
|
+
static readonly SETTING_KEY = "overlay_display_devices";
|
|
24
|
+
|
|
25
|
+
static readonly SETTING_FORMAT = p.separated(
|
|
26
|
+
";",
|
|
27
|
+
p.sequence(
|
|
28
|
+
{
|
|
29
|
+
name: "modes",
|
|
30
|
+
format: p.separated(
|
|
31
|
+
"|",
|
|
32
|
+
p.sequence(
|
|
33
|
+
{ name: "width", format: p.digits() },
|
|
34
|
+
p.literal("x"),
|
|
35
|
+
{ name: "height", format: p.digits() },
|
|
36
|
+
p.literal("/"),
|
|
37
|
+
{ name: "density", format: p.digits() },
|
|
38
|
+
),
|
|
39
|
+
1,
|
|
40
|
+
),
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "flags",
|
|
44
|
+
format: p.map(
|
|
45
|
+
p.repeated(
|
|
46
|
+
p.sequence(p.literal(","), {
|
|
47
|
+
name: "flag",
|
|
48
|
+
format: p.union(
|
|
49
|
+
p.literal("secure"),
|
|
50
|
+
p.literal("own_content_only"),
|
|
51
|
+
p.literal("show_system_decorations"),
|
|
52
|
+
),
|
|
53
|
+
}),
|
|
54
|
+
),
|
|
55
|
+
(value) => value.map((item) => item.flag),
|
|
56
|
+
(value) => value.map((item) => ({ flag: item })),
|
|
57
|
+
),
|
|
58
|
+
},
|
|
59
|
+
),
|
|
60
|
+
);
|
|
24
61
|
|
|
25
62
|
constructor(adb: Adb) {
|
|
26
63
|
super(adb);
|
|
27
|
-
this
|
|
64
|
+
this.#settings = new Settings(adb);
|
|
28
65
|
}
|
|
29
66
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const device: OverlayDisplayDevice = {
|
|
46
|
-
modes: [],
|
|
47
|
-
secure: false,
|
|
48
|
-
ownContentOnly: false,
|
|
49
|
-
showSystemDecorations: false,
|
|
50
|
-
};
|
|
51
|
-
for (const modeString of modesString.split("|")) {
|
|
52
|
-
const match = modeString.match(/(\d+)x(\d+)\/(\d+)/);
|
|
53
|
-
if (!match) {
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
device.modes.push({
|
|
57
|
-
width: parseInt(match[1]!, 10),
|
|
58
|
-
height: parseInt(match[2]!, 10),
|
|
59
|
-
density: parseInt(match[3]!, 10),
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
if (device.modes.length === 0) {
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
for (const flagString of flagStrings) {
|
|
67
|
-
switch (flagString) {
|
|
68
|
-
case "secure":
|
|
69
|
-
device.secure = true;
|
|
70
|
-
break;
|
|
71
|
-
case "own_content_only":
|
|
72
|
-
device.ownContentOnly = true;
|
|
73
|
-
break;
|
|
74
|
-
case "show_system_decorations":
|
|
75
|
-
device.showSystemDecorations = true;
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
devices.push(device);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return devices;
|
|
67
|
+
async get() {
|
|
68
|
+
return OverlayDisplay.SETTING_FORMAT.parse({
|
|
69
|
+
value: await this.#settings.get(
|
|
70
|
+
"global",
|
|
71
|
+
OverlayDisplay.SETTING_KEY,
|
|
72
|
+
),
|
|
73
|
+
position: 0,
|
|
74
|
+
}).map((device) => ({
|
|
75
|
+
modes: device.modes,
|
|
76
|
+
secure: device.flags.includes("secure"),
|
|
77
|
+
ownContentOnly: device.flags.includes("own_content_only"),
|
|
78
|
+
showSystemDecorations: device.flags.includes(
|
|
79
|
+
"show_system_decorations",
|
|
80
|
+
),
|
|
81
|
+
}));
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
for (const device of devices) {
|
|
88
|
-
if (settingString) {
|
|
89
|
-
settingString += ";";
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
settingString += device.modes
|
|
93
|
-
.map((mode) => `${mode.width}x${mode.height}/${mode.density}`)
|
|
94
|
-
.join("|");
|
|
95
|
-
|
|
96
|
-
if (device.secure) {
|
|
97
|
-
settingString += ",secure";
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (device.ownContentOnly) {
|
|
101
|
-
settingString += ",own_content_only";
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (device.showSystemDecorations) {
|
|
105
|
-
settingString += ",show_system_decorations";
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
await this.settings.put(
|
|
84
|
+
async set(devices: OverlayDisplayDevice[]) {
|
|
85
|
+
await this.#settings.put(
|
|
110
86
|
"global",
|
|
111
|
-
OverlayDisplay.
|
|
112
|
-
|
|
87
|
+
OverlayDisplay.SETTING_KEY,
|
|
88
|
+
OverlayDisplay.SETTING_FORMAT.stringify(
|
|
89
|
+
devices.map((device) => {
|
|
90
|
+
const flags: (
|
|
91
|
+
| "secure"
|
|
92
|
+
| "own_content_only"
|
|
93
|
+
| "show_system_decorations"
|
|
94
|
+
)[] = [];
|
|
95
|
+
if (device.secure) {
|
|
96
|
+
flags.push("secure");
|
|
97
|
+
}
|
|
98
|
+
if (device.ownContentOnly) {
|
|
99
|
+
flags.push("own_content_only");
|
|
100
|
+
}
|
|
101
|
+
if (device.showSystemDecorations) {
|
|
102
|
+
flags.push("show_system_decorations");
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
modes: device.modes,
|
|
106
|
+
flags,
|
|
107
|
+
};
|
|
108
|
+
}),
|
|
109
|
+
),
|
|
113
110
|
);
|
|
114
111
|
}
|
|
115
112
|
}
|
package/src/pm.ts
CHANGED
|
@@ -177,25 +177,65 @@ export const PACKAGE_MANAGER_INSTALL_OPTIONS_MAP: Record<
|
|
|
177
177
|
bypassLowTargetSdkBlock: "--bypass-low-target-sdk-block",
|
|
178
178
|
};
|
|
179
179
|
|
|
180
|
+
export interface PackageManagerListPackagesOptions {
|
|
181
|
+
listDisabled: boolean;
|
|
182
|
+
listEnabled: boolean;
|
|
183
|
+
showSourceDir: boolean;
|
|
184
|
+
showInstaller: boolean;
|
|
185
|
+
listSystem: boolean;
|
|
186
|
+
showUid: boolean;
|
|
187
|
+
listThirdParty: boolean;
|
|
188
|
+
showVersionCode: boolean;
|
|
189
|
+
listApexOnly: boolean;
|
|
190
|
+
user: "all" | "current" | number;
|
|
191
|
+
uid: number;
|
|
192
|
+
filter: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export const PACKAGE_MANAGER_LIST_PACKAGES_OPTIONS_MAP: Record<
|
|
196
|
+
keyof PackageManagerListPackagesOptions,
|
|
197
|
+
string
|
|
198
|
+
> = {
|
|
199
|
+
listDisabled: "-d",
|
|
200
|
+
listEnabled: "-e",
|
|
201
|
+
showSourceDir: "-f",
|
|
202
|
+
showInstaller: "-i",
|
|
203
|
+
listSystem: "-s",
|
|
204
|
+
showUid: "-U",
|
|
205
|
+
listThirdParty: "-3",
|
|
206
|
+
showVersionCode: "--show-versioncode",
|
|
207
|
+
listApexOnly: "--apex-only",
|
|
208
|
+
user: "--user",
|
|
209
|
+
uid: "--uid",
|
|
210
|
+
filter: "",
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
export interface PackageManagerListPackagesResult {
|
|
214
|
+
packageName: string;
|
|
215
|
+
sourceDir?: string | undefined;
|
|
216
|
+
versionCode?: number | undefined;
|
|
217
|
+
installer?: string | undefined;
|
|
218
|
+
uid?: number | undefined;
|
|
219
|
+
}
|
|
220
|
+
|
|
180
221
|
export class PackageManager extends AdbCommandBase {
|
|
181
|
-
|
|
222
|
+
#cmd: Cmd;
|
|
182
223
|
|
|
183
|
-
|
|
224
|
+
constructor(adb: Adb) {
|
|
184
225
|
super(adb);
|
|
185
|
-
this
|
|
226
|
+
this.#cmd = new Cmd(adb);
|
|
186
227
|
}
|
|
187
228
|
|
|
188
|
-
|
|
189
|
-
|
|
229
|
+
#buildArguments<T>(
|
|
230
|
+
commands: string[],
|
|
231
|
+
options: Partial<T> | undefined,
|
|
232
|
+
map: Record<keyof T, string>,
|
|
190
233
|
): string[] {
|
|
191
|
-
const args = ["pm",
|
|
234
|
+
const args = ["pm", ...commands];
|
|
192
235
|
if (options) {
|
|
193
236
|
for (const [key, value] of Object.entries(options)) {
|
|
194
237
|
if (value) {
|
|
195
|
-
const option =
|
|
196
|
-
PACKAGE_MANAGER_INSTALL_OPTIONS_MAP[
|
|
197
|
-
key as keyof PackageManagerInstallOptions
|
|
198
|
-
];
|
|
238
|
+
const option = map[key as keyof T];
|
|
199
239
|
if (option) {
|
|
200
240
|
args.push(option);
|
|
201
241
|
switch (typeof value) {
|
|
@@ -213,19 +253,29 @@ export class PackageManager extends AdbCommandBase {
|
|
|
213
253
|
return args;
|
|
214
254
|
}
|
|
215
255
|
|
|
216
|
-
|
|
256
|
+
#buildInstallArguments(
|
|
257
|
+
options: Partial<PackageManagerInstallOptions> | undefined,
|
|
258
|
+
): string[] {
|
|
259
|
+
return this.#buildArguments(
|
|
260
|
+
["install"],
|
|
261
|
+
options,
|
|
262
|
+
PACKAGE_MANAGER_INSTALL_OPTIONS_MAP,
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async install(
|
|
217
267
|
apks: string[],
|
|
218
|
-
options?: Partial<PackageManagerInstallOptions
|
|
268
|
+
options?: Partial<PackageManagerInstallOptions>,
|
|
219
269
|
): Promise<string> {
|
|
220
|
-
const args = this
|
|
270
|
+
const args = this.#buildInstallArguments(options);
|
|
221
271
|
// WIP: old version of pm doesn't support multiple apks
|
|
222
272
|
args.push(...apks);
|
|
223
273
|
return await this.adb.subprocess.spawnAndWaitLegacy(args);
|
|
224
274
|
}
|
|
225
275
|
|
|
226
|
-
|
|
276
|
+
async pushAndInstallStream(
|
|
227
277
|
stream: ReadableStream<Consumable<Uint8Array>>,
|
|
228
|
-
options?: Partial<PackageManagerInstallOptions
|
|
278
|
+
options?: Partial<PackageManagerInstallOptions>,
|
|
229
279
|
): Promise<ReadableStream<string>> {
|
|
230
280
|
const sync = await this.adb.sync();
|
|
231
281
|
|
|
@@ -241,11 +291,15 @@ export class PackageManager extends AdbCommandBase {
|
|
|
241
291
|
await sync.dispose();
|
|
242
292
|
}
|
|
243
293
|
|
|
244
|
-
|
|
294
|
+
// Starting from Android 7, `pm` is a only wrapper for `cmd package`,
|
|
295
|
+
// and `cmd package` launches faster than `pm`.
|
|
296
|
+
// But `cmd package` can't read `/data/local/tmp` folder due to SELinux policy,
|
|
297
|
+
// so installing a file must use `pm`.
|
|
298
|
+
const args = this.#buildInstallArguments(options);
|
|
245
299
|
args.push(filePath);
|
|
246
300
|
const process = await AdbSubprocessNoneProtocol.raw(
|
|
247
301
|
this.adb,
|
|
248
|
-
args.map(escapeArg).join(" ")
|
|
302
|
+
args.map(escapeArg).join(" "),
|
|
249
303
|
);
|
|
250
304
|
return new WrapReadableStream({
|
|
251
305
|
start: () => process.stdout.pipeThrough(new DecodeUtf8Stream()),
|
|
@@ -255,27 +309,95 @@ export class PackageManager extends AdbCommandBase {
|
|
|
255
309
|
});
|
|
256
310
|
}
|
|
257
311
|
|
|
258
|
-
|
|
312
|
+
async installStream(
|
|
259
313
|
size: number,
|
|
260
314
|
stream: ReadableStream<Consumable<Uint8Array>>,
|
|
261
|
-
options?: Partial<PackageManagerInstallOptions
|
|
315
|
+
options?: Partial<PackageManagerInstallOptions>,
|
|
262
316
|
): Promise<ReadableStream<string>> {
|
|
263
|
-
|
|
317
|
+
// Android 7 added both `cmd` command and streaming install support,
|
|
318
|
+
// we can't detect whether `pm` supports streaming install,
|
|
319
|
+
// so we detect `cmd` command support instead.
|
|
320
|
+
if (!this.#cmd.supportsCmd) {
|
|
264
321
|
return this.pushAndInstallStream(stream, options);
|
|
265
322
|
}
|
|
266
323
|
|
|
267
|
-
|
|
268
|
-
//
|
|
269
|
-
// However, `cmd package install` can't read `/data/local/tmp` folder due to SELinux policy,
|
|
270
|
-
// so even ADB today is still using `pm install` for non-streaming installs.
|
|
271
|
-
const args = this.buildInstallArgs(options);
|
|
272
|
-
// Remove `pm` from args, final command will be `cmd package install`
|
|
324
|
+
const args = this.#buildInstallArguments(options);
|
|
325
|
+
// Remove `pm` from args, final command will starts with `cmd package install`
|
|
273
326
|
args.shift();
|
|
274
327
|
args.push("-S", size.toString());
|
|
275
|
-
const process = await this.
|
|
328
|
+
const process = await this.#cmd.spawn(false, "package", ...args);
|
|
276
329
|
await stream.pipeTo(process.stdin);
|
|
277
330
|
return process.stdout.pipeThrough(new DecodeUtf8Stream());
|
|
278
331
|
}
|
|
279
332
|
|
|
333
|
+
static parsePackageListItem(
|
|
334
|
+
line: string,
|
|
335
|
+
): PackageManagerListPackagesResult {
|
|
336
|
+
line = line.substring("package:".length);
|
|
337
|
+
|
|
338
|
+
let packageName: string;
|
|
339
|
+
let sourceDir: string | undefined;
|
|
340
|
+
let versionCode: number | undefined;
|
|
341
|
+
let installer: string | undefined;
|
|
342
|
+
let uid: number | undefined;
|
|
343
|
+
|
|
344
|
+
// Parse backwards
|
|
345
|
+
let index = line.indexOf(" uid:");
|
|
346
|
+
if (index !== -1) {
|
|
347
|
+
uid = Number.parseInt(line.substring(index + " uid:".length), 10);
|
|
348
|
+
line = line.substring(0, index);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
index = line.indexOf(" installer=");
|
|
352
|
+
if (index !== -1) {
|
|
353
|
+
installer = line.substring(index + " installer=".length);
|
|
354
|
+
line = line.substring(0, index);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
index = line.indexOf(" versionCode:");
|
|
358
|
+
if (index !== -1) {
|
|
359
|
+
versionCode = Number.parseInt(
|
|
360
|
+
line.substring(index + " versionCode:".length),
|
|
361
|
+
10,
|
|
362
|
+
);
|
|
363
|
+
line = line.substring(0, index);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// `sourceDir` may contain `=` so use `lastIndexOf`
|
|
367
|
+
index = line.lastIndexOf("=");
|
|
368
|
+
if (index !== -1) {
|
|
369
|
+
sourceDir = line.substring(0, index);
|
|
370
|
+
packageName = line.substring(index + "=".length);
|
|
371
|
+
} else {
|
|
372
|
+
packageName = line;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return {
|
|
376
|
+
packageName,
|
|
377
|
+
sourceDir,
|
|
378
|
+
versionCode,
|
|
379
|
+
installer,
|
|
380
|
+
uid,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
async listPackages(
|
|
385
|
+
options?: Partial<PackageManagerListPackagesOptions>,
|
|
386
|
+
): Promise<PackageManagerListPackagesResult[]> {
|
|
387
|
+
const args = this.#buildArguments(
|
|
388
|
+
["list", "packages"],
|
|
389
|
+
options,
|
|
390
|
+
PACKAGE_MANAGER_LIST_PACKAGES_OPTIONS_MAP,
|
|
391
|
+
);
|
|
392
|
+
if (options?.filter) {
|
|
393
|
+
args.push(options.filter);
|
|
394
|
+
}
|
|
395
|
+
const output = await this.adb.subprocess.spawnAndWaitLegacy(args);
|
|
396
|
+
return output
|
|
397
|
+
.split("\n")
|
|
398
|
+
.filter((line) => !!line)
|
|
399
|
+
.map((line) => PackageManager.parsePackageListItem(line));
|
|
400
|
+
}
|
|
401
|
+
|
|
280
402
|
// TODO: install: support split apk formats (`adb install-multiple`)
|
|
281
403
|
}
|
package/src/settings.ts
CHANGED
|
@@ -1,78 +1,127 @@
|
|
|
1
|
+
import type { Adb, AdbSubprocessWaitResult } from "@yume-chan/adb";
|
|
1
2
|
import { AdbCommandBase } from "@yume-chan/adb";
|
|
2
3
|
|
|
4
|
+
import { Cmd } from "./cmd.js";
|
|
5
|
+
|
|
3
6
|
export type SettingsNamespace = "system" | "secure" | "global";
|
|
4
7
|
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
export enum SettingsResetMode {
|
|
9
|
+
UntrustedDefaults = "untrusted_defaults",
|
|
10
|
+
UntrustedClear = "untrusted_clear",
|
|
11
|
+
TrustedDefaults = "trusted_defaults",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SettingsOptions {
|
|
15
|
+
user?: number | "current";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface SettingsPutOptions extends SettingsOptions {
|
|
19
|
+
tag?: string;
|
|
20
|
+
makeDefault?: boolean;
|
|
21
|
+
}
|
|
9
22
|
|
|
10
23
|
// frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
|
|
11
24
|
export class Settings extends AdbCommandBase {
|
|
12
|
-
|
|
25
|
+
#cmd: Cmd;
|
|
13
26
|
|
|
14
|
-
|
|
15
|
-
|
|
27
|
+
constructor(adb: Adb) {
|
|
28
|
+
super(adb);
|
|
29
|
+
this.#cmd = new Cmd(adb);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async base(
|
|
33
|
+
verb: string,
|
|
16
34
|
namespace: SettingsNamespace,
|
|
35
|
+
options: SettingsOptions | undefined,
|
|
17
36
|
...args: string[]
|
|
18
|
-
) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
37
|
+
): Promise<string> {
|
|
38
|
+
let command = ["settings"];
|
|
39
|
+
|
|
40
|
+
if (options?.user !== undefined) {
|
|
41
|
+
command.push("--user", options.user.toString());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
command.push(verb, namespace);
|
|
45
|
+
command = command.concat(args);
|
|
46
|
+
|
|
47
|
+
let output: AdbSubprocessWaitResult;
|
|
48
|
+
if (this.#cmd.supportsCmd) {
|
|
49
|
+
output = await this.#cmd.spawnAndWait(
|
|
50
|
+
command[0]!,
|
|
51
|
+
...command.slice(1),
|
|
52
|
+
);
|
|
53
|
+
} else {
|
|
54
|
+
output = await this.adb.subprocess.spawnAndWait(command);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (output.stderr) {
|
|
58
|
+
throw new Error(output.stderr);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return output.stdout;
|
|
25
62
|
}
|
|
26
63
|
|
|
27
|
-
|
|
28
|
-
|
|
64
|
+
async get(
|
|
65
|
+
namespace: SettingsNamespace,
|
|
66
|
+
key: string,
|
|
67
|
+
options?: SettingsOptions,
|
|
68
|
+
) {
|
|
69
|
+
const output = await this.base("get", namespace, options, key);
|
|
70
|
+
// Remove last \n
|
|
71
|
+
return output.substring(0, output.length - 1);
|
|
29
72
|
}
|
|
30
73
|
|
|
31
|
-
|
|
32
|
-
|
|
74
|
+
async delete(
|
|
75
|
+
namespace: SettingsNamespace,
|
|
76
|
+
key: string,
|
|
77
|
+
options?: SettingsOptions,
|
|
78
|
+
): Promise<void> {
|
|
79
|
+
await this.base("delete", namespace, options, key);
|
|
33
80
|
}
|
|
34
81
|
|
|
35
|
-
|
|
82
|
+
async put(
|
|
36
83
|
namespace: SettingsNamespace,
|
|
37
84
|
key: string,
|
|
38
85
|
value: string,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
);
|
|
86
|
+
options?: SettingsPutOptions,
|
|
87
|
+
): Promise<void> {
|
|
88
|
+
const args = [key, value];
|
|
89
|
+
if (options?.tag) {
|
|
90
|
+
args.push(options.tag);
|
|
91
|
+
}
|
|
92
|
+
if (options?.makeDefault) {
|
|
93
|
+
args.push("default");
|
|
94
|
+
}
|
|
95
|
+
await this.base("put", namespace, options, ...args);
|
|
50
96
|
}
|
|
51
97
|
|
|
52
|
-
|
|
98
|
+
reset(
|
|
53
99
|
namespace: SettingsNamespace,
|
|
54
|
-
mode: SettingsResetMode
|
|
55
|
-
|
|
56
|
-
|
|
100
|
+
mode: SettingsResetMode,
|
|
101
|
+
options?: SettingsOptions,
|
|
102
|
+
): Promise<void>;
|
|
103
|
+
reset(
|
|
57
104
|
namespace: SettingsNamespace,
|
|
58
105
|
packageName: string,
|
|
59
|
-
tag?: string
|
|
60
|
-
|
|
61
|
-
|
|
106
|
+
tag?: string,
|
|
107
|
+
options?: SettingsOptions,
|
|
108
|
+
): Promise<void>;
|
|
109
|
+
async reset(
|
|
62
110
|
namespace: SettingsNamespace,
|
|
63
111
|
modeOrPackageName: string,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
modeOrPackageName
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
112
|
+
tagOrOptions?: string | SettingsOptions,
|
|
113
|
+
options?: SettingsOptions,
|
|
114
|
+
): Promise<void> {
|
|
115
|
+
const args = [modeOrPackageName];
|
|
116
|
+
if (
|
|
117
|
+
modeOrPackageName === SettingsResetMode.UntrustedDefaults ||
|
|
118
|
+
modeOrPackageName === SettingsResetMode.UntrustedClear ||
|
|
119
|
+
modeOrPackageName === SettingsResetMode.TrustedDefaults
|
|
120
|
+
) {
|
|
121
|
+
options = tagOrOptions as SettingsOptions;
|
|
122
|
+
} else if (typeof tagOrOptions === "string") {
|
|
123
|
+
args.push(tagOrOptions);
|
|
124
|
+
}
|
|
125
|
+
await this.base("reset", namespace, options, ...args);
|
|
77
126
|
}
|
|
78
127
|
}
|