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