diff --git a/wlauto/common/android/workload.py b/wlauto/common/android/workload.py
index 0dbae5bd..34bb8059 100644
--- a/wlauto/common/android/workload.py
+++ b/wlauto/common/android/workload.py
@@ -138,6 +138,11 @@ class ApkWorkload(Workload):
     :view: The class of the main view pane of the app. This needs to be defined in order
            to collect SurfaceFlinger-derived statistics (such as FPS) for the app, but
            may otherwise be left as ``None``.
+    :launch_main: If ``False``, the default activity will not be launched (during setup),
+                  allowing workloads to start the app with an intent of their choice in
+                  the run step. This is useful for apps without a launchable default/main
+                  activity or those where it cannot be launched without intent data (which
+                  is provided at the run phase).
     :install_timeout: Timeout for the installation of the APK. This may vary wildly based on
                       the size and nature of a specific APK, and so should be defined on
                       per-workload basis.
@@ -160,6 +165,7 @@ class ApkWorkload(Workload):
     min_apk_version = None
     max_apk_version = None
     supported_platforms = ['android']
+    launch_main = True
 
     parameters = [
         Parameter('install_timeout', kind=int, default=300,
@@ -214,7 +220,8 @@ class ApkWorkload(Workload):
         if self.check_apk:
             self.check_apk_version()
 
-        self.launch_package()
+        if self.launch_main:
+            self.launch_package() # launch default activity without intent data
         self.device.execute('am kill-all')  # kill all *background* activities
         self.device.clear_logcat()
 
diff --git a/wlauto/workloads/skype/__init__.py b/wlauto/workloads/skype/__init__.py
new file mode 100755
index 00000000..f84c8ec8
--- /dev/null
+++ b/wlauto/workloads/skype/__init__.py
@@ -0,0 +1,99 @@
+#    Copyright 2014-2016 ARM Limited
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import time
+from wlauto import AndroidUxPerfWorkload, Parameter
+
+
+class Skype(AndroidUxPerfWorkload):
+
+    name = 'skype'
+    description = '''
+    A workload to perform standard productivity tasks within Skype. The
+    workload logs in to the Skype application, selects a recipient from the
+    contacts list and then initiates either a voice or video call.
+
+    Test description:
+
+    1. Open Skype application
+    2. Log in to a pre-defined account
+    3. Select a recipient from the Contacts list
+    4. Initiate either a ``voice`` or ``video`` call for ``duration`` time (in seconds)
+
+    **Skype Setup**
+
+       - You should install Skype client from Google Play Store on the device
+         (this was tested with client version 7.01.0.669; other recent versions
+         should also work).
+       - You must have a Skype account set up.
+       - The contact to be called must be added (and has accepted) to the
+         account. It's possible to have multiple contacts in the list, however
+         the contact to be called *must* be visible on initial navigation to the
+         list.
+       - For video calls the contact must be able to received the call. This
+         means that there must be  a Skype client running (somewhere) with the
+         contact logged in and that client must have been configured to
+         auto-accept calls from the account on the device (how to set this
+         varies between different versions of Skype and between platforms --
+         please search online for specific instructions).
+         https://support.skype.com/en/faq/FA3751/can-i-automatically-answer-all-my-calls-with-video-in-skype-for-windows-desktop
+    '''
+    package = 'com.skype.raider'
+    min_apk_version = '7.01.0.669'
+    view = [package + '/com.skype.android.app.calling.CallActivity',
+            package + '/com.skype.android.app.calling.PreCallActivity',
+            package + '/com.skype.android.app.chat.ChatActivity',
+            package + '/com.skype.android.app.main.HubActivity',
+            package + '/com.skype.android.app.main.SplashActivity',
+            package + '/com.skype.android.app.signin.SignInActivity',
+            package + '/com.skype.android.app.signin.UnifiedLandingPageActivity']
+
+    activity = ''  # Skype has no default 'main' activity
+    launch_main = False  # overrides extended class
+
+    parameters = [
+        Parameter('login_name', kind=str, mandatory=True,
+                  description='''
+                  Account to use when logging into the device from which the call will be made
+                  '''),
+        Parameter('login_pass', kind=str, mandatory=True,
+                  description='Password associated with the account to log into the device'),
+        Parameter('contact_name', kind=str, mandatory=True, default='Echo / Sound Test Service',
+                  description='This is the contact display name as it appears in the people list'),
+        Parameter('duration', kind=int, default=10,
+                  description='This is the duration of the call in seconds'),
+        Parameter('action', kind=str, allowed_values=['voice', 'video'], default='voice',
+                  description='Action to take - either voice call (default) or video'),
+    ]
+
+    # This workload relies on the internet so check that there is a working
+    # internet connection
+    requires_network = True
+
+    def __init__(self, device, **kwargs):
+        super(Skype, self).__init__(device, **kwargs)
+        self.run_timeout = self.duration + 240
+
+    def validate(self):
+        super(Skype, self).validate()
+        self.uiauto_params['my_id'] = self.login_name
+        self.uiauto_params['my_pwd'] = self.login_pass
+        self.uiauto_params['name'] = self.contact_name.replace(' ', '0space0')
+        self.uiauto_params['duration'] = self.duration
+        self.uiauto_params['action'] = self.action
+
+    def setup(self, context):
+        super(Skype, self).setup(context)
+        self.device.execute('am start -W -a android.intent.action.VIEW -d skype:dummy?dummy')
diff --git a/wlauto/workloads/skype/com.arm.wlauto.uiauto.skype.jar b/wlauto/workloads/skype/com.arm.wlauto.uiauto.skype.jar
new file mode 100644
index 00000000..44f99436
Binary files /dev/null and b/wlauto/workloads/skype/com.arm.wlauto.uiauto.skype.jar differ
diff --git a/wlauto/workloads/skype/uiauto/build.sh b/wlauto/workloads/skype/uiauto/build.sh
new file mode 100755
index 00000000..d9673df8
--- /dev/null
+++ b/wlauto/workloads/skype/uiauto/build.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# CD into build dir if possible - allows building from any directory
+script_path='.'
+if `readlink -f $0 &>/dev/null`; then
+    script_path=`readlink -f $0 2>/dev/null`
+fi
+script_dir=`dirname $script_path`
+cd $script_dir
+
+# Ensure build.xml exists before starting
+if [[ ! -f build.xml ]]; then
+    echo 'Ant build.xml file not found! Check that you are in the right directory.'
+    exit 9
+fi
+
+# Copy base classes from wlauto dist
+class_dir=bin/classes/com/arm/wlauto/uiauto
+base_classes=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', '*.class')"`
+mkdir -p $class_dir
+cp $base_classes $class_dir
+
+# Build and return appropriate exit code if failed
+ant build
+exit_code=$?
+if [[ $exit_code -ne 0 ]]; then
+    echo "ERROR: 'ant build' exited with code $exit_code"
+    exit $exit_code
+fi
+
+# If successful move JAR file to workload folder (overwrite previous)
+package=com.arm.wlauto.uiauto.skype.jar
+rm -f ../$package
+if [[ -f bin/$package ]]; then
+    cp bin/$package ..
+else
+    echo 'ERROR: UiAutomator JAR could not be found!'
+    exit 9
+fi
diff --git a/wlauto/workloads/skypevideo/uiauto/build.xml b/wlauto/workloads/skype/uiauto/build.xml
similarity index 98%
rename from wlauto/workloads/skypevideo/uiauto/build.xml
rename to wlauto/workloads/skype/uiauto/build.xml
index c2fdeb90..dd54c056 100644
--- a/wlauto/workloads/skypevideo/uiauto/build.xml
+++ b/wlauto/workloads/skype/uiauto/build.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project name="com.arm.wlauto.uiauto.skypevideo" default="help">
+<project name="com.arm.wlauto.uiauto.skype" default="help">
 
     <!-- The local.properties file is created and updated by the 'android' tool.
          It contains the path to the SDK. It should *NOT* be checked into
diff --git a/wlauto/workloads/skypevideo/uiauto/project.properties b/wlauto/workloads/skype/uiauto/project.properties
similarity index 100%
rename from wlauto/workloads/skypevideo/uiauto/project.properties
rename to wlauto/workloads/skype/uiauto/project.properties
diff --git a/wlauto/workloads/skype/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java b/wlauto/workloads/skype/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java
new file mode 100644
index 00000000..78163e42
--- /dev/null
+++ b/wlauto/workloads/skype/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java
@@ -0,0 +1,183 @@
+/*    Copyright 2014-2016 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.arm.wlauto.uiauto.skype;
+
+import android.os.Bundle;
+
+// Import the uiautomator libraries
+import com.android.uiautomator.core.UiObject;
+import com.android.uiautomator.core.UiObjectNotFoundException;
+import com.android.uiautomator.core.UiSelector;
+import com.android.uiautomator.core.UiWatcher;
+import com.arm.wlauto.uiauto.UxPerfUiAutomation;
+
+import java.util.concurrent.TimeUnit;
+
+public class UiAutomation extends UxPerfUiAutomation {
+
+    public static final String TEXT_VIEW = "android.widget.TextView";
+
+    public Bundle parameters;
+    public String packageName;
+    public String packageID;
+
+    // Creates a watcher for when a pop up dialog appears with a dismiss button.
+    private UiWatcher createInfoPopUpWatcher() throws Exception {
+        UiWatcher infoPopUpWatcher = new UiWatcher() {
+            @Override
+            public boolean checkForCondition() {
+                UiObject dismissButton =
+                    new UiObject(new UiSelector().resourceId(packageID + "dismiss_button"));
+
+                if (dismissButton.exists()) {
+                    try {
+                        dismissButton.click();
+                    } catch (UiObjectNotFoundException e) {
+                        e.printStackTrace();
+                    }
+
+                    Long viewTimeout = TimeUnit.SECONDS.toMillis(10);
+                    boolean dismissed = dismissButton.waitUntilGone(viewTimeout);
+
+                    return dismissed;
+                }
+                return false;
+            }
+        };
+
+        return infoPopUpWatcher;
+    }
+
+    public void runUiAutomation() throws Exception {
+        // Override superclass value
+        this.uiAutoTimeout = TimeUnit.SECONDS.toMillis(10);
+
+        // Get Params
+        parameters = getParams();
+        packageName = parameters.getString("package");
+        packageID = packageName + ":id/";
+        String loginName = parameters.getString("my_id");
+        String loginPass = parameters.getString("my_pwd");
+        String contactName = parameters.getString("name").replace("0space0", " ");
+        int callDuration = Integer.parseInt(parameters.getString("duration"));
+        String callType = parameters.getString("action");
+        String resultsFile = parameters.getString("results_file");
+
+        setScreenOrientation(ScreenOrientation.NATURAL);
+
+        UiWatcher infoPopUpWatcher = createInfoPopUpWatcher();
+        registerWatcher("infoPopUpWatcher", infoPopUpWatcher);
+        runWatchers();
+
+        // Run tests
+        handleLoginScreen(loginName, loginPass);
+        searchForContact(contactName);
+
+        if ("video".equalsIgnoreCase(callType)) {
+            videoCallTest(callDuration);
+        } else if ("voice".equalsIgnoreCase(callType)) {
+            voiceCallTest(callDuration);
+        }
+
+        removeWatcher("infoPopUpWatcher");
+        unsetScreenOrientation();
+    }
+
+    public void handleLoginScreen(String username, String password) throws Exception {
+        String useridResoureId = packageID + "sign_in_userid";
+        String nextButtonResourceId = packageID + "sign_in_next_btn";
+        UiObject useridField = new UiObject(new UiSelector().resourceId(useridResoureId));
+        UiObject nextButton = new UiObject(new UiSelector().resourceId(nextButtonResourceId));
+        useridField.setText(username);
+        nextButton.clickAndWaitForNewWindow();
+
+        String passwordResoureId = packageID + "signin_password";
+        String signinButtonResourceId = packageID + "sign_in_btn";
+        UiObject passwordField = new UiObject(new UiSelector().resourceId(passwordResoureId));
+        UiObject signinButton = new UiObject(new UiSelector().resourceId(signinButtonResourceId));
+        passwordField.setText(password);
+        signinButton.clickAndWaitForNewWindow();
+    }
+
+    public void searchForContact(String name) throws Exception {
+        UiObject menuSearch = new UiObject(new UiSelector().resourceId(packageID + "menu_search"));
+        boolean sharingResource = false;
+
+        // If searching for a contact from Skype directly we need
+        // to click the menu search button to display the contact search box.
+        if (menuSearch.waitForExists(uiAutoTimeout)) {
+            menuSearch.click();
+
+        // If sharing a resource from another app the contact search box is shown
+        // by default.
+        } else {
+            sharingResource = true;
+        }
+
+        UiObject search = getUiObjectByText("Search", "android.widget.EditText");
+        search.setText(name);
+
+        UiObject peopleItem = getUiObjectByText(name, "android.widget.TextView");
+
+        peopleItem.waitForExists(uiAutoTimeout);
+        peopleItem.click();
+
+        UiObject avatarPresence =
+            new UiObject(new UiSelector().resourceId(packageID + "skype_avatar_presence"));
+
+        // On some devices two clicks are needed to select a contact.
+        if (!avatarPresence.waitUntilGone(uiAutoTimeout)) {
+            peopleItem.click();
+        }
+
+        // Before sharing a resource from another app we first need to
+        // confirm our selection.
+        if (sharingResource) {
+            UiObject confirm =
+                new UiObject(new UiSelector().resourceId(packageID + "fab"));
+            confirm.click();
+        }
+    }
+
+    private void voiceCallTest(int duration) throws Exception {
+        String testTag = "call_voice";
+        ActionLogger logger = new ActionLogger(testTag, parameters);
+
+        logger.start();
+        makeCall(duration, false, testTag);
+        logger.stop();
+    }
+
+    private void videoCallTest(int duration) throws Exception {
+        String testTag = "call_video";
+        ActionLogger logger = new ActionLogger(testTag, parameters);
+
+        logger.start();
+        makeCall(duration, true, testTag);
+        logger.stop();
+    }
+
+    private void makeCall(int duration, boolean video, String testTag) throws Exception {
+        String description = video ? "Video call" : "Call options";
+
+        UiObject callButton = new UiObject(new UiSelector().descriptionContains(description));
+        callButton.clickAndWaitForNewWindow();
+
+        UiObject muteButton = new UiObject(new UiSelector().descriptionContains("Mute"));
+        muteButton.click();
+        sleep(duration);
+    }
+}
diff --git a/wlauto/workloads/skypevideo/__init__.py b/wlauto/workloads/skypevideo/__init__.py
deleted file mode 100644
index 58959e1f..00000000
--- a/wlauto/workloads/skypevideo/__init__.py
+++ /dev/null
@@ -1,130 +0,0 @@
-#    Copyright 2014-2015 ARM Limited
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# pylint: disable=E1101,W0201,E0203
-
-import time
-
-from wlauto import UiAutomatorWorkload, Parameter
-from wlauto.utils.types import boolean
-
-
-class SkypeVideo(UiAutomatorWorkload):
-
-    name = 'skypevideo'
-    description = """
-    Initiates Skype video call to a specified contact for a pre-determined duration.
-    (Note: requires Skype to be set up appropriately).
-
-    This workload is intended for monitoring the behaviour of a device while a Skype
-    video call is in progress (a common use case). It does not produce any score or
-    metric and the intention is that some addition instrumentation is enabled while
-    running this workload.
-
-    This workload, obviously, requires a network connection (ideally, wifi).
-
-    This workload accepts the following parameters:
-
-
-    **Skype Setup**
-
-       - You should install Skype client from Google Play Store on the device
-         (this was tested with client version 4.5.0.39600; other recent versions
-         should also work).
-       - You must have an account set up and logged into Skype on the device.
-       - The contact to be called must be added (and has accepted) to the
-         account. It's possible to have multiple contacts in the list, however
-         the contact to be called *must* be visible on initial navigation to the
-         list.
-       - The contact must be able to received the call. This means that there
-         must be  a Skype client running (somewhere) with the contact logged in
-         and that client must have been configured to auto-accept calls from the
-         account on the device (how to set this varies between different versions
-         of Skype and between platforms -- please search online for specific
-         instructions).
-         https://support.skype.com/en/faq/FA3751/can-i-automatically-answer-all-my-calls-with-video-in-skype-for-windows-desktop
-
-    """
-
-    package = 'com.skype.raider'
-
-    parameters = [
-        Parameter('duration', kind=int, default=300,
-                  description='Duration of the video call in seconds.'),
-        Parameter('contact', mandatory=True,
-                  description="""
-                  The name of the Skype contact to call. The contact must be already
-                  added (see below). *If use_gui is set*, then this must be the skype
-                  ID of the contact, *otherwise*, this must be the name of the
-                  contact as it appears in Skype client's contacts list. In the latter case
-                  it *must not* contain underscore characters (``_``); it may, however, contain
-                  spaces. There is no default, you **must specify the name of the contact**.
-
-                  .. note:: You may alternatively specify the contact name as
-                            ``skype_contact`` setting in your ``config.py``. If this is
-                            specified, the ``contact`` parameter is optional, though
-                            it may still be specified (in which case it will override
-                            ``skype_contact`` setting).
-                  """),
-        Parameter('use_gui', kind=boolean, default=False,
-                  description="""
-                  Specifies whether the call should be placed directly through a
-                  Skype URI, or by navigating the GUI. The URI is the recommended way
-                  to place Skype calls on a device, but that does not seem to work
-                  correctly on some devices (the URI seems to just start Skype, but not
-                  place the call), so an alternative exists that will start the Skype app
-                  and will then navigate the UI to place the call (incidentally, this method
-                  does not seem to work on all devices either, as sometimes Skype starts
-                  backgrounded...). Please note that the meaning of ``contact`` prameter
-                  is different depending on whether this is set.  Defaults to ``False``.
-
-                  .. note:: You may alternatively specify this as ``skype_use_gui`` setting
-                            in your ``config.py``.
-                  """),
-
-    ]
-
-    def __init__(self, device, **kwargs):
-        super(SkypeVideo, self).__init__(device, **kwargs)
-        if self.use_gui:
-            self.uiauto_params['name'] = self.contact.replace(' ', '_')
-            self.uiauto_params['duration'] = self.duration
-        self.run_timeout = self.duration + 30
-
-    def setup(self, context):
-        if self.use_gui:
-            super(SkypeVideo, self).setup(context)
-            self.device.execute('am force-stop {}'.format(self.package))
-            self.device.execute('am start -W -a android.intent.action.VIEW -d skype:')
-        else:
-            self.device.execute('am force-stop {}'.format(self.package))
-
-    def run(self, context):
-        if self.use_gui:
-            super(SkypeVideo, self).run(context)
-        else:
-            command = "am start -W -a android.intent.action.VIEW -d \"skype:{}?call&video=true\""
-            self.logger.debug(self.device.execute(command.format(self.contact)))
-            self.logger.debug('Call started; waiting for {} seconds...'.format(self.duration))
-            time.sleep(self.duration)
-            self.device.execute('am force-stop com.skype.raider')
-
-    def update_result(self, context):
-        pass
-
-    def teardown(self, context):
-        if self.use_gui:
-            super(SkypeVideo, self).teardown(context)
-        self.device.execute('am force-stop {}'.format(self.package))
diff --git a/wlauto/workloads/skypevideo/com.arm.wlauto.uiauto.skypevideo.jar b/wlauto/workloads/skypevideo/com.arm.wlauto.uiauto.skypevideo.jar
deleted file mode 100644
index dff2302a..00000000
Binary files a/wlauto/workloads/skypevideo/com.arm.wlauto.uiauto.skypevideo.jar and /dev/null differ
diff --git a/wlauto/workloads/skypevideo/uiauto/build.sh b/wlauto/workloads/skypevideo/uiauto/build.sh
deleted file mode 100755
index db6f8ff4..00000000
--- a/wlauto/workloads/skypevideo/uiauto/build.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-#    Copyright 2014-2015 ARM Limited
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-
-
-class_dir=bin/classes/com/arm/wlauto/uiauto
-base_class=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', 'BaseUiAutomation.class')"`
-mkdir -p $class_dir
-cp $base_class $class_dir
-
-ant build
-
-if [[ -f bin/com.arm.wlauto.uiauto.skypevideo.jar ]]; then
-    cp bin/com.arm.wlauto.uiauto.skypevideo.jar ..
-fi
diff --git a/wlauto/workloads/skypevideo/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java b/wlauto/workloads/skypevideo/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java
deleted file mode 100644
index 0743372e..00000000
--- a/wlauto/workloads/skypevideo/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*    Copyright 2014-2015 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
-
-
-package com.arm.wlauto.uiauto.skypevideo;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.KeyEvent;
-
-// Import the uiautomator libraries
-import com.android.uiautomator.core.UiObject;
-import com.android.uiautomator.core.UiObjectNotFoundException;
-import com.android.uiautomator.core.UiScrollable;
-import com.android.uiautomator.core.UiSelector;
-import com.android.uiautomator.testrunner.UiAutomatorTestCase;
-
-import com.arm.wlauto.uiauto.BaseUiAutomation;
-
-public class UiAutomation extends BaseUiAutomation {   
-
-    public static String TAG = "skypevideo";
-    public static String videoCallButtonResourceId = "com.skype.raider:id/chat_menu_item_call_video";
-    public static String noContactMessage = "Could not find contact \"%s\" in the contacts list.";
-
-    public void runUiAutomation() throws Exception {
-            Bundle parameters = getParams();
-            String contactName = parameters.getString("name").replace('_', ' ');
-            int duration = Integer.parseInt(parameters.getString("duration"));
-
-            selectContact(contactName);
-            initiateCall(duration);
-    }
-
-    public void selectContact(String name) throws Exception {
-            UiSelector selector = new UiSelector();
-            UiObject peopleTab = new UiObject(selector.text("People"));
-            peopleTab.click();
-            sleep(1);  // tab transition
-
-            // Note: this assumes that the contact is in view and does not attempt to scroll to find it.
-            // The expectation is that this automation will be used with a dedicated account that was set 
-            // up for the purpose and so would only have the intended target plus one or two other contacts 
-            // at most  in the list. If that is not the case, then this needs to be re-written to scroll to 
-            // find the contact if necessary.
-            UiObject contactCard = new UiObject(selector.text(name));
-            if (!contactCard.exists()) {
-                    throw new UiObjectNotFoundException(String.format(noContactMessage, name));
-            }
-            contactCard.clickAndWaitForNewWindow();
-    }
-
-    public void initiateCall(int duration) throws Exception {
-            UiSelector selector = new UiSelector();
-            UiObject videoCallButton = new UiObject(selector.resourceId(videoCallButtonResourceId));
-            videoCallButton.click();
-            sleep(duration);
-    }
-}