List contents of Flipper folder on Android

Summary:
Design doc: https://docs.google.com/document/d/1HLCFl46RfqG0o1mSt8SWrwf_HMfOCRg_oENioc1rkvQ/edit#

In later diffs, we'll start fetching the actual files as well. The list of available files itself might be useful already to see what we have in our folder on the device

Reviewed By: passy

Differential Revision: D40508960

fbshipit-source-id: 96193fef3fed64d509cd3397513ae3e94438ae22
This commit is contained in:
Andrey Goncharov
2022-10-25 05:31:48 -07:00
committed by Facebook GitHub Bot
parent 2db9bccf75
commit 480a3d26f0
5 changed files with 84 additions and 9 deletions

View File

@@ -0,0 +1,14 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {DeviceDebugData} from 'flipper-common';
export interface DebuggableDevice {
readFlipperFolderForAllApps(): Promise<DeviceDebugData[]>;
}

View File

@@ -7,10 +7,10 @@
* @format
*/
import adb, {Client as ADBClient, PullTransfer} from 'adbkit';
import adb, {util, Client as ADBClient, PullTransfer} from 'adbkit';
import {Reader} from 'adbkit-logcat';
import {createWriteStream} from 'fs';
import type {DeviceType} from 'flipper-common';
import type {DeviceDebugData, DeviceType} from 'flipper-common';
import {spawn} from 'child_process';
import {dirname, join} from 'path';
import {DeviceSpec} from 'flipper-common';
@@ -18,10 +18,15 @@ import {ServerDevice} from '../ServerDevice';
import {FlipperServerImpl} from '../../FlipperServerImpl';
import {AndroidCrashWatcher} from './AndroidCrashUtils';
import {AndroidLogListener} from './AndroidLogListener';
import {DebuggableDevice} from '../DebuggableDevice';
import {executeCommandAsApp} from './androidContainerUtility';
const DEVICE_RECORDING_DIR = '/sdcard/flipper_recorder';
export default class AndroidDevice extends ServerDevice {
export default class AndroidDevice
extends ServerDevice
implements DebuggableDevice
{
adb: ADBClient;
pidAppMapping: {[key: number]: string} = {};
private recordingProcess?: Promise<string>;
@@ -279,6 +284,53 @@ export default class AndroidDevice extends ServerDevice {
console.log(`Installing app with adb ${apkPath}`);
await this.adb.install(this.serial, apkPath);
}
async readFlipperFolderForAllApps(): Promise<DeviceDebugData[]> {
console.debug(
'AndroidDevice.readFlipperFolderForAllApps',
this.info.serial,
);
const output = await this.adb
.shell(this.info.serial, 'pm list packages -3 -e')
.then(util.readAll)
.then((buffer) => buffer.toString());
const appIds = output
.split('\n')
// Last each appId has \n at the end. The last appId also has it.
// As a result, there is an "" (empty string) item at the end after the split.
.filter((appId) => appId !== '')
// Cut off the "package:" prefix
.map((appIdRaw) => appIdRaw.substring('package:'.length));
console.debug(
'AndroidDevice.readFlipperFolderForAllApps -> found apps',
this.info.serial,
appIds,
);
const appsCommandsResults = await Promise.all(
appIds.map(async (appId): Promise<DeviceDebugData> => {
const singleAppCommandResults = await Promise.all([
executeCommandAsApp(
this.adb,
this.info.serial,
appId,
`ls -al /data/data/${appId}/files/sonar`,
).then((output): DeviceDebugData['data'][0] => ({
command: `ls -al /data/data/${appId}/files/sonar`,
result: output,
})),
]);
return {
serial: this.info.serial,
appId,
data: singleAppCommandResults,
};
}),
);
return appsCommandsResults;
}
}
export async function launchEmulator(

View File

@@ -120,7 +120,7 @@ function _pull(
}
// Keep this method private since it relies on pre-validated arguments
function executeCommandAsApp(
export function executeCommandAsApp(
client: Client,
deviceId: string,
app: string,