@@ -83,6 +83,8 @@ public class AndroidDebugBridge
83
83
private DateTime _lastDaemonCheck ; // The last time at which QP checked for existing ADB daemons
84
84
private Process ? _logcatProcess ;
85
85
86
+ private string ? _chosenDeviceId ;
87
+
86
88
public AndroidDebugBridge ( ExternalFilesDownloader filesDownloader , Func < DisconnectionType , Task > onDisconnect )
87
89
{
88
90
_filesDownloader = filesDownloader ;
@@ -187,6 +189,76 @@ private async Task<bool> SetAdbPathIfValid(string adbExecutablePath)
187
189
}
188
190
}
189
191
192
+ /// <summary>
193
+ /// Lists the devices connected to ADB.
194
+ /// </summary>
195
+ /// <returns>A list of the ADB devices.</returns>
196
+ private async Task < List < ( string id , string model ) > > ListDevicesInternal ( )
197
+ {
198
+ var output = await ProcessUtil . InvokeAndCaptureOutput ( _adbExecutableName , "devices -l" ) ;
199
+ Log . Debug ( "Listing devices output {Output}" , output . AllOutput ) ;
200
+
201
+ string [ ] lines = output . StandardOutput . Trim ( ) . Split ( '\n ' ) ;
202
+
203
+ var devices = new List < ( string id , string model ) > ( ) ;
204
+ for ( int i = 1 ; i < lines . Length ; i ++ )
205
+ {
206
+ string line = lines [ i ] ;
207
+
208
+ var endIdIdx = line . IndexOf ( ' ' ) ;
209
+ if ( endIdIdx == - 1 )
210
+ {
211
+ continue ;
212
+ }
213
+
214
+ string id = line . Substring ( 0 , endIdIdx ) ;
215
+ int modelIdx = line . IndexOf ( "model:" ) ;
216
+ if ( modelIdx == - 1 )
217
+ {
218
+ continue ;
219
+ }
220
+
221
+ int endModelIdx = line . IndexOf ( ' ' , modelIdx ) ;
222
+ if ( endModelIdx == - 1 )
223
+ {
224
+ continue ;
225
+ }
226
+
227
+ string model = line . Substring ( modelIdx + 6 , endModelIdx - modelIdx - 6 ) ;
228
+
229
+ devices . Add ( ( id , model ) ) ;
230
+ }
231
+
232
+ return devices ;
233
+ }
234
+
235
+ /// <returns>The device ID of one of the Quest devices connected, or a non-quest device if no quest is present.</returns>
236
+ private async Task < string > GetDeviceIdToUse ( )
237
+ {
238
+ var devices = await ListDevicesInternal ( ) ;
239
+
240
+ var questDevices = devices
241
+ . Where ( device => device . id . Contains ( "quest" , StringComparison . OrdinalIgnoreCase ) )
242
+ . ToList ( ) ;
243
+
244
+ if ( questDevices . Any ( ) )
245
+ {
246
+ Log . Debug ( "Using quest device" ) ;
247
+ if ( questDevices . Count > 1 )
248
+ {
249
+ Log . Warning ( "Multiple quest devices connected - using the first device" ) ;
250
+ }
251
+
252
+ return questDevices . First ( ) . id ;
253
+ }
254
+ else
255
+ {
256
+ Log . Debug ( "Using non-quest device" ) ;
257
+ return devices . First ( ) . id ;
258
+ }
259
+
260
+ }
261
+
190
262
private async Task < bool > FindExistingAdbServer ( )
191
263
{
192
264
_lastDaemonCheck = DateTime . Now ;
@@ -255,7 +327,7 @@ public async Task<ProcessOutput> RunCommand(string command, params int[] allowed
255
327
Log . Debug ( "Executing ADB command: {Command}" , $ "adb { command } ") ;
256
328
while ( true )
257
329
{
258
- var output = await ProcessUtil . InvokeAndCaptureOutput ( _adbPath , command ) ;
330
+ var output = await ProcessUtil . InvokeAndCaptureOutput ( _adbPath , _chosenDeviceId == null ? command : $ "-s { _chosenDeviceId } " + command ) ;
259
331
if ( output . StandardOutput . Length > 0 )
260
332
{
261
333
Log . Verbose ( "Standard output: {StandardOutput}" , output . StandardOutput ) ;
@@ -286,7 +358,10 @@ public async Task<ProcessOutput> RunCommand(string command, params int[] allowed
286
358
}
287
359
else if ( allOutput . Contains ( "multiple devices" ) || output . ErrorOutput . Contains ( "more than one device/emulator" ) )
288
360
{
289
- await _onDisconnect ( DisconnectionType . MultipleDevices ) ;
361
+ Log . Information ( "Multiple devices detected, choosing the Quest device if present" ) ;
362
+ _chosenDeviceId = await GetDeviceIdToUse ( ) ;
363
+
364
+ Log . Information ( "Using {DeviceId}" , _chosenDeviceId ) ;
290
365
}
291
366
else if ( allOutput . Contains ( "unauthorized" ) )
292
367
{
0 commit comments