@yume-chan/android-bin 1.1.0 → 2.0.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/CHANGELOG.md +19 -0
- package/LICENSE +1 -1
- package/esm/am.d.ts +4 -2
- package/esm/am.d.ts.map +1 -1
- package/esm/am.js +9 -17
- package/esm/am.js.map +1 -1
- package/esm/bu.d.ts +2 -2
- package/esm/bu.d.ts.map +1 -1
- package/esm/bu.js +6 -14
- package/esm/bu.js.map +1 -1
- package/esm/bug-report.d.ts +2 -2
- package/esm/bug-report.d.ts.map +1 -1
- package/esm/bug-report.js +15 -13
- package/esm/bug-report.js.map +1 -1
- package/esm/cmd.d.ts +18 -20
- package/esm/cmd.d.ts.map +1 -1
- package/esm/cmd.js +84 -63
- package/esm/cmd.js.map +1 -1
- package/esm/demo-mode.d.ts +2 -2
- package/esm/demo-mode.js +3 -3
- package/esm/demo-mode.js.map +1 -1
- package/esm/dumpsys.d.ts +2 -2
- package/esm/dumpsys.js +6 -6
- package/esm/dumpsys.js.map +1 -1
- package/esm/logcat.d.ts +7 -8
- package/esm/logcat.d.ts.map +1 -1
- package/esm/logcat.js +18 -10
- package/esm/logcat.js.map +1 -1
- package/esm/overlay-display.d.ts +2 -2
- package/esm/overlay-display.js +2 -2
- package/esm/pm.d.ts +7 -3
- package/esm/pm.d.ts.map +1 -1
- package/esm/pm.js +81 -88
- package/esm/pm.js.map +1 -1
- package/esm/settings.d.ts +10 -7
- package/esm/settings.d.ts.map +1 -1
- package/esm/settings.js +14 -23
- package/esm/settings.js.map +1 -1
- package/package.json +9 -9
- package/src/am.ts +14 -21
- package/src/bu.ts +6 -14
- package/src/bug-report.ts +16 -16
- package/src/cmd.ts +136 -85
- package/src/demo-mode.ts +3 -3
- package/src/dumpsys.ts +6 -6
- package/src/logcat.ts +26 -15
- package/src/overlay-display.ts +2 -2
- package/src/pm.ts +92 -96
- package/src/settings.ts +20 -28
- package/tsconfig.build.tsbuildinfo +1 -1
package/src/pm.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// cspell:ignore versioncode
|
|
5
5
|
|
|
6
6
|
import type { Adb } from "@yume-chan/adb";
|
|
7
|
-
import {
|
|
7
|
+
import { AdbServiceBase } from "@yume-chan/adb";
|
|
8
8
|
import type { MaybeConsumable, ReadableStream } from "@yume-chan/stream-extra";
|
|
9
9
|
import {
|
|
10
10
|
ConcatStringStream,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
TextDecoderStream,
|
|
13
13
|
} from "@yume-chan/stream-extra";
|
|
14
14
|
|
|
15
|
-
import {
|
|
15
|
+
import { CmdNoneProtocolService } from "./cmd.js";
|
|
16
16
|
import type { IntentBuilder } from "./intent.js";
|
|
17
17
|
import type { SingleUserOrAll } from "./utils.js";
|
|
18
18
|
import { buildArguments } from "./utils.js";
|
|
@@ -260,7 +260,7 @@ function buildInstallArguments(
|
|
|
260
260
|
options: Partial<PackageManagerInstallOptions> | undefined,
|
|
261
261
|
): string[] {
|
|
262
262
|
const args = buildArguments(
|
|
263
|
-
[
|
|
263
|
+
[PackageManager.ServiceName, command],
|
|
264
264
|
options,
|
|
265
265
|
PACKAGE_MANAGER_INSTALL_OPTIONS_MAP,
|
|
266
266
|
);
|
|
@@ -281,12 +281,15 @@ function buildInstallArguments(
|
|
|
281
281
|
return args;
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
-
export class PackageManager extends
|
|
285
|
-
|
|
284
|
+
export class PackageManager extends AdbServiceBase {
|
|
285
|
+
static ServiceName = "package";
|
|
286
|
+
static CommandName = "pm";
|
|
287
|
+
|
|
288
|
+
#cmd: CmdNoneProtocolService;
|
|
286
289
|
|
|
287
290
|
constructor(adb: Adb) {
|
|
288
291
|
super(adb);
|
|
289
|
-
this.#cmd = new
|
|
292
|
+
this.#cmd = new CmdNoneProtocolService(adb, PackageManager.CommandName);
|
|
290
293
|
}
|
|
291
294
|
|
|
292
295
|
/**
|
|
@@ -299,20 +302,39 @@ export class PackageManager extends AdbCommandBase {
|
|
|
299
302
|
options?: Partial<PackageManagerInstallOptions>,
|
|
300
303
|
): Promise<string> {
|
|
301
304
|
const args = buildInstallArguments("install", options);
|
|
305
|
+
args[0] = PackageManager.CommandName;
|
|
302
306
|
// WIP: old version of pm doesn't support multiple apks
|
|
303
307
|
args.push(...apks);
|
|
304
|
-
|
|
308
|
+
|
|
309
|
+
// Starting from Android 7, `pm` becomes a wrapper to `cmd package`.
|
|
310
|
+
// The benefit of `cmd package` is it starts faster than the old `pm`,
|
|
311
|
+
// because it connects to the already running `system` process,
|
|
312
|
+
// instead of initializing all system components from scratch.
|
|
313
|
+
//
|
|
314
|
+
// But launching `cmd package` directly causes it to not be able to
|
|
315
|
+
// read files in `/data/local/tmp` (and many other places) due to SELinux policies,
|
|
316
|
+
// so installing files must still use `pm`.
|
|
317
|
+
// (the starting executable file decides which SELinux policies to apply)
|
|
318
|
+
const output = await this.adb.subprocess.noneProtocol
|
|
319
|
+
.spawnWaitText(args)
|
|
320
|
+
.then((output) => output.trim());
|
|
321
|
+
|
|
322
|
+
if (output !== "Success") {
|
|
323
|
+
throw new Error(output);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return output;
|
|
305
327
|
}
|
|
306
328
|
|
|
307
329
|
async pushAndInstallStream(
|
|
308
330
|
stream: ReadableStream<MaybeConsumable<Uint8Array>>,
|
|
309
331
|
options?: Partial<PackageManagerInstallOptions>,
|
|
310
|
-
): Promise<
|
|
311
|
-
const sync = await this.adb.sync();
|
|
312
|
-
|
|
332
|
+
): Promise<string> {
|
|
313
333
|
const fileName = Math.random().toString().substring(2);
|
|
314
334
|
const filePath = `/data/local/tmp/${fileName}.apk`;
|
|
315
335
|
|
|
336
|
+
const sync = await this.adb.sync();
|
|
337
|
+
|
|
316
338
|
try {
|
|
317
339
|
await sync.write({
|
|
318
340
|
filename: filePath,
|
|
@@ -322,26 +344,8 @@ export class PackageManager extends AdbCommandBase {
|
|
|
322
344
|
await sync.dispose();
|
|
323
345
|
}
|
|
324
346
|
|
|
325
|
-
// Starting from Android 7, `pm` becomes a wrapper to `cmd package`.
|
|
326
|
-
// The benefit of `cmd package` is it starts faster than the old `pm`,
|
|
327
|
-
// because it connects to the already running `system` process,
|
|
328
|
-
// instead of initializing all system components from scratch.
|
|
329
|
-
//
|
|
330
|
-
// But launching `cmd package` directly causes it to not be able to
|
|
331
|
-
// read files in `/data/local/tmp` (and many other places) due to SELinux policies,
|
|
332
|
-
// so installing files must still use `pm`.
|
|
333
|
-
// (the starting executable file decides which SELinux policies to apply)
|
|
334
|
-
const args = buildInstallArguments("install", options);
|
|
335
|
-
args.push(filePath);
|
|
336
|
-
|
|
337
347
|
try {
|
|
338
|
-
|
|
339
|
-
.spawnAndWaitLegacy(args.map(escapeArg))
|
|
340
|
-
.then((output) => output.trim());
|
|
341
|
-
|
|
342
|
-
if (output !== "Success") {
|
|
343
|
-
throw new Error(output);
|
|
344
|
-
}
|
|
348
|
+
return await this.install([filePath], options);
|
|
345
349
|
} finally {
|
|
346
350
|
await this.adb.rm(filePath);
|
|
347
351
|
}
|
|
@@ -356,20 +360,17 @@ export class PackageManager extends AdbCommandBase {
|
|
|
356
360
|
// It's hard to detect whether `pm` supports streaming install (unless actually trying),
|
|
357
361
|
// so check for whether `cmd` is supported,
|
|
358
362
|
// and assume `pm` streaming install support status is same as that.
|
|
359
|
-
if (!this.#cmd.
|
|
363
|
+
if (!this.#cmd.isSupported) {
|
|
360
364
|
// Fall back to push file then install
|
|
361
365
|
await this.pushAndInstallStream(stream, options);
|
|
362
366
|
return;
|
|
363
367
|
}
|
|
364
368
|
|
|
365
369
|
const args = buildInstallArguments("install", options);
|
|
366
|
-
// Remove `pm` from args, `Cmd#spawn` will prepend `cmd <command>` so the final args
|
|
367
|
-
// will be `cmd package install <args>`
|
|
368
|
-
args.shift();
|
|
369
370
|
args.push("-S", size.toString());
|
|
370
|
-
const process = await this.#cmd.spawn(
|
|
371
|
+
const process = await this.#cmd.spawn(args);
|
|
371
372
|
|
|
372
|
-
const output = process.
|
|
373
|
+
const output = process.output
|
|
373
374
|
.pipeThrough(new TextDecoderStream())
|
|
374
375
|
.pipeThrough(new ConcatStringStream())
|
|
375
376
|
.then((output) => output.trim());
|
|
@@ -437,20 +438,11 @@ export class PackageManager extends AdbCommandBase {
|
|
|
437
438
|
};
|
|
438
439
|
}
|
|
439
440
|
|
|
440
|
-
async #cmdOrSubprocess(args: string[]) {
|
|
441
|
-
if (this.#cmd.supportsCmd) {
|
|
442
|
-
args.shift();
|
|
443
|
-
return await this.#cmd.spawn(false, "package", ...args);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
return this.adb.subprocess.spawn(args);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
441
|
async *listPackages(
|
|
450
442
|
options?: Partial<PackageManagerListPackagesOptions>,
|
|
451
443
|
): AsyncGenerator<PackageManagerListPackagesResult, void, void> {
|
|
452
444
|
const args = buildArguments(
|
|
453
|
-
["
|
|
445
|
+
["package", "list", "packages"],
|
|
454
446
|
options,
|
|
455
447
|
PACKAGE_MANAGER_LIST_PACKAGES_OPTIONS_MAP,
|
|
456
448
|
);
|
|
@@ -458,12 +450,9 @@ export class PackageManager extends AdbCommandBase {
|
|
|
458
450
|
args.push(options.filter);
|
|
459
451
|
}
|
|
460
452
|
|
|
461
|
-
const process = await this.#
|
|
462
|
-
const reader = process.
|
|
453
|
+
const process = await this.#cmd.spawn(args);
|
|
454
|
+
const reader = process.output
|
|
463
455
|
.pipeThrough(new TextDecoderStream())
|
|
464
|
-
// FIXME: `SplitStringStream` will throw away some data
|
|
465
|
-
// if it doesn't end with a separator. So each chunk of data
|
|
466
|
-
// must contain several complete lines.
|
|
467
456
|
.pipeThrough(new SplitStringStream("\n"))
|
|
468
457
|
.getReader();
|
|
469
458
|
while (true) {
|
|
@@ -475,12 +464,27 @@ export class PackageManager extends AdbCommandBase {
|
|
|
475
464
|
}
|
|
476
465
|
}
|
|
477
466
|
|
|
467
|
+
async getPackageSources(packageName: string): Promise<string[]> {
|
|
468
|
+
const args = [PackageManager.ServiceName, "-p", packageName];
|
|
469
|
+
const process = await this.#cmd.spawn(args);
|
|
470
|
+
const result: string[] = [];
|
|
471
|
+
for await (const line of process.output
|
|
472
|
+
.pipeThrough(new TextDecoderStream())
|
|
473
|
+
.pipeThrough(new SplitStringStream("\n"))) {
|
|
474
|
+
if (line.startsWith("package:")) {
|
|
475
|
+
result.push(line.substring("package:".length));
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
return result;
|
|
480
|
+
}
|
|
481
|
+
|
|
478
482
|
async uninstall(
|
|
479
483
|
packageName: string,
|
|
480
484
|
options?: Partial<PackageManagerUninstallOptions>,
|
|
481
485
|
): Promise<void> {
|
|
482
486
|
const args = buildArguments(
|
|
483
|
-
[
|
|
487
|
+
[PackageManager.ServiceName, "uninstall"],
|
|
484
488
|
options,
|
|
485
489
|
PACKAGE_MANAGER_UNINSTALL_OPTIONS_MAP,
|
|
486
490
|
);
|
|
@@ -489,10 +493,8 @@ export class PackageManager extends AdbCommandBase {
|
|
|
489
493
|
args.push(...options.splitNames);
|
|
490
494
|
}
|
|
491
495
|
|
|
492
|
-
const
|
|
493
|
-
|
|
494
|
-
.pipeThrough(new TextDecoderStream())
|
|
495
|
-
.pipeThrough(new ConcatStringStream())
|
|
496
|
+
const output = await this.#cmd
|
|
497
|
+
.spawnWaitText(args)
|
|
496
498
|
.then((output) => output.trim());
|
|
497
499
|
if (output !== "Success") {
|
|
498
500
|
throw new Error(output);
|
|
@@ -503,17 +505,15 @@ export class PackageManager extends AdbCommandBase {
|
|
|
503
505
|
options: PackageManagerResolveActivityOptions,
|
|
504
506
|
): Promise<string | undefined> {
|
|
505
507
|
let args = buildArguments(
|
|
506
|
-
[
|
|
508
|
+
[PackageManager.ServiceName, "resolve-activity", "--components"],
|
|
507
509
|
options,
|
|
508
510
|
PACKAGE_MANAGER_RESOLVE_ACTIVITY_OPTIONS_MAP,
|
|
509
511
|
);
|
|
510
512
|
|
|
511
513
|
args = args.concat(options.intent.build());
|
|
512
514
|
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
.pipeThrough(new TextDecoderStream())
|
|
516
|
-
.pipeThrough(new ConcatStringStream())
|
|
515
|
+
const output = await this.#cmd
|
|
516
|
+
.spawnWaitText(args)
|
|
517
517
|
.then((output) => output.trim());
|
|
518
518
|
|
|
519
519
|
if (output === "No activity found") {
|
|
@@ -538,10 +538,8 @@ export class PackageManager extends AdbCommandBase {
|
|
|
538
538
|
): Promise<number> {
|
|
539
539
|
const args = buildInstallArguments("install-create", options);
|
|
540
540
|
|
|
541
|
-
const
|
|
542
|
-
|
|
543
|
-
.pipeThrough(new TextDecoderStream())
|
|
544
|
-
.pipeThrough(new ConcatStringStream())
|
|
541
|
+
const output = await this.#cmd
|
|
542
|
+
.spawnWaitText(args)
|
|
545
543
|
.then((output) => output.trim());
|
|
546
544
|
|
|
547
545
|
const sessionIdString = output.match(/.*\[(\d+)\].*/);
|
|
@@ -552,6 +550,17 @@ export class PackageManager extends AdbCommandBase {
|
|
|
552
550
|
return Number.parseInt(sessionIdString[1]!, 10);
|
|
553
551
|
}
|
|
554
552
|
|
|
553
|
+
async checkResult(stream: ReadableStream<Uint8Array>) {
|
|
554
|
+
const output = await stream
|
|
555
|
+
.pipeThrough(new TextDecoderStream())
|
|
556
|
+
.pipeThrough(new ConcatStringStream())
|
|
557
|
+
.then((output) => output.trim());
|
|
558
|
+
|
|
559
|
+
if (!output.startsWith("Success")) {
|
|
560
|
+
throw new Error(output);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
555
564
|
async sessionAddSplit(
|
|
556
565
|
sessionId: number,
|
|
557
566
|
splitName: string,
|
|
@@ -565,12 +574,8 @@ export class PackageManager extends AdbCommandBase {
|
|
|
565
574
|
path,
|
|
566
575
|
];
|
|
567
576
|
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
.then((output) => output.trim());
|
|
571
|
-
if (!output.startsWith("Success")) {
|
|
572
|
-
throw new Error(output);
|
|
573
|
-
}
|
|
577
|
+
const process = await this.adb.subprocess.noneProtocol.spawn(args);
|
|
578
|
+
await this.checkResult(process.output);
|
|
574
579
|
}
|
|
575
580
|
|
|
576
581
|
async sessionAddSplitStream(
|
|
@@ -580,7 +585,7 @@ export class PackageManager extends AdbCommandBase {
|
|
|
580
585
|
stream: ReadableStream<MaybeConsumable<Uint8Array>>,
|
|
581
586
|
): Promise<void> {
|
|
582
587
|
const args: string[] = [
|
|
583
|
-
|
|
588
|
+
PackageManager.ServiceName,
|
|
584
589
|
"install-write",
|
|
585
590
|
"-S",
|
|
586
591
|
size.toString(),
|
|
@@ -589,40 +594,31 @@ export class PackageManager extends AdbCommandBase {
|
|
|
589
594
|
"-",
|
|
590
595
|
];
|
|
591
596
|
|
|
592
|
-
const process = await this.#
|
|
593
|
-
const output = process.stdout
|
|
594
|
-
.pipeThrough(new TextDecoderStream())
|
|
595
|
-
.pipeThrough(new ConcatStringStream())
|
|
596
|
-
.then((output) => output.trim());
|
|
597
|
-
|
|
597
|
+
const process = await this.#cmd.spawn(args);
|
|
598
598
|
await Promise.all([
|
|
599
599
|
stream.pipeTo(process.stdin),
|
|
600
|
-
|
|
601
|
-
if (!output.startsWith("Success")) {
|
|
602
|
-
throw new Error(output);
|
|
603
|
-
}
|
|
604
|
-
}),
|
|
600
|
+
this.checkResult(process.output),
|
|
605
601
|
]);
|
|
606
602
|
}
|
|
607
603
|
|
|
608
604
|
async sessionCommit(sessionId: number): Promise<void> {
|
|
609
|
-
const args: string[] = [
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
.
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
605
|
+
const args: string[] = [
|
|
606
|
+
PackageManager.ServiceName,
|
|
607
|
+
"install-commit",
|
|
608
|
+
sessionId.toString(),
|
|
609
|
+
];
|
|
610
|
+
const process = await this.#cmd.spawn(args);
|
|
611
|
+
await this.checkResult(process.output);
|
|
616
612
|
}
|
|
617
613
|
|
|
618
614
|
async sessionAbandon(sessionId: number): Promise<void> {
|
|
619
|
-
const args: string[] = [
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
.
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
615
|
+
const args: string[] = [
|
|
616
|
+
PackageManager.ServiceName,
|
|
617
|
+
"install-abandon",
|
|
618
|
+
sessionId.toString(),
|
|
619
|
+
];
|
|
620
|
+
const process = await this.#cmd.spawn(args);
|
|
621
|
+
await this.checkResult(process.output);
|
|
626
622
|
}
|
|
627
623
|
}
|
|
628
624
|
|
package/src/settings.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import type { Adb
|
|
2
|
-
import {
|
|
1
|
+
import type { Adb } from "@yume-chan/adb";
|
|
2
|
+
import { AdbServiceBase } from "@yume-chan/adb";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { CmdNoneProtocolService } from "./cmd.js";
|
|
5
5
|
import type { SingleUser } from "./utils.js";
|
|
6
6
|
|
|
7
7
|
export type SettingsNamespace = "system" | "secure" | "global";
|
|
8
8
|
|
|
9
|
-
export
|
|
10
|
-
UntrustedDefaults
|
|
11
|
-
UntrustedClear
|
|
12
|
-
TrustedDefaults
|
|
13
|
-
}
|
|
9
|
+
export const SettingsResetMode = {
|
|
10
|
+
UntrustedDefaults: "untrusted_defaults",
|
|
11
|
+
UntrustedClear: "untrusted_clear",
|
|
12
|
+
TrustedDefaults: "trusted_defaults",
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
export type SettingsResetMode =
|
|
16
|
+
(typeof SettingsResetMode)[keyof typeof SettingsResetMode];
|
|
14
17
|
|
|
15
18
|
export interface SettingsOptions {
|
|
16
19
|
user?: SingleUser;
|
|
@@ -22,21 +25,24 @@ export interface SettingsPutOptions extends SettingsOptions {
|
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
// frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
|
|
25
|
-
export class Settings extends
|
|
26
|
-
|
|
28
|
+
export class Settings extends AdbServiceBase {
|
|
29
|
+
static ServiceName = "settings";
|
|
30
|
+
static CommandName = "settings";
|
|
31
|
+
|
|
32
|
+
#cmd: CmdNoneProtocolService;
|
|
27
33
|
|
|
28
34
|
constructor(adb: Adb) {
|
|
29
35
|
super(adb);
|
|
30
|
-
this.#cmd = new
|
|
36
|
+
this.#cmd = new CmdNoneProtocolService(adb, Settings.CommandName);
|
|
31
37
|
}
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
base(
|
|
34
40
|
verb: string,
|
|
35
41
|
namespace: SettingsNamespace,
|
|
36
42
|
options: SettingsOptions | undefined,
|
|
37
43
|
...args: string[]
|
|
38
44
|
): Promise<string> {
|
|
39
|
-
let command = [
|
|
45
|
+
let command = [Settings.ServiceName];
|
|
40
46
|
|
|
41
47
|
if (options?.user !== undefined) {
|
|
42
48
|
command.push("--user", options.user.toString());
|
|
@@ -45,21 +51,7 @@ export class Settings extends AdbCommandBase {
|
|
|
45
51
|
command.push(verb, namespace);
|
|
46
52
|
command = command.concat(args);
|
|
47
53
|
|
|
48
|
-
|
|
49
|
-
if (this.#cmd.supportsCmd) {
|
|
50
|
-
output = await this.#cmd.spawnAndWait(
|
|
51
|
-
command[0]!,
|
|
52
|
-
...command.slice(1),
|
|
53
|
-
);
|
|
54
|
-
} else {
|
|
55
|
-
output = await this.adb.subprocess.spawnAndWait(command);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (output.stderr) {
|
|
59
|
-
throw new Error(output.stderr);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return output.stdout;
|
|
54
|
+
return this.#cmd.spawnWaitText(command);
|
|
63
55
|
}
|
|
64
56
|
|
|
65
57
|
async get(
|