@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.
Files changed (76) hide show
  1. package/CHANGELOG.json +54 -0
  2. package/CHANGELOG.md +25 -1
  3. package/LICENSE +21 -0
  4. package/README.md +40 -14
  5. package/esm/am.d.ts +17 -0
  6. package/esm/am.d.ts.map +1 -0
  7. package/esm/am.js +42 -0
  8. package/esm/am.js.map +1 -0
  9. package/esm/bu.d.ts +20 -7
  10. package/esm/bu.d.ts.map +1 -1
  11. package/esm/bu.js +47 -8
  12. package/esm/bu.js.map +1 -1
  13. package/esm/bug-report.d.ts +82 -21
  14. package/esm/bug-report.d.ts.map +1 -1
  15. package/esm/bug-report.js +187 -53
  16. package/esm/bug-report.js.map +1 -1
  17. package/esm/cmd.d.ts +4 -6
  18. package/esm/cmd.d.ts.map +1 -1
  19. package/esm/cmd.js +36 -21
  20. package/esm/cmd.js.map +1 -1
  21. package/esm/demo-mode.d.ts +3 -3
  22. package/esm/demo-mode.d.ts.map +1 -1
  23. package/esm/demo-mode.js +14 -15
  24. package/esm/demo-mode.js.map +1 -1
  25. package/esm/dumpsys.d.ts +39 -0
  26. package/esm/dumpsys.d.ts.map +1 -1
  27. package/esm/dumpsys.js +111 -0
  28. package/esm/dumpsys.js.map +1 -1
  29. package/esm/index.d.ts +6 -0
  30. package/esm/index.d.ts.map +1 -1
  31. package/esm/index.js +6 -0
  32. package/esm/index.js.map +1 -1
  33. package/esm/intent.d.ts +10 -0
  34. package/esm/intent.d.ts.map +1 -0
  35. package/esm/intent.js +51 -0
  36. package/esm/intent.js.map +1 -0
  37. package/esm/logcat.d.ts +1 -0
  38. package/esm/logcat.d.ts.map +1 -1
  39. package/esm/logcat.js +20 -18
  40. package/esm/logcat.js.map +1 -1
  41. package/esm/overlay-display.d.ts +20 -3
  42. package/esm/overlay-display.d.ts.map +1 -1
  43. package/esm/overlay-display.js +34 -61
  44. package/esm/overlay-display.js.map +1 -1
  45. package/esm/pm.d.ts +42 -5
  46. package/esm/pm.d.ts.map +1 -1
  47. package/esm/pm.js +164 -46
  48. package/esm/pm.js.map +1 -1
  49. package/esm/settings.d.ts +22 -8
  50. package/esm/settings.d.ts.map +1 -1
  51. package/esm/settings.js +50 -25
  52. package/esm/settings.js.map +1 -1
  53. package/esm/string-format.d.ts +40 -0
  54. package/esm/string-format.d.ts.map +1 -0
  55. package/esm/string-format.js +153 -0
  56. package/esm/string-format.js.map +1 -0
  57. package/esm/utils.d.ts +4 -0
  58. package/esm/utils.d.ts.map +1 -0
  59. package/esm/utils.js +23 -0
  60. package/esm/utils.js.map +1 -0
  61. package/package.json +13 -8
  62. package/src/am.ts +69 -0
  63. package/src/bu.ts +68 -14
  64. package/src/bug-report.ts +234 -68
  65. package/src/cmd.ts +64 -30
  66. package/src/demo-mode.ts +47 -43
  67. package/src/dumpsys.ts +129 -0
  68. package/src/index.ts +6 -0
  69. package/src/intent.ts +63 -0
  70. package/src/logcat.ts +45 -42
  71. package/src/overlay-display.ts +82 -85
  72. package/src/pm.ts +274 -61
  73. package/src/settings.ts +94 -43
  74. package/src/string-format.ts +199 -0
  75. package/src/utils.ts +29 -0
  76. package/tsconfig.build.tsbuildinfo +1 -1
