diff --git a/wlauto/workloads/gmail/__init__.py b/wlauto/workloads/gmail/__init__.py new file mode 100755 index 00000000..dd8b93c6 --- /dev/null +++ b/wlauto/workloads/gmail/__init__.py @@ -0,0 +1,78 @@ +import os +import logging +import re +import time + +from wlauto import AndroidUiAutoBenchmark, Parameter + + +class Gmail(AndroidUiAutoBenchmark): + + name = 'gmail' + package = 'com.google.android.gm' + activity = '' + view = [package+'/com.google.android.gm.ConversationListActivityGmail', + package+'/com.google.android.gm.ComposeActivityGmail'] + description = """ + A workload to perform standard productivity tasks within Gmail. + + The workload carries out various tasks, such as creatign new emails and + sending them, whilst also producing metrics for action completion times. + """ + + regex = re.compile(r'uxperf_gmail.*: (?P\w+) (?P\d+)') + + parameters = [ + Parameter('recipient', default='armuxperf@gmail.com', mandatory=False, + description="""" + The email address of the recipient. Setting a void address + will stop any mesage failures clogging up your device inbox + """), + Parameter('dumpsys_enabled', kind=bool, default=True, + description=""" + If ``True``, dumpsys captures will be carried out during the + test run. The output is piped to log files which are then + pulled from the phone. + """), + ] + + instrumentation_log = ''.join([name, '_instrumentation.log']) + + def __init__(self, device, **kwargs): + super(Gmail, self).__init__(device, **kwargs) + self.uiauto_params['recipient'] = self.recipient + + def validate(self): + super(Gmail, self).validate() + self.output_file = os.path.join(self.device.working_directory, self.instrumentation_log) + self.uiauto_params['package'] = self.package + self.uiauto_params['output_dir'] = self.device.working_directory + self.uiauto_params['output_file'] = self.output_file + self.uiauto_params['dumpsys_enabled'] = self.dumpsys_enabled + + def update_result(self, context): + super(Gmail, self).update_result(context) + + if self.dumpsys_enabled: + self.device.pull_file(self.output_file, context.output_directory) + result_file = os.path.join(context.output_directory, self.instrumentation_log) + + with open(result_file, 'r') as wfh: + regex = re.compile(r'(?P\w+)\s+(?P\d+)\s+(?P\d+)\s+(?P\d+)') + for line in wfh: + match = regex.search(line) + if match: + context.result.add_metric((match.group('key') + "_start"), + match.group('value1')) + context.result.add_metric((match.group('key') + "_finish"), + match.group('value2')) + context.result.add_metric((match.group('key') + "_duration"), + match.group('value3')) + + def teardown(self, context): + super(Gmail, self).teardown(context) + + for file in self.device.listdir(self.device.working_directory): + if file.startswith (self.name) and file.endswith(".log"): + self.device.pull_file(os.path.join(self.device.working_directory, file), context.output_directory) + self.device.delete_file(os.path.join(self.device.working_directory, file)) diff --git a/wlauto/workloads/gmail/com.arm.wlauto.uiauto.gmail.jar b/wlauto/workloads/gmail/com.arm.wlauto.uiauto.gmail.jar new file mode 100644 index 00000000..9e50ab70 Binary files /dev/null and b/wlauto/workloads/gmail/com.arm.wlauto.uiauto.gmail.jar differ diff --git a/wlauto/workloads/gmail/uiauto/build.sh b/wlauto/workloads/gmail/uiauto/build.sh new file mode 100755 index 00000000..88752a4b --- /dev/null +++ b/wlauto/workloads/gmail/uiauto/build.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +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 + +ant build + +if [[ -f bin/com.arm.wlauto.uiauto.gmail.jar ]]; then + cp bin/com.arm.wlauto.uiauto.gmail.jar .. +fi diff --git a/wlauto/workloads/gmail/uiauto/build.xml b/wlauto/workloads/gmail/uiauto/build.xml new file mode 100644 index 00000000..a0c4d822 --- /dev/null +++ b/wlauto/workloads/gmail/uiauto/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wlauto/workloads/gmail/uiauto/project.properties b/wlauto/workloads/gmail/uiauto/project.properties new file mode 100644 index 00000000..ce39f2d0 --- /dev/null +++ b/wlauto/workloads/gmail/uiauto/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-18 diff --git a/wlauto/workloads/gmail/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java b/wlauto/workloads/gmail/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java new file mode 100644 index 00000000..afeafcec --- /dev/null +++ b/wlauto/workloads/gmail/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java @@ -0,0 +1,123 @@ +package com.arm.wlauto.uiauto.gmail; + +import android.os.Bundle; +import android.os.SystemClock; + +// 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.UxPerfUiAutomation; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.util.LinkedHashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +public class UiAutomation extends UxPerfUiAutomation { + + public static String TAG = "uxperf_gmail"; + + private Bundle parameters; + private LinkedHashMap timingResults = new LinkedHashMap(); + + public void runUiAutomation() throws Exception { + parameters = getParams(); + + Timer result = new Timer(); + result.start(); + + clearFirstRunDialogues(); + + clickNewMail(); + setToField(); + setSubjectField(); + setComposeField(); + clickSendButton(); + + result.end(); + timingResults.put("Total", result); + + writeResultsToFile(timingResults, parameters.getString("output_file")); + } + + public void clearFirstRunDialogues () throws Exception { + // Enter search text into the file searchBox. This will automatically filter the list. + UiObject gotItBox = getUiObjectByResourceId("com.google.android.gm:id/welcome_tour_got_it", + "android.widget.TextView"); + gotItBox.clickAndWaitForNewWindow(); + UiObject takeMeToBox = getUiObjectByText("Take me to Gmail", "android.widget.TextView"); + takeMeToBox.clickAndWaitForNewWindow(); + } + + public void clickNewMail() throws Exception { + Timer result = new Timer(); + UiObject newMailButton = getUiObjectByDescription("Compose", "android.widget.ImageButton"); + result.start(); + newMailButton.clickAndWaitForNewWindow(timeout); + result.end(); + timingResults.put("newMail", result); + } + + public void setToField() throws Exception { + Timer result = new Timer(); + UiObject toField = getUiObjectByDescription("To", "android.widget.TextView"); + String recipient = parameters.getString("recipient").replace('_', ' '); + result.start(); + toField.setText(recipient); + getUiDevice().pressEnter(); + result.end(); + timingResults.put("To", result); + } + + public void setSubjectField() throws Exception { + Timer result = new Timer(); + UiObject subjectField = getUiObjectByText("Subject", "android.widget.EditText"); + result.start(); + subjectField.setText("This is a test message"); + getUiDevice().pressEnter(); + result.end(); + timingResults.put("Subject", result); + } + + public void setComposeField() throws Exception { + Timer result = new Timer(); + UiObject composeField = getUiObjectByText("Compose email", "android.widget.EditText"); + result.start(); + composeField.setText("This is a test composition"); + getUiDevice().pressEnter(); + result.end(); + timingResults.put("Compose", result); + } + + public void clickSendButton() throws Exception { + Timer result = new Timer(); + UiObject sendButton = getUiObjectByDescription("Send", "android.widget.TextView"); + result.start(); + sendButton.clickAndWaitForNewWindow(timeout); + result.end(); + timingResults.put("Send", result); + } + + private void writeResultsToFile(LinkedHashMap timingResults, String file) throws Exception { + // Write out the key/value pairs to the instrumentation log file + FileWriter fstream = new FileWriter(file); + BufferedWriter out = new BufferedWriter(fstream); + Iterator> it = timingResults.entrySet().iterator(); + + while (it.hasNext()) { + Map.Entry pairs = it.next(); + Timer results = pairs.getValue(); + long start = results.getStart(); + long finish = results.getFinish(); + long duration = results.getDuration(); + out.write(String.format(pairs.getKey() + " " + start + " " + finish + " " + duration + "\n")); + } + out.close(); + } +}