@@ -3,6 +3,7 @@ import * as path from 'path';
3
3
import * as adb from 'adbkit' ;
4
4
5
5
import { reportError } from '../../error-tracking' ;
6
+ import { delay } from '../../util' ;
6
7
7
8
export const ANDROID_TEMP = '/data/local/tmp' ;
8
9
export const SYSTEM_CA_PATH = '/system/etc/security/cacerts' ;
@@ -63,6 +64,15 @@ export const getConnectedDevices = batchCalls(async (adbClient: adb.AdbClient) =
63
64
}
64
65
} ) ;
65
66
67
+ async function waitUntilAvailable ( adbClient : adb . AdbClient , deviceId : string , tries : number ) {
68
+ while ( tries > 0 && ! ( await getConnectedDevices ( adbClient ) ) . includes ( deviceId ) ) {
69
+ tries = tries - 1 ;
70
+ await delay ( 500 ) ;
71
+ }
72
+
73
+ if ( tries <= 0 ) throw new Error ( `Device ${ deviceId } not available via ADB` ) ;
74
+ }
75
+
66
76
export function stringAsStream ( input : string ) {
67
77
const contentStream = new stream . Readable ( ) ;
68
78
contentStream . _read = ( ) => { } ;
@@ -116,7 +126,12 @@ export async function getRootCommand(adbClient: adb.AdbClient, deviceId: string)
116
126
// If no explicit root commands are available, try to restart adb in root
117
127
// mode instead. If this works, *all* commands will run as root.
118
128
// We prefer explicit "su" calls if possible, to limit access & side effects.
119
- await adbClient . root ( deviceId ) . catch ( ( ) => console . log ) ;
129
+ await adbClient . root ( deviceId ) . catch ( console . log ) ;
130
+
131
+ // Sometimes switching to root can disconnect ADB devices, so double-check
132
+ // they're still here, and wait a few seconds for them to come back if not.
133
+ await waitUntilAvailable ( adbClient , deviceId , 10 ) ;
134
+
120
135
const whoami = await run ( adbClient , deviceId , [ 'whoami' ] ) . catch ( console . log ) ;
121
136
122
137
return ( whoami || '' ) . trim ( ) === 'root'
0 commit comments