1import * as osascript from '@expo/osascript'; 2import { execFileSync } from 'child_process'; 3 4import * as Log from '../../../log'; 5import { Device } from './adb'; 6 7function getUnixPID(port: number | string): string { 8 // Runs like `lsof -i:8081 -P -t -sTCP:LISTEN` 9 const args = [`-i:${port}`, '-P', '-t', '-sTCP:LISTEN']; 10 Log.debug('lsof ' + args.join(' ')); 11 return execFileSync('lsof', args, { 12 encoding: 'utf8', 13 stdio: ['pipe', 'pipe', 'ignore'], 14 }) 15 .split('\n')[0] 16 ?.trim?.(); 17} 18 19/** Activate the Emulator window on macOS. */ 20export async function activateWindowAsync(device: Pick<Device, 'type' | 'pid'>): Promise<boolean> { 21 if ( 22 // only mac is supported for now. 23 process.platform !== 'darwin' || 24 // can only focus emulators 25 device.type !== 'emulator' 26 ) { 27 return false; 28 } 29 30 // Google Emulator ID: `emulator-5554` -> `5554` 31 const androidPid = device.pid!.match(/-(\d+)/)?.[1]; 32 if (!androidPid) { 33 return false; 34 } 35 // Unix PID 36 const pid = getUnixPID(androidPid); 37 38 if (!pid) { 39 return false; 40 } 41 try { 42 await osascript.execAsync(` 43 tell application "System Events" 44 set frontmost of the first process whose unix id is ${pid} to true 45 end tell`); 46 return true; 47 } catch { 48 // noop -- this feature is very specific and subject to failure. 49 return false; 50 } 51} 52