@yume-chan/adb 0.0.17 → 0.0.19
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 +27 -0
- package/CHANGELOG.md +16 -1
- package/LICENSE +1 -1
- package/esm/adb.d.ts +63 -60
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +257 -229
- package/esm/adb.js.map +1 -1
- package/esm/auth.d.ts +51 -51
- package/esm/auth.d.ts.map +1 -1
- package/esm/auth.js +95 -96
- package/esm/auth.js.map +1 -1
- package/esm/backend.d.ts +8 -8
- package/esm/backend.d.ts.map +1 -1
- package/esm/backend.js +1 -1
- package/esm/commands/base.d.ts +6 -6
- package/esm/commands/base.js +8 -8
- package/esm/commands/framebuffer.d.ts +53 -53
- package/esm/commands/framebuffer.d.ts.map +1 -1
- package/esm/commands/framebuffer.js +46 -47
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/index.d.ts +7 -8
- package/esm/commands/index.d.ts.map +1 -1
- package/esm/commands/index.js +7 -8
- package/esm/commands/index.js.map +1 -1
- package/esm/commands/install.d.ts +9 -3
- package/esm/commands/install.d.ts.map +1 -1
- package/esm/commands/install.js +27 -21
- package/esm/commands/install.js.map +1 -1
- package/esm/commands/power.d.ts +22 -22
- package/esm/commands/power.d.ts.map +1 -1
- package/esm/commands/power.js +48 -44
- package/esm/commands/power.js.map +1 -1
- package/esm/commands/reverse.d.ts +41 -28
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js +125 -98
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/command.d.ts +57 -51
- package/esm/commands/subprocess/command.d.ts.map +1 -1
- package/esm/commands/subprocess/command.js +86 -82
- package/esm/commands/subprocess/command.js.map +1 -1
- package/esm/commands/subprocess/index.d.ts +3 -3
- package/esm/commands/subprocess/index.js +3 -3
- package/esm/commands/subprocess/protocols/index.d.ts +3 -3
- package/esm/commands/subprocess/protocols/index.js +3 -3
- package/esm/commands/subprocess/protocols/none.d.ts +35 -35
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +65 -55
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/subprocess/protocols/shell.d.ts +39 -38
- package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/shell.js +166 -154
- package/esm/commands/subprocess/protocols/shell.js.map +1 -1
- package/esm/commands/subprocess/protocols/types.d.ts +49 -49
- package/esm/commands/subprocess/protocols/types.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/types.js +1 -1
- package/esm/commands/subprocess/utils.d.ts +1 -1
- package/esm/commands/subprocess/utils.js +18 -18
- package/esm/commands/sync/index.d.ts +8 -7
- package/esm/commands/sync/index.d.ts.map +1 -1
- package/esm/commands/sync/index.js +8 -7
- package/esm/commands/sync/index.js.map +1 -1
- package/esm/commands/sync/list.d.ts +42 -40
- package/esm/commands/sync/list.d.ts.map +1 -1
- package/esm/commands/sync/list.js +67 -35
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts +13 -11
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +35 -36
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.d.ts +46 -7
- package/esm/commands/sync/push.d.ts.map +1 -1
- package/esm/commands/sync/push.js +89 -23
- package/esm/commands/sync/push.js.map +1 -1
- package/esm/commands/sync/request.d.ts +26 -23
- package/esm/commands/sync/request.d.ts.map +1 -1
- package/esm/commands/sync/request.js +40 -42
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +19 -19
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +54 -54
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/socket.d.ts +27 -0
- package/esm/commands/sync/socket.d.ts.map +1 -0
- package/esm/commands/sync/socket.js +66 -0
- package/esm/commands/sync/socket.js.map +1 -0
- package/esm/commands/sync/stat.d.ts +72 -72
- package/esm/commands/sync/stat.d.ts.map +1 -1
- package/esm/commands/sync/stat.js +116 -94
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +72 -60
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +127 -148
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/commands/tcpip.d.ts +5 -5
- package/esm/commands/tcpip.js +18 -18
- package/esm/crypto.d.ts +36 -36
- package/esm/crypto.d.ts.map +1 -1
- package/esm/crypto.js +248 -238
- package/esm/crypto.js.map +1 -1
- package/esm/features.d.ts +10 -7
- package/esm/features.d.ts.map +1 -1
- package/esm/features.js +13 -10
- package/esm/features.js.map +1 -1
- package/esm/index.d.ts +9 -9
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +9 -9
- package/esm/index.js.map +1 -1
- package/esm/packet.d.ts +45 -46
- package/esm/packet.d.ts.map +1 -1
- package/esm/packet.js +43 -46
- package/esm/packet.js.map +1 -1
- package/esm/socket/dispatcher.d.ts +59 -59
- package/esm/socket/dispatcher.d.ts.map +1 -1
- package/esm/socket/dispatcher.js +223 -231
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/socket/index.d.ts +2 -2
- package/esm/socket/index.js +2 -2
- package/esm/socket/socket.d.ts +59 -59
- package/esm/socket/socket.d.ts.map +1 -1
- package/esm/socket/socket.js +118 -98
- package/esm/socket/socket.js.map +1 -1
- package/esm/utils/auto-reset-event.d.ts +9 -9
- package/esm/utils/auto-reset-event.d.ts.map +1 -1
- package/esm/utils/auto-reset-event.js +33 -33
- package/esm/utils/auto-reset-event.js.map +1 -1
- package/esm/utils/base64.d.ts +27 -27
- package/esm/utils/base64.d.ts.map +1 -1
- package/esm/utils/base64.js +246 -245
- package/esm/utils/base64.js.map +1 -1
- package/esm/utils/conditional-variable.d.ts +9 -0
- package/esm/utils/conditional-variable.d.ts.map +1 -0
- package/esm/utils/conditional-variable.js +34 -0
- package/esm/utils/conditional-variable.js.map +1 -0
- package/esm/utils/index.d.ts +4 -3
- package/esm/utils/index.d.ts.map +1 -1
- package/esm/utils/index.js +4 -3
- package/esm/utils/index.js.map +1 -1
- package/package.json +17 -13
- package/src/adb.ts +160 -101
- package/src/auth.ts +31 -22
- package/src/backend.ts +6 -4
- package/src/commands/base.ts +2 -2
- package/src/commands/framebuffer.ts +37 -41
- package/src/commands/index.ts +7 -8
- package/src/commands/power.ts +15 -11
- package/src/commands/reverse.ts +74 -30
- package/src/commands/subprocess/command.ts +34 -23
- package/src/commands/subprocess/index.ts +3 -3
- package/src/commands/subprocess/protocols/index.ts +3 -3
- package/src/commands/subprocess/protocols/none.ts +26 -11
- package/src/commands/subprocess/protocols/shell.ts +110 -56
- package/src/commands/subprocess/protocols/types.ts +10 -6
- package/src/commands/subprocess/utils.ts +1 -1
- package/src/commands/sync/index.ts +8 -7
- package/src/commands/sync/list.ts +74 -28
- package/src/commands/sync/pull.ts +49 -37
- package/src/commands/sync/push.ts +153 -32
- package/src/commands/sync/request.ts +37 -34
- package/src/commands/sync/response.ts +34 -27
- package/src/commands/sync/socket.ts +97 -0
- package/src/commands/sync/stat.ts +98 -70
- package/src/commands/sync/sync.ts +78 -97
- package/src/commands/tcpip.ts +5 -5
- package/src/crypto.ts +60 -32
- package/src/features.ts +9 -6
- package/src/index.ts +9 -10
- package/src/packet.ts +41 -46
- package/src/socket/dispatcher.ts +130 -108
- package/src/socket/index.ts +2 -2
- package/src/socket/socket.ts +84 -34
- package/src/utils/auto-reset-event.ts +16 -17
- package/src/utils/base64.ts +51 -41
- package/src/utils/conditional-variable.ts +45 -0
- package/src/utils/index.ts +4 -3
- package/tsconfig.build.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/src/commands/install.ts +0 -32
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yume-chan/adb",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"description": "TypeScript implementation of Android Debug Bridge (ADB) protocol.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adb",
|
|
@@ -26,24 +26,28 @@
|
|
|
26
26
|
"types": "esm/index.d.ts",
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@yume-chan/async": "^2.2.0",
|
|
29
|
-
"@yume-chan/dataview-bigint-polyfill": "^0.0.
|
|
30
|
-
"@yume-chan/event": "^0.0.
|
|
31
|
-
"@yume-chan/stream-extra": "^0.0.
|
|
32
|
-
"@yume-chan/struct": "^0.0.
|
|
33
|
-
"tslib": "^2.4.
|
|
29
|
+
"@yume-chan/dataview-bigint-polyfill": "^0.0.19",
|
|
30
|
+
"@yume-chan/event": "^0.0.19",
|
|
31
|
+
"@yume-chan/stream-extra": "^0.0.19",
|
|
32
|
+
"@yume-chan/struct": "^0.0.19",
|
|
33
|
+
"tslib": "^2.4.1"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@jest/globals": "^
|
|
37
|
-
"@types/node": "^
|
|
38
|
-
"@yume-chan/
|
|
36
|
+
"@jest/globals": "^29.5.0",
|
|
37
|
+
"@types/node": "^18.15.0",
|
|
38
|
+
"@yume-chan/eslint-config": "^1.0.0",
|
|
39
|
+
"@yume-chan/tsconfig": "^1.0.0",
|
|
39
40
|
"cross-env": "^7.0.3",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
41
|
+
"eslint": "^8.36.0",
|
|
42
|
+
"jest": "^29.5.0",
|
|
43
|
+
"prettier": "^2.8.4",
|
|
44
|
+
"ts-jest": "^29.0.4",
|
|
45
|
+
"typescript": "^4.9.4"
|
|
43
46
|
},
|
|
44
47
|
"scripts": {
|
|
45
48
|
"build": "tsc -b tsconfig.build.json",
|
|
46
49
|
"build:watch": "tsc -b tsconfig.build.json",
|
|
47
|
-
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage"
|
|
50
|
+
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage",
|
|
51
|
+
"lint": "eslint src/**/*.ts --fix && prettier src/**/*.ts --write --tab-width 4"
|
|
48
52
|
}
|
|
49
53
|
}
|
package/src/adb.ts
CHANGED
|
@@ -1,20 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import {
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
import type { Consumable, ReadableWritablePair } from "@yume-chan/stream-extra";
|
|
3
|
+
import {
|
|
4
|
+
AbortController,
|
|
5
|
+
ConsumableWritableStream,
|
|
6
|
+
DecodeUtf8Stream,
|
|
7
|
+
GatherStringStream,
|
|
8
|
+
WritableStream,
|
|
9
|
+
} from "@yume-chan/stream-extra";
|
|
10
|
+
|
|
11
|
+
import type { AdbCredentialStore } from "./auth.js";
|
|
12
|
+
import {
|
|
13
|
+
ADB_DEFAULT_AUTHENTICATORS,
|
|
14
|
+
AdbAuthenticationProcessor,
|
|
15
|
+
} from "./auth.js";
|
|
16
|
+
import type { AdbFrameBuffer } from "./commands/index.js";
|
|
17
|
+
import {
|
|
18
|
+
AdbPower,
|
|
19
|
+
AdbReverseCommand,
|
|
20
|
+
AdbSubprocess,
|
|
21
|
+
AdbSync,
|
|
22
|
+
AdbTcpIpCommand,
|
|
23
|
+
escapeArg,
|
|
24
|
+
framebuffer,
|
|
25
|
+
} from "./commands/index.js";
|
|
26
|
+
import { AdbFeature } from "./features.js";
|
|
27
|
+
import type { AdbPacketData, AdbPacketInit } from "./packet.js";
|
|
28
|
+
import { AdbCommand, calculateChecksum } from "./packet.js";
|
|
29
|
+
import type {
|
|
30
|
+
AdbIncomingSocketHandler,
|
|
31
|
+
AdbSocket,
|
|
32
|
+
Closeable,
|
|
33
|
+
} from "./socket/index.js";
|
|
34
|
+
import { AdbPacketDispatcher } from "./socket/index.js";
|
|
35
|
+
import { decodeUtf8, encodeUtf8 } from "./utils/index.js";
|
|
12
36
|
|
|
13
37
|
export enum AdbPropKey {
|
|
14
|
-
Product =
|
|
15
|
-
Model =
|
|
16
|
-
Device =
|
|
17
|
-
Features =
|
|
38
|
+
Product = "ro.product.name",
|
|
39
|
+
Model = "ro.product.model",
|
|
40
|
+
Device = "ro.product.device",
|
|
41
|
+
Features = "features",
|
|
18
42
|
}
|
|
19
43
|
|
|
20
44
|
export const VERSION_OMIT_CHECKSUM = 0x01000001;
|
|
@@ -26,47 +50,63 @@ export class Adb implements Closeable {
|
|
|
26
50
|
* and starts a new authentication process.
|
|
27
51
|
*/
|
|
28
52
|
public static async authenticate(
|
|
29
|
-
connection: ReadableWritablePair<
|
|
53
|
+
connection: ReadableWritablePair<
|
|
54
|
+
AdbPacketData,
|
|
55
|
+
Consumable<AdbPacketInit>
|
|
56
|
+
>,
|
|
30
57
|
credentialStore: AdbCredentialStore,
|
|
31
|
-
authenticators = ADB_DEFAULT_AUTHENTICATORS
|
|
58
|
+
authenticators = ADB_DEFAULT_AUTHENTICATORS
|
|
32
59
|
): Promise<Adb> {
|
|
33
60
|
// Initially, set to highest-supported version and payload size.
|
|
34
61
|
let version = 0x01000001;
|
|
35
|
-
|
|
62
|
+
// Android 4: 4K, Android 7: 256K, Android 9: 1M
|
|
63
|
+
let maxPayloadSize = 1024 * 1024;
|
|
36
64
|
|
|
37
65
|
const resolver = new PromiseResolver<string>();
|
|
38
|
-
const authProcessor = new AdbAuthenticationProcessor(
|
|
66
|
+
const authProcessor = new AdbAuthenticationProcessor(
|
|
67
|
+
authenticators,
|
|
68
|
+
credentialStore
|
|
69
|
+
);
|
|
39
70
|
|
|
40
71
|
// Here is similar to `AdbPacketDispatcher`,
|
|
41
72
|
// But the received packet types and send packet processing are different.
|
|
42
73
|
const abortController = new AbortController();
|
|
43
74
|
const pipe = connection.readable
|
|
44
|
-
.pipeTo(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
75
|
+
.pipeTo(
|
|
76
|
+
new WritableStream({
|
|
77
|
+
async write(packet) {
|
|
78
|
+
switch (packet.command) {
|
|
79
|
+
case AdbCommand.Connect:
|
|
80
|
+
version = Math.min(version, packet.arg0);
|
|
81
|
+
maxPayloadSize = Math.min(
|
|
82
|
+
maxPayloadSize,
|
|
83
|
+
packet.arg1
|
|
84
|
+
);
|
|
85
|
+
resolver.resolve(decodeUtf8(packet.payload));
|
|
86
|
+
break;
|
|
87
|
+
case AdbCommand.Auth: {
|
|
88
|
+
const response = await authProcessor.process(
|
|
89
|
+
packet
|
|
90
|
+
);
|
|
91
|
+
await sendPacket(response);
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
default:
|
|
95
|
+
// Maybe the previous ADB client exited without reading all packets,
|
|
96
|
+
// so they are still waiting in OS internal buffer.
|
|
97
|
+
// Just ignore them.
|
|
98
|
+
// Because a `Connect` packet will reset the device,
|
|
99
|
+
// Eventually there will be `Connect` and `Auth` response packets.
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
}),
|
|
104
|
+
{
|
|
105
|
+
// Don't cancel the source ReadableStream on AbortSignal abort.
|
|
106
|
+
preventCancel: true,
|
|
107
|
+
signal: abortController.signal,
|
|
64
108
|
}
|
|
65
|
-
|
|
66
|
-
// Don't cancel the source ReadableStream on AbortSignal abort.
|
|
67
|
-
preventCancel: true,
|
|
68
|
-
signal: abortController.signal,
|
|
69
|
-
})
|
|
109
|
+
)
|
|
70
110
|
.catch((e) => {
|
|
71
111
|
resolver.reject(e);
|
|
72
112
|
});
|
|
@@ -75,7 +115,9 @@ export class Adb implements Closeable {
|
|
|
75
115
|
async function sendPacket(init: AdbPacketData) {
|
|
76
116
|
// Always send checksum in auth steps
|
|
77
117
|
// Because we don't know if the device needs it or not.
|
|
78
|
-
|
|
118
|
+
(init as AdbPacketInit).checksum = calculateChecksum(init.payload);
|
|
119
|
+
(init as AdbPacketInit).magic = init.command ^ 0xffffffff;
|
|
120
|
+
await ConsumableWritableStream.write(writer, init as AdbPacketInit);
|
|
79
121
|
}
|
|
80
122
|
|
|
81
123
|
let banner: string;
|
|
@@ -83,25 +125,25 @@ export class Adb implements Closeable {
|
|
|
83
125
|
// https://android.googlesource.com/platform/packages/modules/adb/+/79010dc6d5ca7490c493df800d4421730f5466ca/transport.cpp#1252
|
|
84
126
|
// There are some other feature constants, but some of them are only used by ADB server, not devices (daemons).
|
|
85
127
|
const features = [
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
128
|
+
AdbFeature.ShellV2,
|
|
129
|
+
AdbFeature.Cmd,
|
|
130
|
+
AdbFeature.StatV2,
|
|
131
|
+
AdbFeature.ListV2,
|
|
132
|
+
AdbFeature.FixedPushMkdir,
|
|
133
|
+
"apex",
|
|
134
|
+
AdbFeature.Abb,
|
|
93
135
|
// only tells the client the symlink timestamp issue in `adb push --sync` has been fixed.
|
|
94
136
|
// No special handling required.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
].join(
|
|
137
|
+
"fixed_push_symlink_timestamp",
|
|
138
|
+
AdbFeature.AbbExec,
|
|
139
|
+
"remount_shell",
|
|
140
|
+
"track_app",
|
|
141
|
+
"sendrecv_v2",
|
|
142
|
+
"sendrecv_v2_brotli",
|
|
143
|
+
"sendrecv_v2_lz4",
|
|
144
|
+
"sendrecv_v2_zstd",
|
|
145
|
+
"sendrecv_v2_dry_run_send",
|
|
146
|
+
].join(",");
|
|
105
147
|
|
|
106
148
|
await sendPacket({
|
|
107
149
|
command: AdbCommand.Connect,
|
|
@@ -123,32 +165,44 @@ export class Adb implements Closeable {
|
|
|
123
165
|
await pipe;
|
|
124
166
|
}
|
|
125
167
|
|
|
126
|
-
return new Adb(
|
|
127
|
-
connection,
|
|
128
|
-
version,
|
|
129
|
-
maxPayloadSize,
|
|
130
|
-
banner,
|
|
131
|
-
);
|
|
168
|
+
return new Adb(connection, version, maxPayloadSize, banner);
|
|
132
169
|
}
|
|
133
170
|
|
|
134
171
|
private readonly dispatcher: AdbPacketDispatcher;
|
|
135
172
|
|
|
136
|
-
public get disconnected() {
|
|
173
|
+
public get disconnected() {
|
|
174
|
+
return this.dispatcher.disconnected;
|
|
175
|
+
}
|
|
137
176
|
|
|
138
|
-
private _protocolVersion: number
|
|
139
|
-
public get protocolVersion() {
|
|
177
|
+
private _protocolVersion: number;
|
|
178
|
+
public get protocolVersion() {
|
|
179
|
+
return this._protocolVersion;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private _maxPayloadSize: number;
|
|
183
|
+
public get maxPayloadSize() {
|
|
184
|
+
return this._maxPayloadSize;
|
|
185
|
+
}
|
|
140
186
|
|
|
141
187
|
private _product: string | undefined;
|
|
142
|
-
public get product() {
|
|
188
|
+
public get product() {
|
|
189
|
+
return this._product;
|
|
190
|
+
}
|
|
143
191
|
|
|
144
192
|
private _model: string | undefined;
|
|
145
|
-
public get model() {
|
|
193
|
+
public get model() {
|
|
194
|
+
return this._model;
|
|
195
|
+
}
|
|
146
196
|
|
|
147
197
|
private _device: string | undefined;
|
|
148
|
-
public get device() {
|
|
198
|
+
public get device() {
|
|
199
|
+
return this._device;
|
|
200
|
+
}
|
|
149
201
|
|
|
150
|
-
private _features:
|
|
151
|
-
public get features() {
|
|
202
|
+
private _features: AdbFeature[] = [];
|
|
203
|
+
public get features() {
|
|
204
|
+
return this._features;
|
|
205
|
+
}
|
|
152
206
|
|
|
153
207
|
public readonly subprocess: AdbSubprocess;
|
|
154
208
|
public readonly power: AdbPower;
|
|
@@ -156,10 +210,13 @@ export class Adb implements Closeable {
|
|
|
156
210
|
public readonly tcpip: AdbTcpIpCommand;
|
|
157
211
|
|
|
158
212
|
public constructor(
|
|
159
|
-
connection: ReadableWritablePair<
|
|
213
|
+
connection: ReadableWritablePair<
|
|
214
|
+
AdbPacketData,
|
|
215
|
+
Consumable<AdbPacketInit>
|
|
216
|
+
>,
|
|
160
217
|
version: number,
|
|
161
218
|
maxPayloadSize: number,
|
|
162
|
-
banner: string
|
|
219
|
+
banner: string
|
|
163
220
|
) {
|
|
164
221
|
this.parseBanner(banner);
|
|
165
222
|
|
|
@@ -173,16 +230,14 @@ export class Adb implements Closeable {
|
|
|
173
230
|
appendNullToServiceString = true;
|
|
174
231
|
}
|
|
175
232
|
|
|
176
|
-
this.dispatcher = new AdbPacketDispatcher(
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
maxPayloadSize,
|
|
182
|
-
}
|
|
183
|
-
);
|
|
233
|
+
this.dispatcher = new AdbPacketDispatcher(connection, {
|
|
234
|
+
calculateChecksum,
|
|
235
|
+
appendNullToServiceString,
|
|
236
|
+
maxPayloadSize,
|
|
237
|
+
});
|
|
184
238
|
|
|
185
239
|
this._protocolVersion = version;
|
|
240
|
+
this._maxPayloadSize = maxPayloadSize;
|
|
186
241
|
|
|
187
242
|
this.subprocess = new AdbSubprocess(this);
|
|
188
243
|
this.power = new AdbPower(this);
|
|
@@ -191,15 +246,15 @@ export class Adb implements Closeable {
|
|
|
191
246
|
}
|
|
192
247
|
|
|
193
248
|
private parseBanner(banner: string): void {
|
|
194
|
-
const pieces = banner.split(
|
|
249
|
+
const pieces = banner.split("::");
|
|
195
250
|
if (pieces.length > 1) {
|
|
196
251
|
const props = pieces[1]!;
|
|
197
|
-
for (const prop of props.split(
|
|
252
|
+
for (const prop of props.split(";")) {
|
|
198
253
|
if (!prop) {
|
|
199
254
|
continue;
|
|
200
255
|
}
|
|
201
256
|
|
|
202
|
-
const keyValue = prop.split(
|
|
257
|
+
const keyValue = prop.split("=");
|
|
203
258
|
if (keyValue.length !== 2) {
|
|
204
259
|
continue;
|
|
205
260
|
}
|
|
@@ -216,13 +271,17 @@ export class Adb implements Closeable {
|
|
|
216
271
|
this._device = value;
|
|
217
272
|
break;
|
|
218
273
|
case AdbPropKey.Features:
|
|
219
|
-
this._features = value!.split(
|
|
274
|
+
this._features = value!.split(",") as AdbFeature[];
|
|
220
275
|
break;
|
|
221
276
|
}
|
|
222
277
|
}
|
|
223
278
|
}
|
|
224
279
|
}
|
|
225
280
|
|
|
281
|
+
public supportsFeature(feature: AdbFeature): boolean {
|
|
282
|
+
return this._features.includes(feature);
|
|
283
|
+
}
|
|
284
|
+
|
|
226
285
|
/**
|
|
227
286
|
* Add a handler for incoming socket.
|
|
228
287
|
* @param handler A function to call with new incoming sockets. It must return `true` if it accepts the socket.
|
|
@@ -246,25 +305,25 @@ export class Adb implements Closeable {
|
|
|
246
305
|
}
|
|
247
306
|
|
|
248
307
|
public async getProp(key: string): Promise<string> {
|
|
249
|
-
const stdout = await this.subprocess.spawnAndWaitLegacy(
|
|
250
|
-
|
|
251
|
-
|
|
308
|
+
const stdout = await this.subprocess.spawnAndWaitLegacy([
|
|
309
|
+
"getprop",
|
|
310
|
+
key,
|
|
311
|
+
]);
|
|
252
312
|
return stdout.trim();
|
|
253
313
|
}
|
|
254
314
|
|
|
255
315
|
public async rm(...filenames: string[]): Promise<string> {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
316
|
+
// https://android.googlesource.com/platform/packages/modules/adb/+/1a0fb8846d4e6b671c8aa7f137a8c21d7b248716/client/adb_install.cpp#984
|
|
317
|
+
const stdout = await this.subprocess.spawnAndWaitLegacy([
|
|
318
|
+
"rm",
|
|
319
|
+
...filenames.map((arg) => escapeArg(arg)),
|
|
320
|
+
"</dev/null",
|
|
321
|
+
]);
|
|
259
322
|
return stdout;
|
|
260
323
|
}
|
|
261
324
|
|
|
262
|
-
public install() {
|
|
263
|
-
return install(this);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
325
|
public async sync(): Promise<AdbSync> {
|
|
267
|
-
const socket = await this.createSocket(
|
|
326
|
+
const socket = await this.createSocket("sync:");
|
|
268
327
|
return new AdbSync(this, socket);
|
|
269
328
|
}
|
|
270
329
|
|
package/src/auth.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { PromiseResolver } from
|
|
2
|
-
import type { Disposable } from
|
|
3
|
-
import type { ValueOrPromise } from
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
import type { Disposable } from "@yume-chan/event";
|
|
3
|
+
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
calculatePublicKey,
|
|
7
|
+
calculatePublicKeyLength,
|
|
8
|
+
sign,
|
|
9
|
+
} from "./crypto.js";
|
|
10
|
+
import type { AdbPacketData } from "./packet.js";
|
|
11
|
+
import { AdbCommand } from "./packet.js";
|
|
12
|
+
import { calculateBase64EncodedLength, encodeBase64 } from "./utils/index.js";
|
|
8
13
|
|
|
9
14
|
export type AdbKeyIterable = Iterable<Uint8Array> | AsyncIterable<Uint8Array>;
|
|
10
15
|
|
|
@@ -50,7 +55,7 @@ export interface AdbAuthenticator {
|
|
|
50
55
|
|
|
51
56
|
export const AdbSignatureAuthenticator: AdbAuthenticator = async function* (
|
|
52
57
|
credentialStore: AdbCredentialStore,
|
|
53
|
-
getNextRequest: () => Promise<AdbPacketData
|
|
58
|
+
getNextRequest: () => Promise<AdbPacketData>
|
|
54
59
|
): AsyncIterable<AdbPacketData> {
|
|
55
60
|
for await (const key of credentialStore.iterateKeys()) {
|
|
56
61
|
const packet = await getNextRequest();
|
|
@@ -71,7 +76,7 @@ export const AdbSignatureAuthenticator: AdbAuthenticator = async function* (
|
|
|
71
76
|
|
|
72
77
|
export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
|
|
73
78
|
credentialStore: AdbCredentialStore,
|
|
74
|
-
getNextRequest: () => Promise<AdbPacketData
|
|
79
|
+
getNextRequest: () => Promise<AdbPacketData>
|
|
75
80
|
): AsyncIterable<AdbPacketData> {
|
|
76
81
|
const packet = await getNextRequest();
|
|
77
82
|
|
|
@@ -85,23 +90,20 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
|
|
|
85
90
|
break;
|
|
86
91
|
}
|
|
87
92
|
|
|
88
|
-
|
|
89
93
|
if (!privateKey) {
|
|
90
94
|
privateKey = await credentialStore.generateKey();
|
|
91
95
|
}
|
|
92
96
|
|
|
93
97
|
const publicKeyLength = calculatePublicKeyLength();
|
|
94
|
-
const [publicKeyBase64Length] =
|
|
98
|
+
const [publicKeyBase64Length] =
|
|
99
|
+
calculateBase64EncodedLength(publicKeyLength);
|
|
95
100
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
const publicKeyBuffer = new Uint8Array(
|
|
102
|
+
publicKeyBase64Length + 1 // Null character
|
|
103
|
+
);
|
|
99
104
|
|
|
100
105
|
calculatePublicKey(privateKey, publicKeyBuffer);
|
|
101
|
-
encodeBase64(
|
|
102
|
-
publicKeyBuffer.subarray(0, publicKeyLength),
|
|
103
|
-
publicKeyBuffer
|
|
104
|
-
);
|
|
106
|
+
encodeBase64(publicKeyBuffer.subarray(0, publicKeyLength), publicKeyBuffer);
|
|
105
107
|
|
|
106
108
|
yield {
|
|
107
109
|
command: AdbCommand.Auth,
|
|
@@ -137,9 +139,16 @@ export class AdbAuthenticationProcessor implements Disposable {
|
|
|
137
139
|
return this.pendingRequest.promise;
|
|
138
140
|
};
|
|
139
141
|
|
|
140
|
-
private async*
|
|
142
|
+
private async *invokeAuthenticator(): AsyncGenerator<
|
|
143
|
+
AdbPacketData,
|
|
144
|
+
void,
|
|
145
|
+
void
|
|
146
|
+
> {
|
|
141
147
|
for (const authenticator of this.authenticators) {
|
|
142
|
-
for await (const packet of authenticator(
|
|
148
|
+
for await (const packet of authenticator(
|
|
149
|
+
this.credentialStore,
|
|
150
|
+
this.getNextRequest
|
|
151
|
+
)) {
|
|
143
152
|
// If the authenticator yielded a response
|
|
144
153
|
// Prepare `nextRequest` for next authentication request
|
|
145
154
|
this.pendingRequest = new PromiseResolver();
|
|
@@ -162,13 +171,13 @@ export class AdbAuthenticationProcessor implements Disposable {
|
|
|
162
171
|
|
|
163
172
|
const result = await this.iterator.next();
|
|
164
173
|
if (result.done) {
|
|
165
|
-
throw new Error(
|
|
174
|
+
throw new Error("No authenticator can handle the request");
|
|
166
175
|
}
|
|
167
176
|
|
|
168
177
|
return result.value;
|
|
169
178
|
}
|
|
170
179
|
|
|
171
180
|
public dispose() {
|
|
172
|
-
this.iterator?.return?.();
|
|
181
|
+
void this.iterator?.return?.();
|
|
173
182
|
}
|
|
174
183
|
}
|
package/src/backend.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import type { ReadableWritablePair } from
|
|
2
|
-
import type { ValueOrPromise } from
|
|
1
|
+
import type { Consumable, ReadableWritablePair } from "@yume-chan/stream-extra";
|
|
2
|
+
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
3
3
|
|
|
4
|
-
import type { AdbPacketData, AdbPacketInit } from
|
|
4
|
+
import type { AdbPacketData, AdbPacketInit } from "./packet.js";
|
|
5
5
|
|
|
6
6
|
export interface AdbBackend {
|
|
7
7
|
readonly serial: string;
|
|
8
8
|
|
|
9
9
|
readonly name: string | undefined;
|
|
10
10
|
|
|
11
|
-
connect(): ValueOrPromise<
|
|
11
|
+
connect(): ValueOrPromise<
|
|
12
|
+
ReadableWritablePair<AdbPacketData, Consumable<AdbPacketInit>>
|
|
13
|
+
>;
|
|
12
14
|
}
|
package/src/commands/base.ts
CHANGED
|
@@ -1,48 +1,44 @@
|
|
|
1
|
-
import { BufferedReadableStream } from
|
|
2
|
-
import Struct from
|
|
1
|
+
import { BufferedReadableStream } from "@yume-chan/stream-extra";
|
|
2
|
+
import Struct from "@yume-chan/struct";
|
|
3
3
|
|
|
4
|
-
import type { Adb } from
|
|
4
|
+
import type { Adb } from "../adb.js";
|
|
5
5
|
|
|
6
|
-
const Version =
|
|
7
|
-
new Struct({ littleEndian: true })
|
|
8
|
-
.uint32('version');
|
|
6
|
+
const Version = new Struct({ littleEndian: true }).uint32("version");
|
|
9
7
|
|
|
10
|
-
export const AdbFrameBufferV1 =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.uint8Array('data', { lengthField: 'size' });
|
|
8
|
+
export const AdbFrameBufferV1 = new Struct({ littleEndian: true })
|
|
9
|
+
.uint32("bpp")
|
|
10
|
+
.uint32("size")
|
|
11
|
+
.uint32("width")
|
|
12
|
+
.uint32("height")
|
|
13
|
+
.uint32("red_offset")
|
|
14
|
+
.uint32("red_length")
|
|
15
|
+
.uint32("blue_offset")
|
|
16
|
+
.uint32("blue_length")
|
|
17
|
+
.uint32("green_offset")
|
|
18
|
+
.uint32("green_length")
|
|
19
|
+
.uint32("alpha_offset")
|
|
20
|
+
.uint32("alpha_length")
|
|
21
|
+
.uint8Array("data", { lengthField: "size" });
|
|
25
22
|
|
|
26
|
-
export type AdbFrameBufferV1 = typeof AdbFrameBufferV1[
|
|
23
|
+
export type AdbFrameBufferV1 = (typeof AdbFrameBufferV1)["TDeserializeResult"];
|
|
27
24
|
|
|
28
|
-
export const AdbFrameBufferV2 =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
.uint8Array('data', { lengthField: 'size' });
|
|
25
|
+
export const AdbFrameBufferV2 = new Struct({ littleEndian: true })
|
|
26
|
+
.uint32("bpp")
|
|
27
|
+
.uint32("colorSpace")
|
|
28
|
+
.uint32("size")
|
|
29
|
+
.uint32("width")
|
|
30
|
+
.uint32("height")
|
|
31
|
+
.uint32("red_offset")
|
|
32
|
+
.uint32("red_length")
|
|
33
|
+
.uint32("blue_offset")
|
|
34
|
+
.uint32("blue_length")
|
|
35
|
+
.uint32("green_offset")
|
|
36
|
+
.uint32("green_length")
|
|
37
|
+
.uint32("alpha_offset")
|
|
38
|
+
.uint32("alpha_length")
|
|
39
|
+
.uint8Array("data", { lengthField: "size" });
|
|
44
40
|
|
|
45
|
-
export type AdbFrameBufferV2 = typeof AdbFrameBufferV2[
|
|
41
|
+
export type AdbFrameBufferV2 = (typeof AdbFrameBufferV2)["TDeserializeResult"];
|
|
46
42
|
|
|
47
43
|
/**
|
|
48
44
|
* ADB uses 8 int32 fields to describe bit depths
|
|
@@ -63,7 +59,7 @@ export type AdbFrameBufferV2 = typeof AdbFrameBufferV2['TDeserializeResult'];
|
|
|
63
59
|
export type AdbFrameBuffer = AdbFrameBufferV1 | AdbFrameBufferV2;
|
|
64
60
|
|
|
65
61
|
export async function framebuffer(adb: Adb): Promise<AdbFrameBuffer> {
|
|
66
|
-
const socket = await adb.createSocket(
|
|
62
|
+
const socket = await adb.createSocket("framebuffer:");
|
|
67
63
|
const stream = new BufferedReadableStream(socket.readable);
|
|
68
64
|
const { version } = await Version.deserialize(stream);
|
|
69
65
|
switch (version) {
|
|
@@ -73,6 +69,6 @@ export async function framebuffer(adb: Adb): Promise<AdbFrameBuffer> {
|
|
|
73
69
|
case 2:
|
|
74
70
|
return AdbFrameBufferV2.deserialize(stream);
|
|
75
71
|
default:
|
|
76
|
-
throw new Error(
|
|
72
|
+
throw new Error("Unsupported FrameBuffer version");
|
|
77
73
|
}
|
|
78
74
|
}
|