Apply the toolchain
Issue: INFRA-228
Change-Id: Ie271954879f0b8f645929f9dd6402a4742ef0135
diff --git a/deploy.py b/deploy.py
index a245d19..a0a0b98 100755
--- a/deploy.py
+++ b/deploy.py
@@ -1,62 +1,54 @@
#!/usr/bin/env python3
import os
-import time
-from uiautomator import Device
-import re
-import sys
-import subprocess
import pathlib
+import re
+import subprocess
+import sys
+import time
+
+from uiautomator import Device
+
+VWS_CREDENTIALS = {"user": "fairphonetesting@gmail.com", "password": "aish3echi:uwaiSh"}
-VWS_CREDENTIALS = {
- 'user': 'fairphonetesting@gmail.com',
- 'password': 'aish3echi:uwaiSh'
-}
+PREBUILTS_PATH = "../../vendor/smartviser/viser/prebuilts/apk"
+PREBUILT_PROXY_APK_PATTERN = "com.lunarlabs.panda.proxy-latest-sdk{sdk}-{flavour}.apk"
-PREBUILTS_PATH = '../../vendor/smartviser/viser/prebuilts/apk'
-
-PREBUILT_PROXY_APK_PATTERN = (
- 'com.lunarlabs.panda.proxy-latest-sdk{sdk}-{flavour}.apk')
-
-PREBUILT_APKS = [
- 'com.smartviser.demogame-latest.apk',
- 'com.lunarlabs.panda-latest.apk',
-]
+PREBUILT_APKS = ["com.smartviser.demogame-latest.apk", "com.lunarlabs.panda-latest.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'},
+ "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"},
}
-ADB_DEVICES_PATTERN = re.compile(r'^([a-z0-9-]+)\s+device$', flags=re.M)
+ADB_DEVICES_PATTERN = re.compile(r"^([a-z0-9-]+)\s+device$", flags=re.M)
class HostCommandError(BaseException):
"""An error happened while issuing a command on the host."""
+
def __init__(self, command, error_message):
self.command = command
self.error_message = error_message
- message = 'Command `{}` failed: {}'.format(command, error_message)
+ message = "Command `{}` failed: {}".format(command, error_message)
super(HostCommandError, self).__init__(message)
class DeviceCommandError(BaseException):
"""An error happened while sending a command to a device."""
+
def __init__(self, serial, command, error_message):
self.serial = serial
self.command = command
self.error_message = error_message
- message = 'Command `{}` failed on {}: {}'.format(
- command, serial, error_message)
+ message = "Command `{}` failed on {}: {}".format(command, serial, error_message)
super(DeviceCommandError, self).__init__(message)
-def adb(*args, serial = None, raise_on_error = True):
+def adb(*args, serial=None, raise_on_error=True):
"""Run ADB command attached to serial.
Example:
@@ -82,27 +74,28 @@
# Make sure the adb server is started to avoid the infamous "out of date"
# message that pollutes stdout.
ret = subprocess.run(
- ['adb', 'start-server'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- universal_newlines=True)
+ ["adb", "start-server"],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ universal_newlines=True,
+ )
if ret.returncode < 0:
if raise_on_error:
- raise DeviceCommandError(
- serial if serial else '??', str(args), ret.stderr)
+ raise DeviceCommandError(serial if serial else "??", str(args), ret.stderr)
else:
return None
- command = ['adb']
+ command = ["adb"]
if serial:
- command += ['-s', serial]
+ command += ["-s", serial]
if args:
command += list(args)
ret = subprocess.run(
- command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- universal_newlines=True)
+ command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True
+ )
if raise_on_error and ret.returncode < 0:
- raise DeviceCommandError(
- serial if serial else '??', str(args), ret.stderr)
+ raise DeviceCommandError(serial if serial else "??", str(args), ret.stderr)
return ret
@@ -113,11 +106,11 @@
Raises:
DeviceCommandError: If the underlying adb command failed.
"""
- process = adb('devices')
+ process = adb("devices")
return ADB_DEVICES_PATTERN.findall(process.stdout)
-def aapt(*args, raise_on_error = True):
+def aapt(*args, raise_on_error=True):
"""Run an AAPT command.
:param *args:
@@ -130,12 +123,12 @@
:raises HostCommandError:
If the command failed.
"""
- command = ['aapt']
+ command = ["aapt"]
if args:
command += list(args)
ret = subprocess.run(
- command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- universal_newlines=True)
+ command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True
+ )
if raise_on_error and ret.returncode < 0:
raise HostCommandError(str(args), ret.stderr)
@@ -149,8 +142,11 @@
Raises:
DeviceCommandError: If the underlying adb command failed.
"""
- adb('shell', 'svc power stayon {}'.format(
- 'true' if always else 'false'), serial=serial)
+ adb(
+ "shell",
+ "svc power stayon {}".format("true" if always else "false"),
+ serial=serial,
+ )
def unlock(dut):
@@ -159,15 +155,15 @@
Raises:
DeviceCommandError: If the underlying adb commands failed.
"""
- if not dut.info['screenOn']:
- adb('shell', 'input keyevent KEYCODE_POWER', serial=dut.serial)
+ if not dut.info["screenOn"]:
+ adb("shell", "input keyevent KEYCODE_POWER", serial=dut.serial)
time.sleep(1)
# The KEYCODE_MENU input is enough to unlock a "swipe up to unlock"
# lockscreen on Android 6, but unfortunately not Android 7. So we use a
# swipe up (that depends on the screen resolution) instead.
- adb('shell', 'input touchscreen swipe 930 880 930 380', serial=dut.serial)
+ adb("shell", "input touchscreen swipe 930 880 930 380", serial=dut.serial)
time.sleep(1)
- adb('shell', 'input keyevent KEYCODE_HOME', serial=dut.serial)
+ adb("shell", "input keyevent KEYCODE_HOME", serial=dut.serial)
def getprop(serial, key):
@@ -185,7 +181,7 @@
Value of system property.
:raise DeviceCommandError: If the underlying adb command failed.
"""
- process = adb('shell', 'getprop', key, serial=serial)
+ process = adb("shell", "getprop", key, serial=serial)
return process.stdout.strip()
@@ -202,9 +198,9 @@
True if device runs GMS, false otherwise.
:raise DeviceCommandError: If the underlying adb command failed.
"""
- return (
- getprop(serial, 'ro.build.id').startswith('FP2-gms-')
- or getprop(serial, 'ro.build.version.incremental').startswith('gms-'))
+ return getprop(serial, "ro.build.id").startswith("FP2-gms-") or getprop(
+ serial, "ro.build.version.incremental"
+ ).startswith("gms-")
def uninstall_apk(serial, filename, prebuilts_dir):
@@ -214,21 +210,20 @@
ValueError: If the package name could not be read from the apk.
DeviceCommandError: If the uninstall command failed.
"""
- ret = aapt('dump', 'badging', '{}/{}'.format(prebuilts_dir, filename))
+ ret = aapt("dump", "badging", "{}/{}".format(prebuilts_dir, filename))
package = None
for line in ret.stdout.splitlines():
- if line.startswith('package'):
- for token in line.split(' '):
- if token.startswith('name='):
+ if line.startswith("package"):
+ for token in line.split(" "):
+ if token.startswith("name="):
# Extract the package name out of the token
# (name='some.package.name')
package = token[6:-1]
break
if not package:
- raise ValueError('Could not find package of app `{}`'.format(
- filename))
+ raise ValueError("Could not find package of app `{}`".format(filename))
- adb('uninstall', package, serial=serial)
+ adb("uninstall", package, serial=serial)
def install_apk(dut, filename, prebuilts_dir):
@@ -238,10 +233,10 @@
DeviceCommandError: If the install command failed.
"""
path = os.path.join(prebuilts_dir, filename)
- command = ['install', '-r']
+ command = ["install", "-r"]
if dut.sdk >= 23:
# From Marshmallow onwards, adb has a flag to grant default permissions
- command.append('-g')
+ command.append("-g")
adb(*command, path, serial=dut.serial)
@@ -262,20 +257,22 @@
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)
+ 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')
+ 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.wait()
+ dut(description="More options").click.wait()
time.sleep(1)
- saved_networks = dut(text='Saved networks')
+ saved_networks = dut(text="Saved networks")
if saved_networks.exists:
saved_networks.click.wait()
for ssid in networks.keys():
@@ -286,40 +283,34 @@
missing_networks = networks.keys() - registered_networks
for ssid in registered_networks:
- print('Ignoring `{}` Wi-Fi network, already configured.'.format(ssid))
+ print("Ignoring `{}` Wi-Fi network, already configured.".format(ssid))
for ssid in missing_networks:
- print('Configuring `{}` Wi-Fi network…'.format(ssid))
+ print("Configuring `{}` Wi-Fi network…".format(ssid))
- dut(description='More options').click.wait()
- dut(text='Add network').click.wait()
- 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')
+ dut(description="More options").click.wait()
+ dut(text="Add network").click.wait()
+ 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")
time.sleep(1)
- if 'password' in networks[ssid] and networks[ssid]['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'])
+ 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')
+ 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')
+ 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()
+ 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()
@@ -331,13 +322,16 @@
This simplifies UI automation. Disabling the feature globally is more robust
than clicking through the the Privacy Impact screen per app.
"""
- print('Disabling the Privacy Impact screen…')
- adb('shell',
- ('am start -a android.intent.action.MAIN '
- 'com.fairphone.privacyimpact/.PrivacyImpactPreferenceActivity'),
- serial=dut.serial
+ print("Disabling the Privacy Impact screen…")
+ adb(
+ "shell",
+ (
+ "am start -a android.intent.action.MAIN "
+ "com.fairphone.privacyimpact/.PrivacyImpactPreferenceActivity"
+ ),
+ serial=dut.serial,
)
- disable_privacy_impact_checkbox = dut(className='android.widget.CheckBox')
+ disable_privacy_impact_checkbox = dut(className="android.widget.CheckBox")
if not disable_privacy_impact_checkbox.checked:
disable_privacy_impact_checkbox.click()
@@ -348,91 +342,88 @@
else:
return PREBUILT_PROXY_APK_PATTERN.format(sdk=19, flavour=flavour)
+
# Prepare the DUT
def prepare_dut(dut, scenarios_dir, data_dir, prebuilts_dir):
- flavour = 'gms' if is_gms_device(dut.serial) else 'sibon'
+ flavour = "gms" if is_gms_device(dut.serial) else "sibon"
proxy_apk = get_proxy_apk(dut.sdk, flavour)
# Uninstall the smartviser apps
for app in PREBUILT_APKS + [proxy_apk]:
- print('Uninstalling `{}`…'.format(app))
+ print("Uninstalling `{}`…".format(app))
uninstall_apk(dut.serial, app, prebuilts_dir)
# Copy the scenarios
- print('Pushing scenarios from `{}`…'.format(scenarios_dir))
- adb('push', scenarios_dir, '/sdcard/viser', serial=dut.serial)
+ print("Pushing scenarios from `{}`…".format(scenarios_dir))
+ adb("push", scenarios_dir, "/sdcard/viser", serial=dut.serial)
# Copy the scenarios data
- print('Pushing scenarios data from `{}`…'.format(data_dir))
- adb('push', data_dir, '/sdcard/viser/data', serial=dut.serial)
+ print("Pushing scenarios data from `{}`…".format(data_dir))
+ adb("push", data_dir, "/sdcard/viser/data", serial=dut.serial)
# Install the smartviser apps (starting with the proxy app)
for app in [proxy_apk] + PREBUILT_APKS:
- print('Installing `{}`…'.format(app))
+ print("Installing `{}`…".format(app))
install_apk(dut, app, prebuilts_dir)
# Grant the permissions through the UI
def configure_perms(dut):
# Input the credentials
- dut(resourceId='android:id/content') \
- .child(text='Username') \
- .child(className='android.widget.EditText') \
- .set_text(VWS_CREDENTIALS['user'])
- dut(resourceId='android:id/content') \
- .child(text='Password') \
- .child(className='android.widget.EditText') \
- .set_text(VWS_CREDENTIALS['password'])
+ dut(resourceId="android:id/content").child(text="Username").child(
+ className="android.widget.EditText"
+ ).set_text(VWS_CREDENTIALS["user"])
+ dut(resourceId="android:id/content").child(text="Password").child(
+ className="android.widget.EditText"
+ ).set_text(VWS_CREDENTIALS["password"])
# Sign in
- signin_label = 'SIGN IN' if dut.sdk >= 24 else 'Sign in'
- dut(resourceId='android:id/content') \
- .child(text=signin_label, className='android.widget.Button') \
- .click()
+ signin_label = "SIGN IN" if dut.sdk >= 24 else "Sign in"
+ dut(resourceId="android:id/content").child(
+ text=signin_label, className="android.widget.Button"
+ ).click()
+
def configure_sms(dut):
# TODO wait for the connection to be established and time-out
- prompt = dut(resourceId='android:id/content') \
- .child(text='Viser must be your SMS app to send messages')
+ prompt = dut(resourceId="android:id/content").child(
+ text="Viser must be your SMS app to send messages"
+ )
while not prompt.exists:
time.sleep(1)
# Make viser the default SMS app
- dut(resourceId='android:id/content') \
- .child_by_text('Viser must be your SMS app to send messages',
- className='android.widget.LinearLayout') \
- .child(text='OK', className='android.widget.Button') \
- .click()
+ dut(resourceId="android:id/content").child_by_text(
+ "Viser must be your SMS app to send messages",
+ className="android.widget.LinearLayout",
+ ).child(text="OK", className="android.widget.Button").click()
- dut(resourceId='android:id/content') \
- .child_by_text('Change SMS app?', className='android.widget.LinearLayout') \
- .child(text='Yes', className='android.widget.Button') \
- .click()
+ dut(resourceId="android:id/content").child_by_text(
+ "Change SMS app?", className="android.widget.LinearLayout"
+ ).child(text="Yes", className="android.widget.Button").click()
+
def configure_settings(dut):
# Set the e-mail account
- dut(text='Settings', className='android.widget.TextView') \
- .click()
- dut(resourceId='android:id/list') \
- .child_by_text('User settings', className='android.widget.LinearLayout') \
- .click()
- dut(resourceId='android:id/list') \
- .child_by_text('Email account', className='android.widget.LinearLayout') \
- .click()
- prompt = dut(resourceId='android:id/content') \
- .child_by_text('Email account', className='android.widget.LinearLayout')
- prompt.child(resourceId='android:id/edit') \
- .set_text('fairphone.viser@gmail.com')
- prompt.child(text='OK', className='android.widget.Button') \
- .click()
- dut(resourceId='android:id/list') \
- .child_by_text('Email password', className='android.widget.LinearLayout') \
- .click()
- dut(text='Password :') \
- .child(className='android.widget.EditText') \
- .set_text('fairphoneviser2017')
- dut(description='OK', className='android.widget.TextView') \
- .click()
+ dut(text="Settings", className="android.widget.TextView").click()
+ dut(resourceId="android:id/list").child_by_text(
+ "User settings", className="android.widget.LinearLayout"
+ ).click()
+ dut(resourceId="android:id/list").child_by_text(
+ "Email account", className="android.widget.LinearLayout"
+ ).click()
+ prompt = dut(resourceId="android:id/content").child_by_text(
+ "Email account", className="android.widget.LinearLayout"
+ )
+ prompt.child(resourceId="android:id/edit").set_text("fairphone.viser@gmail.com")
+ prompt.child(text="OK", className="android.widget.Button").click()
+ dut(resourceId="android:id/list").child_by_text(
+ "Email password", className="android.widget.LinearLayout"
+ ).click()
+ dut(text="Password :").child(className="android.widget.EditText").set_text(
+ "fairphoneviser2017"
+ )
+ dut(description="OK", className="android.widget.TextView").click()
dut.press.back()
dut.press.back()
@@ -446,13 +437,13 @@
serials = list_devices()
for serial in serials:
- print('Configuring device {}…'.format(serial))
+ print("Configuring device {}…".format(serial))
dut = Device(serial)
# Work around the not-so-easy Device class
dut.serial = serial
# Cache the Android SDK version (dut.info fetches system properties)
- dut.sdk = dut.info['sdkInt']
+ dut.sdk = dut.info["sdkInt"]
try:
# Make sure the screen stays on - we're going to use UI automation
@@ -463,21 +454,29 @@
if dut.sdk < 24:
configure_wifi_networks(dut, FAIRPHONE_WIFI_NETWORKS)
else:
- print('Uh oh, the device is running Android SDK {} on which we '
- 'do not deploy Wi-Fi networks yet.'.format(dut.sdk))
+ print(
+ "Uh oh, the device is running Android SDK {} on which we "
+ "do not deploy Wi-Fi networks yet.".format(dut.sdk)
+ )
# Disable Privacy Impact popup on Android 5.
if dut.sdk <= 22:
disable_privacy_impact_popup(dut)
# Push the scenarios, their data, and install the apps
- prepare_dut(
- dut, '../scenarios', '../scenarios-data', PREBUILTS_PATH)
+ prepare_dut(dut, "../scenarios", "../scenarios-data", PREBUILTS_PATH)
# Start the viser app
adb(
- 'shell', 'monkey', '-p', 'com.lunarlabs.panda', '-c',
- 'android.intent.category.LAUNCHER', '1', serial=serial)
+ "shell",
+ "monkey",
+ "-p",
+ "com.lunarlabs.panda",
+ "-c",
+ "android.intent.category.LAUNCHER",
+ "1",
+ serial=serial,
+ )
configure_perms(dut)
@@ -487,14 +486,14 @@
configure_settings(dut)
except (HostCommandError, DeviceCommandError) as e:
- print('ERROR {}'.format(e), file=sys.stderr)
+ print("ERROR {}".format(e), file=sys.stderr)
finally:
try:
# Leave the device alone now
force_awake(serial, always=False)
except DeviceCommandError as e:
- print('WARNING {}'.format(e), file=sys.stderr)
+ print("WARNING {}".format(e), file=sys.stderr)
-if __name__ == '__main__':
+if __name__ == "__main__":
deploy()