@@ -0,0 +1,153 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
2
+ export class ParseError extends Error {
3
+ #expected;
4
+ get expected() {
5
+ return this.#expected;
6
+ }
7
+ constructor(expected) {
8
+ super(`Expected ${expected.join(", ")}`);
9
+ this.#expected = expected;
10
+ }
11
+ }
12
+ export const p = {
13
+ literal: (value) => ({
14
+ parse(reader) {
15
+ if (!reader.value.startsWith(value, reader.position)) {
16
+ throw new ParseError([value.charAt(0)]);
17
+ }
18
+ reader.position += value.length;
19
+ return value;
20
+ },
21
+ stringify() {
22
+ return value;
23
+ },
24
+ }),
25
+ digits: () => ({
26
+ parse(reader) {
27
+ const match = reader.value.substring(reader.position).match(/^\d+/);
28
+ if (!match) {
29
+ throw new ParseError("0123456789".split(""));
30
+ }
31
+ reader.position += match[0].length;
32
+ return Number.parseInt(match[0], 10);
33
+ },
34
+ stringify(value) {
35
+ return value.toString();
36
+ },
37
+ }),
38
+ union: (...args) => ({
39
+ parse(reader) {
40
+ const expected = [];
41
+ for (const format of args) {
42
+ try {
43
+ return format.parse(reader);
44
+ }
45
+ catch (e) {
46
+ if (e instanceof ParseError) {
47
+ expected.push(...e.expected);
48
+ }
49
+ else {
50
+ throw e;
51
+ }
52
+ }
53
+ }
54
+ throw new ParseError(expected);
55
+ },
56
+ stringify(value) {
57
+ for (const format of args) {
58
+ try {
59
+ const result = format.stringify(value);
60
+ // Parse the result to make sure it is valid
61
+ format.parse({ value: result, position: 0 });
62
+ }
63
+ catch (e) {
64
+ // ignore
65
+ }
66
+ }
67
+ throw new Error("No format matches");
68
+ },
69
+ }),
70
+ separated: (separator, format, min = 0, max = Infinity) => ({
71
+ parse(reader) {
72
+ const result = [];
73
+ while (true) {
74
+ try {
75
+ result.push(format.parse(reader));
76
+ if (result.length === max) {
77
+ break;
78
+ }
79
+ }
80
+ catch (e) {
81
+ if (result.length < min) {
82
+ throw e;
83
+ }
84
+ else {
85
+ break;
86
+ }
87
+ }
88
+ if (reader.value.startsWith(separator, reader.position)) {
89
+ reader.position += separator.length;
90
+ }
91
+ else if (result.length < min) {
92
+ throw new ParseError([separator.charAt(0)]);
93
+ }
94
+ else {
95
+ break;
96
+ }
97
+ }
98
+ return result;
99
+ },
100
+ stringify(value) {
101
+ return value.map((item) => format.stringify(item)).join(separator);
102
+ },
103
+ }),
104
+ repeated: (format) => ({
105
+ parse(reader) {
106
+ const result = [];
107
+ while (true) {
108
+ try {
109
+ result.push(format.parse(reader));
110
+ }
111
+ catch (e) {
112
+ break;
113
+ }
114
+ }
115
+ return result;
116
+ },
117
+ stringify(value) {
118
+ return value.map((item) => format.stringify(item)).join("");
119
+ },
120
+ }),
121
+ sequence: (...args) => ({
122
+ parse(reader) {
123
+ const result = {};
124
+ for (const part of args) {
125
+ if ("name" in part) {
126
+ result[part.name] = part.format.parse(reader);
127
+ }
128
+ else {
129
+ void part.parse(reader);
130
+ }
131
+ }
132
+ return result;
133
+ },
134
+ stringify: (value) => {
135
+ let result = "";
136
+ for (const part of args) {
137
+ if ("name" in part) {
138
+ result += part.format.stringify(value[part.name]);
139
+ }
140
+ }
141
+ return result;
142
+ },
143
+ }),
144
+ map: (format, map, reverse) => ({
145
+ parse(reader) {
146
+ return map(format.parse(reader));
147
+ },
148
+ stringify(value) {
149
+ return format.stringify(reverse(value));
150
+ },
151
+ }),
152
+ };
153
+ //# sourceMappingURL=string-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string-format.js","sourceRoot":"","sources":["../src/string-format.ts"],"names":[],"mappings":"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"}
package/esm/utils.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare function buildArguments<T>(commands: string[], options: Partial<T> | undefined, map: Partial<Record<keyof T, string>>): string[];
2
+ export type SingleUser = number | "current";
3
+ export type SingleUserOrAll = SingleUser | "all";
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,CAAC,EAC5B,QAAQ,EAAE,MAAM,EAAE,EAClB,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,CAqBV;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;AAC5C,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,KAAK,CAAC"}
package/esm/utils.js ADDED
@@ -0,0 +1,23 @@
1
+ export function buildArguments(commands, options, map) {
2
+ const args = commands;
3
+ if (options) {
4
+ for (const [key, value] of Object.entries(options)) {
5
+ if (value) {
6
+ const option = map[key];
7
+ if (option) {
8
+ args.push(option);
9
+ switch (typeof value) {
10
+ case "number":
11
+ args.push(value.toString());
12
+ break;
13
+ case "string":
14
+ args.push(value);
15
+ break;
16
+ }
17
+ }
18
+ }
19
+ }
20
+ }
21
+ return args;
22
+ }
23
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,cAAc,CAC1B,QAAkB,EAClB,OAA+B,EAC/B,GAAqC;IAErC,MAAM,IAAI,GAAG,QAAQ,CAAC;IACtB,IAAI,OAAO,EAAE,CAAC;QACV,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACjD,IAAI,KAAK,EAAE,CAAC;gBACR,MAAM,MAAM,GAAG,GAAG,CAAC,GAAc,CAAC,CAAC;gBACnC,IAAI,MAAM,EAAE,CAAC;oBACT,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAClB,QAAQ,OAAO,KAAK,EAAE,CAAC;wBACnB,KAAK,QAAQ;4BACT,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;4BAC5B,MAAM;wBACV,KAAK,QAAQ;4BACT,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;4BACjB,MAAM;oBACd,CAAC;gBACL,CAAC;YACL,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": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "description": "Wrappers for Android built-in executables.",
5
5
  "keywords": [
6
6
  "adb",
@@ -25,21 +25,26 @@
25
25
  "main": "esm/index.js",
26
26
  "types": "esm/index.d.ts",
27
27
  "dependencies": {
28
- "@yume-chan/adb": "^0.0.20",
29
- "@yume-chan/stream-extra": "^0.0.20",
30
- "@yume-chan/struct": "^0.0.20",
31
- "tslib": "^2.5.2"
28
+ "@yume-chan/adb": "^0.0.22",
29
+ "@yume-chan/stream-extra": "^0.0.22",
30
+ "@yume-chan/struct": "^0.0.22",
31
+ "tslib": "^2.6.2"
32
32
  },
33
33
  "devDependencies": {
34
+ "@jest/globals": "^29.7.0",
34
35
  "@yume-chan/eslint-config": "^1.0.0",
35
36
  "@yume-chan/tsconfig": "^1.0.0",
36
- "eslint": "^8.41.0",
37
- "prettier": "^2.8.8",
38
- "typescript": "^5.0.3"
37
+ "cross-env": "^7.0.3",
38
+ "eslint": "^8.55.0",
39
+ "jest": "^29.7.0",
40
+ "prettier": "^3.1.0",
41
+ "ts-jest": "^29.1.1",
42
+ "typescript": "^5.3.2"
39
43
  },
40
44
  "scripts": {
41
45
  "build": "tsc -b tsconfig.build.json",
42
46
  "build:watch": "tsc -b tsconfig.build.json",
47
+ "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage",
43
48
  "lint": "eslint src/**/*.ts --fix && prettier src/**/*.ts --write --tab-width 4"
44
49
  }
45
50
  }
