Make sure disconnected devices / apps can be imported and exported

Summary:
It should be possible to exported disconnected devices, so that flipper traces / support form reports can be created from them. This diff introduces this functionality. Support for plugins with custom export logic is introduced in a later diff.

Issues fixed in this diff:
- don't try to take a screenshot for a disconnected device (this would hang forever)
- device plugins were always exported, regardless whether the user did select them or not
- sandy plugins were never part of exported disconnected clients
- increased the amount of data exported for device logs to ~10 MB. This makes more sense now as the logs will no longer be included in all cases
- fixed issue where are plugins would appear to be enabled after the client disconnected (this bug is the result of some unfortunate naming of `isArchived` vs `isConnected` semantics. Will clean up those names in a later diff.

Changelog: It is now possible to create a Flipper trace for disconnected devices and apps

Reviewed By: nikoant

Differential Revision: D26250894

fbshipit-source-id: 4dd0ec0cb152b1a8f649c31913e80efc25bcc5dd
This commit is contained in:
Michel Weststrate
2021-02-09 04:12:09 -08:00
committed by Facebook GitHub Bot
parent 8bc1b953c2
commit ff7997b3fa
11 changed files with 65 additions and 29 deletions

View File

@@ -93,7 +93,10 @@ export default class AndroidDevice extends BaseDevice {
this.adb.shell(this.serial, shellCommand);
}
screenshot(): Promise<Buffer> {
async screenshot(): Promise<Buffer> {
if (this.isArchived) {
return Buffer.from([]);
}
return new Promise((resolve, reject) => {
this.adb.screencap(this.serial).then((stream) => {
const chunks: Array<Buffer> = [];
@@ -108,6 +111,9 @@ export default class AndroidDevice extends BaseDevice {
}
async screenCaptureAvailable(): Promise<boolean> {
if (this.isArchived) {
return false;
}
try {
await this.executeShell(
`[ ! -f /system/bin/screenrecord ] && echo "File does not exist"`,

View File

@@ -99,11 +99,15 @@ export default class BaseDevice {
async exportState(
idler: Idler,
onStatusMessage: (msg: string) => void,
selectedPlugins: string[],
): Promise<Record<string, any>> {
const pluginStates: Record<string, any> = {};
for (const instance of this.sandyPluginStates.values()) {
if (instance.isPersistable()) {
if (
selectedPlugins.includes(instance.definition.id) &&
instance.isPersistable()
) {
pluginStates[instance.definition.id] = await instance.exportState(
idler,
onStatusMessage,

View File

@@ -52,7 +52,10 @@ export default class IOSDevice extends BaseDevice {
this.startLogListener();
}
screenshot(): Promise<Buffer> {
async screenshot(): Promise<Buffer> {
if (this.isArchived) {
return Buffer.from([]);
}
const tmpImageName = uuid() + '.png';
const tmpDirectory = (electron.app || electron.remote.app).getPath('temp');
const tmpFilePath = path.join(tmpDirectory, tmpImageName);
@@ -189,7 +192,7 @@ export default class IOSDevice extends BaseDevice {
}
async screenCaptureAvailable() {
return this.deviceType === 'emulator';
return this.deviceType === 'emulator' && !this.isArchived;
}
async startScreenCapture(destination: string) {