blob: a245d199d61db99a64a5fa1bd82e3a6df8284dd1 [file] [log] [blame]
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +01001#!/usr/bin/env python3
2
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +01003import os
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +01004import time
5from uiautomator import Device
Franz-Xaver Geigerb0f55422018-04-17 10:33:37 +02006import re
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +01007import sys
8import subprocess
9import pathlib
10
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +010011
Borjan Tchakaloffd8445d32018-04-18 18:01:20 +020012VWS_CREDENTIALS = {
13 'user': 'fairphonetesting@gmail.com',
14 'password': 'aish3echi:uwaiSh'
15}
16
17
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +010018PREBUILTS_PATH = '../../vendor/smartviser/viser/prebuilts/apk'
19
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +020020PREBUILT_PROXY_APK_PATTERN = (
21 'com.lunarlabs.panda.proxy-latest-sdk{sdk}-{flavour}.apk')
Franz-Xaver Geigerb3f7c982018-04-12 09:29:32 +020022
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +010023PREBUILT_APKS = [
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +020024 'com.smartviser.demogame-latest.apk',
25 'com.lunarlabs.panda-latest.apk',
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +010026]
27
Borjan Tchakaloff74d962a2018-04-11 17:47:14 +020028FAIRPHONE_WIFI_NETWORKS = {
29 'Fairphone Guest': {'security': 'WPA/WPA2 PSK', 'password': 'fairwifi'},
30 'Fairphone DEV (2.4 GHz)': {
31 'security': 'WPA/WPA2 PSK', 'password': 'fdev@adm'},
32 'Fairphone DEV (5 GHz)': {
33 'security': 'WPA/WPA2 PSK', 'password': 'fdev@adm'},
34}
35
Franz-Xaver Geigerb0f55422018-04-17 10:33:37 +020036ADB_DEVICES_PATTERN = re.compile(r'^([a-z0-9-]+)\s+device$', flags=re.M)
37
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +010038
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +020039class HostCommandError(BaseException):
40 """An error happened while issuing a command on the host."""
41 def __init__(self, command, error_message):
42 self.command = command
43 self.error_message = error_message
44 message = 'Command `{}` failed: {}'.format(command, error_message)
45 super(HostCommandError, self).__init__(message)
46
47
48class DeviceCommandError(BaseException):
49 """An error happened while sending a command to a device."""
50 def __init__(self, serial, command, error_message):
51 self.serial = serial
52 self.command = command
53 self.error_message = error_message
54 message = 'Command `{}` failed on {}: {}'.format(
55 command, serial, error_message)
56 super(DeviceCommandError, self).__init__(message)
57
58
59def adb(*args, serial = None, raise_on_error = True):
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +010060 """Run ADB command attached to serial.
61
62 Example:
63 >>> process = adb('shell', 'getprop', 'ro.build.fingerprint', serial='cc60c021')
64 >>> process.returncode
65 0
66 >>> process.stdout.strip()
67 'Fairphone/FP2/FP2:6.0.1/FP2-gms-18.02.0/FP2-gms-18.02.0:user/release-keys'
68
69 :param *args:
70 List of options to ADB (including command).
71 :param str serial:
72 Identifier for ADB connection to device.
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +020073 :param raise_on_error bool:
74 Whether to raise a DeviceCommandError exception if the return code is
75 less than 0.
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +010076 :returns subprocess.CompletedProcess:
77 Completed process.
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +020078 :raises DeviceCommandError:
79 If the command failed.
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +010080 """
81
82 # Make sure the adb server is started to avoid the infamous "out of date"
83 # message that pollutes stdout.
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +020084 ret = subprocess.run(
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +010085 ['adb', 'start-server'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
86 universal_newlines=True)
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +020087 if ret.returncode < 0:
88 if raise_on_error:
89 raise DeviceCommandError(
90 serial if serial else '??', str(args), ret.stderr)
91 else:
92 return None
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +010093
94 command = ['adb']
95 if serial:
96 command += ['-s', serial]
97 if args:
98 command += list(args)
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +020099 ret = subprocess.run(
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100100 command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
101 universal_newlines=True)
102
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200103 if raise_on_error and ret.returncode < 0:
104 raise DeviceCommandError(
105 serial if serial else '??', str(args), ret.stderr)
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100106
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200107 return ret
108
109
Franz-Xaver Geigerb0f55422018-04-17 10:33:37 +0200110def list_devices():
111 """List serial numbers of devices attached to adb.
112
113 Raises:
114 DeviceCommandError: If the underlying adb command failed.
115 """
116 process = adb('devices')
117 return ADB_DEVICES_PATTERN.findall(process.stdout)
118
119
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200120def aapt(*args, raise_on_error = True):
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100121 """Run an AAPT command.
122
123 :param *args:
124 The AAPT command with its options.
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200125 :param raise_on_error bool:
126 Whether to raise a DeviceCommandError exception if the return code is
127 less than 0.
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100128 :returns subprocess.CompletedProcess:
129 Completed process.
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200130 :raises HostCommandError:
131 If the command failed.
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100132 """
133 command = ['aapt']
134 if args:
135 command += list(args)
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200136 ret = subprocess.run(
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100137 command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
138 universal_newlines=True)
139
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200140 if raise_on_error and ret.returncode < 0:
141 raise HostCommandError(str(args), ret.stderr)
142
143 return ret
144
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100145
Borjan Tchakaloff64ec42b2018-02-07 11:33:15 -0800146def force_awake(serial, always=True):
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200147 """Force the device to stay awake.
148
149 Raises:
150 DeviceCommandError: If the underlying adb command failed.
151 """
152 adb('shell', 'svc power stayon {}'.format(
Borjan Tchakaloff64ec42b2018-02-07 11:33:15 -0800153 'true' if always else 'false'), serial=serial)
154
155
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200156def unlock(dut):
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200157 """Wake-up the device and unlock it.
158
159 Raises:
160 DeviceCommandError: If the underlying adb commands failed.
161 """
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200162 if not dut.info['screenOn']:
163 adb('shell', 'input keyevent KEYCODE_POWER', serial=dut.serial)
164 time.sleep(1)
165 # The KEYCODE_MENU input is enough to unlock a "swipe up to unlock"
166 # lockscreen on Android 6, but unfortunately not Android 7. So we use a
167 # swipe up (that depends on the screen resolution) instead.
168 adb('shell', 'input touchscreen swipe 930 880 930 380', serial=dut.serial)
Borjan Tchakaloff64ec42b2018-02-07 11:33:15 -0800169 time.sleep(1)
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200170 adb('shell', 'input keyevent KEYCODE_HOME', serial=dut.serial)
Borjan Tchakaloff64ec42b2018-02-07 11:33:15 -0800171
172
Franz-Xaver Geigerb3f7c982018-04-12 09:29:32 +0200173def getprop(serial, key):
174 """Get system property of device.
175
176 Example:
177 >>> getprop('167eb6e8', 'ro.build.id')
178 'FP2-gms-18.02.0'
179
180 :param str serial:
181 Identifier for ADB connection to device.
182 :param str key:
183 Key of property to get.
184 :returns str:
185 Value of system property.
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200186 :raise DeviceCommandError: If the underlying adb command failed.
Franz-Xaver Geigerb3f7c982018-04-12 09:29:32 +0200187 """
188 process = adb('shell', 'getprop', key, serial=serial)
189 return process.stdout.strip()
190
191
192def is_gms_device(serial):
193 """Test if device runs GMS or sibon.
194
195 Example:
196 >>> is_gms_device('167eb6e8')
197 True
198
199 :param str serial:
200 Identifier for ADB connection to device.
201 :returns bool:
202 True if device runs GMS, false otherwise.
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200203 :raise DeviceCommandError: If the underlying adb command failed.
Franz-Xaver Geigerb3f7c982018-04-12 09:29:32 +0200204 """
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200205 return (
206 getprop(serial, 'ro.build.id').startswith('FP2-gms-')
207 or getprop(serial, 'ro.build.version.incremental').startswith('gms-'))
Franz-Xaver Geigerb3f7c982018-04-12 09:29:32 +0200208
209
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100210def uninstall_apk(serial, filename, prebuilts_dir):
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200211 """Uninstall apk from prebuilts_dir on device.
212
213 Raises:
214 ValueError: If the package name could not be read from the apk.
215 DeviceCommandError: If the uninstall command failed.
216 """
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100217 ret = aapt('dump', 'badging', '{}/{}'.format(prebuilts_dir, filename))
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200218 package = None
219 for line in ret.stdout.splitlines():
220 if line.startswith('package'):
221 for token in line.split(' '):
222 if token.startswith('name='):
223 # Extract the package name out of the token
224 # (name='some.package.name')
225 package = token[6:-1]
226 break
227 if not package:
228 raise ValueError('Could not find package of app `{}`'.format(
229 filename))
230
231 adb('uninstall', package, serial=serial)
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100232
233
Borjan Tchakaloffd2c92ce2018-08-24 17:13:57 +0200234def install_apk(dut, filename, prebuilts_dir):
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200235 """Install apk from prebuilts_dir on device.
236
237 Raises:
238 DeviceCommandError: If the install command failed.
239 """
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100240 path = os.path.join(prebuilts_dir, filename)
Borjan Tchakaloffd2c92ce2018-08-24 17:13:57 +0200241 command = ['install', '-r']
242 if dut.sdk >= 23:
243 # From Marshmallow onwards, adb has a flag to grant default permissions
244 command.append('-g')
245 adb(*command, path, serial=dut.serial)
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100246
247
Borjan Tchakaloff74d962a2018-04-11 17:47:14 +0200248def configure_wifi_networks(dut, networks):
249 """Configure Wi-Fi networks.
250
251 The `networks` parameters is a list of networks to configure hashed by
252 their SSID. Each network value should have the following format:
253 - security (str): The security value as can be found in the Wi-Fi
254 settings dialog. Common values are 'None' and 'WPA/WPA2 PSK'.
255 - password (str, optional): The network password if the security is
256 'WPA/WPA2 PSK'.
257
258 Parameters:
259 dut (Device): The device object.
260 networks (dict(dict(str))): The list of networks to configure.
261 Raises:
262 DeviceCommandError: If the UI automation fails.
263 """
264 # Open the Wi-Fi settings
265 adb('shell', ('am start -a android.settings.WIFI_SETTINGS '
266 '--activity-clear-task'), serial=dut.serial)
267
268 # Make sure Wi-Fi is enabled
269 wifi_enabler = dut(text='OFF',
270 resourceId='com.android.settings:id/switch_widget')
271 if wifi_enabler.exists:
272 wifi_enabler.click()
273
274 # Check for registered networks
275 registered_networks = set()
Borjan Tchakaloff1d83e562018-05-16 18:47:04 +0200276 dut(description='More options').click.wait()
Borjan Tchakaloff74d962a2018-04-11 17:47:14 +0200277 time.sleep(1)
278 saved_networks = dut(text='Saved networks')
279 if saved_networks.exists:
Borjan Tchakaloff1d83e562018-05-16 18:47:04 +0200280 saved_networks.click.wait()
Borjan Tchakaloff74d962a2018-04-11 17:47:14 +0200281 for ssid in networks.keys():
282 if dut(text=ssid).exists:
283 registered_networks.add(ssid)
284 dut.press.back()
285
286 missing_networks = networks.keys() - registered_networks
287
288 for ssid in registered_networks:
289 print('Ignoring `{}` Wi-Fi network, already configured.'.format(ssid))
290
291 for ssid in missing_networks:
292 print('Configuring `{}` Wi-Fi network…'.format(ssid))
293
Borjan Tchakaloff1d83e562018-05-16 18:47:04 +0200294 dut(description='More options').click.wait()
295 dut(text='Add network').click.wait()
Borjan Tchakaloff74d962a2018-04-11 17:47:14 +0200296 dut(resourceId='com.android.settings:id/ssid') \
297 .set_text(ssid)
298 dut(resourceId='com.android.settings:id/security') \
299 .click()
300 dut(text=networks[ssid]['security']) \
301 .click()
302 password_field = dut(resourceId='com.android.settings:id/password')
Karsten Tauschec20f4f32019-03-04 14:32:04 +0100303 time.sleep(1)
Borjan Tchakaloff74d962a2018-04-11 17:47:14 +0200304 if 'password' in networks[ssid] and networks[ssid]['password']:
305 if not password_field.exists:
306 dut(text='Cancel').click()
307 raise DeviceCommandError(dut, 'UI: add Wi-Fi',
308 'missing password field')
309 password_field.set_text(networks[ssid]['password'])
310 elif password_field.exists:
311 dut(text='Cancel').click()
312 raise DeviceCommandError(dut, 'UI: add Wi-Fi',
313 'missing password data')
314 save_button = dut(text='Save')
315 if not save_button.click():
316 dut(text='Cancel').click()
317 raise DeviceCommandError(dut, 'UI: add Wi-Fi',
318 'could not save network')
319
320 # Force the Wi-Fi on and off to pick the best network available
321 dut(text='ON', resourceId='com.android.settings:id/switch_widget').click()
322 dut(text='OFF', resourceId='com.android.settings:id/switch_widget').click()
323
324 # Leave the settings
325 dut.press.back()
326
327
Karsten Tauscheb36529f2019-03-02 14:13:29 +0100328def disable_privacy_impact_popup(dut):
329 """Disable Privacy Impact popup on Android 5.
330
331 This simplifies UI automation. Disabling the feature globally is more robust
332 than clicking through the the Privacy Impact screen per app.
333 """
334 print('Disabling the Privacy Impact screen…')
335 adb('shell',
336 ('am start -a android.intent.action.MAIN '
337 'com.fairphone.privacyimpact/.PrivacyImpactPreferenceActivity'),
338 serial=dut.serial
339 )
340 disable_privacy_impact_checkbox = dut(className='android.widget.CheckBox')
341 if not disable_privacy_impact_checkbox.checked:
342 disable_privacy_impact_checkbox.click()
343
344
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200345def get_proxy_apk(android_sdk, flavour):
346 if android_sdk >= 24:
347 return PREBUILT_PROXY_APK_PATTERN.format(sdk=24, flavour=flavour)
348 else:
349 return PREBUILT_PROXY_APK_PATTERN.format(sdk=19, flavour=flavour)
350
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100351# Prepare the DUT
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200352def prepare_dut(dut, scenarios_dir, data_dir, prebuilts_dir):
353 flavour = 'gms' if is_gms_device(dut.serial) else 'sibon'
354 proxy_apk = get_proxy_apk(dut.sdk, flavour)
Franz-Xaver Geigerb3f7c982018-04-12 09:29:32 +0200355
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100356 # Uninstall the smartviser apps
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200357 for app in PREBUILT_APKS + [proxy_apk]:
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200358 print('Uninstalling `{}`…'.format(app))
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200359 uninstall_apk(dut.serial, app, prebuilts_dir)
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100360
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100361 # Copy the scenarios
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200362 print('Pushing scenarios from `{}`…'.format(scenarios_dir))
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200363 adb('push', scenarios_dir, '/sdcard/viser', serial=dut.serial)
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100364
365 # Copy the scenarios data
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200366 print('Pushing scenarios data from `{}`…'.format(data_dir))
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200367 adb('push', data_dir, '/sdcard/viser/data', serial=dut.serial)
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100368
Franz-Xaver Geigerb3f7c982018-04-12 09:29:32 +0200369 # Install the smartviser apps (starting with the proxy app)
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200370 for app in [proxy_apk] + PREBUILT_APKS:
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200371 print('Installing `{}`…'.format(app))
Borjan Tchakaloffd2c92ce2018-08-24 17:13:57 +0200372 install_apk(dut, app, prebuilts_dir)
Franz-Xaver Geigerb28348e2018-02-19 14:41:40 +0100373
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100374
375# Grant the permissions through the UI
376def configure_perms(dut):
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100377 # Input the credentials
378 dut(resourceId='android:id/content') \
379 .child(text='Username') \
380 .child(className='android.widget.EditText') \
Borjan Tchakaloffd8445d32018-04-18 18:01:20 +0200381 .set_text(VWS_CREDENTIALS['user'])
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100382 dut(resourceId='android:id/content') \
383 .child(text='Password') \
384 .child(className='android.widget.EditText') \
Borjan Tchakaloffd8445d32018-04-18 18:01:20 +0200385 .set_text(VWS_CREDENTIALS['password'])
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100386
387 # Sign in
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200388 signin_label = 'SIGN IN' if dut.sdk >= 24 else 'Sign in'
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100389 dut(resourceId='android:id/content') \
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200390 .child(text=signin_label, className='android.widget.Button') \
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100391 .click()
392
393def configure_sms(dut):
394 # TODO wait for the connection to be established and time-out
395 prompt = dut(resourceId='android:id/content') \
396 .child(text='Viser must be your SMS app to send messages')
397 while not prompt.exists:
398 time.sleep(1)
399
400 # Make viser the default SMS app
401 dut(resourceId='android:id/content') \
402 .child_by_text('Viser must be your SMS app to send messages',
403 className='android.widget.LinearLayout') \
404 .child(text='OK', className='android.widget.Button') \
405 .click()
406
407 dut(resourceId='android:id/content') \
408 .child_by_text('Change SMS app?', className='android.widget.LinearLayout') \
409 .child(text='Yes', className='android.widget.Button') \
410 .click()
411
412def configure_settings(dut):
413 # Set the e-mail account
414 dut(text='Settings', className='android.widget.TextView') \
415 .click()
416 dut(resourceId='android:id/list') \
417 .child_by_text('User settings', className='android.widget.LinearLayout') \
418 .click()
419 dut(resourceId='android:id/list') \
420 .child_by_text('Email account', className='android.widget.LinearLayout') \
421 .click()
422 prompt = dut(resourceId='android:id/content') \
423 .child_by_text('Email account', className='android.widget.LinearLayout')
424 prompt.child(resourceId='android:id/edit') \
425 .set_text('fairphone.viser@gmail.com')
426 prompt.child(text='OK', className='android.widget.Button') \
427 .click()
428 dut(resourceId='android:id/list') \
429 .child_by_text('Email password', className='android.widget.LinearLayout') \
430 .click()
431 dut(text='Password :') \
432 .child(className='android.widget.EditText') \
433 .set_text('fairphoneviser2017')
434 dut(description='OK', className='android.widget.TextView') \
435 .click()
436 dut.press.back()
437 dut.press.back()
438
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100439
Franz-Xaver Geigerd1079e22018-02-19 14:34:15 +0100440def deploy():
441 serials = []
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100442
Franz-Xaver Geigerd1079e22018-02-19 14:34:15 +0100443 if len(sys.argv) > 1:
444 serials.append(sys.argv[1])
445 else:
Franz-Xaver Geigerb0f55422018-04-17 10:33:37 +0200446 serials = list_devices()
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100447
Franz-Xaver Geigerd1079e22018-02-19 14:34:15 +0100448 for serial in serials:
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200449 print('Configuring device {}…'.format(serial))
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100450
Franz-Xaver Geigerd1079e22018-02-19 14:34:15 +0100451 dut = Device(serial)
Borjan Tchakaloff74d962a2018-04-11 17:47:14 +0200452 # Work around the not-so-easy Device class
453 dut.serial = serial
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200454 # Cache the Android SDK version (dut.info fetches system properties)
455 dut.sdk = dut.info['sdkInt']
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100456
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200457 try:
458 # Make sure the screen stays on - we're going to use UI automation
459 force_awake(serial)
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200460 unlock(dut)
Borjan Tchakaloff64ec42b2018-02-07 11:33:15 -0800461
Borjan Tchakaloff74d962a2018-04-11 17:47:14 +0200462 # Configure common Fairphone Wi-Fi networks
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200463 if dut.sdk < 24:
464 configure_wifi_networks(dut, FAIRPHONE_WIFI_NETWORKS)
465 else:
466 print('Uh oh, the device is running Android SDK {} on which we '
467 'do not deploy Wi-Fi networks yet.'.format(dut.sdk))
Borjan Tchakaloff74d962a2018-04-11 17:47:14 +0200468
Karsten Tauscheb36529f2019-03-02 14:13:29 +0100469 # Disable Privacy Impact popup on Android 5.
470 if dut.sdk <= 22:
471 disable_privacy_impact_popup(dut)
472
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200473 # Push the scenarios, their data, and install the apps
474 prepare_dut(
Borjan Tchakaloffd4ce8072018-05-16 18:20:13 +0200475 dut, '../scenarios', '../scenarios-data', PREBUILTS_PATH)
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100476
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200477 # Start the viser app
478 adb(
Franz-Xaver Geiger223ae752018-02-19 14:54:08 +0100479 'shell', 'monkey', '-p', 'com.lunarlabs.panda', '-c',
480 'android.intent.category.LAUNCHER', '1', serial=serial)
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100481
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200482 configure_perms(dut)
Borjan Tchakaloffa4bdae12017-11-21 14:58:12 +0100483
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200484 # TODO DO NOT DO THE FOLLOWING IF NO SIM CARD IS IN THE DUT
485 # time.sleep(10)
486 # configure_sms(dut)
Franz-Xaver Geigerd1079e22018-02-19 14:34:15 +0100487
Borjan Tchakaloffde9fa0f2018-04-12 12:05:48 +0200488 configure_settings(dut)
489 except (HostCommandError, DeviceCommandError) as e:
490 print('ERROR {}'.format(e), file=sys.stderr)
491 finally:
492 try:
493 # Leave the device alone now
494 force_awake(serial, always=False)
495 except DeviceCommandError as e:
496 print('WARNING {}'.format(e), file=sys.stderr)
Borjan Tchakaloff64ec42b2018-02-07 11:33:15 -0800497
Franz-Xaver Geigerd1079e22018-02-19 14:34:15 +0100498
499if __name__ == '__main__':
500 deploy()