diff --git a/src/devices/AndroidDevice.tsx b/src/devices/AndroidDevice.tsx index 0da485cef..a46724bba 100644 --- a/src/devices/AndroidDevice.tsx +++ b/src/devices/AndroidDevice.tsx @@ -6,14 +6,13 @@ */ import BaseDevice, {DeviceType, DeviceShell, LogLevel} from './BaseDevice'; -import adb from 'adbkit-fb'; +import adb, {Client as ADBClient} from 'adbkit-fb'; import {Priority} from 'adbkit-logcat-fb'; import child_process from 'child_process'; import {spawn} from 'promisify-child-process'; import ArchivedDevice from './ArchivedDevice'; import {createWriteStream} from 'fs'; -type ADBClient = any; const DEVICE_RECORDING_DIR = '/sdcard/flipper_recorder'; export default class AndroidDevice extends BaseDevice { @@ -26,8 +25,8 @@ export default class AndroidDevice extends BaseDevice { super(serial, deviceType, title, 'Android'); this.adb = adb; this.icon = 'icons/android.svg'; - this.adb.openLogcat(this.serial).then((reader: any) => { - reader.on('entry', (entry: any) => { + this.adb.openLogcat(this.serial).then(reader => { + reader.on('entry', entry => { let type: LogLevel = 'unknown'; if (entry.priority === Priority.VERBOSE) { type = 'verbose'; @@ -62,7 +61,6 @@ export default class AndroidDevice extends BaseDevice { adb: ADBClient; pidAppMapping: {[key: number]: string} = {}; - logReader: any; private recordingDestination?: string; supportedColumns(): Array { @@ -105,7 +103,7 @@ export default class AndroidDevice extends BaseDevice { screenshot(): Promise { return new Promise((resolve, reject) => { - this.adb.screencap(this.serial).then((stream: NodeJS.WriteStream) => { + this.adb.screencap(this.serial).then(stream => { const chunks: Array = []; stream .on('data', (chunk: Buffer) => chunks.push(chunk)) @@ -149,13 +147,11 @@ export default class AndroidDevice extends BaseDevice { .then( () => new Promise((resolve, reject) => - this.adb - .pull(this.serial, recordingLocation) - .then((stream: NodeJS.WriteStream) => { - stream.on('end', resolve); - stream.on('error', reject); - stream.pipe(createWriteStream(destination)); - }), + this.adb.pull(this.serial, recordingLocation).then(stream => { + stream.on('end', resolve); + stream.on('error', reject); + stream.pipe(createWriteStream(destination)); + }), ), ); } diff --git a/src/dispatcher/androidDevice.tsx b/src/dispatcher/androidDevice.tsx index 819fc41c1..7ea023f3b 100644 --- a/src/dispatcher/androidDevice.tsx +++ b/src/dispatcher/androidDevice.tsx @@ -15,43 +15,36 @@ import {getAdbClient} from '../utils/adbClient'; import {default as which} from 'which'; import {promisify} from 'util'; import {ServerPorts} from '../reducers/application'; -import {EventEmitter} from 'events'; +import {Client as ADBClient} from 'adbkit-fb'; function createDevice( - adbClient: any, + adbClient: ADBClient, device: any, ports?: ServerPorts, ): Promise { - return new Promise((resolve, reject) => { + return new Promise(resolve => { const type = device.type !== 'device' || device.id.startsWith('emulator') ? 'emulator' : 'physical'; - adbClient - .getProperties(device.id) - .then(async (props: {[key: string]: string}) => { - let name = props['ro.product.model']; - if (type === 'emulator') { - name = (await getRunningEmulatorName(device.id)) || name; - } - const androidDevice = new AndroidDevice( - device.id, - type, - name, - adbClient, - ); - if (ports) { - androidDevice.reverse([ports.secure, ports.insecure]); - } - resolve(androidDevice); - }); + adbClient.getProperties(device.id).then(async props => { + let name = props['ro.product.model']; + if (type === 'emulator') { + name = (await getRunningEmulatorName(device.id)) || name; + } + const androidDevice = new AndroidDevice(device.id, type, name, adbClient); + if (ports) { + androidDevice.reverse([ports.secure, ports.insecure]); + } + resolve(androidDevice); + }); }); } export async function getActiveAndroidDevices(): Promise> { const client = await getAdbClient(); - const androidDevices: Array = await client.listDevices(); + const androidDevices = await client.listDevices(); return await Promise.all( androidDevices.map(device => createDevice(client, device)), ); @@ -85,7 +78,7 @@ export default (store: Store, logger: Logger) => { const watchAndroidDevices = () => { // get emulators promisify(which)('emulator') - .catch(e => `${process.env.ANDROID_HOME || ''}/tools/emulator`) + .catch(() => `${process.env.ANDROID_HOME || ''}/tools/emulator`) .then(emulatorPath => { child_process.exec( `${emulatorPath} -list-avds`, @@ -107,7 +100,7 @@ export default (store: Store, logger: Logger) => { .then(client => { client .trackDevices() - .then((tracker: EventEmitter) => { + .then(tracker => { tracker.on('error', err => { if (err.message === 'Connection closed') { // adb server has shutdown, remove all android devices diff --git a/src/utils/CertificateProvider.tsx b/src/utils/CertificateProvider.tsx index 94111d5ed..dae268c92 100644 --- a/src/utils/CertificateProvider.tsx +++ b/src/utils/CertificateProvider.tsx @@ -20,6 +20,7 @@ import {reportPlatformFailures} from './metrics'; import {getAdbClient} from './adbClient'; import * as androidUtil from './androidContainerUtility'; import os from 'os'; +import {Client as ADBClient} from 'adbkit-fb'; const tmpFile = promisify(tmp.file) as ( options?: FileOptions, @@ -72,7 +73,7 @@ export type SecureServerConfig = { */ export default class CertificateProvider { logger: Logger; - adb: Promise; + adb: Promise; certificateSetup: Promise; server: Server; @@ -260,7 +261,7 @@ export default class CertificateProvider { ): Promise { return this.adb .then(client => client.listDevices()) - .then((devices: Array<{id: string}>) => { + .then(devices => { if (devices.length === 0) { throw new Error('No Android devices found'); } diff --git a/src/utils/adbClient.tsx b/src/utils/adbClient.tsx index 12f7f2d10..34d2395c8 100644 --- a/src/utils/adbClient.tsx +++ b/src/utils/adbClient.tsx @@ -14,7 +14,7 @@ import adbkit, {Client} from 'adbkit-fb'; const MAX_RETRIES = 5; let instance: Promise; -export function getAdbClient(): Promise { +export function getAdbClient(): Promise { if (!instance) { instance = reportPlatformFailures(createClient(), 'createADBClient'); } diff --git a/src/utils/androidContainerUtilityInternal.tsx b/src/utils/androidContainerUtilityInternal.tsx index 07d2d6d43..f634852ef 100644 --- a/src/utils/androidContainerUtilityInternal.tsx +++ b/src/utils/androidContainerUtilityInternal.tsx @@ -12,7 +12,7 @@ */ import {getAdbClient} from './adbClient'; import {UnsupportedError} from './metrics'; -const adbkit = require('adbkit-fb'); +import adbkit from 'adbkit-fb'; const allowedAppNameRegex = /^[a-zA-Z0-9._\-]+$/; const appNotDebuggableRegex = /debuggable/; diff --git a/types/adbkit-fb.d.tsx b/types/adbkit-fb.d.tsx index aa76d3dce..e0119f91a 100644 --- a/types/adbkit-fb.d.tsx +++ b/types/adbkit-fb.d.tsx @@ -14,11 +14,58 @@ interface Util { readAll: (stream: NodeJS.ReadStream) => Promise; } +// https://github.com/openstf/adbkit#pulltransfer +interface PullTransfer extends NodeJS.WriteStream { + cancel: () => this; + on( + event: 'progress', + listener: (stats: {bytesTransferred: number}) => void, + ): this; + on(event: 'error', listener: (err: Error) => void): this; + on(event: 'end', listener: () => void): this; +} + +interface DeviceTracker extends NodeJS.EventEmitter { + on(event: 'add', listener: (device: Device) => void): this; + on(event: 'remove', listener: (device: Device) => void): this; + on(event: 'change', listener: (device: Device) => void): this; + on( + event: 'changeSet', + listener: (changes: { + added: Device[]; + removed: Device[]; + changed: Device[]; + }) => void, + ): this; + on(event: 'error', listener: (err: Error) => void): this; + on(event: 'end', listener: () => void): this; +} + declare module 'adbkit-fb' { const util: Util; const adbkit: any; export interface Client { listDevices: () => Promise; + reverse: ( + serial: string, + remote: string, + local: string, + ) => Promise; + shell: ( + serial: string, + command: string | string[], + ) => Promise; + screencap: (serial: string) => Promise; + pull: (serial: string, path: string) => Promise; + openLogcat: ( + serial: string, + options?: { + clear?: boolean; + }, + ) => Promise; + getProperties: (serial: string) => Promise<{[key: string]: string}>; + trackDevices: () => Promise; + kill: () => Promise; } export function createClient(config: {port: number; host: string}): Client; } diff --git a/types/adbkit-logcat-fb.d.ts b/types/adbkit-logcat-fb.d.ts deleted file mode 100644 index bae4c5e8b..000000000 --- a/types/adbkit-logcat-fb.d.ts +++ /dev/null @@ -1,127 +0,0 @@ -/** - * Copyright 2018-present Facebook. - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * @format - */ - -// This module declaration is a stub! -// Please extend this as needed. - -declare module 'adbkit-logcat-fb' { - class Reader { - constructor(options: any); - - connect(stream: any): any; - - end(): any; - - exclude(tag: any): any; - - excludeAll(): any; - - include(tag: any, priority: any): any; - - includeAll(priority: any): any; - - resetFilters(): any; - - static ANY: string; - - static defaultMaxListeners: number; - - static init(): void; - - static listenerCount(emitter: any, type: any): any; - - static once(emitter: any, name: any): any; - - static usingDomains: boolean; - - } - - function Priority(): void; - - function readStream(stream: any, options: any): any; - - namespace Priority { - const DEBUG: number; - - const DEFAULT: number; - - const ERROR: number; - - const FATAL: number; - - const INFO: number; - - const SILENT: number; - - const UNKNOWN: number; - - const VERBOSE: number; - - const WARN: number; - - function fromLetter(letter: any): any; - - function fromName(name: any): any; - - function toLetter(value: any): any; - - function toName(value: any): any; - - } - - namespace Reader { - class EventEmitter { - constructor(); - - addListener(type: any, listener: any): any; - - emit(type: any, args: any): any; - - eventNames(): any; - - getMaxListeners(): any; - - listenerCount(type: any): any; - - listeners(type: any): any; - - off(type: any, listener: any): any; - - on(type: any, listener: any): any; - - once(type: any, listener: any): any; - - prependListener(type: any, listener: any): any; - - prependOnceListener(type: any, listener: any): any; - - rawListeners(type: any): any; - - removeAllListeners(type: any, ...args: any[]): any; - - removeListener(type: any, listener: any): any; - - setMaxListeners(n: any): any; - - static EventEmitter: any; - - static defaultMaxListeners: number; - - static init(): void; - - static listenerCount(emitter: any, type: any): any; - - static once(emitter: any, name: any): any; - - static usingDomains: boolean; - - } - - } - -} - diff --git a/types/adbkit-logcat-fb.d.tsx b/types/adbkit-logcat-fb.d.tsx new file mode 100644 index 000000000..e08844cca --- /dev/null +++ b/types/adbkit-logcat-fb.d.tsx @@ -0,0 +1,66 @@ +/** + * Copyright 2018-present Facebook. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * @format + */ + +// This module declaration is a stub! +// Please extend this as needed. + +declare module 'adbkit-logcat-fb' { + type PriorityValue = number; + + interface Reader extends NodeJS.EventEmitter { + connect(stream: NodeJS.WriteStream): this; + end(): this; + exclude(tag: string): this; + excludeAll(): this; + include(tag: string, priority?: PriorityValue): this; + includeAll(priority?: PriorityValue): this; + resetFilters(): this; + + on(event: 'error', listener: (err: Error) => void): this; + on(event: 'end', listener: () => void): this; + on(event: 'finish', listener: () => void): this; + on(event: 'entry', listener: (entry: Entry) => void): this; + } + + interface Entry { + date: Date; + pid: number; + tid: number; + priority: PriorityValue; + tag: string; + message: string; + toBinary(): Buffer; + } + + interface Priority { + DEBUG: PriorityValue; + DEFAULT: PriorityValue; + ERROR: PriorityValue; + FATAL: PriorityValue; + INFO: PriorityValue; + SILENT: PriorityValue; + UNKNOWN: PriorityValue; + VERBOSE: PriorityValue; + WARN: PriorityValue; + + fromLetter(letter: string): PriorityValue | undefined; + fromName(name: string): PriorityValue | undefined; + toLetter(value: PriorityValue): string; + toName(value: PriorityValue): string; + } + + function readStream( + stream: NodeJS.WriteStream, + options?: { + format: 'binary'; + fixLineFeeds: boolean; + }, + ): Reader; + + const Priority: Priority; + const Reader: Reader; +}