refactor(adb): change sync push args to objects

This commit is contained in:
Simon Chan 2023-03-06 13:12:41 +08:00
parent 134e48d620
commit cde7923856
6 changed files with 96 additions and 57 deletions

View file

@ -570,18 +570,18 @@ class FileManagerState {
); );
try { try {
await sync.write( await sync.write({
itemPath, filename: itemPath,
createFileStream(file).pipeThrough( file: createFileStream(file).pipeThrough(
new ProgressStream( new ProgressStream(
action((uploaded) => { action((uploaded) => {
this.uploadedSize = uploaded; this.uploadedSize = uploaded;
}) })
) )
), ),
(LinuxFileType.File << 12) | 0o666, mode: (LinuxFileType.File << 12) | 0o666,
file.lastModified / 1000 mtime: file.lastModified / 1000,
); });
runInAction(() => { runInAction(() => {
this.uploadSpeed = this.uploadSpeed =

View file

@ -7,20 +7,39 @@ import { AdbSyncResponseId, adbSyncReadResponse } from "./response.js";
import type { AdbSyncSocket } from "./socket.js"; import type { AdbSyncSocket } from "./socket.js";
import { LinuxFileType } from "./stat.js"; import { LinuxFileType } from "./stat.js";
export const ADB_SYNC_MAX_PACKET_SIZE = 64 * 1024;
export interface AdbSyncPushV1Options {
socket: AdbSyncSocket;
filename: string;
file: ReadableStream<Uint8Array>;
mode?: number;
mtime?: number;
packetSize?: number;
}
export const AdbSyncPushV1DefaultOptions: {
[K in keyof AdbSyncPushV1Options as Pick<
AdbSyncPushV1Options,
K
> extends Required<Pick<AdbSyncPushV1Options, K>>
? never
: K]-?: Exclude<AdbSyncPushV1Options[K], undefined>;
} = {
mode: (LinuxFileType.File << 12) | 0o666,
mtime: (Date.now() / 1000) | 0,
packetSize: ADB_SYNC_MAX_PACKET_SIZE,
};
export const AdbSyncOkResponse = new Struct({ littleEndian: true }).uint32( export const AdbSyncOkResponse = new Struct({ littleEndian: true }).uint32(
"unused" "unused"
); );
export const ADB_SYNC_MAX_PACKET_SIZE = 64 * 1024; export async function adbSyncPushV1(options: AdbSyncPushV1Options) {
const { socket, filename, file, mode, mtime, packetSize } = {
export async function adbSyncPushV1( ...AdbSyncPushV1DefaultOptions,
socket: AdbSyncSocket, ...options,
filename: string, };
file: ReadableStream<Uint8Array>,
mode: number = (LinuxFileType.File << 12) | 0o666,
mtime: number = (Date.now() / 1000) | 0,
packetSize: number = ADB_SYNC_MAX_PACKET_SIZE
) {
const locked = await socket.lock(); const locked = await socket.lock();
try { try {
const pathAndMode = `${filename},${mode.toString()}`; const pathAndMode = `${filename},${mode.toString()}`;
@ -66,28 +85,45 @@ export enum AdbSyncSendV2Flags {
DryRun = (1 << 31) >>> 0, DryRun = (1 << 31) >>> 0,
} }
export interface AdbSyncPushV2Options extends AdbSyncPushV1Options {
dryRun?: boolean;
}
export const AdbSyncPushV2DefaultOptions: {
[K in keyof AdbSyncPushV2Options as Pick<
AdbSyncPushV2Options,
K
> extends Required<Pick<AdbSyncPushV2Options, K>>
? never
: K]-?: Exclude<AdbSyncPushV2Options[K], undefined>;
} = {
...AdbSyncPushV1DefaultOptions,
dryRun: false,
};
export const AdbSyncSendV2Request = new Struct({ littleEndian: true }) export const AdbSyncSendV2Request = new Struct({ littleEndian: true })
.uint32("id", placeholder<AdbSyncRequestId>()) .uint32("id", placeholder<AdbSyncRequestId>())
.uint32("mode") .uint32("mode")
.uint32("flags", placeholder<AdbSyncSendV2Flags>()); .uint32("flags", placeholder<AdbSyncSendV2Flags>());
export async function adbSyncPushV2( export async function adbSyncPushV2(options: AdbSyncPushV2Options) {
socket: AdbSyncSocket, const { socket, filename, file, mode, mtime, packetSize, dryRun } = {
filename: string, ...AdbSyncPushV2DefaultOptions,
file: ReadableStream<Uint8Array>, ...options,
mode: number = (LinuxFileType.File << 12) | 0o666, };
mtime: number = (Date.now() / 1000) | 0,
packetSize: number = ADB_SYNC_MAX_PACKET_SIZE
) {
const locked = await socket.lock(); const locked = await socket.lock();
try { try {
await adbSyncWriteRequest(locked, AdbSyncRequestId.SendV2, filename); await adbSyncWriteRequest(locked, AdbSyncRequestId.SendV2, filename);
let flags: AdbSyncSendV2Flags = AdbSyncSendV2Flags.None;
if (dryRun) {
flags |= AdbSyncSendV2Flags.DryRun;
}
await locked.write( await locked.write(
AdbSyncSendV2Request.serialize({ AdbSyncSendV2Request.serialize({
id: AdbSyncRequestId.SendV2, id: AdbSyncRequestId.SendV2,
mode, mode,
flags: 0, flags,
}) })
); );
@ -114,18 +150,16 @@ export async function adbSyncPushV2(
} }
} }
export function adbSyncPush( export interface AdbSyncPushOptions extends AdbSyncPushV2Options {
v2: boolean, v2: boolean;
socket: AdbSyncSocket, }
filename: string,
file: ReadableStream<Uint8Array>, export function adbSyncPush(options: AdbSyncPushOptions) {
mode: number = (LinuxFileType.File << 12) | 0o666, if (options.v2) {
mtime: number = (Date.now() / 1000) | 0, return adbSyncPushV2(options);
packetSize: number = ADB_SYNC_MAX_PACKET_SIZE } else if (options.dryRun) {
) { throw new Error("dryRun is not supported in v1");
if (v2) {
return adbSyncPushV2(socket, filename, file, mode, mtime, packetSize);
} else { } else {
return adbSyncPushV1(socket, filename, file, mode, mtime, packetSize); return adbSyncPushV1(options);
} }
} }

View file

@ -29,6 +29,13 @@ export function dirname(path: string): string {
return path.substring(0, end); return path.substring(0, end);
} }
export interface AdbSyncWriteOptions {
filename: string;
file: ReadableStream<Uint8Array>;
mode?: number;
mtime?: number;
}
export class AdbSync extends AutoDisposable { export class AdbSync extends AutoDisposable {
protected _adb: Adb; protected _adb: Adb;
protected _socket: AdbSyncSocket; protected _socket: AdbSyncSocket;
@ -129,12 +136,7 @@ export class AdbSync extends AutoDisposable {
* @param mtime The modified time of the file. * @param mtime The modified time of the file.
* @returns A `WritableStream` that writes to the file. * @returns A `WritableStream` that writes to the file.
*/ */
public async write( public async write(options: AdbSyncWriteOptions) {
filename: string,
file: ReadableStream<Uint8Array>,
mode?: number,
mtime?: number
) {
if (this.needPushMkdirWorkaround) { if (this.needPushMkdirWorkaround) {
// It may fail if the path is already existed. // It may fail if the path is already existed.
// Ignore the result. // Ignore the result.
@ -142,18 +144,15 @@ export class AdbSync extends AutoDisposable {
await this._adb.subprocess.spawnAndWait([ await this._adb.subprocess.spawnAndWait([
"mkdir", "mkdir",
"-p", "-p",
escapeArg(dirname(filename)), escapeArg(dirname(options.filename)),
]); ]);
} }
await adbSyncPush( await adbSyncPush({
this.supportsSendReceiveV2, v2: this.supportsSendReceiveV2,
this._socket, socket: this._socket,
filename, ...options,
file, });
mode,
mtime
);
} }
public override async dispose() { public override async dispose() {

View file

@ -233,7 +233,10 @@ export class PackageManager extends AdbCommandBase {
const filePath = `/data/local/tmp/${fileName}.apk`; const filePath = `/data/local/tmp/${fileName}.apk`;
try { try {
await sync.write(filePath, stream); await sync.write({
filename: filePath,
file: stream,
});
} finally { } finally {
await sync.dispose(); await sync.dispose();
} }

View file

@ -98,11 +98,14 @@ export class AdbScrcpyClient {
public static async pushServer( public static async pushServer(
adb: Adb, adb: Adb,
file: ReadableStream<Uint8Array>, file: ReadableStream<Uint8Array>,
path = DEFAULT_SERVER_PATH filename = DEFAULT_SERVER_PATH
) { ) {
const sync = await adb.sync(); const sync = await adb.sync();
try { try {
await sync.write(path, file); await sync.write({
filename: filename,
file,
});
} finally { } finally {
await sync.dispose(); await sync.dispose();
} }

View file

@ -65,8 +65,8 @@ export interface ScrcpyVideoStreamConfigurationPacket {
export interface ScrcpyVideoStreamFramePacket { export interface ScrcpyVideoStreamFramePacket {
type: "frame"; type: "frame";
keyframe?: boolean | undefined; keyframe?: boolean;
pts?: bigint | undefined; pts?: bigint;
data: Uint8Array; data: Uint8Array;
} }