18d307f52SEvan Baconimport * as osascript from '@expo/osascript'; 28d307f52SEvan Baconimport { execFileSync } from 'child_process'; 38d307f52SEvan Bacon 48d307f52SEvan Baconimport { Device } from './adb'; 58d307f52SEvan Bacon 6*474a7a4bSEvan Baconconst debug = require('debug')('expo:start:platforms:android:activateWindow') as typeof console.log; 7*474a7a4bSEvan Bacon 88d307f52SEvan Baconfunction getUnixPID(port: number | string): string { 98d307f52SEvan Bacon // Runs like `lsof -i:8081 -P -t -sTCP:LISTEN` 108d307f52SEvan Bacon const args = [`-i:${port}`, '-P', '-t', '-sTCP:LISTEN']; 11*474a7a4bSEvan Bacon debug('lsof ' + args.join(' ')); 128d307f52SEvan Bacon return execFileSync('lsof', args, { 138d307f52SEvan Bacon encoding: 'utf8', 148d307f52SEvan Bacon stdio: ['pipe', 'pipe', 'ignore'], 158d307f52SEvan Bacon }) 168d307f52SEvan Bacon .split('\n')[0] 178d307f52SEvan Bacon ?.trim?.(); 188d307f52SEvan Bacon} 198d307f52SEvan Bacon 208d307f52SEvan Bacon/** Activate the Emulator window on macOS. */ 218d307f52SEvan Baconexport async function activateWindowAsync(device: Pick<Device, 'type' | 'pid'>): Promise<boolean> { 22*474a7a4bSEvan Bacon debug(`Activating window for device (pid: ${device.pid}, type: ${device.type})`); 238d307f52SEvan Bacon if ( 248d307f52SEvan Bacon // only mac is supported for now. 258d307f52SEvan Bacon process.platform !== 'darwin' || 268d307f52SEvan Bacon // can only focus emulators 278d307f52SEvan Bacon device.type !== 'emulator' 288d307f52SEvan Bacon ) { 298d307f52SEvan Bacon return false; 308d307f52SEvan Bacon } 318d307f52SEvan Bacon 328d307f52SEvan Bacon // Google Emulator ID: `emulator-5554` -> `5554` 338d307f52SEvan Bacon const androidPid = device.pid!.match(/-(\d+)/)?.[1]; 348d307f52SEvan Bacon if (!androidPid) { 3529975bfdSEvan Bacon return false; 368d307f52SEvan Bacon } 378d307f52SEvan Bacon // Unix PID 388d307f52SEvan Bacon const pid = getUnixPID(androidPid); 398d307f52SEvan Bacon 408d307f52SEvan Bacon if (!pid) { 418d307f52SEvan Bacon return false; 428d307f52SEvan Bacon } 43*474a7a4bSEvan Bacon debug(`Activate window for pid:`, pid); 448d307f52SEvan Bacon try { 458d307f52SEvan Bacon await osascript.execAsync(` 468d307f52SEvan Bacon tell application "System Events" 478d307f52SEvan Bacon set frontmost of the first process whose unix id is ${pid} to true 488d307f52SEvan Bacon end tell`); 498d307f52SEvan Bacon return true; 508d307f52SEvan Bacon } catch { 518d307f52SEvan Bacon // noop -- this feature is very specific and subject to failure. 528d307f52SEvan Bacon return false; 538d307f52SEvan Bacon } 548d307f52SEvan Bacon} 55