package/src/am.ts ADDED
@@ -0,0 +1,69 @@
1
+ import type { Adb } from "@yume-chan/adb";
2
+ import { AdbCommandBase } from "@yume-chan/adb";
3
+ import { ConcatStringStream, DecodeUtf8Stream } from "@yume-chan/stream-extra";
4
+
5
+ import { Cmd } from "./cmd.js";
6
+ import type { IntentBuilder } from "./intent.js";
7
+ import type { SingleUser } from "./utils.js";
8
+ import { buildArguments } from "./utils.js";
9
+
10
+ export interface ActivityManagerStartActivityOptions {
11
+ displayId?: number;
12
+ windowingMode?: number;
13
+ forceStop?: boolean;
14
+ user?: SingleUser;
15
+ intent: IntentBuilder;
16
+ }
17
+
18
+ const START_ACTIVITY_OPTIONS_MAP: Partial<
19
+ Record<keyof ActivityManagerStartActivityOptions, string>
20
+ > = {
21
+ displayId: "--display",
22
+ windowingMode: "--windowingMode",
23
+ forceStop: "-S",
24
+ user: "--user",
25
+ };
26
+
27
+ export class ActivityManager extends AdbCommandBase {
28
+ #cmd: Cmd;
29
+
30
+ constructor(adb: Adb) {
31
+ super(adb);
32
+ this.#cmd = new Cmd(adb);
33
+ }
34
+
35
+ async #cmdOrSubprocess(args: string[]) {
36
+ if (this.#cmd.supportsCmd) {
37
+ args.shift();
38
+ return await this.#cmd.spawn(false, "activity", ...args);
39
+ }
40
+
41
+ return this.adb.subprocess.spawn(args);
42
+ }
43
+
44
+ async startActivity(options: ActivityManagerStartActivityOptions) {
45
+ let args = buildArguments(
46
+ ["am", "start-activity", "-W"],
47
+ options,
48
+ START_ACTIVITY_OPTIONS_MAP,
49
+ );
50
+
51
+ args = args.concat(options.intent.build());
52
+
53
+ const process = await this.#cmdOrSubprocess(args);
54
+
55
+ const output = await process.stdout
56
+ .pipeThrough(new DecodeUtf8Stream())
57
+ .pipeThrough(new ConcatStringStream())
58
+ .then((output) => output.trim());
59
+
60
+ for (const line of output) {
61
+ if (line.startsWith("Error:")) {
62
+ throw new Error(line.substring("Error:".length).trim());
63
+ }
64
+ if (line === "Complete") {
65
+ return;
66
+ }
67
+ }
68
+ }
69
+ }
package/src/bu.ts CHANGED
@@ -1,26 +1,80 @@
1
- // cspell: ignore apks
2
- // cspell: ignore obbs
3
-
4
1
  import { AdbCommandBase } from "@yume-chan/adb";
