Allow to start only one instance of log listener and crash watcher

Summary:
Changelog: Allow only a single crash watcher and a single log listener per device. Start log listener and crash watcher for every device upon connection. Remove commands to start/stop them externally.

Monitored CPU load for a physical Android device with the log listener on and off. Did not notice any real difference.

Resolved crashing adbkit-logcat by forcing the usage of 2.0.1. A proper fix would be to unify babel transforms for browser flipper and electron flipper, but we might re-think how we distribute flipper in the next half, so a simple hot fix might be a better use of time and resources.

Reviewed By: mweststrate

Differential Revision: D33132506

fbshipit-source-id: 39d422682a10a64830ac516e30f43f32f416819d
This commit is contained in:
Andrey Goncharov
2021-12-20 11:37:25 -08:00
committed by Facebook GitHub Bot
parent 731749b41f
commit debf872806
19 changed files with 838 additions and 424 deletions

View File

@@ -8,16 +8,17 @@
*/
import adb, {Client as ADBClient, PullTransfer} from 'adbkit';
import {Priority, Reader} from 'adbkit-logcat';
import {Reader} from 'adbkit-logcat';
import {createWriteStream} from 'fs';
import type {DeviceLogLevel, DeviceType} from 'flipper-common';
import type {DeviceType} from 'flipper-common';
import which from 'which';
import {spawn} from 'child_process';
import {dirname, join} from 'path';
import {DeviceSpec} from 'flipper-common';
import {ServerDevice} from '../ServerDevice';
import {FlipperServerImpl} from '../../FlipperServerImpl';
import {startAndroidCrashWatcher} from './AndroidCrashUtils';
import {AndroidCrashWatcher} from './AndroidCrashUtils';
import {AndroidLogListener} from './AndroidLogListener';
const DEVICE_RECORDING_DIR = '/sdcard/flipper_recorder';
@@ -26,6 +27,8 @@ export default class AndroidDevice extends ServerDevice {
pidAppMapping: {[key: number]: string} = {};
private recordingProcess?: Promise<string>;
reader?: Reader;
readonly logListener: AndroidLogListener;
readonly crashWatcher: AndroidCrashWatcher;
constructor(
flipperServer: FlipperServerImpl,
@@ -48,74 +51,30 @@ export default class AndroidDevice extends ServerDevice {
sdkVersion,
});
this.adb = adb;
}
// TODO: Prevent starting logging multiple times
startLogging() {
this.adb
.openLogcat(this.serial, {clear: true})
.then((reader) => {
this.reader = reader;
reader
.on('entry', (entry) => {
let type: DeviceLogLevel = 'unknown';
if (entry.priority === Priority.VERBOSE) {
type = 'verbose';
}
if (entry.priority === Priority.DEBUG) {
type = 'debug';
}
if (entry.priority === Priority.INFO) {
type = 'info';
}
if (entry.priority === Priority.WARN) {
type = 'warn';
}
if (entry.priority === Priority.ERROR) {
type = 'error';
}
if (entry.priority === Priority.FATAL) {
type = 'fatal';
}
this.addLogEntry({
tag: entry.tag,
pid: entry.pid,
tid: entry.tid,
message: entry.message,
date: entry.date,
type,
});
})
.on('end', () => {
if (this.reader) {
// logs didn't stop gracefully
setTimeout(() => {
if (this.connected) {
console.warn(
`Log stream broken: ${this.serial} - restarting`,
);
this.startLogging();
}
}, 100);
}
})
.on('error', (e) => {
console.warn('Failed to read from adb logcat: ', e);
});
})
.catch((e) => {
console.warn('Failed to open log stream: ', e);
});
}
stopLogging() {
this.reader?.end();
this.reader = undefined;
}
protected startCrashWatcherImpl(): () => void {
return startAndroidCrashWatcher(this);
this.logListener = new AndroidLogListener(
() => this.connected,
(logEntry) => this.addLogEntry(logEntry),
this.adb,
this.serial,
);
// It is OK not to await the start of the log listener. We just spawn it and handle errors internally.
this.logListener
.start()
.catch((e) =>
console.error('AndroidDevice.logListener.start -> unexpected error', e),
);
this.crashWatcher = new AndroidCrashWatcher(this);
// It is OK not to await the start of the crash watcher. We just spawn it and handle errors internally.
// Crash watcher depends on functioning log listener. It waits for its start internally.
this.crashWatcher
.start()
.catch((e) =>
console.error(
'AndroidDevice.crashWatcher.start -> unexpected error',
e,
),
);
}
reverse(ports: number[]): Promise<void> {