mirror of
https://github.com/yume-chan/ya-webadb.git
synced 2025-10-06 03:50:18 +02:00
chore: format code
This commit is contained in:
parent
0046c76ee1
commit
19ee58ce29
12 changed files with 122 additions and 51 deletions
|
@ -1,5 +1,3 @@
|
|||
// cspell: ignore libusb
|
||||
|
||||
import { PromiseResolver } from "@yume-chan/async";
|
||||
import {
|
||||
AbortController,
|
||||
|
@ -269,6 +267,10 @@ export class Adb implements Closeable {
|
|||
}
|
||||
}
|
||||
|
||||
public supportsFeature(feature: AdbFeatures): boolean {
|
||||
return this._features.includes(feature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a handler for incoming socket.
|
||||
* @param handler A function to call with new incoming sockets. It must return `true` if it accepts the socket.
|
||||
|
|
|
@ -97,9 +97,9 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
|
|||
const [publicKeyBase64Length] =
|
||||
calculateBase64EncodedLength(publicKeyLength);
|
||||
|
||||
// The public key is null terminated,
|
||||
// So we allocate the buffer with one extra byte.
|
||||
const publicKeyBuffer = new Uint8Array(publicKeyBase64Length + 1);
|
||||
const publicKeyBuffer = new Uint8Array(
|
||||
publicKeyBase64Length + 1 // Null character
|
||||
);
|
||||
|
||||
calculatePublicKey(privateKey, publicKeyBuffer);
|
||||
encodeBase64(publicKeyBuffer.subarray(0, publicKeyLength), publicKeyBuffer);
|
||||
|
|
|
@ -69,6 +69,6 @@ export async function framebuffer(adb: Adb): Promise<AdbFrameBuffer> {
|
|||
case 2:
|
||||
return AdbFrameBufferV2.deserialize(stream);
|
||||
default:
|
||||
throw new Error("Unknown FrameBuffer version");
|
||||
throw new Error("Unsupported FrameBuffer version");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,16 +14,22 @@ import { type AdbSubprocessProtocol } from "./types.js";
|
|||
* * `resize`: No
|
||||
*/
|
||||
export class AdbSubprocessNoneProtocol implements AdbSubprocessProtocol {
|
||||
public static isSupported() { return true; }
|
||||
public static isSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static async pty(adb: Adb, command: string) {
|
||||
return new AdbSubprocessNoneProtocol(await adb.createSocket(`shell:${command}`));
|
||||
return new AdbSubprocessNoneProtocol(
|
||||
await adb.createSocket(`shell:${command}`)
|
||||
);
|
||||
}
|
||||
|
||||
public static async raw(adb: Adb, command: string) {
|
||||
// `shell,raw:${command}` also triggers raw mode,
|
||||
// But is not supported on Android version <7.
|
||||
return new AdbSubprocessNoneProtocol(await adb.createSocket(`exec:${command}`));
|
||||
return new AdbSubprocessNoneProtocol(
|
||||
await adb.createSocket(`exec:${command}`)
|
||||
);
|
||||
}
|
||||
|
||||
private readonly socket: AdbSocket;
|
||||
|
@ -31,22 +37,30 @@ export class AdbSubprocessNoneProtocol implements AdbSubprocessProtocol {
|
|||
private readonly duplex: DuplexStreamFactory<Uint8Array, Uint8Array>;
|
||||
|
||||
// Legacy shell forwards all data to stdin.
|
||||
public get stdin() { return this.socket.writable; }
|
||||
public get stdin() {
|
||||
return this.socket.writable;
|
||||
}
|
||||
|
||||
private _stdout: ReadableStream<Uint8Array>;
|
||||
/**
|
||||
* Legacy shell mixes stdout and stderr.
|
||||
*/
|
||||
public get stdout() { return this._stdout; }
|
||||
public get stdout() {
|
||||
return this._stdout;
|
||||
}
|
||||
|
||||
private _stderr: ReadableStream<Uint8Array>;
|
||||
/**
|
||||
* `stderr` will always be empty.
|
||||
*/
|
||||
public get stderr() { return this._stderr; }
|
||||
public get stderr() {
|
||||
return this._stderr;
|
||||
}
|
||||
|
||||
private _exit: Promise<number>;
|
||||
public get exit() { return this._exit; }
|
||||
public get exit() {
|
||||
return this._exit;
|
||||
}
|
||||
|
||||
public constructor(socket: AdbSocket) {
|
||||
this.socket = socket;
|
||||
|
|
|
@ -13,9 +13,9 @@ import {
|
|||
import Struct, { placeholder, type StructValueType } from '@yume-chan/struct';
|
||||
|
||||
import { type Adb } from "../../../adb.js";
|
||||
import { AdbFeatures } from '../../../features.js';
|
||||
import { AdbFeatures } from "../../../features.js";
|
||||
import { type AdbSocket } from "../../../socket/index.js";
|
||||
import { encodeUtf8 } from '../../../utils/index.js';
|
||||
import { encodeUtf8 } from "../../../utils/index.js";
|
||||
|
||||
import { type AdbSubprocessProtocol } from "./types.js";
|
||||
|
||||
|
@ -29,17 +29,19 @@ export enum AdbShellProtocolId {
|
|||
}
|
||||
|
||||
// This packet format is used in both direction.
|
||||
const AdbShellProtocolPacket =
|
||||
new Struct({ littleEndian: true })
|
||||
.uint8('id', placeholder<AdbShellProtocolId>())
|
||||
.uint32('length')
|
||||
.uint8Array('data', { lengthField: 'length' });
|
||||
const AdbShellProtocolPacket = new Struct({ littleEndian: true })
|
||||
.uint8("id", placeholder<AdbShellProtocolId>())
|
||||
.uint32("length")
|
||||
.uint8Array("data", { lengthField: "length" });
|
||||
|
||||
type AdbShellProtocolPacketInit = typeof AdbShellProtocolPacket['TInit'];
|
||||
type AdbShellProtocolPacketInit = typeof AdbShellProtocolPacket["TInit"];
|
||||
|
||||
type AdbShellProtocolPacket = StructValueType<typeof AdbShellProtocolPacket>;
|
||||
|
||||
class StdinSerializeStream extends TransformStream<Uint8Array, AdbShellProtocolPacketInit>{
|
||||
class StdinSerializeStream extends TransformStream<
|
||||
Uint8Array,
|
||||
AdbShellProtocolPacketInit
|
||||
> {
|
||||
constructor() {
|
||||
super({
|
||||
transform(chunk, controller) {
|
||||
|
@ -50,12 +52,15 @@ class StdinSerializeStream extends TransformStream<Uint8Array, AdbShellProtocolP
|
|||
},
|
||||
flush() {
|
||||
// TODO: AdbShellSubprocessProtocol: support closing stdin
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class StdoutDeserializeStream extends TransformStream<AdbShellProtocolPacket, Uint8Array>{
|
||||
class StdoutDeserializeStream extends TransformStream<
|
||||
AdbShellProtocolPacket,
|
||||
Uint8Array
|
||||
> {
|
||||
constructor(type: AdbShellProtocolId.Stdout | AdbShellProtocolId.Stderr) {
|
||||
super({
|
||||
transform(chunk, controller) {
|
||||
|
@ -116,7 +121,7 @@ class MultiplexStream<T> {
|
|||
*/
|
||||
export class AdbSubprocessShellProtocol implements AdbSubprocessProtocol {
|
||||
public static isSupported(adb: Adb) {
|
||||
return adb.features.includes(AdbFeatures.ShellV2);
|
||||
return adb.supportsFeature(AdbFeatures.ShellV2);
|
||||
}
|
||||
|
||||
public static async pty(adb: Adb, command: string) {
|
||||
|
|
|
@ -46,21 +46,21 @@ export class AdbSync extends AutoDisposable {
|
|||
protected sendLock = this.addDisposable(new AutoResetEvent());
|
||||
|
||||
public get supportsStat(): boolean {
|
||||
return this.adb.features.includes(AdbFeatures.StatV2);
|
||||
return this.adb.supportsFeature(AdbFeatures.StatV2);
|
||||
}
|
||||
|
||||
public get supportsList2(): boolean {
|
||||
return this.adb.features.includes(AdbFeatures.ListV2);
|
||||
return this.adb.supportsFeature(AdbFeatures.ListV2);
|
||||
}
|
||||
|
||||
public get fixedPushMkdir(): boolean {
|
||||
return this.adb.features.includes(AdbFeatures.FixedPushMkdir);
|
||||
return this.adb.supportsFeature(AdbFeatures.FixedPushMkdir);
|
||||
}
|
||||
|
||||
public get needPushMkdirWorkaround(): boolean {
|
||||
// https://android.googlesource.com/platform/packages/modules/adb/+/91768a57b7138166e0a3d11f79cd55909dda7014/client/file_sync_client.cpp#1361
|
||||
return (
|
||||
this.adb.features.includes(AdbFeatures.ShellV2) &&
|
||||
this.adb.supportsFeature(AdbFeatures.ShellV2) &&
|
||||
!this.fixedPushMkdir
|
||||
);
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ export class AdbSync extends AutoDisposable {
|
|||
this.supportsStat
|
||||
);
|
||||
} finally {
|
||||
this.sendLock.notify();
|
||||
this.sendLock.notifyOne();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,7 @@ export class AdbSync extends AutoDisposable {
|
|||
try {
|
||||
return adbSyncStat(this.stream, this.writer, path);
|
||||
} finally {
|
||||
this.sendLock.notify();
|
||||
this.sendLock.notifyOne();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ export class AdbSync extends AutoDisposable {
|
|||
this.supportsList2
|
||||
);
|
||||
} finally {
|
||||
this.sendLock.notify();
|
||||
this.sendLock.notifyOne();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ export class AdbSync extends AutoDisposable {
|
|||
return adbSyncPull(this.stream, this.writer, filename);
|
||||
},
|
||||
close: () => {
|
||||
this.sendLock.notify();
|
||||
this.sendLock.notifyOne();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ export class AdbSync extends AutoDisposable {
|
|||
);
|
||||
},
|
||||
close: () => {
|
||||
this.sendLock.notify();
|
||||
this.sendLock.notifyOne();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,40 +2,39 @@ import { PromiseResolver } from "@yume-chan/async";
|
|||
import { type Disposable } from "@yume-chan/event";
|
||||
|
||||
export class AutoResetEvent implements Disposable {
|
||||
private readonly list: PromiseResolver<void>[] = [];
|
||||
|
||||
private blocking: boolean;
|
||||
private _set: boolean;
|
||||
private readonly _queue: PromiseResolver<void>[] = [];
|
||||
|
||||
public constructor(initialSet = false) {
|
||||
this.blocking = initialSet;
|
||||
this._set = initialSet;
|
||||
}
|
||||
|
||||
public wait(): Promise<void> {
|
||||
if (!this.blocking) {
|
||||
this.blocking = true;
|
||||
if (!this._set) {
|
||||
this._set = true;
|
||||
|
||||
if (this.list.length === 0) {
|
||||
if (this._queue.length === 0) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
const resolver = new PromiseResolver<void>();
|
||||
this.list.push(resolver);
|
||||
this._queue.push(resolver);
|
||||
return resolver.promise;
|
||||
}
|
||||
|
||||
public notify() {
|
||||
if (this.list.length !== 0) {
|
||||
this.list.pop()!.resolve();
|
||||
public notifyOne() {
|
||||
if (this._queue.length !== 0) {
|
||||
this._queue.pop()!.resolve();
|
||||
} else {
|
||||
this.blocking = false;
|
||||
this._set = false;
|
||||
}
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
for (const item of this.list) {
|
||||
for (const item of this._queue) {
|
||||
item.reject(new Error("The AutoResetEvent has been disposed"));
|
||||
}
|
||||
this.list.length = 0;
|
||||
this._queue.length = 0;
|
||||
}
|
||||
}
|
||||
|
|
45
libraries/adb/src/utils/conditional-variable.ts
Normal file
45
libraries/adb/src/utils/conditional-variable.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import { PromiseResolver } from "@yume-chan/async";
|
||||
import { type Disposable } from "@yume-chan/event";
|
||||
|
||||
interface WaitEntry {
|
||||
condition: () => boolean;
|
||||
resolver: PromiseResolver<void>;
|
||||
}
|
||||
|
||||
export class ConditionalVariable implements Disposable {
|
||||
private _locked = false;
|
||||
private readonly _queue: WaitEntry[] = [];
|
||||
|
||||
public wait(condition: () => boolean): Promise<void> {
|
||||
if (!this._locked) {
|
||||
this._locked = true;
|
||||
if (this._queue.length === 0 && condition()) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
const resolver = new PromiseResolver<void>();
|
||||
this._queue.push({ condition, resolver });
|
||||
return resolver.promise;
|
||||
}
|
||||
|
||||
public notifyOne() {
|
||||
const entry = this._queue.shift();
|
||||
if (entry) {
|
||||
if (entry.condition()) {
|
||||
entry.resolver.resolve();
|
||||
}
|
||||
} else {
|
||||
this._locked = false;
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
for (const item of this._queue) {
|
||||
item.resolver.reject(
|
||||
new Error("The ConditionalVariable has been disposed")
|
||||
);
|
||||
}
|
||||
this._queue.length = 0;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
export { decodeUtf8, encodeUtf8 } from '@yume-chan/struct';
|
||||
export * from './auto-reset-event.js';
|
||||
export * from './base64.js';
|
||||
export * from "./conditional-variable.js";
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// cspell: ignore systemui
|
||||
// cspell: ignore sysui
|
||||
|
||||
import { type Adb, AdbCommandBase } from "@yume-chan/adb";
|
||||
import { AdbCommandBase, type Adb } from "@yume-chan/adb";
|
||||
|
||||
import { Settings } from "./settings.js";
|
||||
|
||||
|
|
|
@ -2,9 +2,9 @@ import { type Adb } from "@yume-chan/adb";
|
|||
|
||||
import { type ScrcpyOptionsInit1_22 } from "../../options/index.js";
|
||||
import {
|
||||
type AdbScrcpyConnection,
|
||||
AdbScrcpyForwardConnection,
|
||||
AdbScrcpyReverseConnection,
|
||||
type AdbScrcpyConnection,
|
||||
} from "../connection.js";
|
||||
|
||||
import { AdbScrcpyOptions1_16 } from "./1_16.js";
|
||||
|
|
|
@ -18,8 +18,12 @@ export class BufferedReadableStream {
|
|||
private bufferedOffset = 0;
|
||||
private bufferedLength = 0;
|
||||
|
||||
protected readonly stream: ReadableStream<Uint8Array>;
|
||||
private _position = 0;
|
||||
public get position() {
|
||||
return this._position;
|
||||
}
|
||||
|
||||
protected readonly stream: ReadableStream<Uint8Array>;
|
||||
protected readonly reader: ReadableStreamDefaultReader<Uint8Array>;
|
||||
|
||||
public constructor(stream: ReadableStream<Uint8Array>) {
|
||||
|
@ -32,6 +36,7 @@ export class BufferedReadableStream {
|
|||
if (done) {
|
||||
throw new BufferedReadableStreamEndedError();
|
||||
}
|
||||
this._position += value.byteLength;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue