@@ -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,74 @@ 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 id , string model ) > GetDeviceToUse ( )
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
+ if ( questDevices . Count > 1 )
247
+ {
248
+ Log . Warning ( "Multiple quest devices connected - using the first device" ) ;
249
+ }
250
+
251
+ return questDevices . First ( ) ;
252
+ }
253
+ else
254
+ {
255
+ return devices . First ( ) ;
256
+ }
257
+
258
+ }
259
+
190
260
private async Task < bool > FindExistingAdbServer ( )
191
261
{
192
262
_lastDaemonCheck = DateTime . Now ;
@@ -255,7 +325,7 @@ public async Task<ProcessOutput> RunCommand(string command, params int[] allowed
255
325
Log . Debug ( "Executing ADB command: {Command}" , $ "adb { command } ") ;
256
326
while ( true )
257
327
{
258
- var output = await ProcessUtil . InvokeAndCaptureOutput ( _adbPath , command ) ;
328
+ var output = await ProcessUtil . InvokeAndCaptureOutput ( _adbPath , _chosenDeviceId == null ? command : $ "-s { _chosenDeviceId } " + command ) ;
259
329
if ( output . StandardOutput . Length > 0 )
260
330
{
261
331
Log . Verbose ( "Standard output: {StandardOutput}" , output . StandardOutput ) ;
@@ -286,7 +356,11 @@ public async Task<ProcessOutput> RunCommand(string command, params int[] allowed
286
356
}
287
357
else if ( allOutput . Contains ( "multiple devices" ) || output . ErrorOutput . Contains ( "more than one device/emulator" ) )
288
358
{
289
- await _onDisconnect ( DisconnectionType . MultipleDevices ) ;
359
+ Log . Information ( "Multiple devices detected, choosing the Quest device if present" ) ;
360
+ var device = await GetDeviceToUse ( ) ;
361
+ _chosenDeviceId = device . id ;
362
+
363
+ Log . Information ( "Using id: {DeviceId} model: {Model}" , device . id , device . model ) ;
290
364
}
291
365
else if ( allOutput . Contains ( "unauthorized" ) )
292
366
{
0 commit comments