From b0d0a19bf0829d0d9a10e2a0d9d617ffb0192a16 Mon Sep 17 00:00:00 2001 From: James Hartley Date: Thu, 28 Apr 2016 13:13:36 +0100 Subject: [PATCH] Reader productivity workload A new workload to perform standard productivity tasks within Reader. Each user event/step is timed and reported back as a metric. Dumpsys also captures SurfaceFlinger logs for each event for post analysis. --- wlauto/workloads/reader/__init__.py | 93 ++++ .../reader/com.arm.wlauto.uiauto.reader.jar | Bin 0 -> 11683 bytes wlauto/workloads/reader/uiauto/build.sh | 12 + wlauto/workloads/reader/uiauto/build.xml | 92 ++++ .../reader/uiauto/project.properties | 14 + .../com/arm/wlauto/uiauto/UiAutomation.java | 399 ++++++++++++++++++ 6 files changed, 610 insertions(+) create mode 100755 wlauto/workloads/reader/__init__.py create mode 100644 wlauto/workloads/reader/com.arm.wlauto.uiauto.reader.jar create mode 100755 wlauto/workloads/reader/uiauto/build.sh create mode 100644 wlauto/workloads/reader/uiauto/build.xml create mode 100644 wlauto/workloads/reader/uiauto/project.properties create mode 100755 wlauto/workloads/reader/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java diff --git a/wlauto/workloads/reader/__init__.py b/wlauto/workloads/reader/__init__.py new file mode 100755 index 00000000..53c6fe3d --- /dev/null +++ b/wlauto/workloads/reader/__init__.py @@ -0,0 +1,93 @@ +import os +import logging +import re +import time + +from wlauto import AndroidUiAutoBenchmark, Parameter + + +class Reader(AndroidUiAutoBenchmark): + + activity = 'com.adobe.reader.AdobeReader' + name = 'reader' + package = 'com.adobe.reader' + view = [package+'/com.adobe.reader.help.AROnboardingHelpActivity', + package+'/com.adobe.reader.viewer.ARSplitPaneActivity', + package+'/com.adobe.reader.viewer.ARViewerActivity'] + description = """ + A workload to perform standard productivity tasks within Adobe Reader. + + The workload carries out various tasks, such as opening PDF documents, + scrolling and searching through them, whilst also producing metrics for + action completion times. + """ + + parameters = [ + 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. + """), + Parameter('email', kind=str, default="email@gmail.com", + description=""" + Email account used to register with Adobe online services. + """), + Parameter('password', kind=str, default="password", + description=""" + Password for Adobe online services. + """), + ] + + instrumentation_log = ''.join([name, '_instrumentation.log']) + + def validate(self): + super(Reader, 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['email'] = self.email + self.uiauto_params['password'] = self.password + self.uiauto_params['dumpsys_enabled'] = self.dumpsys_enabled + + def setup(self, context): + super(Reader, self).setup(context) + + self.reader_local_dir = self.device.path.join(self.device.external_storage_directory, + 'Android/data/com.adobe.reader/files/') + + for file in os.listdir(self.dependencies_directory): + if file.endswith(".pdf"): + self.device.push_file(os.path.join(self.dependencies_directory, file), + os.path.join(self.reader_local_dir, file), timeout=300) + + def update_result(self, context): + super(Reader, 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(Reader, self).teardown(context) + for file in self.device.listdir(self.reader_local_dir): + if file.endswith(".pdf"): + self.device.delete_file(os.path.join(self.reader_local_dir, file)) + + 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/reader/com.arm.wlauto.uiauto.reader.jar b/wlauto/workloads/reader/com.arm.wlauto.uiauto.reader.jar new file mode 100644 index 0000000000000000000000000000000000000000..5be714c62c575d14bc71c50dc9969f60c1694692 GIT binary patch literal 11683 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 literal 0 HcmV?d00001 diff --git a/wlauto/workloads/reader/uiauto/build.sh b/wlauto/workloads/reader/uiauto/build.sh new file mode 100755 index 00000000..a32e8f49 --- /dev/null +++ b/wlauto/workloads/reader/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.reader.jar ]]; then + cp bin/com.arm.wlauto.uiauto.reader.jar .. +fi diff --git a/wlauto/workloads/reader/uiauto/build.xml b/wlauto/workloads/reader/uiauto/build.xml new file mode 100644 index 00000000..0714c6a4 --- /dev/null +++ b/wlauto/workloads/reader/uiauto/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wlauto/workloads/reader/uiauto/project.properties b/wlauto/workloads/reader/uiauto/project.properties new file mode 100644 index 00000000..6e18427a --- /dev/null +++ b/wlauto/workloads/reader/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-21 diff --git a/wlauto/workloads/reader/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java b/wlauto/workloads/reader/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java new file mode 100755 index 00000000..c51f38da --- /dev/null +++ b/wlauto/workloads/reader/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java @@ -0,0 +1,399 @@ +package com.arm.wlauto.uiauto.reader; + +import android.graphics.Rect; +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.core.UiCollection; +import com.android.uiautomator.testrunner.UiAutomatorTestCase; + +import com.arm.wlauto.uiauto.UxPerfUiAutomation; + +import java.io.File; +import java.io.FileWriter; +import java.io.BufferedWriter; +import java.util.concurrent.TimeUnit; +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_reader"; + + private Bundle parameters; + private long networkTimeout = TimeUnit.SECONDS.toMillis(20); + private long searchTimeout = TimeUnit.SECONDS.toMillis(20); + private LinkedHashMap timingResults = new LinkedHashMap(); + + public void runUiAutomation() throws Exception { + Timer result = new Timer(); + result.start(); + parameters = getParams(); + + dismissWelcomeView(); + + signInOnline(parameters); + + confirmLocalFileAccess(); + + gesturesTest("Getting Started.pdf"); + + String [] searchStrings = {"Glossary", "cortex"}; + searchPdfTest("cortex_m4", searchStrings); + + result.end(); + timingResults.put("Total", result); + + writeResultsToFile(timingResults, parameters.getString("output_file")); + } + + private void dismissWelcomeView() throws Exception { + UiObject welcomeView = getUiObjectByDescription("Acrobat - First Time Experience", + "android.webkit.WebView"); + // Click through the first two pages and wait for pages to transition. + // These pages are webkit views so clickAndWaitForNewWindow or waitForExists cannot be used + tapDisplayCentre(); + sleep(1); + tapDisplayCentre(); + sleep(1); + + // Get the box coords for the webView window + Rect webViewCoords = welcomeView.getBounds(); + + // Iterate up from the bottom middle of the webView until we hit these + // Continue button and change view + int i = 0; + do { + i += 10; + tapDisplay(webViewCoords.centerX(), webViewCoords.bottom - i); + } while ( welcomeView.exists() || i < webViewCoords.top ); + } + + private void signInOnline(Bundle parameters) throws Exception { + String email = parameters.getString("email"); + String password = parameters.getString("password"); + + UiObject homeButton = getUiObjectByResourceId("android:id/home", "android.widget.ImageView"); + homeButton.clickAndWaitForNewWindow(); + + UiObject firstSignInButton = getUiObjectByResourceId("com.adobe.reader:id/user_info_title", + "android.widget.TextView"); + firstSignInButton.clickAndWaitForNewWindow(); + + // resourceId cannot be trusted across different devices in this view so use description + // and indexes instead + UiObject secondSignInButton = getUiObjectByDescription("Sign In", "android.view.View"); + secondSignInButton.clickAndWaitForNewWindow(); + + UiObject emailBox = new UiObject(new UiSelector().className("android.webkit.WebView") + .description("Sign in - Adobe ID") + .childSelector(new UiSelector() + .index(0).className("android.view.View") + .childSelector(new UiSelector() + .index(1).className("android.view.View") + .childSelector(new UiSelector() + .index(0).className("android.view.View") + .childSelector(new UiSelector() + .index(0).className("android.widget.EditText")))))); + emailBox.setText(email); + UiObject passwordBox = new UiObject(new UiSelector().className("android.webkit.WebView") + .description("Sign in - Adobe ID") + .childSelector(new UiSelector() + .index(0).className("android.view.View") + .childSelector(new UiSelector() + .index(1).className("android.view.View") + .childSelector(new UiSelector() + .index(1).className("android.view.View") + .childSelector(new UiSelector() + .index(0).className("android.widget.EditText")))))); + passwordBox.setText(password); + UiObject lastSignInButton = new UiObject(new UiSelector().className("android.webkit.WebView") + .description("Sign in - Adobe ID") + .childSelector(new UiSelector() + .index(0).className("android.view.View") + .childSelector(new UiSelector() + .index(1).className("android.view.View") + .childSelector(new UiSelector() + .index(3).className("android.view.View") + .childSelector(new UiSelector() + .index(0).className("android.widget.Button")))))); + lastSignInButton.clickAndWaitForNewWindow(); + + UiObject upButton = new UiObject(new UiSelector().resourceId("android:id/up") + .className("android.widget.ImageView")); + if (upButton.waitForExists(TimeUnit.SECONDS.toMillis(networkTimeout))) { + upButton.clickAndWaitForNewWindow(); + } + } + + private void confirmLocalFileAccess() throws Exception { + // First time run requires confirmation to allow access to local files + UiObject allowButton = new UiObject(new UiSelector().textContains("Allow") + .className("android.widget.Button")); + if (allowButton.waitForExists(timeout)) { + allowButton.clickAndWaitForNewWindow(timeout); + }; + } + + private void openFile(String filename) throws Exception { + // Replace whitespace and full stops within the filename + String file = filename.replaceAll("\\.", "_").replaceAll("\\s+", "_"); + + timingResults.put(String.format("selectLocalFilesList" + "_" + file), selectLocalFilesList()); + timingResults.put(String.format("selectSearchDuration" + "_" + file), selectSearchFileButton()); + timingResults.put(String.format("searchFileList" + "_" + file), searchFileList(filename)); + timingResults.put(String.format("openFileFromList" + "_" + file), openFileFromList(filename)); + + // Cludge to get rid of the first time run help dialogue boxes + tapDisplayCentre(); + sleep(1); + tapDisplayCentre(); + sleep(1); + } + + private Timer selectLocalFilesList() throws Exception { + // Select the local files list from the My Documents view + UiObject localButton = getUiObjectByText("LOCAL", "android.widget.TextView"); + Timer result = new Timer(); + result.start(); + localButton.clickAndWaitForNewWindow(timeout); + long finish = SystemClock.elapsedRealtime(); + result.end(); + return result; + } + + private Timer selectSearchFileButton() throws Exception { + // Click the button to search from the present file list view + UiObject searchButton = getUiObjectByResourceId("com.adobe.reader:id/split_pane_search", + "android.widget.TextView"); + Timer result = new Timer(); + result.start(); + searchButton.click(); + long finish = SystemClock.elapsedRealtime(); + result.end(); + return result; + } + + private Timer searchFileList(String searchText) throws Exception { + // Enter search text into the file searchBox. This will automatically filter the list. + UiObject searchBox = getUiObjectByResourceId("android:id/search_src_text", + "android.widget.EditText"); + Timer result = new Timer(); + result.start(); + searchBox.setText(searchText); + long finish = SystemClock.elapsedRealtime(); + result.end(); + return result; + } + + private Timer openFileFromList(String file) throws Exception { + // Open a file from a file list view by searching for UiObjects containing the doc title. + UiObject fileObject = getUiObjectByText(file, "android.widget.TextView"); + Timer result = new Timer(); + result.start(); + fileObject.clickAndWaitForNewWindow(timeout); + result.end(); + + // Wait for the doc to open by waiting for the viewPager UiObject to exist + UiObject viewPager = new UiObject(new UiSelector().resourceId("com.adobe.reader:id/viewPager")); + if (!viewPager.waitForExists(timeout)) { + throw new UiObjectNotFoundException("Could not find \"viewPager\"."); + }; + return result; + } + + private class GestureTestParams { + GestureType gestureType; + Direction gestureDirection; + PinchType pinchType; + int percent; + int steps; + + GestureTestParams(GestureType gesture, Direction direction, int steps) { + this.gestureType = gesture; + this.gestureDirection = direction; + this.pinchType = PinchType.NULL; + this.steps = steps; + this.percent = 0; + } + + GestureTestParams(GestureType gesture, PinchType pinchType, int steps, int percent) { + this.gestureType = gesture; + this.gestureDirection = Direction.NULL; + this.pinchType = pinchType; + this.steps = steps; + this.percent = percent; + } + } + + private void gesturesTest (String filename) throws Exception { + + String TestTag = "gestures"; + + // Perform a range of swipe tests at different speeds and on different views + LinkedHashMap testParams = new LinkedHashMap(); + testParams.put("1", new GestureTestParams(GestureType.UIDEVICE_SWIPE, Direction.DOWN, 100)); + testParams.put("2", new GestureTestParams(GestureType.UIDEVICE_SWIPE, Direction.UP, 100)); + testParams.put("3", new GestureTestParams(GestureType.UIOBJECT_SWIPE, Direction.RIGHT, 50)); + testParams.put("4", new GestureTestParams(GestureType.UIOBJECT_SWIPE, Direction.LEFT, 50)); + testParams.put("5", new GestureTestParams(GestureType.PINCH, PinchType.OUT, 100, 200)); + testParams.put("6", new GestureTestParams(GestureType.PINCH, PinchType.IN, 100, 50)); + + Iterator> it = testParams.entrySet().iterator(); + + openFile(filename); + + while (it.hasNext()) { + Map.Entry pair = it.next(); + GestureType type = pair.getValue().gestureType; + Direction dir = pair.getValue().gestureDirection; + PinchType pinch = pair.getValue().pinchType; + int steps = pair.getValue().steps; + int percent = pair.getValue().percent; + + String runName = String.format(TestTag + "_" + pair.getKey()); + String gfxInfologName = String.format(TAG + "_" + runName + "_gfxInfo.log"); + String surfFlingerlogName = String.format(runName + "_surfFlinger.log"); + String viewName = new String("com.adobe.reader.viewer.ARViewerActivity"); + + UiObject view = new UiObject(new UiSelector().resourceId("com.adobe.reader:id/viewPager")); + + startDumpsysGfxInfo(); + startDumpsysSurfaceFlinger(viewName); + + Timer results = new Timer(); + + switch (type) { + case UIDEVICE_SWIPE: + results = uiDeviceSwipeTest(dir, steps); + break; + case UIOBJECT_SWIPE: + results = uiObjectSwipeTest(view, dir, steps); + break; + case PINCH: + results = uiObjectPinchTest(view, pinch, steps, percent); + break; + default: + break; + } + + stopDumpsysSurfaceFlinger(viewName, surfFlingerlogName); + stopDumpsysGfxInfo(gfxInfologName); + + timingResults.put(runName, results); + } + + exitDocument(); + } + + private void searchPdfTest (String filename, String [] searchStrings) throws Exception { + + String TestTag = "search"; + + openFile(filename); + + // Get the page view for the opened document which we can use for pinch actions + UiObject pageView = getUiObjectByResourceId("com.adobe.reader:id/pageView", + "android.widget.RelativeLayout"); + for ( int i=0; i < searchStrings.length; i++) { + timingResults.put(String.format(TestTag + "_" + i), + searchTest(searchStrings[i])); + } + + exitDocument(); + } + + private Timer searchTest(String searchText) throws Exception { + // Click on the search button icon and enter text in the box. This closes the keyboad + // so click the box again and press Enter to start the search. + UiObject searchButton = getUiObjectByResourceId("com.adobe.reader:id/document_view_search_icon", + "android.widget.TextView"); + searchButton.clickAndWaitForNewWindow(); + UiObject searchBox = getUiObjectByResourceId("android:id/search_src_text", + "android.widget.EditText"); + searchBox.setText(searchText); + searchBox.click(); + Timer result = new Timer(); + result.start(); + getUiDevice().getInstance().pressEnter(); + + // Check the progress bar icon. When this disappears the search is complete. + UiObject progressBar = new UiObject(new UiSelector().resourceId("com.adobe.reader:id/searchProgress") + .className("android.widget.ProgressBar")); + progressBar.waitForExists(timeout); + progressBar.waitUntilGone(searchTimeout); + result.end(); + + // Get back to the main document view by clicking twice on the close button + UiObject searchCloseButton = getUiObjectByResourceId("android:id/search_close_btn", + "android.widget.ImageView"); + searchCloseButton.clickAndWaitForNewWindow(); + searchCloseButton.clickAndWaitForNewWindow(); + + return result; + } + + private void exitDocument() throws Exception { + // Return from the document view to the file list view by pressing home and my documents. + UiObject homeButton = new UiObject(new UiSelector().resourceId("android:id/home") + .className("android.widget.ImageView")); + if (!homeButton.waitForExists(timeout)) { + tapDisplayCentre(); + } + homeButton.clickAndWaitForNewWindow(); + UiObject myDocsButton = getUiObjectByDescription("My Documents", "android.widget.LinearLayout" ); + myDocsButton.clickAndWaitForNewWindow(); + UiObject upButton = getUiObjectByResourceId("android:id/up", "android.widget.ImageView" ); + upButton.clickAndWaitForNewWindow(); + } + + 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(); + } + + private void startDumpsysSurfaceFlinger(String view) { + if (Boolean.parseBoolean(parameters.getString("dumpsys_enabled"))) { + initDumpsysSurfaceFlinger(parameters.getString("package"), view); + } + } + + private void stopDumpsysSurfaceFlinger(String view, String filename) throws Exception { + if (Boolean.parseBoolean(parameters.getString("dumpsys_enabled"))) { + File out_file = new File(parameters.getString("output_dir"), filename); + exitDumpsysSurfaceFlinger(parameters.getString("package"), view, out_file); + } + } + + private void startDumpsysGfxInfo() { + if (Boolean.parseBoolean(parameters.getString("dumpsys_enabled"))) { + initDumpsysGfxInfo(parameters.getString("package")); + } + } + + private void stopDumpsysGfxInfo(String filename) throws Exception { + if (Boolean.parseBoolean(parameters.getString("dumpsys_enabled"))) { + File out_file = new File(parameters.getString("output_dir"), filename); + exitDumpsysGfxInfo(parameters.getString("package"), out_file); + } + } +}