From 65aa00483b983cd32bbf307f7fc9bb586c76db5e Mon Sep 17 00:00:00 2001 From: jummp01 Date: Tue, 31 Jan 2017 17:31:03 +0000 Subject: [PATCH 01/10] Add pressHome() method in the Base class This function Presses Home button on the Android User Interface. --- .../common/android/BaseUiAutomation$1.class | Bin 1786 -> 1786 bytes wlauto/common/android/BaseUiAutomation.class | Bin 17621 -> 17711 bytes .../arm/wlauto/uiauto/BaseUiAutomation.java | 3 +++ 3 files changed, 3 insertions(+) diff --git a/wlauto/common/android/BaseUiAutomation$1.class b/wlauto/common/android/BaseUiAutomation$1.class index 5a216cc3d3776d94ec9b697c0a9de60b3cac54a0..8298936c63c8830c153f9b39dc5842fbb98e27ad 100644 GIT binary patch delta 21 dcmeyx`-^wOS~kv?3}%e87;+eGCU0YN0RUX;2XO!Z delta 21 dcmeyx`-^wOS~kvS3}%ee8FCmcCvRhO0RUW?2WS8Q diff --git a/wlauto/common/android/BaseUiAutomation.class b/wlauto/common/android/BaseUiAutomation.class index 2188bd5fee26416ae3546e741b5904302f122444..b20d2376aefce4382a6942d9b37cecf622be87ee 100644 GIT binary patch literal 17711 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 literal 17621 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 diff --git a/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/BaseUiAutomation.java b/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/BaseUiAutomation.java index eb1e583b..1a234d52 100755 --- a/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/BaseUiAutomation.java +++ b/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/BaseUiAutomation.java @@ -228,6 +228,9 @@ public class BaseUiAutomation extends UiAutomatorTestCase { UiDevice.getInstance().pressEnter(); } + public void pressHome() { + UiDevice.getInstance().pressHome(); + } public void pressBack() { UiDevice.getInstance().pressBack(); From 4ce20e2d3f3cfd6cbcecdae2c6d1400e2e263f1a Mon Sep 17 00:00:00 2001 From: jummp01 Date: Tue, 31 Jan 2017 17:34:45 +0000 Subject: [PATCH 02/10] Move package parameters to UxperfUiAutomation All the uxperf workloads get some common package parameters. These are moved to the parent class and a new method is introduced to fill these parameter values. All the uxperf workloads can call this method to resolve the package parameters. --- ...UxPerfUiAutomation$GestureTestParams.class | Bin 1554 -> 1554 bytes .../UxPerfUiAutomation$GestureType.class | Bin 1287 -> 1287 bytes .../common/android/UxPerfUiAutomation.class | Bin 777 -> 1271 bytes .../arm/wlauto/uiauto/UxPerfUiAutomation.java | 11 +++++++++++ 4 files changed, 11 insertions(+) diff --git a/wlauto/common/android/UxPerfUiAutomation$GestureTestParams.class b/wlauto/common/android/UxPerfUiAutomation$GestureTestParams.class index d793d013fc00403942e06813619fc9326d0fb2ed..a62db9e1671530650ff9fc2b95eb0ab24044af5d 100644 GIT binary patch delta 67 zcmbQlGl^%zKNd+H1{MZg22KV&20jLT22lnB1}O$Z26+af$>OYKk|sb|Q=qIFg8+j$ SP}Tw{YssL%U^RIeYYqTf;0cca delta 67 zcmbQlGl^%zKNd+v1{MY-22KWL20jKA22lo81}O$L26+bc$>OYKlA1tSEugG6g8+jL SP*xWxtH+?gpg(yTYYqTMpa}H< diff --git a/wlauto/common/android/UxPerfUiAutomation$GestureType.class b/wlauto/common/android/UxPerfUiAutomation$GestureType.class index 8cc30f68d657406ecb7468e201c73005d2173529..fc2cf4d2339e7c337c2fe1ecdf169e7a06f736e9 100644 GIT binary patch delta 31 icmZqYYUkSUg_%)#@>gbkAgRh?2P9Ki8i3?e79{|h!U-n; delta 31 icmZqYYUkSUg_%)e@>gbkAgRh?2P9Ki8i3?e79{|fS_u09 diff --git a/wlauto/common/android/UxPerfUiAutomation.class b/wlauto/common/android/UxPerfUiAutomation.class index 1be53c1fea49f0f16764876678617a925da57df2..016b784f1d8d39acdd75838d693c8a3206e5c082 100644 GIT binary patch literal 1271 zcmb7DYfsZq7=F%}>sAV51LWcrMJQEPQM_?yAcSNgBwP~xcG!-y+O`*xQ{ux zd7$8-3Ki3Gna|>pw2$S@69rEdJYy(q3qJ@waX@B|d%WQ@XgiK0ybYWCzVH<+F!Y|H zJ~jn|+LS;M2#>&n74FnL*Q%MWZo)OfnM0doR4Yx+l^A*bxyJ6#4 zcnAF0j>5TBZXa>alKbQ^9lW+EU87QU8z%P}=6jomfoq0VWDY;<3GdaRwN7UZ9$2nJ z0f*{>ni3Tf^(HA<-FHK;Dz+>cY^0M}lGSRshU*OaMZ+mr)UbqQ1uGg>v8Le)u4=f9 z5e6k`m4bB*Wo&2|#TbSDyQ}5UvTMTAu!-l?p9LC7?=2|?zxn?FU}Xvu+SaY zS?T1dF3zcE{=dnQsPbpUM9QP8sr#{hhV+?k3L1?lU9>{tB5tf3hLYY%PW*M@(%1_f zijEz|(xpEB+u@%Q&+ukbI5mdZ3o(-MQ3lz-je}u=e%1l{>(lg*7NRd2eq?E=WK&Wo zk!4bHV7NiMRXS&63&shUQB1Yb^9AV^E`5riH)&M~0t}Pm33>o6Cg2us(~e>Cx3ib% ziSBg6_>4?ZX(QW0&iDrP#R+=pEZ2rs?4zZP{uc6QG5U!KN~@22O;ciLar7ik3U>&R V!W0I{7U`=%ZxJ~RksV$e`vq6VLgWAd delta 211 zcmW-axedZV5Jlfw$cxQ#8O(iOw#cXeBmxS6795cvj(`#zB1hCgMnC~{KqX{|fnere z`ZI4Qwu9&A{s3kKE;dz7&81GmrAf=dqOIv@x|j7h-&15((cyU7N1O95y1cGQtO7en zUJ)i+EA%ye!+@b?WEe9s7_zsy6{-$>IcCczB`EHnDWoh;A(^HI%c6L$q);YB1y7if Z6pEC@Lo)xrD>#ClXf2Z#_3LF8^)LVC7Ks1= diff --git a/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/UxPerfUiAutomation.java b/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/UxPerfUiAutomation.java index 10367015..68ec38fc 100644 --- a/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/UxPerfUiAutomation.java +++ b/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/UxPerfUiAutomation.java @@ -16,8 +16,19 @@ package com.arm.wlauto.uiauto; import java.util.logging.Logger; +import android.os.Bundle; public class UxPerfUiAutomation extends BaseUiAutomation { + + protected Bundle parameters; + protected String packageName; + protected String packageID; + + //Get application package parameters and create package ID + public void getPackageParameters() { + packageName = parameters.getString("package"); + packageID = packageName + ":id/"; + } private Logger logger = Logger.getLogger(UxPerfUiAutomation.class.getName()); From 99b46b4630c2864ce18b20ac43a0441aaf8a2459 Mon Sep 17 00:00:00 2001 From: jummp01 Date: Tue, 31 Jan 2017 17:44:51 +0000 Subject: [PATCH 03/10] Add UiAutoUtils class UiAutoUtility class added to support utility functions used for UiAutomation. This class can help in refactoring some existing fucntionalities into utility functions. Launch command generation is added as a utility class method which can be used by workloads to construct their launch command from parameters passed. --- wlauto/common/android/UiAutoUtils.class | Bin 0 -> 957 bytes .../com/arm/wlauto/uiauto/UiAutoUtils.java | 36 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 wlauto/common/android/UiAutoUtils.class create mode 100644 wlauto/external/uiauto/src/com/arm/wlauto/uiauto/UiAutoUtils.java diff --git a/wlauto/common/android/UiAutoUtils.class b/wlauto/common/android/UiAutoUtils.class new file mode 100644 index 0000000000000000000000000000000000000000..fb1da9afd7029e99667eb8ea3a933cea05a4c879 GIT binary patch literal 957 zcmah{%Wl&^6g`udoz$hR)09^WX-nE9O=5~*K@%ZCC01@&lvXM%(8L+iDSi}ZT*Rla zWy2OW1tGx)@KK2CJivlVcrkbG^*QIBxide0e*F$$8+QuOv7+Nf0XI?Bv8rROfOXu` zQPHpwZ#Q*RHPje#9qCK;fFWJ29WrEggT7#xv!yS(k=GO9Q{Ho_V%mYj-9sMAIG+?V z>R1jL)@>*7EFOB+8<$5aup&7M2l63h2THobHbc<~1y{o6k?$Pu2A;?LKEr0!rWgjY zZv{i^QRMes(XQDi{ES;J_XpO#3Z*|F{w!%HndU{H!YL2ACzJ@uSMdUA27^0Fo=Nq# zOF)L1Q|`Rt12N7D`#}^s;<1d+JfAo~D|TeSz${H??BvB%NJHJg78(rNM2rU64Sb=Y zX`ls*x^S;NR6JDW3K^UKbG#?L6X7TWx3SHz@Eg_i324RG)&I^m=KVcFhWtRN@$48j zs{hXF!Wk!wO}RPoI^r%FDJ4b5w%fI5^nzXnp~n@&{Ul&=ZO;>pr<_D-f}%G&Lr*sT zQlJ~cEUlL)vnVo(+4^U&Pov*+wB|;|66R@di~(4HNm(96EK(&Vzeg4sik-TdI!Ai1 zZe}QS8)o(#xp!DJwaho@N9pGN7v${^D4B)qq;QmJjEY+yiJwB;^BQ%HR}I%meHoXr wf-1_`!P>~jUFudr8YL`^9CZkBg%~@;AJ;V8!&Um5B7TdMmI%#AE$*=V3(IZeJOBUy literal 0 HcmV?d00001 diff --git a/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/UiAutoUtils.java b/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/UiAutoUtils.java new file mode 100644 index 00000000..35bebd03 --- /dev/null +++ b/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/UiAutoUtils.java @@ -0,0 +1,36 @@ +/* Copyright 2013-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; + +import android.os.Bundle; +import java.util.logging.Logger; + +public final class UiAutoUtils { + + /** Construct launch command of an application. */ + public static String createLaunchCommand(Bundle parameters) { + String launchCommand; + String activityName = parameters.getString("launch_activity"); + String packageName = parameters.getString("package"); + if (activityName.equals("None")) { + launchCommand = String.format("am start %s", packageName); + } + else { + launchCommand = String.format("am start -n %s/%s", packageName, activityName); + } + return launchCommand; + } +} From 0f57dee6bf7c428594371e42e7f60b9810171171 Mon Sep 17 00:00:00 2001 From: jummp01 Date: Tue, 31 Jan 2017 17:48:30 +0000 Subject: [PATCH 04/10] Add ApplaunchInterface class Inorder to support application launch workload, a new interface is created which has methods that need to be implemented by all workloads that support application launch time instrumentation. --- .../common/android/ApplaunchInterface.class | Bin 0 -> 412 bytes .../arm/wlauto/uiauto/ApplaunchInterface.java | 54 ++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 wlauto/common/android/ApplaunchInterface.class create mode 100644 wlauto/external/uiauto/src/com/arm/wlauto/uiauto/ApplaunchInterface.java diff --git a/wlauto/common/android/ApplaunchInterface.class b/wlauto/common/android/ApplaunchInterface.class new file mode 100644 index 0000000000000000000000000000000000000000..0bd8e05310cf2e761da653c577c22888dce01670 GIT binary patch literal 412 zcmZWl%TB{E5S%Tcf$}Qlb>Rcj3l`^|3Mx{iN+4Ch**GS+BzEOEfcP{Hd;lMX*aX@h zxUAPRYtPJneSdrcI7ctWUW_iGm+3H(l~qq8n_fT6vELU*Zp>5777 z2#2gWlP^-_(q>{Bys;U7e^lyl@BDM_WO^gLEOgMmBpfG`g*#V@i^`_C9yC%@S9ztc zOs)whwX-JO*z&tasq|SbLP(l?z7Vg>2lp3I{GVsDD_e^N9ju^bvNnOx;_U)a#K949 cLs&j~fB*mh literal 0 HcmV?d00001 diff --git a/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/ApplaunchInterface.java b/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/ApplaunchInterface.java new file mode 100644 index 00000000..b53c7bb4 --- /dev/null +++ b/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/ApplaunchInterface.java @@ -0,0 +1,54 @@ + +/* Copyright 2013-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; + +import android.os.Bundle; +import android.util.Log; + +// Import the uiautomator libraries +import com.android.uiautomator.core.UiObject; + +/** + * ApplaunchInterface.java + * Interface used for enabling uxperfapplaunch workload. + * This interface gets implemented by all workloads that support application launch + * instrumentation. + */ + +public interface ApplaunchInterface { + + /** + * Sets the launchEndObject of a workload, which is a UiObject that marks + * the end of the application launch. + */ + public UiObject getLaunchEndObject(); + + /** + * Runs the Uiautomation methods for clearing the initial run + * dialogues on the first time installation of an application package. + */ + public void runApplicationInitialization() throws Exception; + + /** + * Provides the application launch command of the application which is + * constructed as a string from the workload. + */ + public String getLaunchCommand(); + + /** Passes the workload parameters. */ + public void setWorkloadParameters(Bundle parameters); +} From 3feb702898b9707e89196330749db1eb8a6dea1e Mon Sep 17 00:00:00 2001 From: jummp01 Date: Thu, 2 Feb 2017 17:32:12 +0000 Subject: [PATCH 05/10] fps: move VSYNC_INTERVAL into utils It is not anything to do with instrument, but a generic ocnstant, and this way it can be used by the other parts of the code line. --- wlauto/instrumentation/fps/__init__.py | 5 ++--- wlauto/utils/fps.py | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/wlauto/instrumentation/fps/__init__.py b/wlauto/instrumentation/fps/__init__.py index 54fb353d..9cadeebd 100755 --- a/wlauto/instrumentation/fps/__init__.py +++ b/wlauto/instrumentation/fps/__init__.py @@ -39,10 +39,9 @@ from wlauto.instrumentation import instrument_is_installed from wlauto.exceptions import (InstrumentError, WorkerThreadError, ConfigError, DeviceNotRespondingError, TimeoutError) from wlauto.utils.types import boolean, numeric -from wlauto.utils.fps import FpsProcessor, SurfaceFlingerFrame, GfxInfoFrame, GFXINFO_EXEMPT +from wlauto.utils.fps import (FpsProcessor, SurfaceFlingerFrame, GfxInfoFrame, GFXINFO_EXEMPT, + VSYNC_INTERVAL) - -VSYNC_INTERVAL = 16666667 PAUSE_LATENCY = 20 EPSYLON = 0.0001 diff --git a/wlauto/utils/fps.py b/wlauto/utils/fps.py index 84016622..735be824 100755 --- a/wlauto/utils/fps.py +++ b/wlauto/utils/fps.py @@ -29,6 +29,8 @@ GfxInfoFrame = collections.namedtuple('GfxInfoFrame', 'Flags IntendedVsync Vsync # Android M: WindowLayoutChanged | SurfaceCanvas GFXINFO_EXEMPT = 1 | 4 +VSYNC_INTERVAL = 16666667 + class FpsProcessor(object): """ From c38dc287ab79179560fa1c383b1ed73a567e9f1b Mon Sep 17 00:00:00 2001 From: jummp01 Date: Thu, 2 Feb 2017 17:31:20 +0000 Subject: [PATCH 06/10] Move UxperfParser into utils UxperfParser class is moved from the UxperfResultProcessor class into a new python module in utils. This will help to use the UxperfParser even when the result procesor is not configured. --- wlauto/result_processors/uxperf.py | 167 +--------------------------- wlauto/utils/uxperf.py | 170 +++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 164 deletions(-) create mode 100644 wlauto/utils/uxperf.py diff --git a/wlauto/result_processors/uxperf.py b/wlauto/result_processors/uxperf.py index ff9027f8..6221afde 100755 --- a/wlauto/result_processors/uxperf.py +++ b/wlauto/result_processors/uxperf.py @@ -14,17 +14,13 @@ # import os -import re -import logging - -from collections import defaultdict from distutils.version import LooseVersion + from wlauto import ResultProcessor, Parameter from wlauto.instrumentation import instrument_is_enabled -from wlauto.instrumentation.fps import VSYNC_INTERVAL from wlauto.exceptions import ResultProcessorError, ConfigError -from wlauto.utils.fps import FpsProcessor, SurfaceFlingerFrame, GfxInfoFrame from wlauto.utils.types import numeric, boolean +from wlauto.utils.uxperf import UxPerfParser try: import pandas as pd @@ -77,6 +73,7 @@ class UxPerfResultProcessor(ResultProcessor): ] def initialize(self, context): + # needed for uxperf parser if not pd or LooseVersion(pd.__version__) < LooseVersion('0.13.1'): message = ('uxperf result processor requires pandas Python package ' '(version 0.13.1 or higher) to be installed.\n' @@ -101,161 +98,3 @@ class UxPerfResultProcessor(ResultProcessor): if self.add_frames: self.logger.debug('Adding per-action frame metrics') parser.add_action_frames(framelog, self.drop_threshold, self.generate_csv) - - -class UxPerfParser(object): - ''' - Parses logcat messages for UX Performance markers. - - UX Performance markers are output from logcat under a debug priority. The - logcat tag for the marker messages is UX_PERF. The messages associated with - this tag consist of a name for the action to be recorded and a timestamp. - These fields are delimited by a single space. e.g. - - : - UX_PERF : gestures_swipe_left_start 861975087367 - ... - ... - UX_PERF : gestures_swipe_left_end 862132085804 - - Timestamps are produced using the running Java Virtual Machine's - high-resolution time source, in nanoseconds. - ''' - def __init__(self, context): - self.context = context - self.actions = defaultdict(list) - self.logger = logging.getLogger('UxPerfParser') - # regex for matching logcat message format: - self.regex = re.compile(r'UX_PERF.*?:\s*(?P.*\d+$)') - - def parse(self, log): - ''' - Opens log file and parses UX_PERF markers. - - Actions delimited by markers are captured in a dictionary with - actions mapped to timestamps. - ''' - loglines = self._read(log) - self._gen_action_timestamps(loglines) - - def add_action_frames(self, frames, drop_threshold, generate_csv): # pylint: disable=too-many-locals - ''' - Uses FpsProcessor to parse frame.csv extracting fps, frame count, jank - and vsync metrics on a per action basis. Adds results to metrics. - ''' - refresh_period = self._parse_refresh_peroid() - - for action in self.actions: - # default values - fps, frame_count, janks, not_at_vsync = float('nan'), 0, 0, 0 - p90, p95, p99 = [float('nan')] * 3 - metrics = (fps, frame_count, janks, not_at_vsync) - - df = self._create_sub_df(self.actions[action], frames) - if not df.empty: # pylint: disable=maybe-no-member - fp = FpsProcessor(df, action=action) - try: - per_frame_fps, metrics = fp.process(refresh_period, drop_threshold) - fps, frame_count, janks, not_at_vsync = metrics - - if generate_csv: - name = action + '_fps' - filename = name + '.csv' - fps_outfile = os.path.join(self.context.output_directory, filename) - per_frame_fps.to_csv(fps_outfile, index=False, header=True) - self.context.add_artifact(name, path=filename, kind='data') - - p90, p95, p99 = fp.percentiles() - except AttributeError: - self.logger.warning('Non-matched timestamps in dumpsys output: action={}' - .format(action)) - - self.context.result.add_metric(action + '_FPS', fps) - self.context.result.add_metric(action + '_frame_count', frame_count) - self.context.result.add_metric(action + '_janks', janks, lower_is_better=True) - self.context.result.add_metric(action + '_not_at_vsync', not_at_vsync, lower_is_better=True) - self.context.result.add_metric(action + '_frame_time_90percentile', p90, 'ms', lower_is_better=True) - self.context.result.add_metric(action + '_frame_time_95percentile', p95, 'ms', lower_is_better=True) - self.context.result.add_metric(action + '_frame_time_99percentile', p99, 'ms', lower_is_better=True) - - def add_action_timings(self): - ''' - Add simple action timings in millisecond resolution to metrics - ''' - for action, timestamps in self.actions.iteritems(): - # nanosecond precision, but not necessarily nanosecond resolution - # truncate to guarantee millisecond precision - ts_ms = tuple(int(ts) for ts in timestamps) - if len(ts_ms) == 2: - start, finish = ts_ms - duration = finish - start - result = self.context.result - - result.add_metric(action + "_start", start, units='ms') - result.add_metric(action + "_finish", finish, units='ms') - result.add_metric(action + "_duration", duration, units='ms', lower_is_better=True) - else: - self.logger.warning('Expected two timestamps. Received {}'.format(ts_ms)) - - def _gen_action_timestamps(self, lines): - ''' - Parses lines and matches against logcat tag. - Groups timestamps by action name. - Creates a dictionary of lists with actions mapped to timestamps. - ''' - for line in lines: - match = self.regex.search(line) - - if match: - message = match.group('message') - action_with_suffix, timestamp = message.rsplit(' ', 1) - action, _ = action_with_suffix.rsplit('_', 1) - self.actions[action].append(timestamp) - - def _parse_refresh_peroid(self): - ''' - Reads the first line of the raw dumpsys output for the refresh period. - ''' - raw_path = os.path.join(self.context.output_directory, 'surfaceflinger.raw') - if os.path.isfile(raw_path): - raw_lines = self._read(raw_path) - refresh_period = int(raw_lines.next()) - else: - refresh_period = VSYNC_INTERVAL - - return refresh_period - - def _create_sub_df(self, action, frames): - ''' - Creates a data frame containing fps metrics for a captured action. - ''' - if len(action) == 2: - start, end = map(int, action) - df = pd.read_csv(frames) - # SurfaceFlinger Algorithm - if df.columns.tolist() == list(SurfaceFlingerFrame._fields): # pylint: disable=maybe-no-member - field = 'actual_present_time' - # GfxInfo Algorithm - elif df.columns.tolist() == list(GfxInfoFrame._fields): # pylint: disable=maybe-no-member - field = 'FrameCompleted' - else: - field = '' - self.logger.error('frames.csv not in a recognised format. Cannot parse.') - if field: - df = df[start < df[field]] - df = df[df[field] <= end] - else: - self.logger.warning('Discarding action. Expected 2 timestamps, got {}!'.format(len(action))) - df = pd.DataFrame() - return df - - def _read(self, log): - ''' - Opens a file a yields the lines with whitespace stripped. - ''' - try: - with open(log, 'r') as rfh: - for line in rfh: - yield line.strip() - except IOError: - self.logger.error('Could not open {}'.format(log)) diff --git a/wlauto/utils/uxperf.py b/wlauto/utils/uxperf.py new file mode 100644 index 00000000..36b9ee06 --- /dev/null +++ b/wlauto/utils/uxperf.py @@ -0,0 +1,170 @@ +import os +import re +import logging +from collections import defaultdict + +from wlauto.utils.fps import FpsProcessor, SurfaceFlingerFrame, GfxInfoFrame, VSYNC_INTERVAL + +try: + import pandas as pd +except ImportError: + pd = None + + +class UxPerfParser(object): + ''' + Parses logcat messages for UX Performance markers. + + UX Performance markers are output from logcat under a debug priority. The + logcat tag for the marker messages is UX_PERF. The messages associated with + this tag consist of a name for the action to be recorded and a timestamp. + These fields are delimited by a single space. e.g. + + : + UX_PERF : gestures_swipe_left_start 861975087367 + ... + ... + UX_PERF : gestures_swipe_left_end 862132085804 + + Timestamps are produced using the running Java Virtual Machine's + high-resolution time source, in nanoseconds. + ''' + def __init__(self, context, prefix=''): + self.context = context + self.prefix = prefix + self.actions = defaultdict(list) + self.logger = logging.getLogger('UxPerfParser') + # regex for matching logcat message format: + self.regex = re.compile(r'UX_PERF.*?:\s*(?P.*\d+$)') + + def parse(self, log): + ''' + Opens log file and parses UX_PERF markers. + + Actions delimited by markers are captured in a dictionary with + actions mapped to timestamps. + ''' + loglines = self._read(log) + self._gen_action_timestamps(loglines) + + def add_action_frames(self, frames, drop_threshold, generate_csv): # pylint: disable=too-many-locals + ''' + Uses FpsProcessor to parse frame.csv extracting fps, frame count, jank + and vsync metrics on a per action basis. Adds results to metrics. + ''' + refresh_period = self._parse_refresh_peroid() + + for action in self.actions: + # default values + fps, frame_count, janks, not_at_vsync = float('nan'), 0, 0, 0 + p90, p95, p99 = [float('nan')] * 3 + metrics = (fps, frame_count, janks, not_at_vsync) + + df = self._create_sub_df(self.actions[action], frames) + if not df.empty: # pylint: disable=maybe-no-member + fp = FpsProcessor(df, action=action) + try: + per_frame_fps, metrics = fp.process(refresh_period, drop_threshold) + fps, frame_count, janks, not_at_vsync = metrics + + if generate_csv: + name = action + '_fps' + filename = name + '.csv' + fps_outfile = os.path.join(self.context.output_directory, filename) + per_frame_fps.to_csv(fps_outfile, index=False, header=True) + self.context.add_artifact(name, path=filename, kind='data') + + p90, p95, p99 = fp.percentiles() + except AttributeError: + self.logger.warning('Non-matched timestamps in dumpsys output: action={}' + .format(action)) + + self.context.result.add_metric(self.prefix + action + '_FPS', fps) + self.context.result.add_metric(self.prefix + action + '_frame_count', frame_count) + self.context.result.add_metric(self.prefix + action + '_janks', janks, lower_is_better=True) + self.context.result.add_metric(self.prefix + action + '_not_at_vsync', not_at_vsync, lower_is_better=True) + self.context.result.add_metric(self.prefix + action + '_frame_time_90percentile', p90, 'ms', lower_is_better=True) + self.context.result.add_metric(self.prefix + action + '_frame_time_95percentile', p95, 'ms', lower_is_better=True) + self.context.result.add_metric(self.prefix + action + '_frame_time_99percentile', p99, 'ms', lower_is_better=True) + + def add_action_timings(self): + ''' + Add simple action timings in millisecond resolution to metrics + ''' + for action, timestamps in self.actions.iteritems(): + # nanosecond precision, but not necessarily nanosecond resolution + # truncate to guarantee millisecond precision + ts_ms = tuple(int(ts) for ts in timestamps) + if len(ts_ms) == 2: + start, finish = ts_ms + duration = finish - start + result = self.context.result + + result.add_metric(self.prefix + action + "_start", start, units='ms') + result.add_metric(self.prefix + action + "_finish", finish, units='ms') + result.add_metric(self.prefix + action + "_duration", duration, units='ms', lower_is_better=True) + else: + self.logger.warning('Expected two timestamps. Received {}'.format(ts_ms)) + + def _gen_action_timestamps(self, lines): + ''' + Parses lines and matches against logcat tag. + Groups timestamps by action name. + Creates a dictionary of lists with actions mapped to timestamps. + ''' + for line in lines: + match = self.regex.search(line) + + if match: + message = match.group('message') + action_with_suffix, timestamp = message.rsplit(' ', 1) + action, _ = action_with_suffix.rsplit('_', 1) + self.actions[action].append(timestamp) + + def _parse_refresh_peroid(self): + ''' + Reads the first line of the raw dumpsys output for the refresh period. + ''' + raw_path = os.path.join(self.context.output_directory, 'surfaceflinger.raw') + if os.path.isfile(raw_path): + raw_lines = self._read(raw_path) + refresh_period = int(raw_lines.next()) + else: + refresh_period = VSYNC_INTERVAL + + return refresh_period + + def _create_sub_df(self, action, frames): + ''' + Creates a data frame containing fps metrics for a captured action. + ''' + if len(action) == 2: + start, end = map(int, action) + df = pd.read_csv(frames) + # SurfaceFlinger Algorithm + if df.columns.tolist() == list(SurfaceFlingerFrame._fields): # pylint: disable=maybe-no-member + field = 'actual_present_time' + # GfxInfo Algorithm + elif df.columns.tolist() == list(GfxInfoFrame._fields): # pylint: disable=maybe-no-member + field = 'FrameCompleted' + else: + field = '' + self.logger.error('frames.csv not in a recognised format. Cannot parse.') + if field: + df = df[start < df[field]] + df = df[df[field] <= end] + else: + self.logger.warning('Discarding action. Expected 2 timestamps, got {}!'.format(len(action))) + df = pd.DataFrame() + return df + + def _read(self, log): + ''' + Opens a file a yields the lines with whitespace stripped. + ''' + try: + with open(log, 'r') as rfh: + for line in rfh: + yield line.strip() + except IOError: + self.logger.error('Could not open {}'.format(log)) From bd379734423160ec8d48bda52c2b16df3eb4dd63 Mon Sep 17 00:00:00 2001 From: jummp01 Date: Thu, 2 Feb 2017 14:54:38 +0000 Subject: [PATCH 07/10] Remove existing applaunch workload The applaunch workload is deprecated to be replaced by another implementation. --- wlauto/workloads/applaunch/__init__.py | 189 ------------------ .../applaunch/device_script.template | 88 -------- 2 files changed, 277 deletions(-) delete mode 100644 wlauto/workloads/applaunch/__init__.py delete mode 100644 wlauto/workloads/applaunch/device_script.template diff --git a/wlauto/workloads/applaunch/__init__.py b/wlauto/workloads/applaunch/__init__.py deleted file mode 100644 index 40dcb7b7..00000000 --- a/wlauto/workloads/applaunch/__init__.py +++ /dev/null @@ -1,189 +0,0 @@ -# Copyright 2013-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 - -from __future__ import division -import os - -try: - import jinja2 -except ImportError: - jinja2 = None - -from wlauto import Workload, settings, Parameter -from wlauto.exceptions import WorkloadError -from wlauto.utils.hwmon import discover_sensors -from wlauto.utils.misc import get_meansd -from wlauto.utils.types import boolean, identifier, list_of_strs - - -THIS_DIR = os.path.dirname(__file__) -TEMPLATE_NAME = 'device_script.template' -SCRIPT_TEMPLATE = os.path.join(THIS_DIR, TEMPLATE_NAME) - -APP_CONFIG = { - 'browser': { - 'package': 'com.android.browser', - 'activity': '.BrowserActivity', - 'options': '-d about:blank', - }, - 'calculator': { - 'package': 'com.android.calculator2', - 'activity': '.Calculator', - 'options': '', - }, - 'calendar': { - 'package': 'com.android.calendar', - 'activity': '.LaunchActivity', - 'options': '', - }, -} - - -class ApplaunchWorkload(Workload): - - name = 'applaunch' - description = """ - Measures the time and energy used in launching an application. - - """ - supported_platforms = ['android'] - - parameters = [ - Parameter('app', default='browser', allowed_values=['calculator', 'browser', 'calendar'], - description='The name of the application to measure.'), - Parameter('set_launcher_affinity', kind=bool, default=True, - description=('If ``True``, this will explicitly set the affinity of the launcher ' - 'process to the A15 cluster.')), - Parameter('times', kind=int, default=8, - description='Number of app launches to do on the device.'), - Parameter('measure_energy', kind=boolean, default=False, - description=""" - Specfies wether energy measurments should be taken during the run. - - .. note:: This depends on appropriate sensors to be exposed through HWMON. - - """), - Parameter('io_stress', kind=boolean, default=False, - description='Specifies whether to stress IO during App launch.'), - Parameter('io_scheduler', allowed_values=['noop', 'deadline', 'row', 'cfq', 'bfq'], - description='Set the IO scheduler to test on the device.'), - Parameter('cleanup', kind=boolean, default=True, - description='Specifies whether to clean up temporary files on the device.'), - ] - - def __init__(self, device, **kwargs): - super(ApplaunchWorkload, self).__init__(device, **kwargs) - if not jinja2: - raise WorkloadError('Please install jinja2 Python package: "sudo pip install jinja2"') - filename = '{}-{}.sh'.format(self.name, self.app) - self.host_script_file = os.path.join(settings.meta_directory, filename) - self.device_script_file = os.path.join(self.device.working_directory, filename) - self._launcher_pid = None - self._old_launcher_affinity = None - self.sensors = [] - - def on_run_init(self, context): # pylint: disable=W0613 - if self.measure_energy: - self.sensors = discover_sensors(self.device, ['energy']) - for sensor in self.sensors: - sensor.label = identifier(sensor.label).upper() - - def setup(self, context): - self.logger.debug('Creating script {}'.format(self.host_script_file)) - with open(self.host_script_file, 'w') as wfh: - env = jinja2.Environment(loader=jinja2.FileSystemLoader(THIS_DIR)) - template = env.get_template(TEMPLATE_NAME) - wfh.write(template.render(device=self.device, # pylint: disable=maybe-no-member - sensors=self.sensors, - iterations=self.times, - io_stress=self.io_stress, - io_scheduler=self.io_scheduler, - cleanup=self.cleanup, - package=APP_CONFIG[self.app]['package'], - activity=APP_CONFIG[self.app]['activity'], - options=APP_CONFIG[self.app]['options'], - busybox=self.device.busybox, - )) - self.device_script_file = self.device.install(self.host_script_file) - if self.set_launcher_affinity: - self._set_launcher_affinity() - self.device.clear_logcat() - - def run(self, context): - self.device.execute('sh {}'.format(self.device_script_file), timeout=300, as_root=self.io_stress) - - def update_result(self, context): # pylint: disable=too-many-locals - result_files = ['time.result'] - result_files += ['{}.result'.format(sensor.label) for sensor in self.sensors] - metric_suffix = '' - if self.io_stress: - host_scheduler_file = os.path.join(context.output_directory, 'scheduler') - device_scheduler_file = '/sys/block/mmcblk0/queue/scheduler' - self.device.pull_file(device_scheduler_file, host_scheduler_file) - with open(host_scheduler_file) as fh: - scheduler = fh.read() - scheduler_used = scheduler[scheduler.index("[") + 1:scheduler.index("]")] - metric_suffix = '_' + scheduler_used - for filename in result_files: - self._extract_results_from_file(context, filename, metric_suffix) - - def teardown(self, context): - if self.set_launcher_affinity: - self._reset_launcher_affinity() - if self.cleanup: - self.device.delete_file(self.device_script_file) - - def _set_launcher_affinity(self): - try: - self._launcher_pid = self.device.get_pids_of('com.android.launcher')[0] - result = self.device.execute('taskset -p {}'.format(self._launcher_pid), busybox=True, as_root=True) - self._old_launcher_affinity = int(result.split(':')[1].strip(), 16) - - cpu_ids = [i for i, x in enumerate(self.device.core_names) if x == 'a15'] - if not cpu_ids or len(cpu_ids) == len(self.device.core_names): - self.logger.debug('Cannot set affinity.') - return - - new_mask = reduce(lambda x, y: x | y, cpu_ids, 0x0) - self.device.execute('taskset -p 0x{:X} {}'.format(new_mask, self._launcher_pid), busybox=True, as_root=True) - except IndexError: - raise WorkloadError('Could not set affinity of launcher: PID not found.') - - def _reset_launcher_affinity(self): - command = 'taskset -p 0x{:X} {}'.format(self._old_launcher_affinity, self._launcher_pid) - self.device.execute(command, busybox=True, as_root=True) - - def _extract_results_from_file(self, context, filename, metric_suffix): - host_result_file = os.path.join(context.output_directory, filename) - device_result_file = self.device.path.join(self.device.working_directory, filename) - self.device.pull_file(device_result_file, host_result_file) - - with open(host_result_file) as fh: - if filename == 'time.result': - values = [v / 1000 for v in map(int, fh.read().split())] - _add_metric(context, 'time' + metric_suffix, values, 'Seconds') - else: - metric = filename.replace('.result', '').lower() - numbers = iter(map(int, fh.read().split())) - deltas = [(after - before) / 1000000 for before, after in zip(numbers, numbers)] - _add_metric(context, metric, deltas, 'Joules') - - -def _add_metric(context, metric, values, units): - mean, sd = get_meansd(values) - context.result.add_metric(metric, mean, units) - context.result.add_metric(metric + ' sd', sd, units, lower_is_better=True) diff --git a/wlauto/workloads/applaunch/device_script.template b/wlauto/workloads/applaunch/device_script.template deleted file mode 100644 index 1e940d70..00000000 --- a/wlauto/workloads/applaunch/device_script.template +++ /dev/null @@ -1,88 +0,0 @@ -#!{{ device.binaries_directory.rstrip('/') }}/sh - - -{% for sensor in sensors %} -GET_{{ sensor.label }}="cat {{ sensor.filepath }}" -{% endfor %} - -LAUNCH_COMMAND="am start -W -n {{ package }}/{{ activity }} {{ options }}" -STOP_COMMAND="am force-stop {{ package }}" -TEMP_FILE=tmp.txt - -TIME_RESULT="" -{% for sensor in sensors %} -{{ sensor.label }}="" -{% endfor %} - -cd {{ device.working_directory }} - -# esc esc down down down ENTER (this should bring up the apps menu) -input keyevent 111 -sleep 1 -input keyevent 111 -sleep 1 -input keyevent 20 -sleep 1 -input keyevent 20 -sleep 1 -input keyevent 20 -sleep 1 -input keyevent 66 -sleep 1 - -# Warm up caches. -$LAUNCH_COMMAND -$STOP_COMMAND -$LAUNCH_COMMAND -$STOP_COMMAND -$LAUNCH_COMMAND -$STOP_COMMAND - -{% if io_scheduler != None %} -echo {{ io_scheduler }} > /sys/block/mmcblk0/queue/scheduler -{% endif %} - -for i in $({{ busybox }} seq 1 {{ iterations }}) -do - {% for sensor in sensors %} - {{ sensor.label }}="${{ sensor.label }} `$GET_{{ sensor.label }}`" - {% endfor %} - - {% if io_stress %} - # Drop caches to get a cold start. - sync; echo 3 > /proc/sys/vm/drop_caches - # Run IO stress during App launch. - {{ busybox }} dd if=/dev/zero of=write.img bs=1048576 count=2000 conv=fsync > dd_write.txt 2>&1 & - io_write=$! - {{ busybox }} dd if=/dev/block/mmcblk0 of=/dev/null bs=1048576 > dd_read.txt 2>&1 & - io_read=$! - {% endif %} - - $LAUNCH_COMMAND > $TEMP_FILE - - {% for sensor in sensors %} - {{ sensor.label }}="${{ sensor.label }} `$GET_{{ sensor.label }}`" - {% endfor %} - - TIME=`{{ busybox }} awk '{if($1~"TotalTime") print $2}' $TEMP_FILE` - TIME_RESULT="$TIME_RESULT $TIME" - {% if cleanup %} - rm $TEMP_FILE - {% if io_stress %} - kill $io_write - kill $io_read - rm -f write.img - {% endif %} - {% endif %} - - $STOP_COMMAND - sleep 2 -done - -{% for sensor in sensors %} -echo ${{ sensor.label }} > {{ sensor.label }}.result -{% endfor %} -echo $TIME_RESULT > time.result -# esc esc down down down ENTER (this should bring up the apps menu) -input keyevent 111 -sleep 1 From ca7a1abe785ec3a6529c79218ccec2cc44a48228 Mon Sep 17 00:00:00 2001 From: jummp01 Date: Tue, 31 Jan 2017 17:50:04 +0000 Subject: [PATCH 08/10] Add new applaunch workload. The workload supports launch time measurement of other uxperf workloads that implement the ApplicationlaunchInterface. It takes a uxperf workload as a parameter and helps to instrument the application launch time in two modes. a)launch_from_background b)launch_from_long_idle The workload executes in two major phases. 1- Setup phase: clears initial dialogues on the first launch of an application. 2- Run phase: Runs multiple iterations of the application launch and measures the time taken for launch. Iteration number can be specified as parameter applaunch_iterations. Applaunch measurements are captured in the logcat file. --- wlauto/workloads/applaunch/__init__.py | 169 ++++++++++++++ .../com.arm.wlauto.uiauto.applaunch.jar | Bin 0 -> 14149 bytes wlauto/workloads/applaunch/uiauto/build.sh | 39 ++++ wlauto/workloads/applaunch/uiauto/build.xml | 92 ++++++++ .../applaunch/uiauto/project.properties | 14 ++ .../com/arm/wlauto/uiauto/UiAutomation.java | 220 ++++++++++++++++++ 6 files changed, 534 insertions(+) create mode 100644 wlauto/workloads/applaunch/__init__.py create mode 100644 wlauto/workloads/applaunch/com.arm.wlauto.uiauto.applaunch.jar create mode 100755 wlauto/workloads/applaunch/uiauto/build.sh create mode 100644 wlauto/workloads/applaunch/uiauto/build.xml create mode 100644 wlauto/workloads/applaunch/uiauto/project.properties create mode 100755 wlauto/workloads/applaunch/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java diff --git a/wlauto/workloads/applaunch/__init__.py b/wlauto/workloads/applaunch/__init__.py new file mode 100644 index 00000000..19fcac96 --- /dev/null +++ b/wlauto/workloads/applaunch/__init__.py @@ -0,0 +1,169 @@ +# Copyright 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=attribute-defined-outside-init +import os + +from time import sleep + +from wlauto import Workload, AndroidBenchmark, AndroidUxPerfWorkload, UiAutomatorWorkload +from wlauto import Parameter +from wlauto import ExtensionLoader +from wlauto import File +from wlauto import settings +from wlauto.exceptions import ConfigError +from wlauto.exceptions import ResourceError +from wlauto.utils.android import ApkInfo +from wlauto.utils.uxperf import UxPerfParser + +import wlauto.common.android.resources + + +class Applaunch(AndroidUxPerfWorkload): + + name = 'applaunch' + description = ''' + This workload launches and measures the launch time of applications for supporting workloads. + + Currently supported workloads are the ones that implement ``ApplaunchInterface``. For any + workload to support this workload, it should implement the ``ApplaunchInterface``. + The corresponding java file of the workload associated with the application being measured + is executed during the run. The application that needs to be + measured is passed as a parametre ``workload_name``. The parameters required for that workload + have to be passed as a dictionary which is captured by the parametre ``workload_params``. + This information can be obtained by inspecting the workload details of the specific workload. + + The workload allows to run multiple iterations of an application + launch in two modes: + + 1. Launch from background + 2. Launch from long-idle + + These modes are captured as a parameter applaunch_type. + + ``launch_from_background`` + Launches an application after the application is sent to background by + pressing Home button. + + ``launch_from_long-idle`` + Launches an application after killing an application process and + clearing all the caches. + + **Test Description:** + + - During the initialization and setup, the application being launched is launched + for the first time. The jar file of the workload of the application + is moved to device at the location ``workdir`` which further implements the methods + needed to measure the application launch time. + + - Run phase calls the UiAutomator of the applaunch which runs in two subphases. + A. Applaunch Setup Run: + During this phase, welcome screens and dialogues during the first launch + of the instrumented application are cleared. + B. Applaunch Metric Run: + During this phase, the application is launched multiple times determined by + the iteration number specified by the parametre ``applaunch_iterations``. + Each of these iterations are instrumented to capture the launch time taken + and the values are recorded as UXPERF marker values in logfile. + ''' + supported_platforms = ['android'] + + parameters = [ + Parameter('workload_name', kind=str, + description='Name of the uxperf workload to launch', + default='gmail'), + Parameter('workload_params', kind=dict, default={}, + description=""" + parameters of the uxperf workload whose application launch + time is measured + """), + Parameter('applaunch_type', kind=str, default='launch_from_background', + allowed_values=['launch_from_background', 'launch_from_long-idle'], + description=""" + Choose launch_from_long-idle for measuring launch time + from long-idle. These two types are described in the class + description. + """), + Parameter('applaunch_iterations', kind=int, default=1, + description=""" + Number of iterations of the application launch + """), + Parameter('report_results', kind=bool, default=True, + description=""" + Choose to report results of the application launch time. + """), + ] + + def __init__(self, device, **kwargs): + super(Applaunch, self).__init__(device, **kwargs) + + def init_resources(self, context): + super(Applaunch, self).init_resources(context) + loader = ExtensionLoader(packages=settings.extension_packages, paths=settings.extension_paths) + self.workload_params['markers_enabled'] = True + self.workload = loader.get_workload(self.workload_name, self.device, + **self.workload_params) + self.init_workload_resources(context) + + def init_workload_resources(self, context): + self.workload.uiauto_file = context.resolver.get(wlauto.common.android.resources.JarFile(self.workload)) + if not self.workload.uiauto_file: + raise ResourceError('No UI automation JAR file found for workload {}.'.format(self.workload.name)) + self.workload.device_uiauto_file = self.device.path.join(self.device.working_directory, os.path.basename(self.workload.uiauto_file)) + if not self.workload.uiauto_package: + self.workload.uiauto_package = os.path.splitext(os.path.basename(self.workload.uiauto_file))[0] + + def validate(self): + super(Applaunch, self).validate() + self.workload.validate() + self.pass_parameters() + + def pass_parameters(self): + self.uiauto_params['workload'] = self.workload.name + self.uiauto_params['package'] = self.workload.package + self.uiauto_params['binaries_directory'] = self.device.binaries_directory + self.uiauto_params.update(self.workload.uiauto_params) + if self.workload.activity: + self.uiauto_params['launch_activity'] = self.workload.activity + else: + self.uiauto_params['launch_activity'] = "None" + self.uiauto_params['applaunch_type'] = self.applaunch_type + self.uiauto_params['applaunch_iterations'] = self.applaunch_iterations + + def setup(self, context): + AndroidBenchmark.setup(self.workload, context) + if not self.workload.launch_main: + self.workload.launch_app() + UiAutomatorWorkload.setup(self, context) + self.workload.device.push_file(self.workload.uiauto_file, self.workload.device_uiauto_file) + + def run(self, context): + UiAutomatorWorkload.run(self, context) + + def update_result(self, context): + super(Applaunch, self).update_result(context) + if self.report_results: + parser = UxPerfParser(context, prefix='applaunch_') + logfile = os.path.join(context.output_directory, 'logcat.log') + parser.parse(logfile) + parser.add_action_timings() + + def teardown(self, context): + super(Applaunch, self).teardown(context) + AndroidBenchmark.teardown(self.workload, context) + UiAutomatorWorkload.teardown(self.workload, context) + #Workload uses Dexclass loader while loading the jar file of the instrumented workload. + #Dexclassloader unzips and generates .dex file in the .jar directory during the run. + device_uiauto_dex_file = self.workload.device_uiauto_file.replace(".jar", ".dex") + self.workload.device.delete_file(self.device.path.join(self.device.binaries_directory, device_uiauto_dex_file)) diff --git a/wlauto/workloads/applaunch/com.arm.wlauto.uiauto.applaunch.jar b/wlauto/workloads/applaunch/com.arm.wlauto.uiauto.applaunch.jar new file mode 100644 index 0000000000000000000000000000000000000000..c10edd6fd0b011f3b0e0a105fa6a2e52a5747d09 GIT binary patch literal 14149 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 Y;Y_Bf@&@%koyf0G%WE0H|DW3b0#m0TY5)KL literal 0 HcmV?d00001 diff --git a/wlauto/workloads/applaunch/uiauto/build.sh b/wlauto/workloads/applaunch/uiauto/build.sh new file mode 100755 index 00000000..1c5233c5 --- /dev/null +++ b/wlauto/workloads/applaunch/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.applaunch.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/applaunch/uiauto/build.xml b/wlauto/workloads/applaunch/uiauto/build.xml new file mode 100644 index 00000000..b4e76972 --- /dev/null +++ b/wlauto/workloads/applaunch/uiauto/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/wlauto/workloads/applaunch/uiauto/project.properties b/wlauto/workloads/applaunch/uiauto/project.properties new file mode 100644 index 00000000..ce39f2d0 --- /dev/null +++ b/wlauto/workloads/applaunch/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/applaunch/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java b/wlauto/workloads/applaunch/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java new file mode 100755 index 00000000..b0e9f80f --- /dev/null +++ b/wlauto/workloads/applaunch/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java @@ -0,0 +1,220 @@ +/* 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.applaunch; + +import android.os.Bundle; +import android.util.Log; + +// Import the uiautomator libraries +import com.android.uiautomator.core.UiObject; +import com.android.uiautomator.core.UiObjectNotFoundException; +import com.android.uiautomator.core.UiSelector; + +import com.arm.wlauto.uiauto.ApplaunchInterface; +import com.arm.wlauto.uiauto.UxPerfUiAutomation; + +import static com.arm.wlauto.uiauto.BaseUiAutomation.FindByCriteria.BY_ID; +import static com.arm.wlauto.uiauto.BaseUiAutomation.FindByCriteria.BY_TEXT; +import static com.arm.wlauto.uiauto.BaseUiAutomation.FindByCriteria.BY_DESC; + +import java.util.concurrent.TimeUnit; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Map.Entry; +import dalvik.system.DexClassLoader; +import java.lang.reflect.Method; + + +public class UiAutomation extends UxPerfUiAutomation { + + /** + * Uiobject that marks the end of launch of an application, which is workload + * specific and added in the workload Java file by a method called getLaunchEndObject(). + */ + public UiObject launchEndObject; + /** Timeout to wait for application launch to finish. */ + private Integer launch_timeout = 10; + public String applaunchType; + public String applaunchIterations; + public String activityName; + public ApplaunchInterface launch_workload; + + /** Uiautomator function called by the applaunch workload. */ + public void runUiAutomation() throws Exception{ + parameters = getParams(); + + // Get workload jar file parameters + String workload = parameters.getString("workload"); + String binariesDirectory = parameters.getString("binaries_directory"); + String workloadJarPath = parameters.getString("workdir"); + String workloadJarName = String.format("com.arm.wlauto.uiauto.%1s.jar",workload); + String workloadJarFile = String.format("%1s/%2s",workloadJarPath, workloadJarName); + + // Load the jar file + File jarFile = new File(workloadJarFile); + if(!jarFile.exists()) { + throw new Exception(String.format("Jar file not found: %s", workloadJarFile)); + } + DexClassLoader classloader = new DexClassLoader(jarFile.toURI().toURL().toString(), + binariesDirectory, null, ClassLoader.getSystemClassLoader()); + Class uiautomation = null; + Object uiautomation_interface = null; + String workloadClass = String.format("com.arm.wlauto.uiauto.%1s.UiAutomation",workload); + try { + uiautomation = classloader.loadClass(workloadClass); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + Log.d("Class loaded:", uiautomation.getCanonicalName()); + uiautomation_interface = uiautomation.newInstance(); + + // Create an Application Interface object from the workload + launch_workload = ((ApplaunchInterface)uiautomation_interface); + + // Get parameters for application launch + getPackageParameters(); + applaunchType = parameters.getString("applaunch_type"); + applaunchIterations = parameters.getString("applaunch_iterations"); + activityName = parameters.getString("launch_activity"); + + // Run the workload for application launch initialization + runApplaunchSetup(); + + // Run the workload for application launch measurement + for (int iteration = 0; iteration < Integer.parseInt(applaunchIterations); iteration++) { + Log.d("Applaunch iteration number: ", applaunchIterations); + sleep(20);//sleep for a while before next iteration + killBackground(); + runApplaunchIteration(iteration); + closeApplication(); + } + } + + /** + * Setup run for applaunch workload that clears the initial + * run dialogues on launching an application package. + */ + public void runApplaunchSetup() throws Exception{ + setScreenOrientation(ScreenOrientation.NATURAL); + launch_workload.setWorkloadParameters(parameters); + launch_workload.runApplicationInitialization(); + launchEndObject = launch_workload.getLaunchEndObject(); + unsetScreenOrientation(); + closeApplication(); + } + + /** + * This method performs multiple iterations of application launch and + * records the time taken for each iteration. + */ + public void runApplaunchIteration(Integer iteration_count) throws Exception{ + String testTag = "applaunch" + iteration_count; + String launchCommand = launch_workload.getLaunchCommand(); + AppLaunch applaunch = new AppLaunch(testTag, launchCommand); + applaunch.startLaunch();//Launch the application and start timer + applaunch.endLaunch();//marks the end of launch and stops timer + } + + /* + * AppLaunch class implements methods that facilitates launching applications + * from the uiautomator. It has methods that are used for one complete iteration of application + * launch instrumentation. + * ActionLogger class is instantiated within the class for measuring applaunch time. + * startLaunch(): Marks the beginning of the application launch, starts Timer + * endLaunch(): Marks the end of application, ends Timer + * launchMain(): Starts the application launch process and validates the finish of launch. + */ + private class AppLaunch { + + private String testTag; + private String launchCommand; + private ActionLogger logger; + Process launch_p; + + public AppLaunch(String testTag, String launchCommand) { + this.testTag = testTag; + this.launchCommand = launchCommand; + this.logger = new ActionLogger(testTag, parameters); + } + + // Called by launchMain() to check if app launch is successful + public void launchValidate(Process launch_p) throws Exception { + launch_p.waitFor(); + Integer exit_val = launch_p.exitValue(); + if (exit_val != 0) { + throw new Exception("Application could not be launched"); + } + } + + // Marks the end of application launch of the workload. + public void endLaunch() throws Exception{ + waitObject(launchEndObject, launch_timeout); + logger.stop(); + launch_p.destroy(); + } + + // Launches the application. + public void launchMain() throws Exception{ + launch_p = Runtime.getRuntime().exec(launchCommand); + + launchValidate(launch_p); + } + + // Beginning of application launch + public void startLaunch() throws Exception{ + logger.start(); + launchMain(); + } + } + + // Exits the application according to application launch type. + public void closeApplication() throws Exception{ + if(applaunchType.equals("launch_from_background")) { + pressHome(); + } + else if(applaunchType.equals("launch_from_long-idle")) { + killApplication(); + dropCaches(); + } + } + + // Kills the application process + public void killApplication() throws Exception{ + Process kill_p; + kill_p = Runtime.getRuntime().exec(String.format("am force-stop %s", packageName)); + kill_p.waitFor(); + kill_p.destroy(); + } + + // Kills the background processes + public void killBackground() throws Exception{ + Process kill_p; + kill_p = Runtime.getRuntime().exec("am kill-all"); + kill_p.waitFor(); + kill_p.destroy(); + } + + // Drop the caches + public void dropCaches() throws Exception{ + Process drop_cache; + drop_cache = Runtime.getRuntime().exec("su sync; su echo 3 > /proc/sys/vm/drop_caches"); + drop_cache.waitFor(); + drop_cache.destroy(); + } +} From d8438c5ae839ebd73721bfab388041b874467b43 Mon Sep 17 00:00:00 2001 From: jummp01 Date: Thu, 2 Feb 2017 14:31:35 +0000 Subject: [PATCH 09/10] Gmail: implement ApplaunchInterface Adapts gmail workload to support applaunch workload by implementing the required methods of the interface. Tested on Huawei Mate8 and Samsung S7. --- .../gmail/com.arm.wlauto.uiauto.gmail.jar | Bin 13552 -> 14132 bytes .../com/arm/wlauto/uiauto/UiAutomation.java | 37 ++++++++++++++---- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/wlauto/workloads/gmail/com.arm.wlauto.uiauto.gmail.jar b/wlauto/workloads/gmail/com.arm.wlauto.uiauto.gmail.jar index 12e12841e1b56be7e3b699a22096f7efe811e80a..4511eb4c953afe1e5899290c1692472a3e82e3e1 100644 GIT binary patch delta 13923 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 delta 13338 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 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 index d24f2757..edae608a 100755 --- a/wlauto/workloads/gmail/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java +++ b/wlauto/workloads/gmail/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java @@ -23,28 +23,24 @@ import com.android.uiautomator.core.UiObjectNotFoundException; import com.android.uiautomator.core.UiSelector; import com.arm.wlauto.uiauto.UxPerfUiAutomation; +import com.arm.wlauto.uiauto.ApplaunchInterface; +import com.arm.wlauto.uiauto.UiAutoUtils; import java.util.concurrent.TimeUnit; -public class UiAutomation extends UxPerfUiAutomation { - - public Bundle parameters; - public String packageName; - public String packageID; +public class UiAutomation extends UxPerfUiAutomation implements ApplaunchInterface{ private int networkTimeoutSecs = 30; private long networkTimeout = TimeUnit.SECONDS.toMillis(networkTimeoutSecs); public void runUiAutomation() throws Exception { parameters = getParams(); - packageName = parameters.getString("package"); - packageID = packageName + ":id/"; String recipient = parameters.getString("recipient"); setScreenOrientation(ScreenOrientation.NATURAL); + runApplicationInitialization(); - clearFirstRunDialogues(); clickNewMail(); attachImage(); setToField(recipient); @@ -54,6 +50,31 @@ public class UiAutomation extends UxPerfUiAutomation { unsetScreenOrientation(); } + + // Get application parameters and clear the initial run dialogues of the application launch. + public void runApplicationInitialization() throws Exception { + getPackageParameters(); + clearFirstRunDialogues(); + } + + // Sets the UiObject that marks the end of the application launch. + public UiObject getLaunchEndObject() { + UiObject launchEndObject = + new UiObject(new UiSelector().className("android.widget.ImageButton")); + return launchEndObject; + } + + // Returns the launch command for the application. + public String getLaunchCommand() { + String launch_command; + launch_command = UiAutoUtils.createLaunchCommand(parameters); + return launch_command; + } + + // Pass the workload parameters, used for applaunch + public void setWorkloadParameters(Bundle workload_parameters) { + parameters = workload_parameters; + } public void clearFirstRunDialogues() throws Exception { // The first run dialogues vary on different devices so check if they are there and dismiss From 75b56e462cb83a3202de21b278dcdc5b90054698 Mon Sep 17 00:00:00 2001 From: jummp01 Date: Tue, 31 Jan 2017 17:53:08 +0000 Subject: [PATCH 10/10] Adobereader: implement ApplaunchInterface Adapts adobereader to support uxperfapplaunch workload by implementing the required methods of the interface. Tested on Huwaei Mate8 and Samsung S7. --- .../com.arm.wlauto.uiauto.adobereader.jar | Bin 14767 -> 15557 bytes .../com/arm/wlauto/uiauto/UiAutomation.java | 38 ++++++++++++++---- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/wlauto/workloads/adobereader/com.arm.wlauto.uiauto.adobereader.jar b/wlauto/workloads/adobereader/com.arm.wlauto.uiauto.adobereader.jar index a99b0d7097481ff19c7b4f46d8bd5de7e3192532..a49643bff4cca606d6706c8e45c81d2e5be9aa30 100644 GIT binary patch delta 15359 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

-m3>hW0V|+_g8iR! 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 NkUTF2<2V2S006