Repository: beeware/briefcase
Pull request #433 (2020-06-25 00:35:29)

Rely on Android device model, in device list
Example output:

When emulator is running:

```
$ briefcase run android

Select device:

  1) @beePhone (Android SDK built for x86 emulator)
  2) Pixel 3a (94AAY0LNE1)
  3) Create a new Android emulator

> 
```

When emulator is not running:

```
Select device:

  1) Pixel 3a (94AAY0LNE1)
  2) @beePhone (emulator)
  3) Create a new Android emulator

> 
```

You had mentioned that "Android_SDK_built_for_x86" wasn't necessarily useful. IMHO it is -- it could be e.g. a x86_64 emulator instead of an x86 one.

Let's use this PR to get the output exactly right. Code refactoring can wait IMHO.


Patch:
diff --git a/changes/433.feature.rst b/changes/433.feature.rst
new file mode 100644
index 00000000..f728b62a
--- /dev/null
+++ b/changes/433.feature.rst
@@ -0,0 +1,3 @@
+The device list returned by ``briefcase run android`` now uses the Android
+device model name and unique ID e.g. a Pixel 3a shows up as ``Pixel 3a
+(adbDeviceId)``.
diff --git a/src/briefcase/integrations/android_sdk.py b/src/briefcase/integrations/android_sdk.py
index 11f4b95e..c0ae2e1f 100644
--- a/src/briefcase/integrations/android_sdk.py
+++ b/src/briefcase/integrations/android_sdk.py
@@ -320,7 +320,7 @@ class AndroidSDK:
                         details[key] = value
 
                     if parts[1] == "device":
-                        name = details["device"]
+                        name = details["model"].replace("_", " ")
                         authorized = True
                     elif parts[1] == "offline":
                         name = "Unknown device (offline)"
@@ -377,8 +377,8 @@ class AndroidSDK:
             if avd:
                 # It's a running emulator
                 running_avds[avd] = d
-                full_name = "@{avd} ({name} emulator)".format(
-                    avd=avd, name=name,
+                full_name = "@{avd} (running emulator)".format(
+                    avd=avd,
                 )
                 choices.append((d, full_name))
 
@@ -390,8 +390,9 @@ class AndroidSDK:
                 device_choices["@" + avd] = full_name
             else:
                 # It's a physical device (might be disabled)
-                choices.append((d, name))
-                device_choices[d] = name
+                full_name = "{name} ({d})".format(name=name, d=d)
+                choices.append((d, full_name))
+                device_choices[d] = full_name
 
         # Add any non-running emulator AVDs to the list of candidate devices
         for avd in self.emulators():
@@ -687,9 +688,8 @@ find this page helpful in diagnosing emulator problems.
                         if device_avd == avd:
                             # Found an active device that matches
                             # the AVD we are starting.
-                            name = details["name"]
-                            full_name = "@{avd} ({name} emulator)".format(
-                                avd=avd, name=name,
+                            full_name = "@{avd} (running emulator)".format(
+                                avd=avd,
                             )
                             break
                         else:


Test patch:
diff --git a/tests/integrations/android_sdk/AndroidSDK/test_devices.py b/tests/integrations/android_sdk/AndroidSDK/test_devices.py
index b1781a3c..3454428e 100644
--- a/tests/integrations/android_sdk/AndroidSDK/test_devices.py
+++ b/tests/integrations/android_sdk/AndroidSDK/test_devices.py
@@ -26,7 +26,7 @@ def test_one_emulator(mock_sdk):
 
     assert mock_sdk.devices() == {
         'emulator-5554': {
-            'name': 'generic_x86',
+            'name': 'Android SDK built for x86',
             'authorized': True,
         },
     }
@@ -42,11 +42,11 @@ def test_multiple_devices(mock_sdk):
             'authorized': False,
         },
         'KABCDABCDA1513': {
-            'name': 'Kogan_Agora_9',
+            'name': 'Kogan Agora 9',
             'authorized': True,
         },
         'emulator-5554': {
-            'name': 'generic_x86',
+            'name': 'Android SDK built for x86',
             'authorized': True,
         },
         'emulator-5556': {
diff --git a/tests/integrations/android_sdk/AndroidSDK/test_select_target_device.py b/tests/integrations/android_sdk/AndroidSDK/test_select_target_device.py
index 9821f4bb..eede01f2 100644
--- a/tests/integrations/android_sdk/AndroidSDK/test_select_target_device.py
+++ b/tests/integrations/android_sdk/AndroidSDK/test_select_target_device.py
@@ -23,11 +23,11 @@ def mock_sdk(tmp_path):
             'authorized': False,
         },
         'KABCDABCDA1513': {
-            'name': 'Kogan_Agora_9',
+            'name': 'Kogan Agora 9',
             'authorized': True,
         },
         'emulator-5554': {
-            'name': 'generic_x86',
+            'name': 'Android SDK built for x86',
             'authorized': True,
         },
     })
@@ -59,7 +59,7 @@ def test_explicit_device(mock_sdk):
 
     # Physical running device, so no AVD
     assert device == 'KABCDABCDA1513'
-    assert name == 'Kogan_Agora_9'
+    assert name == 'Kogan Agora 9 (KABCDABCDA1513)'
     assert avd is None
 
     # No input was requested
@@ -85,7 +85,7 @@ def test_explicit_running_emulator_by_id(mock_sdk):
 
     # Emulator is running, so there is a device ID
     assert device == 'emulator-5554'
