Deployment script to configure a device

* The required files are expected in the following structure:
  - ../scenarios
    The scenarios file (XML).
  - ../scenarios-data
    The scenarios data (e.g. videos, images, etc.).
  - ../../vendor/smartviser/viser
    The viser applications (APK).
* The device must have an Internet connection and the screen must be
  turned on.

Change-Id: I4516a078a573aa669f914aa6e1bbba6aa30ddf8b
diff --git a/deploy.py b/deploy.py
new file mode 100755
index 0000000..9b069c9
--- /dev/null
+++ b/deploy.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python3
+
+import time
+from uiautomator import Device
+import sys
+import subprocess
+import pathlib
+
+# Prepare the DUT
+def prepare_dut(serial, scenarios_dir, data_dir, apps):
+    # Copy the scenarios
+    ret = subprocess.run(['adb', '-s', serial, 'push', scenarios_dir,
+            '/sdcard/viser'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+            universal_newlines=True)
+    if 0 < ret.returncode:
+        print('Could not push the scenarios, error was: {}'.format(ret.stderr),
+                file=sys.stderr)
+    else:
+        print('Scenarios pushed.')
+
+    # Copy the scenarios data
+    ret = subprocess.run(['adb', '-s', serial, 'push', data_dir,
+            '/sdcard/viser/data'], stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE, universal_newlines=True)
+    if 0 < ret.returncode:
+        print('Could not push the scenarios data, error was: {}'.format(ret.stderr),
+                file=sys.stderr)
+    else:
+        print('Scenarios data pushed.')
+
+    # Install the smartviser apps
+    for app in apps:
+        ret = subprocess.run(['adb', '-s', serial, 'install', '-r', app],
+                stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+                universal_newlines=True)
+        if 0 < ret.returncode:
+            print('Could not install app `{}`, error was: {}'.format(app,
+                    ret.stderr), file=sys.stderr)
+        else:
+            print('App `{}` installed.'.format(app))
+
+# Grant the permissions through the UI
+def configure_perms(dut):
+    prompt = dut(resourceId='android:id/content') \
+        .child_by_text('You need to grant access for the Permissions Group '
+                'Calendar Camera Contacts Microphone SMS Storage Telephone Location',
+                className='android.widget.LinearLayout') \
+        .child(text='OK', className='android.widget.Button').click()
+
+    # Accept any permission that is asked for
+    prompt = dut(resourceId='com.android.packageinstaller:id/permission_allow_button',
+            className='android.widget.Button')
+    while prompt.exists:
+        prompt.click()
+
+    # Input the credentials
+    dut(resourceId='android:id/content') \
+        .child(text='Username') \
+        .child(className='android.widget.EditText') \
+        .set_text('borjan@fairphone.com')
+    dut(resourceId='android:id/content') \
+        .child(text='Password') \
+        .child(className='android.widget.EditText') \
+        .set_text('Rickisalso1niceguy!')
+
+    # Sign in
+    dut(resourceId='android:id/content') \
+        .child(text='Sign in', 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')
+    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('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.press.back()
+    dut.press.back()
+
+serials = []
+
+if len(sys.argv) > 1:
+    serials.append(sys.argv[1])
+else:
+    # List devices attached to adb
+    ret = subprocess.run(
+            "adb devices | grep -E '^[a-z0-9-]+\s+device$' | awk '{{print $1}}'",
+            shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+            universal_newlines=True)
+
+    if 0 < ret.returncode:
+        # TODO handle the error
+        raise Exception('Failed to list adb devices')
+    elif ret.stdout:
+        for line in ret.stdout.splitlines():
+            serial = line.strip()
+            if serial:
+                serials.append(serial)
+
+for serial in serials:
+    print('Configuring device {}'.format(serial))
+
+    dut = Device(serial)
+
+    # Push the scenarios, their data, and install the apps
+    prepare_dut(serial, '../scenarios', '../scenarios-data', [
+        '../../vendor/smartviser/viser/prebuilts/apk/com.smartviser.demogame.apk',
+        '../../vendor/smartviser/viser/prebuilts/apk/com.lunarlabs.panda.proxy.apk',
+        '../../vendor/smartviser/viser/prebuilts/apk/com.lunarlabs.panda.apk'
+    ])
+
+    # Start the viser app
+    ret = subprocess.run(['adb', '-s', serial, 'shell', 'monkey', '-p',
+            'com.lunarlabs.panda', '-c', 'android.intent.category.LAUNCHER',
+            '1'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+            universal_newlines=True)
+    if 0 < ret.returncode:
+        print('Could not start the viser app, error was: {}'.format(app,
+                ret.stderr), file=sys.stderr)
+        exit(-1)
+
+    configure_perms(dut)
+
+    # TODO DO NOT DO THE FOLLOWING IF NO SIM CARD IS IN THE DUT
+    # time.sleep(10)
+    # configure_sms(dut)
+
+    configure_settings(dut)