Add option to cold boot emulators

Summary: This is useful when your emulator freezes.

Reviewed By: mweststrate

Differential Revision: D25998579

fbshipit-source-id: 236c16c3008f0e33d62e4c486b5a04383b1a59ba
This commit is contained in:
John Knox
2021-01-25 08:55:03 -08:00
committed by Facebook GitHub Bot
parent d77940a839
commit 3e911c8288
3 changed files with 55 additions and 24 deletions

View File

@@ -202,16 +202,20 @@ export default class AndroidDevice extends BaseDevice {
} }
} }
export async function launchEmulator(name: string) { export async function launchEmulator(name: string, coldBoot: boolean = false) {
// On Linux, you must run the emulator from the directory it's in because // On Linux, you must run the emulator from the directory it's in because
// reasons ... // reasons ...
return which('emulator') return which('emulator')
.then((emulatorPath) => { .then((emulatorPath) => {
if (emulatorPath) { if (emulatorPath) {
const child = spawn(emulatorPath, [`@${name}`], { const child = spawn(
detached: true, emulatorPath,
cwd: dirname(emulatorPath), [`@${name}`, ...(coldBoot ? ['-no-snapshot-load'] : [])],
}); {
detached: true,
cwd: dirname(emulatorPath),
},
);
child.stderr.on('data', (data) => { child.stderr.on('data', (data) => {
console.error(`Android emulator error: ${data}`); console.error(`Android emulator error: ${data}`);
}); });

View File

@@ -8,8 +8,13 @@
*/ */
import React, {useEffect, useState} from 'react'; import React, {useEffect, useState} from 'react';
import {Modal, Button, message, Alert} from 'antd'; import {Modal, Button, message, Alert, Menu, Dropdown} from 'antd';
import {AndroidOutlined, AppleOutlined} from '@ant-design/icons'; import {
AppleOutlined,
PoweroffOutlined,
MoreOutlined,
AndroidOutlined,
} from '@ant-design/icons';
import {Store} from '../../reducers'; import {Store} from '../../reducers';
import {useStore} from '../../utils/useStore'; import {useStore} from '../../utils/useStore';
import {launchEmulator} from '../../devices/AndroidDevice'; import {launchEmulator} from '../../devices/AndroidDevice';
@@ -23,6 +28,8 @@ import {
import GK from '../../fb-stubs/GK'; import GK from '../../fb-stubs/GK';
import {JSEmulatorLauncherSheetSandy} from '../../chrome/JSEmulatorLauncherSheet'; import {JSEmulatorLauncherSheetSandy} from '../../chrome/JSEmulatorLauncherSheet';
const COLD_BOOT = 'cold-boot';
export function showEmulatorLauncher(store: Store) { export function showEmulatorLauncher(store: Store) {
renderReactRoot((unmount) => ( renderReactRoot((unmount) => (
<Provider store={store}> <Provider store={store}>
@@ -65,25 +72,45 @@ export const LaunchEmulatorDialog = withTrackingScope(
}, [iosEnabled, getSimulators]); }, [iosEnabled, getSimulators]);
const items = [ const items = [
...androidEmulators.map((name) => ( ...(androidEmulators.length > 0 ? [<AndroidOutlined />] : []),
<Button ...androidEmulators.map((name) => {
key={name} const launch = (coldBoot: boolean) => {
icon={<AndroidOutlined />} launchEmulator(name, coldBoot)
onClick={() => .catch((e) => {
launchEmulator(name) console.error(e);
.catch((e) => { message.error('Failed to start emulator: ' + e);
console.error(e); })
message.error('Failed to start emulator: ' + e); .then(onClose);
}) };
.then(onClose) const menu = (
}> <Menu
{name} onClick={({key}) => {
</Button> switch (key) {
)), case COLD_BOOT: {
launch(true);
break;
}
}
}}>
<Menu.Item key={COLD_BOOT} icon={<PoweroffOutlined />}>
Cold Boot
</Menu.Item>
</Menu>
);
return (
<Dropdown.Button
key={name}
overlay={menu}
icon={<MoreOutlined />}
onClick={() => launch(false)}>
{name}
</Dropdown.Button>
);
}),
...(iosEmulators.length > 0 ? [<AppleOutlined />] : []),
...iosEmulators.map((device) => ( ...iosEmulators.map((device) => (
<Button <Button
key={device.udid} key={device.udid}
icon={<AppleOutlined />}
onClick={() => onClick={() =>
launchSimulator(device.udid) launchSimulator(device.udid)
.catch((e) => { .catch((e) => {

View File

@@ -66,5 +66,5 @@ test('Can render and launch android apps', async () => {
fireEvent.click(renderer.getByText('emulator2')); fireEvent.click(renderer.getByText('emulator2'));
await sleep(1000); await sleep(1000);
expect(onClose).toBeCalled(); expect(onClose).toBeCalled();
expect(launchEmulator).toBeCalledWith('emulator2'); expect(launchEmulator).toBeCalledWith('emulator2', false);
}); });