1import { assertSdkRoot } from './AndroidSdk'; 2import { adbArgs, Device, getAttachedDevicesAsync, getServer, logUnauthorized } from './adb'; 3import * as Log from '../../../log'; 4import { installExitHooks } from '../../../utils/exit'; 5 6const debug = require('debug')('expo:start:platforms:android:adbReverse') as typeof console.log; 7 8let removeExitHook: (() => void) | null = null; 9 10export function hasAdbReverseAsync(): boolean { 11 try { 12 return !!assertSdkRoot(); 13 } catch (error: any) { 14 debug('Failed to resolve the Android SDK path, skipping ADB: %s', error.message); 15 return false; 16 } 17} 18 19export async function startAdbReverseAsync(ports: number[]): Promise<boolean> { 20 // Install cleanup automatically... 21 removeExitHook = installExitHooks(() => { 22 stopAdbReverseAsync(ports); 23 }); 24 25 const devices = await getAttachedDevicesAsync(); 26 for (const device of devices) { 27 for (const port of ports) { 28 if (!(await adbReverseAsync(device, port))) { 29 debug(`Failed to start reverse port ${port} on device "${device.name}"`); 30 return false; 31 } 32 } 33 } 34 return true; 35} 36 37export async function stopAdbReverseAsync(ports: number[]): Promise<void> { 38 removeExitHook?.(); 39 40 const devices = await getAttachedDevicesAsync(); 41 for (const device of devices) { 42 for (const port of ports) { 43 await adbReverseRemoveAsync(device, port); 44 } 45 } 46} 47 48async function adbReverseAsync(device: Device, port: number): Promise<boolean> { 49 if (!device.isAuthorized) { 50 logUnauthorized(device); 51 return false; 52 } 53 54 try { 55 await getServer().runAsync(adbArgs(device.pid, 'reverse', `tcp:${port}`, `tcp:${port}`)); 56 return true; 57 } catch (error: any) { 58 Log.warn(`[ADB] Couldn't reverse port ${port}: ${error.message}`); 59 return false; 60 } 61} 62 63async function adbReverseRemoveAsync(device: Device, port: number): Promise<boolean> { 64 if (!device.isAuthorized) { 65 return false; 66 } 67 68 try { 69 await getServer().runAsync(adbArgs(device.pid, 'reverse', '--remove', `tcp:${port}`)); 70 return true; 71 } catch (error: any) { 72 // Don't send this to warn because we call this preemptively sometimes 73 debug(`Could not unforward port ${port}: ${error.message}`); 74 return false; 75 } 76} 77