-    assert name == '@runningEmulator (generic_x86 emulator)'
+    assert name == '@runningEmulator (running emulator)'
     assert avd == "runningEmulator"
 
     # No input was requested
@@ -100,7 +100,7 @@ def test_explicit_running_emulator_by_avd(mock_sdk):
 
     # Emulator is running, so there is a device ID
     assert device == 'emulator-5554'
-    assert name == '@runningEmulator (generic_x86 emulator)'
+    assert name == '@runningEmulator (running emulator)'
     assert avd == "runningEmulator"
 
     # No input was requested
@@ -147,14 +147,14 @@ def test_explicit_invalid_avd(mock_sdk):
 def test_select_device(mock_sdk, capsys):
     "If the user manually selects a physical device, details are returned"
     # Mock the user input
-    mock_sdk.command.input.values = ["1"]
+    mock_sdk.command.input.values = ["2"]
 
     # Run the selection with no pre-existing choice
     device, name, avd = mock_sdk.select_target_device(None)
 
     # Physical running device, so no AVD
     assert device == 'KABCDABCDA1513'
-    assert name == 'Kogan_Agora_9'
+    assert name == 'Kogan Agora 9 (KABCDABCDA1513)'
     assert avd is None
 
     # The user was asked to select a device
@@ -168,7 +168,7 @@ def test_select_device(mock_sdk, capsys):
 def test_select_unauthorized_device(mock_sdk):
     "If the user manually selects an unauthorized running device, an error is raised"
     # Mock the user input
-    mock_sdk.command.input.values = ['2']
+    mock_sdk.command.input.values = ['3']
 
     # Run the selection with no pre-existing choice
     with pytest.raises(AndroidDeviceNotAuthorized):
@@ -178,14 +178,14 @@ def test_select_unauthorized_device(mock_sdk):
 def test_select_running_emulator(mock_sdk, capsys):
     "If the user manually selects a running emulator, details are returned"
     # Mock the user input
-    mock_sdk.command.input.values = ['3']
+    mock_sdk.command.input.values = ['1']
 
     # Run the selection with no pre-existing choice
     device, name, avd = mock_sdk.select_target_device(None)
 
     # Emulator is running, so there is a device ID
     assert device == 'emulator-5554'
-    assert name == '@runningEmulator (generic_x86 emulator)'
+    assert name == '@runningEmulator (running emulator)'
     assert avd == "runningEmulator"
 
     # A re-run prompt has been provided
@@ -268,7 +268,7 @@ def test_input_disabled_one_device(mock_sdk):
     # Set up a single device.
     mock_sdk.devices = MagicMock(return_value={
         'KABCDABCDA1513': {
-            'name': 'Kogan_Agora_9',
+            'name': 'Kogan Agora 9',
             'authorized': True,
         },
     })
@@ -279,7 +279,7 @@ def test_input_disabled_one_device(mock_sdk):
 
     # The only device is returned
     assert device == 'KABCDABCDA1513'
-    assert name == "Kogan_Agora_9"
+    assert name == "Kogan Agora 9 (KABCDABCDA1513)"
     assert avd is None
 
     # No input was requested
diff --git a/tests/integrations/android_sdk/AndroidSDK/test_start_emulator.py b/tests/integrations/android_sdk/AndroidSDK/test_start_emulator.py
index 4e6595af..af31a748 100644
--- a/tests/integrations/android_sdk/AndroidSDK/test_start_emulator.py
+++ b/tests/integrations/android_sdk/AndroidSDK/test_start_emulator.py
@@ -52,11 +52,11 @@ def test_start_emulator(mock_sdk):
             'authorized': False,
         },
         'KABCDABCDA1513': {
-            'name': 'Kogan_Agora_9',
+            'name': 'Kogan Agora 9',
             'authorized': True,
         },
         'emulator-5554': {
-            'name': 'generic_x86',
+            'name': 'Android SDK built for x86',
             'authorized': True,
         },
     }
@@ -99,7 +99,7 @@ def test_start_emulator(mock_sdk):
 
     # The device details are as expected
     assert device == 'emulator-5556'
-    assert name == '@idleEmulator (generic_x86 emulator)'
+    assert name == '@idleEmulator (running emulator)'
 
     # The process was started.
     mock_sdk.command.subprocess.Popen.assert_called_with(
@@ -141,11 +141,11 @@ def test_emulator_fail_to_start(mock_sdk):
             'authorized': False,
         },
         'KABCDABCDA1513': {
-            'name': 'Kogan_Agora_9',
+            'name': 'Kogan Agora 9',
             'authorized': True,
         },
         'emulator-5554': {
-            'name': 'generic_x86',
+            'name': 'Android SDK built for x86',
             'authorized': True,
         },
     }
@@ -224,11 +224,11 @@ def test_emulator_fail_to_boot(mock_sdk):
             'authorized': False,
         },
         'KABCDABCDA1513': {
-            'name': 'Kogan_Agora_9',
+            'name': 'Kogan Agora 9',
             'authorized': True,
         },
         'emulator-5554': {
-            'name': 'generic_x86',
+            'name': 'Android SDK built for x86',
             'authorized': True,
         },
     }
@@ -239,7 +239,7 @@ def test_emulator_fail_to_boot(mock_sdk):
     }
     devices_4 = devices.copy()
     devices_4['emulator-5556'] = {
-        'name': 'generic_x86',
+        'name': 'Android SDK built for x86',
         'authorized': True,
     }