Configure common Fairphone Wi-Fi networks

Change-Id: I4819ad1a9e380297cb46584747e2381b4d40f65c
diff --git a/deploy.py b/deploy.py
index 437548d..f08920c 100755
--- a/deploy.py
+++ b/deploy.py
@@ -20,6 +20,14 @@
     'com.lunarlabs.panda.apk',
 ]
 
+FAIRPHONE_WIFI_NETWORKS = {
+    'Fairphone Guest': {'security': 'WPA/WPA2 PSK', 'password': 'fairwifi'},
+    'Fairphone DEV (2.4 GHz)': {
+        'security': 'WPA/WPA2 PSK', 'password': 'fdev@adm'},
+    'Fairphone DEV (5 GHz)': {
+        'security': 'WPA/WPA2 PSK', 'password': 'fdev@adm'},
+}
+
 
 class HostCommandError(BaseException):
     """An error happened while issuing a command on the host."""
@@ -210,6 +218,85 @@
     adb('install', '-r', path, serial=serial)
 
 
+def configure_wifi_networks(dut, networks):
+    """Configure Wi-Fi networks.
+
+        The `networks` parameters is a list of networks to configure hashed by
+        their SSID. Each network value should have the following format:
+          - security (str): The security value as can be found in the Wi-Fi
+            settings dialog. Common values are 'None' and 'WPA/WPA2 PSK'.
+          - password (str, optional): The network password if the security is
+            'WPA/WPA2 PSK'.
+
+        Parameters:
+            dut (Device): The device object.
+            networks (dict(dict(str))): The list of networks to configure.
+        Raises:
+            DeviceCommandError: If the UI automation fails.
+    """
+    # Open the Wi-Fi settings
+    adb('shell', ('am start -a android.settings.WIFI_SETTINGS '
+        '--activity-clear-task'), serial=dut.serial)
+
+    # Make sure Wi-Fi is enabled
+    wifi_enabler = dut(text='OFF',
+        resourceId='com.android.settings:id/switch_widget')
+    if wifi_enabler.exists:
+        wifi_enabler.click()
+
+    # Check for registered networks
+    registered_networks = set()
+    dut(description='More options').click()
+    time.sleep(1)
+    saved_networks = dut(text='Saved networks')
+    if saved_networks.exists:
+        saved_networks.click()
+        for ssid in networks.keys():
+            if dut(text=ssid).exists:
+                registered_networks.add(ssid)
+    dut.press.back()
+
+    missing_networks = networks.keys() - registered_networks
+
+    for ssid in registered_networks:
+        print('Ignoring `{}` Wi-Fi network, already configured.'.format(ssid))
+
+    for ssid in missing_networks:
+        print('Configuring `{}` Wi-Fi network…'.format(ssid))
+
+        dut(description='More options').click()
+        dut(text='Add network').click()
+        dut(resourceId='com.android.settings:id/ssid') \
+            .set_text(ssid)
+        dut(resourceId='com.android.settings:id/security') \
+            .click()
+        dut(text=networks[ssid]['security']) \
+            .click()
+        password_field = dut(resourceId='com.android.settings:id/password')
+        if 'password' in networks[ssid] and networks[ssid]['password']:
+            if not password_field.exists:
+                dut(text='Cancel').click()
+                raise DeviceCommandError(dut, 'UI: add Wi-Fi',
+                    'missing password field')
+            password_field.set_text(networks[ssid]['password'])
+        elif password_field.exists:
+            dut(text='Cancel').click()
+            raise DeviceCommandError(dut, 'UI: add Wi-Fi',
+                'missing password data')
+        save_button = dut(text='Save')
+        if not save_button.click():
+            dut(text='Cancel').click()
+            raise DeviceCommandError(dut, 'UI: add Wi-Fi',
+                'could not save network')
+
+    # Force the Wi-Fi on and off to pick the best network available
+    dut(text='ON', resourceId='com.android.settings:id/switch_widget').click()
+    dut(text='OFF', resourceId='com.android.settings:id/switch_widget').click()
+
+    # Leave the settings
+    dut.press.back()
+
+
 # Prepare the DUT
 def prepare_dut(serial, scenarios_dir, data_dir, prebuilts_dir):
     flavour = 'gms' if is_gms_device(serial) else 'sibon'
@@ -335,12 +422,17 @@
         print('Configuring device {}…'.format(serial))
 
         dut = Device(serial)
+        # Work around the not-so-easy Device class
+        dut.serial = serial
 
         try:
             # Make sure the screen stays on - we're going to use UI automation
             force_awake(serial)
             unlock(serial)
 
+            # Configure common Fairphone Wi-Fi networks
+            configure_wifi_networks(dut, FAIRPHONE_WIFI_NETWORKS)
+
             # Push the scenarios, their data, and install the apps
             prepare_dut(
                 serial, '../scenarios', '../scenarios-data', PREBUILTS_PATH)