2
+ import type { Consumable, ReadableStream } from "@yume-chan/stream-extra";
3
+ import { ConcatStringStream, DecodeUtf8Stream } from "@yume-chan/stream-extra";
5
4
 
6
5
  export interface AdbBackupOptions {
7
- apps: string[] | "all" | "all-including-system";
8
- apks: boolean;
9
- obbs: boolean;
10
- shared: boolean;
11
- widgets: boolean;
6
+ user: number;
7
+ saveSharedStorage?: boolean;
8
+ saveWidgets?: boolean;
9
+ packages: string[] | "user" | "all";
10
+ savePackageApk: boolean;
11
+ savePackageObb: boolean;
12
+ savePackageKeyValue: boolean;
12
13
  compress: boolean;
14
+ }
15
+
16
+ export interface AdbRestoreOptions {
13
17
  user: number;
18
+ file: ReadableStream<Consumable<Uint8Array>>;
14
19
  }
15
20
 
16
21
  export class AdbBackup extends AdbCommandBase {
17
- backup(options: AdbBackupOptions): Promise<void> {
18
- void options;
19
- throw new Error("Not implemented");
22
+ /**
23
+ * User must confirm backup on device within 60 seconds.
24
+ */
25
+ async backup(
26
+ options: AdbBackupOptions,
27
+ ): Promise<ReadableStream<Uint8Array>> {
28
+ const args = ["bu", "backup"];
29
+
30
+ if (options.user !== undefined) {
31
+ args.push("--user", options.user.toString());
32
+ }
33
+
34
+ args.push(options.saveSharedStorage ? "--shared" : "--no-shared");
35
+ args.push(options.saveWidgets ? "--widgets" : "--no-widgets");
36
+
37
+ args.push(options.savePackageApk ? "--apk" : "--no-apk");
38
+ args.push(options.savePackageObb ? "--obb" : "--no-obb");
39
+ args.push(
40
+ options.savePackageKeyValue ? "--key-value" : "--no-key-value",
41
+ );
42
+
43
+ args.push(options.compress ? "--compress" : "--no-compress");
44
+
45
+ if (typeof options.packages === "string") {
46
+ switch (options.packages) {
47
+ case "user":
48
+ args.push("--all", "--no-system");
49
+ break;
50
+ case "all":
51
+ args.push("--all", "--system");
52
+ break;
53
+ }
54
+ } else {
55
+ args.push(...options.packages);
56
+ }
57
+
58
+ const process = await this.adb.subprocess.spawn(args);
59
+ return process.stdout;
20
60
  }
21
61
 
22
- restore(options: AdbBackupOptions): Promise<void> {
23
- void options;
24
- throw new Error("Not implemented");
62
+ /**
63
+ * User must enter the password (if any) and
64
+ * confirm restore on device within 60 seconds.
65
+ */
66
+ async restore(options: AdbRestoreOptions): Promise<string> {
67
+ const args = ["bu", "restore"];
68
+ if (options.user !== undefined) {
69
+ args.push("--user", options.user.toString());
70
+ }
71
+ const process = await this.adb.subprocess.spawn(args);
72
+ const [output] = await Promise.all([
73
+ process.stdout
74
+ .pipeThrough(new DecodeUtf8Stream())
75
+ .pipeThrough(new ConcatStringStream()),
76
+ options.file.pipeTo(process.stdin),
77
+ ]);
78
+ return output;
25
79
  }
26
80
  }