1
0
mirror of https://github.com/ARM-software/workload-automation.git synced 2025-09-02 03:12:34 +01:00

Initial commit of open source Workload Automation.

This commit is contained in:
Sergei Trofimov
2015-03-10 13:09:31 +00:00
commit a747ec7e4c
412 changed files with 41401 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
# 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.
#

View File

@@ -0,0 +1,88 @@
# 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.
#
import re
from wlauto import AndroidUiAutoBenchmark, Parameter, Alias
from wlauto.exceptions import ConfigError
class Andebench(AndroidUiAutoBenchmark):
name = 'andebench'
description = """
AndEBench is an industry standard Android benchmark provided by The
Embedded Microprocessor Benchmark Consortium (EEMBC).
http://www.eembc.org/andebench/about.php
From the website:
- Initial focus on CPU and Dalvik interpreter performance
- Internal algorithms concentrate on integer operations
- Compares the difference between native and Java performance
- Implements flexible multicore performance analysis
- Results displayed in Iterations per second
- Detailed log file for comprehensive engineering analysis
"""
package = 'com.eembc.coremark'
activity = 'com.eembc.coremark.splash'
summary_metrics = ['AndEMark Java', 'AndEMark Native']
parameters = [
Parameter('number_of_threads', kind=int,
description='Number of threads that will be spawned by AndEBench.'),
Parameter('single_threaded', kind=bool,
description="""
If ``true``, AndEBench will run with a single thread. Note: this must
not be specified if ``number_of_threads`` has been specified.
"""),
]
aliases = [
Alias('andebenchst', number_of_threads=1),
]
regex = re.compile('\s*(?P<key>(AndEMark Native|AndEMark Java))\s*:'
'\s*(?P<value>\d+)')
def validate(self):
if (self.number_of_threads is not None) and (self.single_threaded is not None): # pylint: disable=E1101
raise ConfigError('Can\'t specify both number_of_threads and single_threaded parameters.')
def setup(self, context):
if self.number_of_threads is None: # pylint: disable=access-member-before-definition
if self.single_threaded: # pylint: disable=E1101
self.number_of_threads = 1 # pylint: disable=attribute-defined-outside-init
else:
self.number_of_threads = self.device.number_of_cores # pylint: disable=W0201
self.logger.debug('Using {} threads'.format(self.number_of_threads))
self.uiauto_params['number_of_threads'] = self.number_of_threads
# Called after this setup as modifying uiauto_params
super(Andebench, self).setup(context)
def update_result(self, context):
super(Andebench, self).update_result(context)
results = {}
with open(self.logcat_log) as fh:
for line in fh:
match = self.regex.search(line)
if match:
data = match.groupdict()
results[data['key']] = data['value']
for key, value in results.iteritems():
context.result.add_metric(key, value)

View File

@@ -0,0 +1,29 @@
#!/bin/bash
# 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.
#
class_dir=bin/classes/com/arm/wlauto/uiauto
base_class=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', 'BaseUiAutomation.class')"`
mkdir -p $class_dir
cp $base_class $class_dir
${ANDROID_HOME}/tools/android update project -p .
ant build
if [[ -f bin/com.arm.wlauto.uiauto.andebench.jar ]]; then
cp bin/com.arm.wlauto.uiauto.andebench.jar ..
fi

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.arm.wlauto.uiauto.andebench" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: VERSION_TAG -->
<import file="${sdk.dir}/tools/ant/uibuild.xml" />
</project>

View File

@@ -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-17

View File

@@ -0,0 +1,108 @@
/* 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.
*/
package com.arm.wlauto.uiauto.andebench;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import com.arm.wlauto.uiauto.BaseUiAutomation;
public class UiAutomation extends BaseUiAutomation {
public static String TAG = "andebench";
private static int initialTimeoutSeconds = 20;
private static int shortDelaySeconds = 3;
public void runUiAutomation() throws Exception{
Bundle status = new Bundle();
Bundle params = getParams();
String numThreads = params.getString("number_of_threads");
status.putString("product", getUiDevice().getProductName());
waitForStartButton();
setNumberOfThreads(numThreads);
hitStart();
waitForAndExtractResuts();
getAutomationSupport().sendStatus(Activity.RESULT_OK, status);
}
public void waitForStartButton() throws Exception {
UiSelector selector = new UiSelector();
UiObject startButton = new UiObject(selector.className("android.widget.ImageButton")
.packageName("com.eembc.coremark"));
if (!startButton.waitForExists(TimeUnit.SECONDS.toMillis(initialTimeoutSeconds))) {
throw new UiObjectNotFoundException("Did not see start button.");
}
}
public void setNumberOfThreads(String numThreads) throws Exception {
UiSelector selector = new UiSelector();
getUiDevice().pressMenu();
UiObject settingsButton = new UiObject(selector.clickable(true));
settingsButton.click();
UiObject threadNumberField = new UiObject(selector.className("android.widget.EditText"));
threadNumberField.clearTextField();
threadNumberField.setText(numThreads);
getUiDevice().pressBack();
sleep(shortDelaySeconds);
// If the device does not have a physical keyboard, a virtual one might have
// poped up when setting the number of threads. If that happend, then the above
// backpress would dismiss the vkb and another one will be necessary to return
// from the settings screen.
if(threadNumberField.exists())
{
getUiDevice().pressBack();
sleep(shortDelaySeconds);
}
}
public void hitStart() throws Exception {
UiSelector selector = new UiSelector();
UiObject startButton = new UiObject(selector.className("android.widget.ImageButton")
.packageName("com.eembc.coremark"));
startButton.click();
sleep(shortDelaySeconds);
}
public void waitForAndExtractResuts() throws Exception {
UiSelector selector = new UiSelector();
UiObject runningText = new UiObject(selector.textContains("Running...")
.className("android.widget.TextView")
.packageName("com.eembc.coremark"));
runningText.waitUntilGone(TimeUnit.SECONDS.toMillis(600));
UiObject resultText = new UiObject(selector.textContains("Results in Iterations/sec:")
.className("android.widget.TextView")
.packageName("com.eembc.coremark"));
resultText.waitForExists(TimeUnit.SECONDS.toMillis(shortDelaySeconds));
Log.v(TAG, resultText.getText());
sleep(shortDelaySeconds);
}
}

View File

@@ -0,0 +1,30 @@
# 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.
#
from wlauto import GameWorkload
class AngryBirds(GameWorkload):
name = 'angrybirds'
description = """
Angry Birds game.
A very popular Android 2D game.
"""
package = 'com.rovio.angrybirds'
activity = 'com.rovio.ka3d.App'

Binary file not shown.

View File

@@ -0,0 +1,30 @@
# 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.
#
from wlauto import GameWorkload
class AngryBirdsRio(GameWorkload):
name = 'angrybirds_rio'
description = """
Angry Birds Rio game.
The sequel to the very popular Android 2D game.
"""
package = 'com.rovio.angrybirdsrio'
activity = 'com.rovio.ka3d.App'

View File

@@ -0,0 +1,63 @@
# Copyright 2014-2015 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import os
import json
from wlauto.common.android.workload import GameWorkload
from wlauto.exceptions import WorkloadError, DeviceError
class Anomaly2(GameWorkload):
name = 'anomaly2'
description = """
Anomaly 2 game demo and benchmark.
Plays three scenes from the game, benchmarking each one. Scores reported are intended to
represent overall perceived quality of the game, based not only on raw FPS but also factors
like smoothness.
"""
package = 'com.elevenbitstudios.anomaly2Benchmark'
activity = 'com.android.Game11Bits.MainActivity'
loading_time = 30
asset_file = 'obb:com.elevenbitstudios.anomaly2Benchmark.tar.gz'
def reset(self, context):
pass
def update_result(self, context):
super(Anomaly2, self).update_result(context)
sent_blobs = {'data': []}
with open(self.logcat_log) as fh:
for line in fh:
if 'sendHttpRequest: json = ' in line:
data = json.loads(line.split('json = ')[1])
sent_blobs['data'].append(data)
if 'scene' not in data['intValues']:
continue
scene = data['intValues']['scene']
score = data['intValues']['score']
fps = data['floatValues']['fps']
context.result.add_metric('scene_{}_score'.format(scene), score)
context.result.add_metric('scene_{}_fps'.format(scene), fps)
outfile = os.path.join(context.output_directory, 'anomaly2.json')
with open(outfile, 'wb') as wfh:
json.dump(sent_blobs, wfh, indent=4)
def teardown(self, context):
self.device.execute('am force-stop {}'.format(self.package))

View File

@@ -0,0 +1,136 @@
# 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.
#
import os
from collections import defaultdict, OrderedDict
from wlauto import AndroidUiAutoBenchmark, Parameter
class Antutu(AndroidUiAutoBenchmark):
name = 'antutu'
description = """
AnTuTu Benchmark is an benchmarking tool for Android Mobile Phone/Pad. It
can run a full test of a key project, through the "Memory Performance","CPU
Integer Performance","CPU Floating point Performance","2D 3D Graphics
Performance","SD card reading/writing speed","Database IO" performance
testing, and gives accurate analysis for Andriod smart phones.
http://www.antutulabs.com/AnTuTu-Benchmark
From the website:
AnTuTu Benchmark can support the latest quad-core cpu. In reaching the
overall and individual scores of the hardware, AnTuTu Benchmark could judge
your phone by the scores of the performance of the hardware. By uploading
the scores, Benchmark can view your device in the world rankings, allowing
points to let you know the level of hardware performance equipment.
"""
#pylint: disable=E1101
package = "com.antutu.ABenchMark"
activity = ".ABenchMarkStart"
summary_metrics = ['score', 'Overall_Score']
valid_versions = ['3.3.2', '4.0.3', '5.3.0']
device_prefs_directory = '/data/data/com.antutu.ABenchMark/shared_prefs'
device_prefs_file = '/'.join([device_prefs_directory, 'com.antutu.ABenchMark_preferences.xml'])
local_prefs_directory = os.path.join(os.path.dirname(__file__), 'shared_prefs')
parameters = [
Parameter('version', allowed_values=valid_versions, default=sorted(valid_versions, reverse=True)[0],
description=('Specify the version of AnTuTu to be run. If not specified, the latest available '
'version will be used.')),
Parameter('times', kind=int, default=1,
description=('The number of times the benchmark will be executed in a row (i.e. '
'without going through the full setup/teardown process). Note: this does '
'not work with versions prior to 4.0.3.')),
Parameter('enable_sd_tests', kind=bool, default=False,
description=('If ``True`` enables SD card tests in pre version 4 AnTuTu. These tests '
'were know to cause problems on platforms without an SD card. This parameter '
'will be ignored on AnTuTu version 4 and higher.')),
]
def __init__(self, device, **kwargs): # pylint: disable=W0613
super(Antutu, self).__init__(device, **kwargs)
self.run_timeout = 6 * 60 * self.times
self.uiauto_params['version'] = self.version
self.uiauto_params['times'] = self.times
self.uiauto_params['enable_sd_tests'] = self.enable_sd_tests
def update_result(self, context):
super(Antutu, self).update_result(context)
with open(self.logcat_log) as fh:
if self.version == '4.0.3':
metrics = extract_version4_metrics(fh)
else:
metrics = extract_older_version_metrics(fh)
for key, value in metrics.iteritems():
key = key.replace(' ', '_')
context.result.add_metric(key, value)
# Utility functions
def extract_version4_metrics(fh):
metrics = OrderedDict()
metric_counts = defaultdict(int)
for line in fh:
if 'ANTUTU RESULT:' in line:
parts = line.split(':')
metric = parts[2].strip()
# If times prameter > 1 the same metric will appear
# multiple times in logcat -- we want to collet all of
# them as they're from different iterations.
metric_counts[metric] += 1
if metric_counts[metric] > 1:
metric += '_' + str(metric_counts[metric])
value_string = parts[3].strip()
# Grahics results report resolution in square brackets
# as part of value string.
if ']' in value_string:
value = int(value_string.split(']')[1].strip())
else:
value = int(value_string)
metrics[metric] = value
return metrics
def extract_older_version_metrics(fh):
metrics = {}
metric_counts = defaultdict(int)
for line in fh:
if 'i/antutu' in line.lower():
parts = line.split(':')
if not len(parts) == 3:
continue
metric = parts[1].strip()
value = int(parts[2].strip())
# If times prameter > 1 the same metric will appear
# multiple times in logcat -- we want to collet all of
# them as they're from different iterations.
metric_counts[metric] += 1
if metric_counts[metric] > 1:
metric += ' ' + str(metric_counts[metric])
metrics[metric] = value
return metrics

View File

@@ -0,0 +1,28 @@
#!/bin/bash
# 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.
#
class_dir=bin/classes/com/arm/wlauto/uiauto
base_class=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', 'BaseUiAutomation.class')"`
mkdir -p $class_dir
cp $base_class $class_dir
ant build
if [[ -f bin/com.arm.wlauto.uiauto.antutu.jar ]]; then
cp bin/com.arm.wlauto.uiauto.antutu.jar ..
fi

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.arm.wlauto.uiauto.antutu" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: VERSION_TAG -->
<import file="${sdk.dir}/tools/ant/uibuild.xml" />
</project>

View File

@@ -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-19

View File

@@ -0,0 +1,295 @@
/* 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.
*/
package com.arm.wlauto.uiauto.antutu;
import java.util.Set;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
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.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.core.UiCollection;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import com.arm.wlauto.uiauto.BaseUiAutomation;
public class UiAutomation extends BaseUiAutomation {
public static String TAG = "antutu";
private static int initialTimeoutSeconds = 20;
public void runUiAutomation() throws Exception{
Bundle parameters = getParams();
String version = parameters.getString("version");
boolean enableSdTests = Boolean.parseBoolean(parameters.getString("enable_sd_tests"));
int times = Integer.parseInt(parameters.getString("times"));
if (times < 1) {
times = 1;
}
if (version.equals("4.0.3") || version.equals("5.3.0")){
int iteration = 0;
dismissNewVersionNotificationIfNecessary();
hitTestButton();
while (true) {
if (version.equals("5.3.0"))
hitTestButtonVersion5();
else
hitTestButton();
waitForVersion4Results();
viewDetails();
extractResults();
iteration++;
if (iteration >= times) {
break;
}
returnToTestScreen();
}
} else { // version earlier than 4.0.3
dismissReleaseNotesDialogIfNecessary();
if(!enableSdTests){
disableSdCardTests();
}
hitStart();
waitForAndViewResults();
}
Bundle status = new Bundle();
getAutomationSupport().sendStatus(Activity.RESULT_OK, status);
}
public boolean dismissNewVersionNotificationIfNecessary() throws Exception {
UiSelector selector = new UiSelector();
UiObject closeButton = new UiObject(selector.text("Cancel"));
if (closeButton.waitForExists(TimeUnit.SECONDS.toMillis(initialTimeoutSeconds))) {
closeButton.click();
sleep(1); // diaglog dismissal
return true;
} else {
return false;
}
}
public boolean dismissReleaseNotesDialogIfNecessary() throws Exception {
UiSelector selector = new UiSelector();
UiObject closeButton = new UiObject(selector.text("Close"));
if (closeButton.waitForExists(TimeUnit.SECONDS.toMillis(initialTimeoutSeconds))) {
closeButton.click();
sleep(1); // diaglog dismissal
return true;
} else {
return false;
}
}
public void hitTestButton() throws Exception {
UiSelector selector = new UiSelector();
UiObject test = new UiObject(selector.text("Test")
.className("android.widget.Button"));
test.waitForExists(initialTimeoutSeconds);
test.click();
sleep(1); // possible tab transtion
}
/* In version 5 of antutu, the test has been changed from a button widget to a textview */
public void hitTestButtonVersion5() throws Exception {
UiSelector selector = new UiSelector();
UiObject test = new UiObject(selector.resourceId("com.antutu.ABenchMark:id/start_test_region")
.className("android.widget.TextView"));
test.waitForExists(initialTimeoutSeconds);
test.click();
sleep(1); // possible tab transtion
}
public void hitTest() throws Exception {
UiSelector selector = new UiSelector();
UiObject test = new UiObject(selector.text("Test"));
test.click();
sleep(1); // possible tab transtion
}
public void disableSdCardTests() throws Exception {
UiSelector selector = new UiSelector();
UiObject custom = new UiObject(selector.textContains("Custom"));
custom.click();
sleep(1); // tab transition
UiObject sdCardButton = new UiObject(selector.text("SD card IO"));
sdCardButton.click();
}
public void hitStart() throws Exception {
UiSelector selector = new UiSelector();
Log.v(TAG, "Start the test");
UiObject startButton = new UiObject(selector.text("Start Test")
.className("android.widget.Button"));
startButton.click();
}
public void waitForVersion4Results() throws Exception {
// The observed behaviour seems to vary between devices. On some platforms,
// the benchmark terminates in the barchart screen; on others, it terminates in
// details screen. So we have to wait for either and then act appropriatesl (on the barchart
// screen a back button press is required to get to the details screen.
UiSelector selector = new UiSelector();
UiObject barChart = new UiObject(new UiSelector().className("android.widget.TextView")
.text("Bar Chart"));
UiObject detailsButton = new UiObject(new UiSelector().className("android.widget.Button")
.text("Details"));
for (int i = 0; i < 60; i++) {
if (detailsButton.exists() || barChart.exists()) {
break;
}
sleep(5);
}
if (barChart.exists()) {
getUiDevice().pressBack();
}
}
public void viewDetails() throws Exception {
UiSelector selector = new UiSelector();
UiObject detailsButton = new UiObject(new UiSelector().className("android.widget.Button")
.text("Details"));
detailsButton.clickAndWaitForNewWindow();
}
public void extractResults() throws Exception {
extractOverallResult();
extractSectionResults();
}
public void extractOverallResult() throws Exception {
UiSelector selector = new UiSelector();
UiSelector resultTextSelector = selector.className("android.widget.TextView").index(0);
UiSelector relativeLayoutSelector = selector.className("android.widget.RelativeLayout").index(1);
UiObject result = new UiObject(selector.className("android.widget.LinearLayout")
.childSelector(relativeLayoutSelector)
.childSelector(resultTextSelector));
if (result.exists()) {
Log.v(TAG, String.format("ANTUTU RESULT: Overall Score: %s", result.getText()));
}
}
public void extractSectionResults() throws Exception {
UiSelector selector = new UiSelector();
Set<String> processedMetrics = new HashSet<String>();
actuallyExtractSectionResults(processedMetrics);
UiScrollable resultsList = new UiScrollable(selector.className("android.widget.ScrollView"));
// Note: there is an assumption here that the entire results list fits on at most
// two screens on the device. Given then number of entries in the current
// antutu verion and the devices we're dealing with, this is a reasonable
// assumption. But if this changes, this will need to be adapted to scroll more
// slowly.
resultsList.scrollToEnd(10);
actuallyExtractSectionResults(processedMetrics);
}
public void actuallyExtractSectionResults(Set<String> processedMetrics) throws Exception {
UiSelector selector = new UiSelector();
for (int i = 1; i < 8; i += 2) {
UiObject table = new UiObject(selector.className("android.widget.TableLayout").index(i));
for (int j = 0; j < 3; j += 2) {
UiObject row = table.getChild(selector.className("android.widget.TableRow").index(j));
UiObject metric = row.getChild(selector.className("android.widget.TextView").index(0));
UiObject value = row.getChild(selector.className("android.widget.TextView").index(1));
if (metric.exists() && value.exists()) {
String metricText = metric.getText();
if (!processedMetrics.contains(metricText)) {
Log.v(TAG, String.format("ANTUTU RESULT: %s %s", metric.getText(), value.getText()));
processedMetrics.add(metricText);
}
}
}
}
}
public void returnToTestScreen() throws Exception {
getUiDevice().pressBack();
UiSelector selector = new UiSelector();
UiObject retestButton = new UiObject(selector.text("Test Again")
.className("android.widget.Button"));
retestButton.clickAndWaitForNewWindow();
}
public void waitForAndViewResults() throws Exception {
UiSelector selector = new UiSelector();
UiObject submitTextView = new UiObject(selector.text("Submit Scores")
.className("android.widget.TextView"));
UiObject detailTextView = new UiObject(selector.text("Detailed Scores")
.className("android.widget.TextView"));
UiObject commentTextView = new UiObject(selector.text("User comment")
.className("android.widget.TextView"));
boolean foundResults = false;
for (int i = 0; i < 60; i++) {
if (detailTextView.exists() || submitTextView.exists() || commentTextView.exists()) {
foundResults = true;
break;
}
sleep(5);
}
if (!foundResults) {
throw new UiObjectNotFoundException("Did not see AnTuTu results screen.");
}
if (commentTextView.exists()) {
getUiDevice().pressBack();
}
// Yes, sometimes, it needs to be done twice...
if (commentTextView.exists()) {
getUiDevice().pressBack();
}
if (detailTextView.exists()) {
detailTextView.click();
sleep(1); // tab transition
UiObject testTextView = new UiObject(selector.text("Test")
.className("android.widget.TextView"));
if (testTextView.exists()) {
testTextView.click();
sleep(1); // tab transition
}
UiObject scoresTextView = new UiObject(selector.text("Scores")
.className("android.widget.TextView"));
if (scoresTextView.exists()) {
scoresTextView.click();
sleep(1); // tab transition
}
}
}
}

View File

@@ -0,0 +1,169 @@
# 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.
"""
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('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,
package=APP_CONFIG[self.app]['package'],
activity=APP_CONFIG[self.app]['activity'],
options=APP_CONFIG[self.app]['options'],
))
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)
def update_result(self, context):
result_files = ['time.result']
result_files += ['{}.result'.format(sensor.label) for sensor in self.sensors]
for filename in result_files:
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', 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 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 _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)

View File

@@ -0,0 +1,69 @@
#!{{ 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
for i in $(busybox seq 1 {{ iterations }})
do
{% for sensor in sensors %}
{{ sensor.label }}="${{ sensor.label }} `$GET_{{ sensor.label }}`"
{% endfor %}
$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
{% 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

View File

@@ -0,0 +1,102 @@
# Copyright 2012-2015 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# pylint: disable=E1101,W0201
import os
import time
import urllib
from wlauto import settings, Workload, Parameter
from wlauto.exceptions import ConfigError
from wlauto.utils.types import boolean
DEFAULT_AUDIO_FILE_URL = "http://archive.org/download/PachelbelsCanoninD/Canon_in_D_Piano.mp3"
class Audio(Workload):
name = 'audio'
description = """
Audio workload plays an MP3 file using the built-in music player. By default,
it plays Canon_in_D_Pieano.mp3 for 30 seconds.
"""
parameters = [
Parameter('duration', kind=int, default=30,
description='The duration the music will play for in seconds.'),
Parameter('audio_file', default=os.path.join(settings.dependencies_directory, 'Canon_in_D_Piano.mp3'),
description='''The (on-host) path to the audio file to be played.
.. note:: If the default file is not present locally, it will be downloaded.
'''),
Parameter('perform_cleanup', kind=boolean, default=False,
description='If ``True``, workload files on the device will be deleted after execution.'),
Parameter('clear_file_cache', kind=boolean, default=True,
description='Clear the the file cache on the target device prior to running the workload.')
]
def init_resources(self, context):
if not os.path.isfile(self.audio_file):
self._download_audio_file()
def setup(self, context):
self.on_device_file = os.path.join(self.device.working_directory,
os.path.basename(self.audio_file))
self.device.push_file(self.audio_file, self.on_device_file, timeout=120)
# Open the browser with default page
self.device.execute('am start -n com.android.browser/.BrowserActivity about:blank')
time.sleep(5)
# Stop the browser if already running and wait for it to stop
self.device.execute('am force-stop com.android.browser')
time.sleep(5)
# Clear the logs
self.device.clear_logcat()
# Clear browser cache
self.device.execute('pm clear com.android.browser')
if self.clear_file_cache:
self.device.execute('sync')
self.device.set_sysfile_value('/proc/sys/vm/drop_caches', 3)
# Start the background music
self.device.execute('am start -W -S -n com.android.music/.MediaPlaybackActivity -d {}'.format(self.on_device_file))
# Launch the browser to blank the screen
self.device.execute('am start -W -n com.android.browser/.BrowserActivity about:blank')
time.sleep(5) # Wait for browser to be properly launched
def run(self, context):
time.sleep(self.duration)
def update_result(self, context):
# Stop the browser
self.device.execute('am force-stop com.android.browser')
# Stop the audio
self.device.execute('am force-stop com.android.music')
def teardown(self, context):
if self.perform_cleanup:
self.device.delete_file(self.on_device_file)
def _download_audio_file(self):
self.logger.debug('Downloading audio file from {}'.format(DEFAULT_AUDIO_FILE_URL))
urllib.urlretrieve(DEFAULT_AUDIO_FILE_URL, self.audio_file)

View File

@@ -0,0 +1,231 @@
# Copyright 2012-2015 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# pylint: disable=E1101,W0201
import os
import time
import urllib
import tarfile
import shutil
import json
import re
from collections import defaultdict
from wlauto import settings, Workload, Parameter, Alias, Executable
from wlauto.exceptions import ConfigError
from wlauto.utils.types import boolean
DEFAULT_BBENCH_FILE = "http://bbench.eecs.umich.edu/bbench/bbench_2.0.tgz"
DOWNLOADED_FILE_NAME = "bbench_2.0.tgz"
BBENCH_SERVER_NAME = 'bbench_server'
PATCH_FILES = os.path.join(os.path.dirname(__file__), "patches")
DEFAULT_AUDIO_FILE = "http://archive.org/download/PachelbelsCanoninD/Canon_in_D_Piano.mp3"
DEFAULT_AUDIO_FILE_NAME = 'Canon_in_D_Piano.mp3'
class BBench(Workload):
name = 'bbench'
description = """
BBench workload opens the built-in browser and navigates to, and
scrolls through, some preloaded web pages and ends the workload by trying to
connect to a local server it runs after it starts. It can also play the
workload while it plays an audio file in the background.
"""
summary_metrics = ['Mean Latency']
parameters = [
Parameter('with_audio', kind=boolean, default=False,
description=('Specifies whether an MP3 should be played in the background during '
'workload execution.')),
Parameter('server_timeout', kind=int, default=300,
description='Specifies the timeout (in seconds) before the server is stopped.'),
Parameter('force_dependency_push', kind=boolean, default=False,
description=('Specifies whether to push dependency files to the device to the device '
'if they are already on it.')),
Parameter('audio_file', default=os.path.join(settings.dependencies_directory, 'Canon_in_D_Piano.mp3'),
description=('The (on-host) path to the audio file to be played. This is only used if '
'``with_audio`` is ``True``.')),
Parameter('perform_cleanup', kind=boolean, default=False,
description='If ``True``, workload files on the device will be deleted after execution.'),
Parameter('clear_file_cache', kind=boolean, default=True,
description='Clear the the file cache on the target device prior to running the workload.'),
Parameter('browser_package', default='com.android.browser',
description='Specifies the package name of the device\'s browser app.'),
Parameter('browser_activity', default='.BrowserActivity',
description='Specifies the startup activity name of the device\'s browser app.'),
]
aliases = [
Alias('bbench_with_audio', with_audio=True),
]
def setup(self, context): # NOQA
self.bbench_on_device = '/'.join([self.device.working_directory, 'bbench'])
self.bbench_server_on_device = os.path.join(self.device.working_directory, BBENCH_SERVER_NAME)
self.audio_on_device = os.path.join(self.device.working_directory, DEFAULT_AUDIO_FILE_NAME)
self.index_noinput = 'file:///{}'.format(self.bbench_on_device) + '/index_noinput.html'
self.luanch_server_command = '{} {}'.format(BBENCH_SERVER_NAME, self.server_timeout)
if not os.path.isdir(os.path.join(self.dependencies_directory, "sites")):
self._download_bbench_file()
if self.with_audio and not os.path.isfile(self.audio_file):
self._download_audio_file()
if not os.path.isdir(self.dependencies_directory):
raise ConfigError('Bbench directory does not exist: {}'.format(self.dependencies_directory))
self._apply_patches()
if self.with_audio:
if self.force_dependency_push or not self.device.file_exists(self.audio_on_device):
self.device.push_file(self.audio_file, self.audio_on_device, timeout=120)
# Push the bbench site pages and http server to target device
if self.force_dependency_push or not self.device.file_exists(self.bbench_on_device):
self.logger.debug('Copying bbench sites to device.')
self.device.push_file(self.dependencies_directory, self.bbench_on_device, timeout=300)
# Push the bbench server
host_binary = context.resolver.get(Executable(self, self.device.abi, 'bbench_server'))
self.device.install(host_binary)
# Open the browser with default page
self.device.execute('am start -n {}/{} about:blank'.format(self.browser_package, self.browser_activity))
time.sleep(5)
# Stop the browser if already running and wait for it to stop
self.device.execute('am force-stop {}'.format(self.browser_package))
time.sleep(5)
# Clear the logs
self.device.clear_logcat()
# clear browser cache
self.device.execute('pm clear {}'.format(self.browser_package))
if self.clear_file_cache:
self.device.execute('sync')
self.device.set_sysfile_value('/proc/sys/vm/drop_caches', 3)
# Launch the background music
if self.with_audio:
self.device.execute('am start -W -S -n com.android.music/.MediaPlaybackActivity -d {}'.format(self.audio_on_device))
def run(self, context):
# Launch the bbench
self.device.execute('am start -n {}/{} {}'.format(self.browser_package, self.browser_activity, self.index_noinput))
time.sleep(5) # WA1 parity
# Launch the server waiting for Bbench to complete
self.device.execute(self.luanch_server_command, self.server_timeout)
def update_result(self, context):
# Stop the browser
self.device.execute('am force-stop {}'.format(self.browser_package))
# Stop the music
if self.with_audio:
self.device.execute('am force-stop com.android.music')
# Get index_no_input.html
indexfile = os.path.join(self.device.working_directory, 'bbench/index_noinput.html')
self.device.pull_file(indexfile, context.output_directory)
# Get the logs
output_file = os.path.join(self.device.working_directory, 'browser_bbench_logcat.txt')
self.device.execute('logcat -v time -d > {}'.format(output_file))
self.device.pull_file(output_file, context.output_directory)
metrics = _parse_metrics(os.path.join(context.output_directory, 'browser_bbench_logcat.txt'),
os.path.join(context.output_directory, 'index_noinput.html'),
context.output_directory)
for key, values in metrics:
for i, value in enumerate(values):
metric = '{}_{}'.format(key, i) if i else key
context.result.add_metric(metric, value, units='ms', lower_is_better=True)
def teardown(self, context):
if self.perform_cleanup:
self.device.execute('rm -r {}'.format(self.bbench_on_device))
self.device.execute('rm {}'.format(self.audio_on_device))
def _download_audio_file(self):
self.logger.debug('Downloadling audio file.')
urllib.urlretrieve(DEFAULT_AUDIO_FILE, self.audio_file)
def _download_bbench_file(self):
# downloading the file to bbench_dir
self.logger.debug('Downloading bbench dependencies.')
full_file_path = os.path.join(self.dependencies_directory, DOWNLOADED_FILE_NAME)
urllib.urlretrieve(DEFAULT_BBENCH_FILE, full_file_path)
# Extracting Bbench to bbench_dir/
self.logger.debug('Extracting bbench dependencies.')
tar = tarfile.open(full_file_path)
tar.extractall(os.path.dirname(self.dependencies_directory))
# Removing not needed files and the compressed file
os.remove(full_file_path)
youtube_dir = os.path.join(self.dependencies_directory, 'sites', 'youtube')
os.remove(os.path.join(youtube_dir, 'www.youtube.com', 'kp.flv'))
os.remove(os.path.join(youtube_dir, 'kp.flv'))
def _apply_patches(self):
self.logger.debug('Applying patches.')
shutil.copy(os.path.join(PATCH_FILES, "bbench.js"), self.dependencies_directory)
shutil.copy(os.path.join(PATCH_FILES, "results.html"), self.dependencies_directory)
shutil.copy(os.path.join(PATCH_FILES, "index_noinput.html"), self.dependencies_directory)
def _parse_metrics(logfile, indexfile, output_directory): # pylint: disable=R0914
regex_bbscore = re.compile(r'(?P<head>\w+)=(?P<val>\w+)')
regex_bbmean = re.compile(r'Mean = (?P<mean>[0-9\.]+)')
regex_pagescore_head = re.compile(r'metrics:(\w+),(\d+)')
regex_pagescore_tail = re.compile(r',(\d+.\d+)')
regex_indexfile = re.compile(r'<body onload="startTest\((.*)\)">')
settings_dict = defaultdict()
with open(indexfile) as fh:
for line in fh:
match = regex_indexfile.search(line)
if match:
settings_dict['iterations'], settings_dict['scrollDelay'], settings_dict['scrollSize'] = match.group(1).split(',')
with open(logfile) as fh:
results_dict = defaultdict(list)
for line in fh:
if 'metrics:Mean' in line:
results_list = regex_bbscore.findall(line)
results_dict['Mean Latency'].append(regex_bbmean.search(line).group('mean'))
if results_list:
break
elif 'metrics:' in line:
page_results = [0]
match = regex_pagescore_head.search(line)
name, page_results[0] = match.groups()
page_results.extend(regex_pagescore_tail.findall(line[match.end():]))
for val in page_results[:-2]:
results_list.append((name, int(float(val))))
setting_names = ['siteIndex', 'CGTPreviousTime', 'scrollDelay', 'scrollSize', 'iterations']
for k, v in results_list:
if k not in setting_names:
results_dict[k].append(v)
sorted_results = sorted(results_dict.items())
with open(os.path.join(output_directory, 'settings.json'), 'w') as wfh:
json.dump(settings_dict, wfh)
return sorted_results

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,177 @@
//Author: Anthony Gutierrez
var bb_site = [];
var bb_results = [];
var globalSiteIndex = 0;
var numWebsites = 9;
var bb_path = document.location.pathname;
var bb_home = "file:///" + bb_path.substr(1, bb_path.lastIndexOf("bbench") + 5);
var num_iters = 0;
var init = false;
function generateSiteArray(numTimesToExecute) {
for (i = 0; i < numTimesToExecute * numWebsites; i += numWebsites) {
bb_site[i+0] = bb_home + "/sites/amazon/www.amazon.com/index.html";
bb_site[i+1] = bb_home + "/sites/bbc/www.bbc.co.uk/index.html";
bb_site[i+2] = bb_home + "/sites/cnn/www.cnn.com/index.html";
bb_site[i+3] = bb_home + "/sites/craigslist/newyork.craigslist.org/index.html";
bb_site[i+4] = bb_home + "/sites/ebay/www.ebay.com/index.html";
bb_site[i+5] = bb_home + "/sites/google/www.google.com/index.html";
// bb_site[i+6] = bb_home + "/sites/youtube/www.youtube.com/index.html";
bb_site[i+6] = bb_home + "/sites/msn/www.msn.com/index.html";
bb_site[i+7] = bb_home + "/sites/slashdot/slashdot.org/index.html";
bb_site[i+8] = bb_home + "/sites/twitter/twitter.com/index.html";
// bb_site[i+10] = bb_home + "/sites/espn/espn.go.com/index.html";
}
bb_site[i] = bb_home + "/results.html";
}
/* gets the URL parameters and removes from window href */
function getAndRemoveURLParams(windowURL, param) {
var regex_string = "(.*)(\\?)" + param + "(=)([0-9]+)(&)(.*)";
var regex = new RegExp(regex_string);
var results = regex.exec(windowURL.value);
if (results == null)
return "";
else {
windowURL.value = results[1] + results[6];
return results[4];
}
}
/* gets the URL parameters */
function getURLParams(param) {
var regex_string = "(.*)(\\?)" + param + "(=)([0-9]+)(&)(.*)";
var regex = new RegExp(regex_string);
var results = regex.exec(window.location.href);
if (results == null)
return "";
else
return results[4];
}
/* gets all the parameters */
function getAllParams() {
var regex_string = "(\\?.*)(\\?siteIndex=)([0-9]+)(&)";
var regex = new RegExp(regex_string);
var results = regex.exec(window.location.href);
/*alert(" Result is 1: " + results[1] + " 2: " + results[2] + " 3: " + results[3]);*/
if (results == null)
return "";
else
return results[1];
}
/* sets a cookie */
function setCookie(c_name, value) {
var c_value = escape(value) + ";";
document.cookie = c_name + "=" + c_value + " path=/";
}
/* gets a cookie */
function getCookie(c_name) {
var cookies = document.cookie.split(";");
var i, x, y;
for (i = 0; i < cookies.length; ++i) {
x = cookies[i].substr(0, cookies[i].indexOf("="));
y = cookies[i].substr(cookies[i].indexOf("=") + 1);
x = x.replace(/^\s+|\s+$/g,"");
if (x == c_name)
return unescape(y);
}
}
/* start the test, simply go to site 1. */
function startTest(n, del, y) {
//var start_time = (new Date()).getTime();
//setCookie("PreviousTime", start_time);
init = true;
generateSiteArray(n);
siteTest(bb_site[0], globalSiteIndex, new Date().getTime(), "scrollSize=" + y + "&?scrollDelay=" + del + "&?iterations=" + n + "&?" + "StartPage");
//siteTest(bb_site[0], globalSiteIndex, new Date().getTime(), "scrollDelay=" + del + "&?iterations=" + n + "&?" + "StartPage");
//goToSite(bb_site[0], new Date().getTime());
}
/* jump to the next site */
function goToSite(site) {
curr_time = new Date().getTime();
setCookie("CGTPreviousTime", curr_time);
site+="?CGTPreviousTime="+curr_time+"&";
window.location.href = site;
}
/*
the test we want to run on the site.
for now, simply scroll to the bottom
and jump to the next site. in the
future we will want to do some more
realistic browsing tests.
*/
function siteTest(nextSite, siteIndex, startTime, siteName) {
if (!init) {
var iterations = getURLParams("iterations");
var params = getAllParams();
var delay = getURLParams("scrollDelay");
var verticalScroll = getURLParams("scrollSize");
generateSiteArray(iterations);
nextSite = bb_site[siteIndex] + params;
}
else {
var delay = 500;
var verticalScroll = 500;
}
var cgtPreviousTime = getURLParams("CGTPreviousTime");
var load_time = 0;
siteIndex++;
if (siteIndex > 1) {
cur_time = new Date().getTime();
// alert("previous " + cgtPreviousTime + " foo " + getCookie("CGTPreviousTime"));
load_time = (cur_time - cgtPreviousTime);
setCookie("CGTLoadTime", load_time);
// diff = cur_time-startTime;
// alert("starttime "+startTime+" currtime "+ cur_time + " diff " + diff + "load_time " + load_time );
}
setTimeout(function() {
scrollToBottom(0, verticalScroll, delay,load_time,
function(load_time_param){
cur_time = new Date().getTime();
load_time = (cur_time - startTime);
//load_time = (cur_time - getCookie("PreviousTime"));
// alert("Done with this site! " + window.cur_time + " " + startTime + " " + window.load_time);
//alert("Done with this site! " + window.cur_time + " " + getCookie("PreviousTime") + " " + window.load_time);
//goToSite(nextSite + "?iterations=" + iterations + "&?" + siteName + "=" + load_time + "&" + "?siteIndex=" + siteIndex + "&" );
// alert("loadtime in cookie="+ getCookie("CGTLoadTime")+" loadtime in var="+load_time_param);
goToSite(nextSite + "?" + siteName + "=" + load_time_param + "&" + "?siteIndex=" + siteIndex + "&" );
}
);},(siteIndex > 1) ? 1000 : 0);
}
/*
scroll to the bottom of the page in
num_y pixel increments. may want to
do some horizontal scrolling in the
future as well.
*/
function scrollToBottom(num_x, num_y, del, load_time, k) {
++num_iters;
var diff = document.body.scrollHeight - num_y * num_iters;
//var num_scrolls = 0;
if (diff > num_y) {
//self.scrollBy(num_x, num_y);
//setTimeout(function(){self.scrollBy(num_x, num_y); /*diff -= 100;*/ scrollToBottom(num_x, num_y, k);}, 2);
setTimeout(function(){self.scrollBy(num_x, num_y); /*diff -= 100;*/ scrollToBottom(num_x, num_y, del, load_time,k);}, del);
}
else{
k(load_time);
}
}

View File

@@ -0,0 +1,56 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1.dtd">
<!--
Author: Anthony Gutierrez
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>University of Michigan - BBench 2.0</title>
<script type="text/javascript" src="bbench.js"></script>
<script type="text/javascript" src="forms.js"></script>
</head>
<body onload="startTest(2,2000,500)">
<!--
<body>
<img src="mich_engin.png" width="35%"/>
<h2>University of Michigan BBench version 2.0</h2>
<form name="config_form">
<b>Number of iterations:</b> <input type="text" name="numIterations" value="5" size="4" onchange="setIters();">
<input type="button" value="-" name="iterPlusButton" onClick="document.config_form.numIterations.value=numItersDec(); return true;">
<input type="button" value="+" name="iterMinusButton" onClick="document.config_form.numIterations.value=numItersInc(); return true;">
(Number of times the page set is iterated through.)
<br/><br/>
<b>Scroll Delay (ms):</b> <input type="text" name="scrollDelay" value="0" size="8" onchange="setScrollDelay();">
<input type="button" value="-" name="scrollDelayPlusButton" onClick="document.config_form.scrollDelay.value=scrollDelayDec(); return true;">
<input type="button" value="+" name="scrollDelayMinusButton" onClick="document.config_form.scrollDelay.value=scrollDelayInc(); return true;">
(Number of milliseconds to pause before scrolling.)
<br/><br/>
<b>Scroll Size:</b> <input type="text" name="scrollSize" value="500" size="8" onchange="setScrollSize();">
<input type="button" value="-" name="scrollSizePlusButton" onClick="document.config_form.scrollSize.value=scrollSizeDec(); return true;">
<input type="button" value="+" name="scrollSizeMinusButton" onClick="document.config_form.scrollSize.value=scrollSizeInc(); return true;">
(Number of pixel to scroll.)
<br/><br/>
</form>
<p>
<b>Click on the start button to begin the benchmark.</b>
</p>
<button onclick="startTest(numIters, scrollDelay, scrollSize)">start</button>
<p>
If you use BBench in your work please cite our <a href="http://www.eecs.umich.edu/~atgutier/iiswc_2011.pdf">2011 IISWC paper</a>:<br/><br/>
A. Gutierrez, R.G. Dreslinksi, T.F. Wenisch, T. Mudge, A. Saidi, C. Emmons, and N. Paver. Full-System Analysis and Characterization
of Interactive Smartphone Applications. <i>IEEE International Symposium on Workload Characterization</i>, 2011.
</p>
--!>
</body>
</html>

View File

@@ -0,0 +1,158 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1.dtd">
<!--
Author: Anthony Gutierrez
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>University of Michigan - BBench 2.0</title>
<script type="text/javascript" src="bbench.js"></script>
<script type="text/javascript">
var numTimesToExecute = getURLParams("iterations");
function closeWindow() {
window.open('','_self','');
window.close();
}
function averageWarm(siteTimes) {
var sum = 0;
if (numTimesToExecute == 1)
return siteTimes[0];
for (i = 0; i < numTimesToExecute - 1; ++i)
sum = eval(sum + siteTimes[i]);
return (sum / (numTimesToExecute - 1));
}
function stdDevWarm(siteTimes) {
var avg = averageWarm(siteTimes)
var tmpArray = [];
if (numTimesToExecute == 1)
return 0;
for (i = 0; i < numTimesToExecute - 1; ++i)
tmpArray[i] = Math.pow((siteTimes[i] - avg), 2);
avg = averageWarm(tmpArray);
return Math.sqrt(avg);
}
function geoMean(avgTimes) {
var prod = 1;
for (i = 0; i < numWebsites; ++i)
prod = eval(prod * avgTimes[i]);
return Math.pow(prod, (1/numWebsites));
}
</script>
</head>
<body>
<img src="mich_engin.png" width="35%"/>
<h2>University of Michigan BBench version 2.0</h2>
<h3>Results</h3>
<script type="text/javascript">
var bbSiteColdTimes = [];
var bbSiteTimes = [];
var bbSiteAvgRunTime = [];
var bbSiteStdDev = [];
var bbSiteCoeffVar = [];
var bbSiteNames = ["amazon",
"bbc",
"cnn",
"craigslist",
"ebay",
// "espn",
"google",
"msn",
"slashdot",
"twitter"];
// "youtube"];
var windowURL = new Object();
var windowURL2 = new Object();
windowURL.value = window.location.href;
windowURL2.value = window.location.href;
for (j = 0; j < numWebsites; ++j) {
for (i = 0; i < numTimesToExecute; ++i) {
var site_time = getAndRemoveURLParams(windowURL, bbSiteNames[j]) - 0;
bbSiteTimes[i] = site_time;
}
bbSiteColdTimes[j] = bbSiteTimes[i - 1];
bbSiteAvgRunTime[j] = averageWarm(bbSiteTimes);
bbSiteStdDev[j] = stdDevWarm(bbSiteTimes);
bbSiteCoeffVar[j] = (bbSiteStdDev[j] / bbSiteAvgRunTime[j]) * 100;
}
var bbSiteAvgGeoMean = geoMean(bbSiteAvgRunTime);
</script>
<table border="1">
<script type="text/javascript">
document.write("<tr align=\"right\"><td>Site Name</td><td>Cold Start Time</td><td>Avg Warm Page Rendering Time (ms)</td><td>Std Dev of Warm Runs</td><td>%Coeff Var of Warm Runs</td>");
for (i = 0; i < numWebsites; ++i) {
document.write("<tr align=\"right\">");
document.write("<td>" + bbSiteNames[i] + "</td>");
document.write("<td>" + bbSiteColdTimes[i] + "</td>");
document.write("<td>" + bbSiteAvgRunTime[i].toFixed(2) + "</td>");
document.write("<td>" + bbSiteStdDev[i].toFixed(2) + "</td>");
document.write("<td>" + bbSiteCoeffVar[i].toFixed(2) + "</td>");
document.write("</tr>");
}
</script>
</table>
<br />
<table border="1">
<script type="text/javascript">
document.write("<tr><td>Geometric Mean of Average Warm Runs</td><td>" + bbSiteAvgGeoMean.toFixed(2) + "</td></tr>");
console.log("metrics:" + "Mean = " + bbSiteAvgGeoMean.toFixed(2) + ":")
</script>
</table>
<h3>CSV version of the table:</h3>
<script type="text/javascript">
document.write("Site Name,Cold Start Time, Avg Warm Page Rendering Time (ms),Std Dev of Warm Runs,%Coeff Var of Warm Runs<br />");
for (i = 0; i < numWebsites; ++i) {
document.write(bbSiteNames[i] + ",");
document.write(bbSiteColdTimes[i] + ",");
document.write(bbSiteAvgRunTime[i].toFixed(2) + ",");
document.write(bbSiteStdDev[i].toFixed(2) + ",");
document.write(bbSiteCoeffVar[i].toFixed(2) + "<br />");
console.log("metrics:" + bbSiteNames[i] + "," + bbSiteColdTimes[i] + "," + bbSiteAvgRunTime[i].toFixed(2) + "," + bbSiteStdDev[i].toFixed(2) + "," + bbSiteCoeffVar[i].toFixed(2) + ":");
}
document.write("<h3>Individual Site Times:</h3>");
for (j = 0; j < numWebsites; ++j) {
for (i = 0; i < numTimesToExecute; ++i) {
var site_time = getAndRemoveURLParams(windowURL2, bbSiteNames[j]) - 0;
bbSiteTimes[i] = site_time;
document.write(bbSiteNames[j] + " load time: " + site_time + "<br />");
}
document.write("<br />");
}
setTimeout("window.location.href='http://localhost:3030/'", 1);
</script>
<p>
<b>Click the return button to go to the start page.</b>
</p>
<button onclick="window.location.href='index.html'">return</button>
</body>
</html>

View File

@@ -0,0 +1,63 @@
# 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.
#
import re
from wlauto import AndroidUiAutoBenchmark
class BenchmarkPi(AndroidUiAutoBenchmark):
name = 'benchmarkpi'
description = """
Measures the time the target device takes to run and complete the Pi
calculation algorithm.
http://androidbenchmark.com/howitworks.php
from the website:
The whole idea behind this application is to use the same Pi calculation
algorithm on every Android Device and check how fast that proccess is.
Better calculation times, conclude to faster Android devices. This way you
can also check how lightweight your custom made Android build is. Or not.
As Pi is an irrational number, Benchmark Pi does not calculate the actual Pi
number, but an approximation near the first digits of Pi over the same
calculation circles the algorithms needs.
So, the number you are getting in miliseconds is the time your mobile device
takes to run and complete the Pi calculation algorithm resulting in a
approximation of the first Pi digits.
"""
package = 'gr.androiddev.BenchmarkPi'
activity = '.BenchmarkPi'
summary_metrics = ['pi calculation']
regex = re.compile('You calculated Pi in ([0-9]+)')
def update_result(self, context):
super(BenchmarkPi, self).update_result(context)
result = None
with open(self.logcat_log) as fh:
for line in fh:
match = self.regex.search(line)
if match:
result = int(match.group(1))
if result is not None:
context.result.add_metric('pi calculation', result,
'Milliseconds', lower_is_better=True)

View File

@@ -0,0 +1,28 @@
#!/bin/bash
# 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.
#
class_dir=bin/classes/com/arm/wlauto/uiauto
base_class=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', 'BaseUiAutomation.class')"`
mkdir -p $class_dir
cp $base_class $class_dir
ant build
if [[ -f bin/com.arm.wlauto.uiauto.benchmarkpi.jar ]]; then
cp bin/com.arm.wlauto.uiauto.benchmarkpi.jar ..
fi

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.arm.wlauto.uiauto.benchmarkpi" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: VERSION_TAG -->
<import file="${sdk.dir}/tools/ant/uibuild.xml" />
</project>

View File

@@ -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-17

View File

@@ -0,0 +1,62 @@
/* 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.
*/
package com.arm.wlauto.uiauto.benchmarkpi;
import android.app.Activity;
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.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import com.arm.wlauto.uiauto.BaseUiAutomation;
public class UiAutomation extends BaseUiAutomation {
public static String TAG = "benchmarkpi";
public void runUiAutomation() throws Exception{
Bundle status = new Bundle();
startTest();
waitForAndExtractResults();
getAutomationSupport().sendStatus(Activity.RESULT_OK, status);
}
public void startTest() throws Exception{
UiSelector selector = new UiSelector();
UiObject benchButton = new UiObject(selector.text("Benchmark my Android!")
.className("android.widget.Button"));
benchButton.click();
}
public void waitForAndExtractResults() throws Exception{
UiSelector selector = new UiSelector();
UiObject submitButton = new UiObject(selector.text("Submit")
.className("android.widget.Button"));
submitButton.waitForExists(10 * 1000);
UiObject resultsText = new UiObject(selector.textContains("You calculated Pi in")
.className("android.widget.TextView"));
Log.v(TAG, resultsText.getText());
}
}

View File

@@ -0,0 +1,68 @@
# 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.
#
import re
from wlauto import AndroidUiAutoBenchmark
class Caffeinemark(AndroidUiAutoBenchmark):
name = 'caffeinemark'
description = """
CaffeineMark is a series of tests that measure the speed of Java
programs running in various hardware and software configurations.
http://www.benchmarkhq.ru/cm30/info.html
From the website:
CaffeineMark scores roughly correlate with the number of Java instructions
executed per second, and do not depend significantly on the the amount of
memory in the system or on the speed of a computers disk drives or internet
connection.
The following is a brief description of what each test does:
- Sieve: The classic sieve of eratosthenes finds prime numbers.
- Loop: The loop test uses sorting and sequence generation as to measure
compiler optimization of loops.
- Logic: Tests the speed with which the virtual machine executes
decision-making instructions.
- Method: The Method test executes recursive function calls to see how
well the VM handles method calls.
- Float: Simulates a 3D rotation of objects around a point.
- Graphics: Draws random rectangles and lines.
- Image: Draws a sequence of three graphics repeatedly.
- Dialog: Writes a set of values into labels and editboxes on a form.
The overall CaffeineMark score is the geometric mean of the individual
scores, i.e., it is the 9th root of the product of all the scores.
"""
package = "com.flexycore.caffeinemark"
activity = ".Application"
summary_metrics = ['OverallScore']
regex = re.compile(r'CAFFEINEMARK RESULT: (?P<type>\w+) (?P<value>\S+)')
def update_result(self, context):
super(Caffeinemark, self).update_result(context)
with open(self.logcat_log) as fh:
for line in fh:
match = self.regex.search(line)
if match:
metric = match.group('type')
value = float(match.group('value'))
context.result.add_metric(metric, value)

View File

@@ -0,0 +1,28 @@
#!/bin/bash
# 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.
#
class_dir=bin/classes/com/arm/wlauto/uiauto
base_class=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', 'BaseUiAutomation.class')"`
mkdir -p $class_dir
cp $base_class $class_dir
ant build
if [[ -f bin/com.arm.wlauto.uiauto.caffeinemark.jar ]]; then
cp bin/com.arm.wlauto.uiauto.caffeinemark.jar ..
fi

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.arm.wlauto.uiauto.caffeinemark" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: VERSION_TAG -->
<import file="${sdk.dir}/tools/ant/uibuild.xml" />
</project>

View File

@@ -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-17

View File

@@ -0,0 +1,85 @@
/* 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.
*/
package com.arm.wlauto.uiauto.caffeinemark;
import android.app.Activity;
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.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import com.arm.wlauto.uiauto.BaseUiAutomation;
public class UiAutomation extends BaseUiAutomation {
public static String TAG = "caffeinemark";
public String[] categories = {"Sieve", "Loop", "Logic", "String", "Float", "Method"};
public void runUiAutomation() throws Exception {
Bundle status = new Bundle();
status.putString("product", getUiDevice().getProductName());
UiSelector selector = new UiSelector();
UiObject runButton = new UiObject(selector.text("Run benchmark")
.className("android.widget.Button"));
runButton.click();
try {
waitText("CaffeineMark results");
extractOverallScore();
extractDetailedScores();
} catch(UiObjectNotFoundException e) {
takeScreenshot("caffeine-error");
}
getAutomationSupport().sendStatus(Activity.RESULT_OK, status);
}
public void extractOverallScore() throws Exception {
UiSelector selector = new UiSelector();
UiObject linearLayoutOverallScore = new UiObject(selector.className("android.widget.LinearLayout")
.instance(1));
UiObject overallScore = linearLayoutOverallScore.getChild(selector.className("android.widget.TextView")
.instance(2));
Log.v(TAG, "CAFFEINEMARK RESULT: OverallScore " + overallScore.getText());
}
public void extractDetailedScores() throws Exception {
UiSelector selector = new UiSelector();
UiObject detailsButton = new UiObject(selector.text("Details")
.className("android.widget.Button"));
detailsButton.click();
sleep(2);
UiObject linearObject;
UiObject detailedScore;
for (int i = 1; i <= 6; i++) {
linearObject = new UiObject(selector.className("android.widget.LinearLayout")
.instance(i));
detailedScore = linearObject.getChild(selector.className("android.widget.TextView")
.instance(1));
Log.v(TAG,"CAFFEINEMARK RESULT: " + categories[i-1] + " " + detailedScore.getText());
}
}
}

View File

@@ -0,0 +1,51 @@
# 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 wlauto import UiAutomatorWorkload, Parameter
class Cameracapture(UiAutomatorWorkload):
name = 'cameracapture'
description = """
Uses in-built Android camera app to take photos.
"""
package = 'com.google.android.gallery3d'
activity = 'com.android.camera.CameraActivity'
parameters = [
Parameter('no_of_captures', kind=int, default=5,
description='Number of photos to be taken.'),
Parameter('time_between_captures', kind=int, default=5,
description='Time, in seconds, between two consecutive camera clicks.'),
]
def __init__(self, device, **kwargs):
super(Cameracapture, self).__init__(device, **kwargs)
self.uiauto_params['no_of_captures'] = self.no_of_captures
self.uiauto_params['time_between_captures'] = self.time_between_captures
def setup(self, context):
super(Cameracapture, self).setup(context)
self.device.execute('am start -n {}/{}'.format(self.package, self.activity))
def update_result(self, context):
pass
def teardown(self, context):
super(Cameracapture, self).teardown(context)

View File

@@ -0,0 +1,28 @@
#!/bin/bash
# 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.
#
class_dir=bin/classes/com/arm/wlauto/uiauto
base_class=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', 'BaseUiAutomation.class')"`
mkdir -p $class_dir
cp $base_class $class_dir
ant build
if [[ -f bin/com.arm.wlauto.uiauto.cameracapture.jar ]]; then
cp bin/com.arm.wlauto.uiauto.cameracapture.jar ..
fi

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.arm.wlauto.uiauto.cameracapture" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: VERSION_TAG -->
<import file="${sdk.dir}/tools/ant/uibuild.xml" />
</project>

View File

@@ -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-17

View File

@@ -0,0 +1,68 @@
/* 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.
*/
package com.arm.wlauto.uiauto.cameracapture;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import com.arm.wlauto.uiauto.BaseUiAutomation;
public class UiAutomation extends BaseUiAutomation {
public static String TAG = "cameracapture";
public void runUiAutomation() throws Exception {
int timeDurationBetweenEachCapture = 0;
int sleepTime = 2;
Bundle parameters = getParams();
String noOfCaptures = "";
int iterations = 0;
if (parameters.size() > 0) {
iterations = Integer.parseInt(parameters
.getString("no_of_captures"));
timeDurationBetweenEachCapture = Integer.parseInt(parameters
.getString("time_between_captures"));
}
// switch to camera capture mode
UiObject clickModes = new UiObject(new UiSelector().descriptionMatches("Camera, video or panorama selector"));
clickModes.click();
sleep(sleepTime);
UiObject changeModeToCapture = new UiObject(new UiSelector().descriptionMatches("Switch to photo"));
changeModeToCapture.click();
sleep(sleepTime);
// click to capture photos
UiObject clickCaptureButton = new UiObject(new UiSelector().descriptionMatches("Shutter button"));
for (int i = 0; i < iterations; i++) {
clickCaptureButton.longClick();
sleep(timeDurationBetweenEachCapture);
}
getUiDevice().pressBack();
}
}

View File

@@ -0,0 +1,47 @@
# 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.
#
from wlauto import UiAutomatorWorkload, Parameter
class Camerarecord(UiAutomatorWorkload):
name = 'camerarecord'
description = """
Uses in-built Android camera app to record the video for given interval
of time.
"""
package = 'com.google.android.gallery3d'
activity = 'com.android.camera.CameraActivity'
run_timeout = 0
parameters = [
Parameter('recording_time', kind=int, default=60,
description='The video recording time in seconds.'),
]
def __init__(self, device, **kwargs):
super(Camerarecord, self).__init__(device)
self.uiauto_params['recording_time'] = self.recording_time # pylint: disable=E1101
self.run_timeout = 3 * self.uiauto_params['recording_time']
def setup(self, context):
super(Camerarecord, self).setup(context)
self.device.execute('am start -n {}/{}'.format(self.package, self.activity))
def teardown(self, context):
self.device.execute('am force-stop {}'.format(self.package))
super(Camerarecord, self).teardown(context)

View File

@@ -0,0 +1,28 @@
#!/bin/bash
# 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.
#
class_dir=bin/classes/com/arm/wlauto/uiauto
base_class=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', 'BaseUiAutomation.class')"`
mkdir -p $class_dir
cp $base_class $class_dir
ant build
if [[ -f bin/com.arm.wlauto.uiauto.camerarecord.jar ]]; then
cp bin/com.arm.wlauto.uiauto.camerarecord.jar ..
fi

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.arm.wlauto.uiauto.camerarecord" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: VERSION_TAG -->
<import file="${sdk.dir}/tools/ant/uibuild.xml" />
</project>

View File

@@ -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-17

View File

@@ -0,0 +1,65 @@
/* 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.
*/
package com.arm.wlauto.uiauto.camerarecord;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import com.arm.wlauto.uiauto.BaseUiAutomation;
public class UiAutomation extends BaseUiAutomation {
public static String TAG = "camerarecord";
public void runUiAutomation() throws Exception {
Bundle parameters = getParams();
int timeToRecord = 0;
int timeout = 4;
int sleepTime = 2;
int recordingTime = 0;
if (parameters.size() > 0) {
recordingTime = Integer.parseInt(parameters
.getString("recording_time"));
}
// switch to camera capture mode
UiObject clickModes = new UiObject(new UiSelector().descriptionMatches("Camera, video or panorama selector"));
clickModes.click();
sleep(sleepTime);
UiObject changeModeToCapture = new UiObject(new UiSelector().descriptionMatches("Switch to video"));
changeModeToCapture.click();
sleep(sleepTime);
UiObject clickRecordingButton = new UiObject(new UiSelector().descriptionMatches("Shutter button"));
clickRecordingButton.longClick();
sleep(recordingTime);
// Stop video recording
clickRecordingButton.longClick();
getUiDevice().pressBack();
}
}

View File

@@ -0,0 +1,28 @@
# 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.
#
from wlauto import GameWorkload
class Castlebuilder(GameWorkload):
name = 'castlebuilder'
description = """
Castle Builder game.
"""
package = 'com.ettinentertainment.castlebuilder'
activity = 'com.unity3d.player.UnityPlayerProxyActivity'

View File

@@ -0,0 +1,30 @@
# 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.
#
from wlauto import GameWorkload
class CastleMaster(GameWorkload):
name = 'castlemaster'
description = """
Castle Master v1.09 game.
"""
package = 'com.alphacloud.castlemaster'
activity = 'com.unity3d.player.UnityPlayerActivity'
install_timeout = 500

View File

@@ -0,0 +1,72 @@
# 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.
#
import os
import xml.etree.ElementTree as ET
from wlauto import AndroidUiAutoBenchmark
class Cfbench(AndroidUiAutoBenchmark):
name = 'cfbench'
description = """
CF-Bench is (mainly) CPU and memory benchmark tool specifically designed to
be able to handle multi-core devices, produce a fairly stable score, and
test both native as well managed code performance.
https://play.google.com/store/apps/details?id=eu.chainfire.cfbench&hl=en
From the website:
It tests specific device properties you do not regularly see tested by other
benchmarks, and runs in a set timeframe.
It does produce some "final" scores, but as with every benchmark, you should
take those with a grain of salt. It is simply not theoretically possible to
produce a single number that accurately describes a device's performance.
.. note:: This workload relies on the device being rooted
"""
package = 'eu.chainfire.cfbench'
activity = '.MainActivity'
run_timeout = 5 * 60 # seconds
summary_metrics = ['overall_score']
cfbench_params = ['java_mdflops', 'native_memory_read', 'java_msflops', 'native_disk_read', 'native_score', 'java_efficiency_memory_read',
'native_mips', 'native_mdflops', 'java_score', 'native_memory_write', 'java_memory_write', 'native_mallocs', 'native_msflops',
'java_mips', 'java_efficiency_mdflops', 'overall_score', 'java_memory_read', 'java_efficiency_memory_write', 'java_efficiency_mips',
'java_efficiency_msflops', 'native_disk_write']
def update_result(self, context):
super(Cfbench, self).update_result(context)
device_results_file = os.path.join(self.device.package_data_directory,
self.package,
'shared_prefs', 'eu.chainfire.cfbench_preferences.xml ')
self.device.execute('cp {} {}'.format(device_results_file, self.device.working_directory), as_root=True)
self.device.pull_file(os.path.join(self.device.working_directory, 'eu.chainfire.cfbench_preferences.xml'), context.output_directory)
result_file = os.path.join(context.output_directory, 'eu.chainfire.cfbench_preferences.xml')
tree = ET.parse(result_file)
root = tree.getroot()
for child in root:
if child.attrib['name'] in self.cfbench_params:
if '%' in child.text:
value = float(child.text.split('%')[0]) / 100
else:
value = int(child.text)
context.result.add_metric(child.attrib['name'], value)

View File

@@ -0,0 +1,28 @@
#!/bin/bash
# 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.
#
class_dir=bin/classes/com/arm/wlauto/uiauto
base_class=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', 'BaseUiAutomation.class')"`
mkdir -p $class_dir
cp $base_class $class_dir
ant build
if [[ -f bin/com.arm.wlauto.uiauto.cfbench.jar ]]; then
cp bin/com.arm.wlauto.uiauto.cfbench.jar ..
fi

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.arm.wlauto.uiauto.cfbench" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: VERSION_TAG -->
<import file="${sdk.dir}/tools/ant/uibuild.xml" />
</project>

View File

@@ -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-17

View File

@@ -0,0 +1,63 @@
/* 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.
*/
package com.arm.wlauto.uiauto.cfbench;
import android.app.Activity;
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.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import com.arm.wlauto.uiauto.BaseUiAutomation;
public class UiAutomation extends BaseUiAutomation {
public static String TAG = "cfbench";
public void runUiAutomation() throws Exception{
Bundle status = new Bundle();
status.putString("product", getUiDevice().getProductName());
UiSelector selector = new UiSelector();
UiObject text_bench = new UiObject(selector.text("Full Benchmark")
.className("android.widget.TextView"));
text_bench.click();
sleep(2);
try{
UiObject stop_text = new UiObject(selector.textContains("Benchmarking ...")
.className("android.widget.TextView"));
waitUntilNoObject(stop_text, 600);
sleep(2);
}finally{
takeScreenshot("cf-bench");
}
UiScrollable res = new UiScrollable(new UiSelector());//.scrollable(true));
res.flingToEnd(10);
sleep(2);
getAutomationSupport().sendStatus(Activity.RESULT_OK, status);
}
}

View File

@@ -0,0 +1,44 @@
# 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
import time
from wlauto import GameWorkload, Parameter
class EpicCitadel(GameWorkload):
name = 'citadel'
description = """
Epic Citadel demo showcasing Unreal Engine 3.
The game has very rich graphics details. The workload only moves around its
environment for the specified time.
"""
package = 'com.epicgames.EpicCitadel'
activity = '.UE3JavaApp'
install_timeout = 120
parameters = [
Parameter('duration', kind=int, default=60,
description=('Duration, in seconds, of the run (may need to be adjusted for '
'different devices.')),
]
def run(self, context):
super(EpicCitadel, self).run(context)
time.sleep(self.duration)

View File

@@ -0,0 +1,8 @@
cyclictest binaries included here are part of the Linux kernel and are distributed
under GPL version 2; The full text of the license may be viewed here:
http://www.gnu.org/licenses/gpl-2.0.html
Source for these binaries can be obtained here:
http://git.kernel.org/cgit/linux/kernel/git/clrkwllms/rt-tests.git

View File

@@ -0,0 +1,141 @@
# Copyright 2012-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=no-member
# pylint: disable=attribute-defined-outside-init
import os
import time
from wlauto import settings, Workload, Executable, Parameter
from wlauto.exceptions import ConfigError, WorkloadError
from wlauto.utils.types import boolean
TXT_RESULT_NAME = 'cyclictest_result.txt'
RESULT_INTERPRETATION = {
'T': 'Thread',
'P': 'Priority',
'C': 'Clock',
}
class Cyclictest(Workload):
name = 'cyclictest'
description = """
Measures the amount of time that passes between when a timer expires and
when the thread which set the timer actually runs.
Cyclic test works by taking a time snapshot just prior to waiting for a specific
time interval (t1), then taking another time snapshot after the timer
finishes (t2), then comparing the theoretical wakeup time with the actual
wakeup time (t2 -(t1 + sleep_time)). This value is the latency for that
timers wakeup.
"""
parameters = [
Parameter('clock', allowed_values=['monotonic', 'realtime'], default='realtime',
description=('specify the clock to be used during the test.')),
Parameter('duration', kind=int, default=30,
description=('Specify the length for the test to run in seconds.')),
Parameter('quiet', kind=boolean, default=True,
description=('Run the tests quiet and print only a summary on exit.')),
Parameter('thread', kind=int, default=8,
description=('Set the number of test threads')),
Parameter('latency', kind=int, default=1000000,
description=('Write the value to /dev/cpu_dma_latency')),
Parameter('extra_parameters', kind=str, default="",
description=('Any additional command line parameters to append to the '
'existing parameters above. A list can be found at '
'https://rt.wiki.kernel.org/index.php/Cyclictest or '
'in the help page ``cyclictest -h``')),
Parameter('clear_file_cache', kind=boolean, default=True,
description=('Clear file caches before starting test')),
Parameter('screen_off', kind=boolean, default=True,
description=('If true it will turn the screen off so that onscreen '
'graphics do not effect the score. This is predominantly '
'for devices without a GPU')),
]
def setup(self, context):
self.cyclictest_on_device = 'cyclictest'
self.cyclictest_result = os.path.join(self.device.working_directory, TXT_RESULT_NAME)
self.cyclictest_command = '{} --clock={} --duration={}s --thread={} --latency={} {} {} > {}'
self.device_binary = None
if not self.device.is_rooted:
raise WorkloadError("This workload requires a device with root premissions to run")
if not self.device.is_installed('cyclictest'):
host_binary = context.resolver.get(Executable(self, self.device.abi, 'cyclictest'))
self.device_binary = self.device.install(host_binary)
else:
self.device_binary = 'cyclictest'
self.cyclictest_command = self.cyclictest_command.format(self.device_binary,
0 if self.clock == 'monotonic' else 1,
self.duration,
self.thread,
self.latency,
"--quiet" if self.quiet else "",
self.extra_parameters,
self.cyclictest_result)
if self.clear_file_cache:
self.device.execute('sync')
self.device.set_sysfile_value('/proc/sys/vm/drop_caches', 3)
if self.device.platform == 'android':
if self.screen_off and self.device.is_screen_on:
self.device.execute('input keyevent 26')
def run(self, context):
self.device.execute(self.cyclictest_command, self.duration * 2, as_root=True)
def update_result(self, context):
self.device.pull_file(self.cyclictest_result, context.output_directory)
# Parsing the output
# Standard Cyclictest Output:
# T: 0 (31974) P:95 I:1000 C:4990 Min:9 Act:37 Avg:31 Max:59
with open(os.path.join(context.output_directory, TXT_RESULT_NAME)) as f:
for line in f:
if line.find('C:') is not -1:
# Key = T: 0 (31974) P:95 I:1000
# Remaing = 49990 Min:9 Act:37 Avg:31 Max:59
# sperator = C:
(key, sperator, remaing) = line.partition('C:')
index = key.find('T')
key = key.replace(key[index], RESULT_INTERPRETATION['T'])
index = key.find('P')
key = key.replace(key[index], RESULT_INTERPRETATION['P'])
index = sperator.find('C')
sperator = sperator.replace(sperator[index], RESULT_INTERPRETATION['C'])
metrics = (sperator + remaing).split()
# metrics is now in the from of ['Min:', '9', 'Act:', '37', 'Avg:', '31' , 'Max', '59']
for i in range(0, len(metrics), 2):
full_key = key + ' ' + metrics[i][:-1]
value = int(metrics[i + 1])
context.result.add_metric(full_key, value, 'microseconds')
def teardown(self, context):
if self.device.platform == 'android':
if self.screen_off:
self.device.ensure_screen_is_on()
self.device.execute('rm -f {}'.format(self.cyclictest_result))

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,121 @@
# Copyright 2014-2015 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# pylint: disable=no-member,attribute-defined-outside-init
import re
import os
import sys
from wlauto import Workload, Parameter, ExtensionLoader
from wlauto.exceptions import WorkloadError
from wlauto.utils.android import ApkInfo
import wlauto.common.android.resources
class Dex2oatBenchmark(Workload):
name = 'dex2oat'
description = """
Benchmarks the execution time of dex2oat (a key part of APK installation process).
ART is a new Android runtime in KitKat, which replaces Dalvik VM. ART uses Ahead-Of-Time
compilation. It pre-compiles ODEX files used by Dalvik using dex2oat tool as part of APK
installation process.
This workload benchmarks the time it take to compile an APK using dex2oat, which has a
significant impact on the total APK installation time, and therefore user experience.
"""
command_template = 'dex2oat --dex-file={} --oat-file={} --instruction-set={} --dump-timing'
run_timeout = 5 * 60
parameters = [
Parameter('instruction_set', default='arm64',
allowed_values=['arm', 'arm64', 'x86', 'x86_64', 'mips'],
description="""Specifies the instruction set to compile for. Only options supported by
the target device can be used."""),
]
def init_resources(self, context):
# TODO: find a better APK to use for this.
peacekeeper = ExtensionLoader().get_workload('peacekeeper', self.device)
self.apk_file = context.resolver.get(wlauto.common.android.resources.ApkFile(peacekeeper), version='chrome')
self.package = ApkInfo(self.apk_file).package
def setup(self, context):
if self.device.getprop('persist.sys.dalvik.vm.lib.2') != 'libart.so':
raise WorkloadError('Android system must be using ART (rather than Dalvik) in order for dex2oat to work.')
supported = [eabi == 'armeabi' and 'arm' or eabi.split('-')[0]
for eabi in self.device.supported_eabi]
if self.instruction_set not in supported:
message = 'Instruction set "{}" is not supported by the device; (supported: {})'
raise WorkloadError(message.format(self.instruction_set, supported))
on_device_apk = self.device.path.join(self.device.working_directory,
os.path.basename(self.apk_file))
self.on_device_oat = on_device_apk.replace('.apk', '-{}.oat'.format(self.instruction_set))
self.command = self.command_template.format(on_device_apk, self.on_device_oat, self.instruction_set)
if not self.device.file_exists(on_device_apk):
self.device.push_file(self.apk_file, on_device_apk)
def run(self, context):
self.device.execute(self.command, self.run_timeout)
def update_result(self, context):
"""
Retrieve the last dex2oat time from the logs. That will correspond with the run() method.
The compilation time does not.
Pulls out the compilation time and dex2oat execution time:
I/dex2oat ( 2522): 1.8s Compile Dex File
I/dex2oat ( 2522): dex2oat took 2.366s (threads: 6)
"""
logcat_log = os.path.join(context.output_directory, 'logcat.log')
self.device.dump_logcat(logcat_log)
regex_time = re.compile("^I\/dex2oat \( *[0-9]+\): dex2oat took (?P<time>[0-9]+\.?[0-9]*)(?P<unit>m?s)")
regex_comp_time = re.compile("^I\/dex2oat \( *[0-9]+\): +(?P<time>[0-9]*\.?[0-9]*)(?P<unit>m?s) Compile Dex File")
time_data, comp_time_data = None, None
with open(logcat_log) as fh:
for line in fh:
match = regex_time.search(line)
if match:
time_data = match.groupdict()
match = regex_comp_time.search(line)
if match:
comp_time_data = match.groupdict()
# Last dex2oat time wins.
if time_data is not None:
time = time_data['time']
if time_data['unit'] == "s":
time = float(time) * 1000.0
context.result.add_metric('dex2oat_time', time, "ms", lower_is_better=True)
if comp_time_data is not None:
time = comp_time_data['time']
if comp_time_data['unit'] == "s":
time = float(time) * 1000.0
context.result.add_metric('dex2oat_comp_time', time, "ms", lower_is_better=True)
def teardown(self, context):
self.device.delete_file(self.on_device_oat)

View File

@@ -0,0 +1,109 @@
# 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,W0201
import os
import re
from wlauto import Workload, Parameter
from wlauto.exceptions import ConfigError
this_dir = os.path.dirname(__file__)
class Dhrystone(Workload):
name = 'dhrystone'
description = """
Runs the Dhrystone benchmark.
Original source from::
http://classes.soe.ucsc.edu/cmpe202/benchmarks/standard/dhrystone.c
This version has been modified to configure duration and the number of
threads used.
"""
bm_regex = re.compile(r'This machine benchmarks at (?P<score>\d+)')
dmips_regex = re.compile(r'(?P<score>\d+) DMIPS')
time_regex = re.compile(r'Total dhrystone run time: (?P<time>[0-9.]+)')
default_mloops = 100
parameters = [
Parameter('duration', kind=int, default=0,
description='The duration, in seconds, for which dhrystone will be executed. '
'Either this or ``mloops`` should be specified but not both.'),
Parameter('mloops', kind=int, default=0,
description='Millions of loops to run. Either this or ``duration`` should be '
'specified, but not both. If neither is specified, this will default '
'to ``{}``'.format(default_mloops)),
Parameter('threads', kind=int, default=4,
description='The number of separate dhrystone "threads" that will be forked.'),
Parameter('delay', kind=int, default=0,
description=('The delay, in seconds, between kicking off of dhrystone '
'threads (if ``threads`` > 1).')),
]
def setup(self, context):
host_exe = os.path.join(this_dir, 'dhrystone')
self.device_exe = self.device.install(host_exe)
execution_mode = '-l {}'.format(self.mloops) if self.mloops else '-r {}'.format(self.duration)
self.command = '{} {} -t {} -d {}'.format(self.device_exe,
execution_mode,
self.threads, self.delay)
self.timeout = self.duration and self.duration + self.delay * self.threads + 10 or 300
def run(self, context):
self.output = self.device.execute(self.command, timeout=self.timeout, check_exit_code=False)
def update_result(self, context):
outfile = os.path.join(context.output_directory, 'dhrystone.output')
with open(outfile, 'w') as wfh:
wfh.write(self.output)
score_count = 0
dmips_count = 0
for line in self.output.split('\n'):
match = self.time_regex.search(line)
if match:
context.result.add_metric('time', float(match.group('time')), 'seconds', lower_is_better=True)
else:
match = self.bm_regex.search(line)
if match:
metric = 'thread {} score'.format(score_count)
value = int(match.group('score'))
context.result.add_metric(metric, value)
score_count += 1
else:
match = self.dmips_regex.search(line)
if match:
metric = 'thread {} DMIPS'.format(dmips_count)
value = int(match.group('score'))
context.result.add_metric(metric, value)
dmips_count += 1
def teardown(self, context):
self.device.uninstall_executable('dhrystone')
def validate(self):
if self.mloops and self.duration: # pylint: disable=E0203
raise ConfigError('mloops and duration cannot be both specified at the same time for dhrystone.')
if not self.mloops and not self.duration: # pylint: disable=E0203
self.mloops = self.default_mloops

Binary file not shown.

View File

@@ -0,0 +1,23 @@
# 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.
#
ndk-build
if [[ -f libs/armeabi/dhrystone ]]; then
echo "Dhrystone binary updated."
cp libs/armeabi/dhrystone ..
rm -rf libs
rm -rf obj
fi

View File

@@ -0,0 +1,11 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= dhrystone.c
LOCAL_MODULE := dhrystone
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_LIBRARIES := libc
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_LDLIBS := -llog
LOCAL_CFLAGS := -O2
include $(BUILD_EXECUTABLE)

View File

@@ -0,0 +1,959 @@
/* ARM modifications to the original Dhrystone are */
/* 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.
*/
/***** hpda:net.sources / homxb!gemini / 1:58 am Apr 1, 1986*/
/* EVERBODY: Please read "APOLOGY" below. -rick 01/06/85
* See introduction in net.arch, or net.micro
*
* "DHRYSTONE" Benchmark Program
*
* Version: C/1.1, 12/01/84
*
* Date: PROGRAM updated 01/06/86, RESULTS updated 03/31/86
*
* Author: Reinhold P. Weicker, CACM Vol 27, No 10, 10/84 pg. 1013
* Translated from ADA by Rick Richardson
* Every method to preserve ADA-likeness has been used,
* at the expense of C-ness.
*
* Compile: cc -O dry.c -o drynr : No registers
* cc -O -DREG=register dry.c -o dryr : Registers
*
* Defines: Defines are provided for old C compiler's
* which don't have enums, and can't assign structures.
* The time(2) function is library dependant; Most
* return the time in seconds, but beware of some, like
* Aztec C, which return other units.
* The LOOPS define is initially set for 50000 loops.
* If you have a machine with large integers and is
* very fast, please change this number to 500000 to
* get better accuracy. Please select the way to
* measure the execution time using the TIME define.
* For single user machines, time(2) is adequate. For
* multi-user machines where you cannot get single-user
* access, use the times(2) function. If you have
* neither, use a stopwatch in the dead of night.
* Use a "printf" at the point marked "start timer"
* to begin your timings. DO NOT use the UNIX "time(1)"
* command, as this will measure the total time to
* run this program, which will (erroneously) include
* the time to malloc(3) storage and to compute the
* time it takes to do nothing.
*
* Run: drynr; dryr
*
* Results: If you get any new machine/OS results, please send to:
*
* ihnp4!castor!pcrat!rick
*
* and thanks to all that do. Space prevents listing
* the names of those who have provided some of these
* results. I'll be forwarding these results to
* Rheinhold Weicker.
*
* Note: I order the list in increasing performance of the
* "with registers" benchmark. If the compiler doesn't
* provide register variables, then the benchmark
* is the same for both REG and NOREG.
*
* PLEASE: Send complete information about the machine type,
* clock speed, OS and C manufacturer/version. If
* the machine is modified, tell me what was done.
* On UNIX, execute uname -a and cc -V to get this info.
*
* 80x8x NOTE: 80x8x benchers: please try to do all memory models
* for a particular compiler.
*
* APOLOGY (1/30/86):
* Well, I goofed things up! As pointed out by Haakon Bugge,
* the line of code marked "GOOF" below was missing from the
* Dhrystone distribution for the last several months. It
* *WAS* in a backup copy I made last winter, so no doubt it
* was victimized by sleepy fingers operating vi!
*
* The effect of the line missing is that the reported benchmarks
* are 15% too fast (at least on a 80286). Now, this creates
* a dilema - do I throw out ALL the data so far collected
* and use only results from this (corrected) version, or
* do I just keep collecting data for the old version?
*
* Since the data collected so far *is* valid as long as it
* is compared with like data, I have decided to keep
* TWO lists- one for the old benchmark, and one for the
* new. This also gives me an opportunity to correct one
* other error I made in the instructions for this benchmark.
* My experience with C compilers has been mostly with
* UNIX 'pcc' derived compilers, where the 'optimizer' simply
* fixes sloppy code generation (peephole optimization).
* But today, there exist C compiler optimizers that will actually
* perform optimization in the Computer Science sense of the word,
* by removing, for example, assignments to a variable whose
* value is never used. Dhrystone, unfortunately, provides
* lots of opportunities for this sort of optimization.
*
* I request that benchmarkers re-run this new, corrected
* version of Dhrystone, turning off or bypassing optimizers
* which perform more than peephole optimization. Please
* indicate the version of Dhrystone used when reporting the
* results to me.
*
* RESULTS BEGIN HERE
*
*----------------DHRYSTONE VERSION 1.1 RESULTS BEGIN--------------------------
*
* MACHINE MICROPROCESSOR OPERATING COMPILER DHRYSTONES/SEC.
* TYPE SYSTEM NO REG REGS
* -------------------------- ------------ ----------- ---------------
* Apple IIe 65C02-1.02Mhz DOS 3.3 Aztec CII v1.05i 37 37
* - Z80-2.5Mhz CPM-80 v2.2 Aztec CII v1.05g 91 91
* - 8086-8Mhz RMX86 V6 Intel C-86 V2.0 197 203LM??
* IBM PC/XT 8088-4.77Mhz COHERENT 2.3.43 Mark Wiiliams 259 275
* - 8086-8Mhz RMX86 V6 Intel C-86 V2.0 287 304 ??
* Fortune 32:16 68000-6Mhz V7+sys3+4.1BSD cc 360 346
* PDP-11/34A w/FP-11C UNIX V7m cc 406 449
* Macintosh512 68000-7.7Mhz Mac ROM O/S DeSmet(C ware) 625 625
* VAX-11/750 w/FPA UNIX 4.2BSD cc 831 852
* DataMedia 932 68000-10Mhz UNIX sysV cc 837 888
* Plexus P35 68000-12.5Mhz UNIX sysIII cc 835 894
* ATT PC7300 68010-10Mhz UNIX 5.0.3 cc 973 1034
* Compaq II 80286-8Mhz MSDOS 3.1 MS C 3.0 1086 1140 LM
* IBM PC/AT 80286-7.5Mhz Venix/286 SVR2 cc 1159 1254 *15
* Compaq II 80286-8Mhz MSDOS 3.1 MS C 3.0 1190 1282 MM
* MicroVAX II - Mach/4.3 cc 1361 1385
* DEC uVAX II - Ultrix-32m v1.1 cc 1385 1399
* Compaq II 80286-8Mhz MSDOS 3.1 MS C 3.0 1351 1428
* VAX 11/780 - UNIX 4.2BSD cc 1417 1441
* VAX-780/MA780 Mach/4.3 cc 1428 1470
* VAX 11/780 - UNIX 5.0.1 cc 4.1.1.31 1650 1640
* Ridge 32C V1 - ROS 3.3 Ridge C (older) 1628 1695
* Gould PN6005 - UTX 1.1c+ (4.2) cc 1732 1884
* Gould PN9080 custom ECL UTX-32 1.1C cc 4745 4992
* VAX-784 - Mach/4.3 cc 5263 5555 &4
* VAX 8600 - 4.3 BSD cc 6329 6423
* Amdahl 5860 - UTS sysV cc 1.22 28735 28846
* IBM3090/200 - ? ? 31250 31250
*
*
*----------------DHRYSTONE VERSION 1.0 RESULTS BEGIN--------------------------
*
* MACHINE MICROPROCESSOR OPERATING COMPILER DHRYSTONES/SEC.
* TYPE SYSTEM NO REG REGS
* -------------------------- ------------ ----------- ---------------
* Commodore 64 6510-1MHz C64 ROM C Power 2.8 36 36
* HP-110 8086-5.33Mhz MSDOS 2.11 Lattice 2.14 284 284
* IBM PC/XT 8088-4.77Mhz PC/IX cc 271 294
* CCC 3205 - Xelos(SVR2) cc 558 592
* Perq-II 2901 bitslice Accent S5c cc (CMU) 301 301
* IBM PC/XT 8088-4.77Mhz COHERENT 2.3.43 MarkWilliams cc 296 317
* Cosmos 68000-8Mhz UniSoft cc 305 322
* IBM PC/XT 8088-4.77Mhz Venix/86 2.0 cc 297 324
* DEC PRO 350 11/23 Venix/PRO SVR2 cc 299 325
* IBM PC 8088-4.77Mhz MSDOS 2.0 b16cc 2.0 310 340
* PDP11/23 11/23 Venix (V7) cc 320 358
* Commodore Amiga ? Lattice 3.02 368 371
* PC/XT 8088-4.77Mhz Venix/86 SYS V cc 339 377
* IBM PC 8088-4.77Mhz MSDOS 2.0 CI-C86 2.20M 390 390
* IBM PC/XT 8088-4.77Mhz PCDOS 2.1 Wizard 2.1 367 403
* IBM PC/XT 8088-4.77Mhz PCDOS 3.1 Lattice 2.15 403 403 @
* Colex DM-6 68010-8Mhz Unisoft SYSV cc 378 410
* IBM PC 8088-4.77Mhz PCDOS 3.1 Datalight 1.10 416 416
* IBM PC NEC V20-4.77Mhz MSDOS 3.1 MS 3.1 387 420
* IBM PC/XT 8088-4.77Mhz PCDOS 2.1 Microsoft 3.0 390 427
* IBM PC NEC V20-4.77Mhz MSDOS 3.1 MS 3.1 (186) 393 427
* PDP-11/34 - UNIX V7M cc 387 438
* IBM PC 8088, 4.77mhz PC-DOS 2.1 Aztec C v3.2d 423 454
* Tandy 1000 V20, 4.77mhz MS-DOS 2.11 Aztec C v3.2d 423 458
* Tandy TRS-16B 68000-6Mhz Xenix 1.3.5 cc 438 458
* PDP-11/34 - RSTS/E decus c 438 495
* Onyx C8002 Z8000-4Mhz IS/1 1.1 (V7) cc 476 511
* Tandy TRS-16B 68000-6Mhz Xenix 1.3.5 Green Hills 609 617
* DEC PRO 380 11/73 Venix/PRO SVR2 cc 577 628
* FHL QT+ 68000-10Mhz Os9/68000 version 1.3 603 649 FH
* Apollo DN550 68010-?Mhz AegisSR9/IX cc 3.12 666 666
* HP-110 8086-5.33Mhz MSDOS 2.11 Aztec-C 641 676
* ATT PC6300 8086-8Mhz MSDOS 2.11 b16cc 2.0 632 684
* IBM PC/AT 80286-6Mhz PCDOS 3.0 CI-C86 2.1 666 684
* Tandy 6000 68000-8Mhz Xenix 3.0 cc 694 694
* IBM PC/AT 80286-6Mhz Xenix 3.0 cc 684 704 MM
* Macintosh 68000-7.8Mhz 2M Mac Rom Mac C 32 bit int 694 704
* Macintosh 68000-7.7Mhz - MegaMax C 2.0 661 709
* Macintosh512 68000-7.7Mhz Mac ROM O/S DeSmet(C ware) 714 714
* IBM PC/AT 80286-6Mhz Xenix 3.0 cc 704 714 LM
* Codata 3300 68000-8Mhz UniPlus+ (v7) cc 678 725
* WICAT MB 68000-8Mhz System V WICAT C 4.1 585 731 ~
* Cadmus 9000 68010-10Mhz UNIX cc 714 735
* AT&T 6300 8086-8Mhz Venix/86 SVR2 cc 668 743
* Cadmus 9790 68010-10Mhz 1MB SVR0,Cadmus3.7 cc 720 747
* NEC PC9801F 8086-8Mhz PCDOS 2.11 Lattice 2.15 768 - @
* ATT PC6300 8086-8Mhz MSDOS 2.11 CI-C86 2.20M 769 769
* Burroughs XE550 68010-10Mhz Centix 2.10 cc 769 769 CT1
* EAGLE/TURBO 8086-8Mhz Venix/86 SVR2 cc 696 779
* ALTOS 586 8086-10Mhz Xenix 3.0b cc 724 793
* DEC 11/73 J-11 micro Ultrix-11 V3.0 cc 735 793
* ATT 3B2/300 WE32000-?Mhz UNIX 5.0.2 cc 735 806
* Apollo DN320 68010-?Mhz AegisSR9/IX cc 3.12 806 806
* IRIS-2400 68010-10Mhz UNIX System V cc 772 829
* Atari 520ST 68000-8Mhz TOS DigResearch 839 846
* IBM PC/AT 80286-6Mhz PCDOS 3.0 MS 3.0(large) 833 847 LM
* WICAT MB 68000-8Mhz System V WICAT C 4.1 675 853 S~
* VAX 11/750 - Ultrix 1.1 4.2BSD cc 781 862
* CCC 7350A 68000-8MHz UniSoft V.2 cc 821 875
* VAX 11/750 - UNIX 4.2bsd cc 862 877
* Fast Mac 68000-7.7Mhz - MegaMax C 2.0 839 904 +
* IBM PC/XT 8086-9.54Mhz PCDOS 3.1 Microsoft 3.0 833 909 C1
* DEC 11/44 Ultrix-11 V3.0 cc 862 909
* Macintosh 68000-7.8Mhz 2M Mac Rom Mac C 16 bit int 877 909 S
* CCC 3210 - Xelos R01(SVR2) cc 849 924
* CCC 3220 - Ed. 7 v2.3 cc 892 925
* IBM PC/AT 80286-6Mhz Xenix 3.0 cc -i 909 925
* AT&T 6300 8086, 8mhz MS-DOS 2.11 Aztec C v3.2d 862 943
* IBM PC/AT 80286-6Mhz Xenix 3.0 cc 892 961
* VAX 11/750 w/FPA Eunice 3.2 cc 914 976
* IBM PC/XT 8086-9.54Mhz PCDOS 3.1 Wizard 2.1 892 980 C1
* IBM PC/XT 8086-9.54Mhz PCDOS 3.1 Lattice 2.15 980 980 C1
* Plexus P35 68000-10Mhz UNIX System III cc 984 980
* PDP-11/73 KDJ11-AA 15Mhz UNIX V7M 2.1 cc 862 981
* VAX 11/750 w/FPA UNIX 4.3bsd cc 994 997
* IRIS-1400 68010-10Mhz UNIX System V cc 909 1000
* IBM PC/AT 80286-6Mhz Venix/86 2.1 cc 961 1000
* IBM PC/AT 80286-6Mhz PCDOS 3.0 b16cc 2.0 943 1063
* Zilog S8000/11 Z8001-5.5Mhz Zeus 3.2 cc 1011 1084
* NSC ICM-3216 NSC 32016-10Mhz UNIX SVR2 cc 1041 1084
* IBM PC/AT 80286-6Mhz PCDOS 3.0 MS 3.0(small) 1063 1086
* VAX 11/750 w/FPA VMS VAX-11 C 2.0 958 1091
* Stride 68000-10Mhz System-V/68 cc 1041 1111
* Plexus P/60 MC68000-12.5Mhz UNIX SYSIII Plexus 1111 1111
* ATT PC7300 68010-10Mhz UNIX 5.0.2 cc 1041 1111
* CCC 3230 - Xelos R01(SVR2) cc 1040 1126
* Stride 68000-12Mhz System-V/68 cc 1063 1136
* IBM PC/AT 80286-6Mhz Venix/286 SVR2 cc 1056 1149
* Plexus P/60 MC68000-12.5Mhz UNIX SYSIII Plexus 1111 1163 T
* IBM PC/AT 80286-6Mhz PCDOS 3.0 Datalight 1.10 1190 1190
* ATT PC6300+ 80286-6Mhz MSDOS 3.1 b16cc 2.0 1111 1219
* IBM PC/AT 80286-6Mhz PCDOS 3.1 Wizard 2.1 1136 1219
* Sun2/120 68010-10Mhz Sun 4.2BSD cc 1136 1219
* IBM PC/AT 80286-6Mhz PCDOS 3.0 CI-C86 2.20M 1219 1219
* WICAT PB 68000-8Mhz System V WICAT C 4.1 998 1226 ~
* MASSCOMP 500 68010-10MHz RTU V3.0 cc (V3.2) 1156 1238
* Alliant FX/8 IP (68012-12Mhz) Concentrix cc -ip;exec -i 1170 1243 FX
* Cyb DataMate 68010-12.5Mhz Uniplus 5.0 Unisoft cc 1162 1250
* PDP 11/70 - UNIX 5.2 cc 1162 1250
* IBM PC/AT 80286-6Mhz PCDOS 3.1 Lattice 2.15 1250 1250
* IBM PC/AT 80286-7.5Mhz Venix/86 2.1 cc 1190 1315 *15
* Sun2/120 68010-10Mhz Standalone cc 1219 1315
* Intel 380 80286-8Mhz Xenix R3.0up1 cc 1250 1315 *16
* Sequent Balance 8000 NS32032-10MHz Dynix 2.0 cc 1250 1315 N12
* IBM PC/DSI-32 32032-10Mhz MSDOS 3.1 GreenHills 2.14 1282 1315 C3
* ATT 3B2/400 WE32100-?Mhz UNIX 5.2 cc 1315 1315
* CCC 3250XP - Xelos R01(SVR2) cc 1215 1318
* IBM PC/RT 032 RISC(801?)?Mhz BSD 4.2 cc 1248 1333 RT
* DG MV4000 - AOS/VS 5.00 cc 1333 1333
* IBM PC/AT 80286-8Mhz Venix/86 2.1 cc 1275 1380 *16
* IBM PC/AT 80286-6Mhz MSDOS 3.0 Microsoft 3.0 1250 1388
* ATT PC6300+ 80286-6Mhz MSDOS 3.1 CI-C86 2.20M 1428 1428
* COMPAQ/286 80286-8Mhz Venix/286 SVR2 cc 1326 1443
* IBM PC/AT 80286-7.5Mhz Venix/286 SVR2 cc 1333 1449 *15
* WICAT PB 68000-8Mhz System V WICAT C 4.1 1169 1464 S~
* Tandy II/6000 68000-8Mhz Xenix 3.0 cc 1384 1477
* MicroVAX II - Mach/4.3 cc 1513 1536
* WICAT MB 68000-12.5Mhz System V WICAT C 4.1 1246 1537 ~
* IBM PC/AT 80286-9Mhz SCO Xenix V cc 1540 1556 *18
* Cyb DataMate 68010-12.5Mhz Uniplus 5.0 Unisoft cc 1470 1562 S
* VAX 11/780 - UNIX 5.2 cc 1515 1562
* MicroVAX-II - - - 1562 1612
* VAX-780/MA780 Mach/4.3 cc 1587 1612
* VAX 11/780 - UNIX 4.3bsd cc 1646 1662
* Apollo DN660 - AegisSR9/IX cc 3.12 1666 1666
* ATT 3B20 - UNIX 5.2 cc 1515 1724
* NEC PC-98XA 80286-8Mhz PCDOS 3.1 Lattice 2.15 1724 1724 @
* HP9000-500 B series CPU HP-UX 4.02 cc 1724 -
* Ridge 32C V1 - ROS 3.3 Ridge C (older) 1776 -
* IBM PC/STD 80286-8Mhz MSDOS 3.0 Microsoft 3.0 1724 1785 C2
* WICAT MB 68000-12.5Mhz System V WICAT C 4.1 1450 1814 S~
* WICAT PB 68000-12.5Mhz System V WICAT C 4.1 1530 1898 ~
* DEC-2065 KL10-Model B TOPS-20 6.1FT5 Port. C Comp. 1937 1946
* Gould PN6005 - UTX 1.1(4.2BSD) cc 1675 1964
* DEC2060 KL-10 TOPS-20 cc 2000 2000 NM
* Intel 310AP 80286-8Mhz Xenix 3.0 cc 1893 2009
* VAX 11/785 - UNIX 5.2 cc 2083 2083
* VAX 11/785 - VMS VAX-11 C 2.0 2083 2083
* VAX 11/785 - UNIX SVR2 cc 2123 2083
* VAX 11/785 - ULTRIX-32 1.1 cc 2083 2091
* VAX 11/785 - UNIX 4.3bsd cc 2135 2136
* WICAT PB 68000-12.5Mhz System V WICAT C 4.1 1780 2233 S~
* Pyramid 90x - OSx 2.3 cc 2272 2272
* Pyramid 90x FPA,cache,4Mb OSx 2.5 cc no -O 2777 2777
* Pyramid 90x w/cache OSx 2.5 cc w/-O 3333 3333
* IBM-4341-II - VM/SP3 Waterloo C 1.2 3333 3333
* IRIS-2400T 68020-16.67Mhz UNIX System V cc 3105 3401
* Celerity C-1200 ? UNIX 4.2BSD cc 3485 3468
* SUN 3/75 68020-16.67Mhz SUN 4.2 V3 cc 3333 3571
* IBM-4341 Model 12 UTS 5.0 ? 3685 3685
* SUN-3/160 68020-16.67Mhz Sun 4.2 V3.0A cc 3381 3764
* Sun 3/180 68020-16.67Mhz Sun 4.2 cc 3333 3846
* IBM-4341 Model 12 UTS 5.0 ? 3910 3910 MN
* MC 5400 68020-16.67MHz RTU V3.0 cc (V4.0) 3952 4054
* Intel 386/20 80386-12.5Mhz PMON debugger Intel C386v0.2 4149 4386
* NCR Tower32 68020-16.67Mhz SYS 5.0 Rel 2.0 cc 3846 4545
* MC 5600/5700 68020-16.67MHz RTU V3.0 cc (V4.0) 4504 4746 %
* Intel 386/20 80386-12.5Mhz PMON debugger Intel C386v0.2 4534 4794 i1
* Intel 386/20 80386-16Mhz PMON debugger Intel C386v0.2 5304 5607
* Gould PN9080 custom ECL UTX-32 1.1C cc 5369 5676
* Gould 1460-342 ECL proc UTX/32 1.1/c cc 5342 5677 G1
* VAX-784 - Mach/4.3 cc 5882 5882 &4
* Intel 386/20 80386-16Mhz PMON debugger Intel C386v0.2 5801 6133 i1
* VAX 8600 - UNIX 4.3bsd cc 7024 7088
* VAX 8600 - VMS VAX-11 C 2.0 7142 7142
* Alliant FX/8 CE Concentrix cc -ce;exec -c 6952 7655 FX
* CCI POWER 6/32 COS(SV+4.2) cc 7500 7800
* CCI POWER 6/32 POWER 6 UNIX/V cc 8236 8498
* CCI POWER 6/32 4.2 Rel. 1.2b cc 8963 9544
* Sperry (CCI Power 6) 4.2BSD cc 9345 10000
* CRAY-X-MP/12 105Mhz COS 1.14 Cray C 10204 10204
* IBM-3083 - UTS 5.0 Rel 1 cc 16666 12500
* CRAY-1A 80Mhz CTSS Cray C 2.0 12100 13888
* IBM-3083 - VM/CMS HPO 3.4 Waterloo C 1.2 13889 13889
* Amdahl 470 V/8 UTS/V 5.2 cc v1.23 15560 15560
* CRAY-X-MP/48 105Mhz CTSS Cray C 2.0 15625 17857
* Amdahl 580 - UTS 5.0 Rel 1.2 cc v1.5 23076 23076
* Amdahl 5860 UTS/V 5.2 cc v1.23 28970 28970
*
* NOTE
* * Crystal changed from 'stock' to listed value.
* + This Macintosh was upgraded from 128K to 512K in such a way that
* the new 384K of memory is not slowed down by video generator accesses.
* % Single processor; MC == MASSCOMP
* NM A version 7 C compiler written at New Mexico Tech.
* @ vanilla Lattice compiler used with MicroPro standard library
* S Shorts used instead of ints
* T with Chris Torek's patches (whatever they are).
* ~ For WICAT Systems: MB=MultiBus, PB=Proprietary Bus
* LM Large Memory Model. (Otherwise, all 80x8x results are small model)
* MM Medium Memory Model. (Otherwise, all 80x8x results are small model)
* C1 Univation PC TURBO Co-processor; 9.54Mhz 8086, 640K RAM
* C2 Seattle Telecom STD-286 board
* C3 Definicon DSI-32 coprocessor
* C? Unknown co-processor board?
* CT1 Convergent Technologies MegaFrame, 1 processor.
* MN Using Mike Newtons 'optimizer' (see net.sources).
* G1 This Gould machine has 2 processors and was able to run 2 dhrystone
* Benchmarks in parallel with no slowdown.
* FH FHC == Frank Hogg Labs (Hazelwood Uniquad 2 in an FHL box).
* FX The Alliant FX/8 is a system consisting of 1-8 CEs (computation
* engines) and 1-12 IPs (interactive processors). Note N8 applies.
* RT This is one of the RT's that CMU has been using for awhile. I'm
* not sure that this is identical to the machine that IBM is selling
* to the public.
* i1 Normally, the 386/20 starter kit has a 16k direct mapped cache
* which inserts 2 or 3 wait states on a write thru. These results
* were obtained by disabling the write-thru, or essentially turning
* the cache into 0 wait state memory.
* Nnn This machine has multiple processors, allowing "nn" copies of the
* benchmark to run in the same time as 1 copy.
* &nn This machine has "nn" processors, and the benchmark results were
* obtained by having all "nn" processors working on 1 copy of dhrystone.
* (Note, this is different than Nnn. Salesmen like this measure).
* ? I don't trust results marked with '?'. These were sent to me with
* either incomplete info, or with times that just don't make sense.
* ?? means I think the performance is too poor, ?! means too good.
* If anybody can confirm these figures, please respond.
*
* ABBREVIATIONS
* CCC Concurrent Computer Corp. (was Perkin-Elmer)
* MC Masscomp
*
*--------------------------------RESULTS END----------------------------------
*
* The following program contains statements of a high-level programming
* language (C) in a distribution considered representative:
*
* assignments 53%
* control statements 32%
* procedure, function calls 15%
*
* 100 statements are dynamically executed. The program is balanced with
* respect to the three aspects:
* - statement type
* - operand type (for simple data types)
* - operand access
* operand global, local, parameter, or constant.
*
* The combination of these three aspects is balanced only approximately.
*
* The program does not compute anything meaningfull, but it is
* syntactically and semantically correct.
*
*/
/* Accuracy of timings and human fatigue controlled by next two lines */
/*#define LOOPS 5000 /* Use this for slow or 16 bit machines */
/*#define LOOPS 50000 /* Use this for slow or 16 bit machines */
#define LOOPS 500000 /* Use this for faster machines */
/* Compiler dependent options */
#undef NOENUM /* Define if compiler has no enum's */
#undef NOSTRUCTASSIGN /* Define if compiler can't assign structures */
/* define only one of the next three defines */
#define GETRUSAGE /* Use getrusage(2) time function */
/*#define TIMES /* Use times(2) time function */
/*#define TIME /* Use time(2) time function */
/* define the granularity of your times(2) function (when used) */
/*#define HZ 60 /* times(2) returns 1/60 second (most) */
/*#define HZ 100 /* times(2) returns 1/100 second (WECo) */
/* for compatibility with goofed up version */
/*#define GOOF /* Define if you want the goofed up version */
/* default number of threads that will be spawned */
#define DEFAULT_THREADS 1
/* Dhrystones per second obtained on VAX11/780 -- a notional 1MIPS machine. */
/* Used in DMIPS calculation. */
#define ONE_MIPS 1757
#ifdef GOOF
char Version[] = "1.0";
#else
char Version[] = "1.1";
#endif
#ifdef NOSTRUCTASSIGN
#define structassign(d, s) memcpy(&(d), &(s), sizeof(d))
#else
#define structassign(d, s) d = s
#endif
#ifdef NOENUM
#define Ident1 1
#define Ident2 2
#define Ident3 3
#define Ident4 4
#define Ident5 5
typedef int Enumeration;
#else
typedef enum {Ident1, Ident2, Ident3, Ident4, Ident5} Enumeration;
#endif
typedef int OneToThirty;
typedef int OneToFifty;
typedef char CapitalLetter;
typedef char String30[31];
typedef int Array1Dim[51];
typedef int Array2Dim[51][51];
struct Record
{
struct Record *PtrComp;
Enumeration Discr;
Enumeration EnumComp;
OneToFifty IntComp;
String30 StringComp;
};
typedef struct Record RecordType;
typedef RecordType * RecordPtr;
typedef int boolean;
//#define NULL 0
#define TRUE 1
#define FALSE 0
#ifndef REG
#define REG
#endif
extern Enumeration Func1();
extern boolean Func2();
#ifdef TIMES
#include <sys/param.h>
#include <sys/types.h>
#endif
#ifdef GETRUSAGE
#include <sys/resource.h>
#endif
#include <time.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
main(int argc, char** argv)
{
int num_threads = DEFAULT_THREADS;
int runtime = 0;
int delay = 0;
long mloops = 0;
int opt;
while ((opt = getopt(argc, argv, "ht:r:d:l:")) != -1) {
switch (opt) {
case 'h':
printhelp();
exit(0);
break;
case 't':
num_threads = atoi(optarg);
break;
case 'r':
runtime = atoi(optarg);
break;
case 'd':
delay = atoi(optarg);
break;
case 'l':
mloops = atoll(optarg);
break;
}
}
if (runtime && mloops) {
fprintf(stderr, "-r and -l options cannot be specified at the same time.\n");
exit(1);
} else if (!runtime && !mloops) {
fprintf(stderr, "Must specify either -r or -l option; use -h to see help.\n");
exit(1);
}
long num_loops = mloops ? mloops * 1000000L : LOOPS * num_threads;
run_dhrystone(runtime, num_threads, num_loops, delay);
}
run_dhrystone(int duration, int num_threads, long num_loops, int delay) {
printf("duration: %d seconds\n", duration);
printf("number of threads: %d\n", num_threads);
printf("number of loops: %ld\n", num_loops);
printf("delay between starting threads: %d seconds\n", delay);
printf("\n");
pid_t *children = malloc(num_threads* sizeof(pid_t));
int loops_per_thread = num_loops / num_threads;
clock_t run_start = clock();
long i;
int actual_duration;
for (i = 0; i < (num_threads - 1); i++) {
pid_t c = fork();
if (c == 0) {
// child
actual_duration = duration - i * delay;
if (actual_duration < 0)
actual_duration = 0;
run_for_duration(actual_duration, loops_per_thread);
exit(0);
}
children[i] = c;
sleep(delay);
}
run_for_duration(duration - delay * (num_threads - 1), loops_per_thread);
for (i = 0; i < num_threads; i++) {
int status, w;
do {
w= wait(&status);
} while (w != -1 && (!WIFEXITED(status) && !WIFSIGNALED(status)));
}
clock_t run_end = clock();
printf("\nTotal dhrystone run time: %f seconds.\n", (double)(run_end - run_start) / CLOCKS_PER_SEC);
exit(0);
}
run_for_duration(int duration, long num_loops) {
clock_t end = clock() + duration * CLOCKS_PER_SEC;
do {
Proc0(num_loops, duration == 0);
} while (clock() < end);
}
printhelp() {
printf("Usage: dhrystone (-h | -l MLOOPS | -r DURATION) [-t THREADS [-d DELAY]]\n");
printf("\n");
printf("Runs dhrystone benchmark either for a specfied duration or for a specified\n");
printf("number of iterations.\n");
printf("\n");
printf("Options:\n");
printf(" -h Print this message and exit.\n");
printf(" -l MLOOPS Run dhrystone for the specified number of millions\n");
printf(" of iterations (i.e. the actual number of iterations is\n");
printf(" MLOOPS * 1e6).\n");
printf(" -r DURATION Run dhhrystone for the specified duration (in seconds). \n");
printf(" dhrystone will be run 500000 iterations, looping until\n");
printf(" the specified time period has passed.\n");
printf("\n");
printf(" Note: -r and -l options may not be specified at the same time.\n");
printf("\n");
printf(" -t THREADS Specified the number of concurrent threads (processes,\n");
printf(" actually) that will be spawned. Defaults to 1.\n");
printf(" -d DELAY if THREADS is > 1, this specifies the delay between\n");
printf(" spawning the threads.\n");
printf("\n");
}
/*
* Package 1
*/
int IntGlob;
boolean BoolGlob;
char Char1Glob;
char Char2Glob;
Array1Dim Array1Glob;
Array2Dim Array2Glob;
RecordPtr PtrGlb;
RecordPtr PtrGlbNext;
Proc0(long numloops, boolean print_result)
{
OneToFifty IntLoc1;
REG OneToFifty IntLoc2;
OneToFifty IntLoc3;
REG char CharLoc;
REG char CharIndex;
Enumeration EnumLoc;
String30 String1Loc;
String30 String2Loc;
// extern char *malloc();
register unsigned int i;
#ifdef TIME
long time();
long starttime;
long benchtime;
long nulltime;
starttime = time( (long *) 0);
for (i = 0; i < numloops; ++i);
nulltime = time( (long *) 0) - starttime; /* Computes o'head of loop */
#endif
#ifdef TIMES
time_t starttime;
time_t benchtime;
time_t nulltime;
struct tms tms;
times(&tms); starttime = tms.tms_utime;
for (i = 0; i < numloops; ++i);
times(&tms);
nulltime = tms.tms_utime - starttime; /* Computes overhead of looping */
#endif
#ifdef GETRUSAGE
struct rusage starttime;
struct rusage endtime;
struct timeval nulltime;
getrusage(RUSAGE_SELF, &starttime);
for (i = 0; i < numloops; ++i);
getrusage(RUSAGE_SELF, &endtime);
nulltime.tv_sec = endtime.ru_utime.tv_sec - starttime.ru_utime.tv_sec;
nulltime.tv_usec = endtime.ru_utime.tv_usec - starttime.ru_utime.tv_usec;
#endif
PtrGlbNext = (RecordPtr) malloc(sizeof(RecordType));
PtrGlb = (RecordPtr) malloc(sizeof(RecordType));
PtrGlb->PtrComp = PtrGlbNext;
PtrGlb->Discr = Ident1;
PtrGlb->EnumComp = Ident3;
PtrGlb->IntComp = 40;
strcpy(PtrGlb->StringComp, "DHRYSTONE PROGRAM, SOME STRING");
#ifndef GOOF
strcpy(String1Loc, "DHRYSTONE PROGRAM, 1'ST STRING"); /*GOOF*/
#endif
Array2Glob[8][7] = 10; /* Was missing in published program */
/*****************
-- Start Timer --
*****************/
#ifdef TIME
starttime = time( (long *) 0);
#endif
#ifdef TIMES
times(&tms); starttime = tms.tms_utime;
#endif
#ifdef GETRUSAGE
getrusage (RUSAGE_SELF, &starttime);
#endif
for (i = 0; i < numloops; ++i)
{
Proc5();
Proc4();
IntLoc1 = 2;
IntLoc2 = 3;
strcpy(String2Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
EnumLoc = Ident2;
BoolGlob = ! Func2(String1Loc, String2Loc);
while (IntLoc1 < IntLoc2)
{
IntLoc3 = 5 * IntLoc1 - IntLoc2;
Proc7(IntLoc1, IntLoc2, &IntLoc3);
++IntLoc1;
}
Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3);
Proc1(PtrGlb);
for (CharIndex = 'A'; CharIndex <= Char2Glob; ++CharIndex)
if (EnumLoc == Func1(CharIndex, 'C'))
Proc6(Ident1, &EnumLoc);
IntLoc3 = IntLoc2 * IntLoc1;
IntLoc2 = IntLoc3 / IntLoc1;
IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1;
Proc2(&IntLoc1);
}
/*****************
-- Stop Timer --
*****************/
if (print_result) {
#ifdef TIME
benchtime = time( (long *) 0) - starttime - nulltime;
printf("Dhrystone(%s) time for %ld passes = %ld\n",
Version,
(long) numloops, benchtime);
printf("This machine benchmarks at %ld dhrystones/second\n",
((long) numloops) / benchtime);
printf(" %ld DMIPS\n",
((long) numloops) / benchtime / ONE_MIPS);
#endif
#ifdef TIMES
times(&tms);
benchtime = tms.tms_utime - starttime - nulltime;
printf("Dhrystone(%s) time for %ld passes = %ld\n",
Version,
(long) numloops, benchtime/HZ);
printf("This machine benchmarks at %ld dhrystones/second\n",
((long) numloops) * HZ / benchtime);
printf(" %ld DMIPS\n",
((long) numloops) * HZ / benchtime / ONE_MIPS);
#endif
#ifdef GETRUSAGE
getrusage(RUSAGE_SELF, &endtime);
{
double t = (double)(endtime.ru_utime.tv_sec
- starttime.ru_utime.tv_sec
- nulltime.tv_sec)
+ (double)(endtime.ru_utime.tv_usec
- starttime.ru_utime.tv_usec
- nulltime.tv_usec) * 1e-6;
printf("Dhrystone(%s) time for %ld passes = %.1f\n",
Version,
(long)numloops,
t);
printf("This machine benchmarks at %.0f dhrystones/second\n",
(double)numloops / t);
printf(" %.0f DMIPS\n",
(double)numloops / t / ONE_MIPS);
}
#endif
}
}
Proc1(PtrParIn)
REG RecordPtr PtrParIn;
{
#define NextRecord (*(PtrParIn->PtrComp))
structassign(NextRecord, *PtrGlb);
PtrParIn->IntComp = 5;
NextRecord.IntComp = PtrParIn->IntComp;
NextRecord.PtrComp = PtrParIn->PtrComp;
Proc3(NextRecord.PtrComp);
if (NextRecord.Discr == Ident1)
{
NextRecord.IntComp = 6;
Proc6(PtrParIn->EnumComp, &NextRecord.EnumComp);
NextRecord.PtrComp = PtrGlb->PtrComp;
Proc7(NextRecord.IntComp, 10, &NextRecord.IntComp);
}
else
structassign(*PtrParIn, NextRecord);
#undef NextRecord
}
Proc2(IntParIO)
OneToFifty *IntParIO;
{
REG OneToFifty IntLoc;
REG Enumeration EnumLoc;
IntLoc = *IntParIO + 10;
for(;;)
{
if (Char1Glob == 'A')
{
--IntLoc;
*IntParIO = IntLoc - IntGlob;
EnumLoc = Ident1;
}
if (EnumLoc == Ident1)
break;
}
}
Proc3(PtrParOut)
RecordPtr *PtrParOut;
{
if (PtrGlb != NULL)
*PtrParOut = PtrGlb->PtrComp;
else
IntGlob = 100;
Proc7(10, IntGlob, &PtrGlb->IntComp);
}
Proc4()
{
REG boolean BoolLoc;
BoolLoc = Char1Glob == 'A';
BoolLoc |= BoolGlob;
Char2Glob = 'B';
}
Proc5()
{
Char1Glob = 'A';
BoolGlob = FALSE;
}
extern boolean Func3();
Proc6(EnumParIn, EnumParOut)
REG Enumeration EnumParIn;
REG Enumeration *EnumParOut;
{
*EnumParOut = EnumParIn;
if (! Func3(EnumParIn) )
*EnumParOut = Ident4;
switch (EnumParIn)
{
case Ident1: *EnumParOut = Ident1; break;
case Ident2: if (IntGlob > 100) *EnumParOut = Ident1;
else *EnumParOut = Ident4;
break;
case Ident3: *EnumParOut = Ident2; break;
case Ident4: break;
case Ident5: *EnumParOut = Ident3;
}
}
Proc7(IntParI1, IntParI2, IntParOut)
OneToFifty IntParI1;
OneToFifty IntParI2;
OneToFifty *IntParOut;
{
REG OneToFifty IntLoc;
IntLoc = IntParI1 + 2;
*IntParOut = IntParI2 + IntLoc;
}
Proc8(Array1Par, Array2Par, IntParI1, IntParI2)
Array1Dim Array1Par;
Array2Dim Array2Par;
OneToFifty IntParI1;
OneToFifty IntParI2;
{
REG OneToFifty IntLoc;
REG OneToFifty IntIndex;
IntLoc = IntParI1 + 5;
Array1Par[IntLoc] = IntParI2;
Array1Par[IntLoc+1] = Array1Par[IntLoc];
Array1Par[IntLoc+30] = IntLoc;
for (IntIndex = IntLoc; IntIndex <= (IntLoc+1); ++IntIndex)
Array2Par[IntLoc][IntIndex] = IntLoc;
++Array2Par[IntLoc][IntLoc-1];
Array2Par[IntLoc+20][IntLoc] = Array1Par[IntLoc];
IntGlob = 5;
}
Enumeration Func1(CharPar1, CharPar2)
CapitalLetter CharPar1;
CapitalLetter CharPar2;
{
REG CapitalLetter CharLoc1;
REG CapitalLetter CharLoc2;
CharLoc1 = CharPar1;
CharLoc2 = CharLoc1;
if (CharLoc2 != CharPar2)
return (Ident1);
else
return (Ident2);
}
boolean Func2(StrParI1, StrParI2)
String30 StrParI1;
String30 StrParI2;
{
REG OneToThirty IntLoc;
REG CapitalLetter CharLoc;
IntLoc = 1;
while (IntLoc <= 1)
if (Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1)
{
CharLoc = 'A';
++IntLoc;
}
if (CharLoc >= 'W' && CharLoc <= 'Z')
IntLoc = 7;
if (CharLoc == 'X')
return(TRUE);
else
{
if (strcmp(StrParI1, StrParI2) > 0)
{
IntLoc += 7;
return (TRUE);
}
else
return (FALSE);
}
}
boolean Func3(EnumParIn)
REG Enumeration EnumParIn;
{
REG Enumeration EnumLoc;
EnumLoc = EnumParIn;
if (EnumLoc == Ident3) return (TRUE);
return (FALSE);
}
#ifdef NOSTRUCTASSIGN
memcpy(d, s, l)
register char *d;
register char *s;
register int l;
{
while (l--) *d++ = *s++;
}
#endif
/* ---------- */

View File

@@ -0,0 +1,34 @@
# 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=R0801
import os
import time
from wlauto import GameWorkload
from wlauto.exceptions import WorkloadError, DeviceError
class DungeonDefenders(GameWorkload):
name = 'dungeondefenders'
description = """
Dungeon Defenders game.
"""
package = 'com.trendy.ddapp'
activity = 'com.trendy.ddapp.ddapp'
loading_time = 20
asset_file = 'com.trendy.ddapp.tar.gz'

View File

@@ -0,0 +1,82 @@
# 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.
#
import os
import time
import sys
from wlauto import AndroidUiAutoBenchmark
from wlauto import UiAutomatorWorkload
from wlauto import AndroidBenchmark
class Facebook(AndroidUiAutoBenchmark):
name = 'facebook'
description = """
Uses com.facebook.patana apk for facebook workload.
This workload does the following activities in facebook
Login to facebook account.
Send a message.
Check latest notification.
Search particular user account and visit his/her facebook account.
Find friends.
Update the facebook status
[NOTE: This workload starts disableUpdate workload as a part of setup to
disable online updates, which helps to tackle problem of uncertain
behavier during facebook workload run.]
"""
package = 'com.facebook.katana'
activity = '.LoginActivity'
#'du' specify 'disable update'
du_activity = 'com.android.vending/.AssetBrowserActivity'
du_method_string = 'com.arm.wlauto.uiauto.facebook.UiAutomation#disableUpdate'
du_jar_file = '/data/local/wa_usecases/com.arm.wlauto.uiauto.facebook.jar'
du_run_timeout = 4 * 60
du_working_dir = '/data/local/wa_usecases'
du_apk_file = '/disableupdateapk/com.android.vending-4.3.10.apk'
DELAY = 5
def setup(self, context):
UiAutomatorWorkload.setup(self, context)
#Start the play store activity
self.device.execute('am start {}'.format(self.du_activity))
#Creating command
command = 'uiautomator runtest {} -e workdir {} -c {}'.format(self.du_jar_file,
self.du_working_dir,
self.du_method_string)
#Start the disable update workload
self.device.execute(command, self.du_run_timeout)
time.sleep(self.DELAY)
#Stop the play store activity
self.device.execute('am force-stop com.android.vending')
AndroidBenchmark.setup(self, context)
def update_result(self, context):
super(Facebook, self).update_result(context)
def teardown(self, context):
pass

View File

@@ -0,0 +1,27 @@
#!/bin/bash
# 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.
#
class_dir=bin/classes/com/arm/wlauto/uiauto
base_class=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', 'BaseUiAutomation.class')"`
mkdir -p $class_dir
cp $base_class $class_dir
ant build
if [[ -f bin/com.arm.wlauto.uiauto.facebook.jar ]]; then
cp bin/com.arm.wlauto.uiauto.facebook.jar ..
fi

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.arm.wlauto.uiauto.facebook" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: VERSION_TAG -->
<import file="${sdk.dir}/tools/ant/uibuild.xml" />
</project>

View File

@@ -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-17

View File

@@ -0,0 +1,257 @@
/* 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.
*/
package com.arm.wlauto.uiauto.facebook;
import android.app.Activity;
import android.os.Bundle;
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import com.arm.wlauto.uiauto.BaseUiAutomation;
public class UiAutomation extends BaseUiAutomation {
public static String TAG = "facebook";
/*
* The 'runUiAutomation' method implements the following activities
* Login to facebook account.
* Send a message.
* Check latest notification.
* Search particular user account and visit his/her facebook account.
* Go to find friends.
* Update the facebook status
*/
public void runUiAutomation() throws Exception {
final int timeout = 5;
UiSelector selector = new UiSelector();
UiObject logInButton = new UiObject(selector
.className("android.widget.Button").index(3).text("Log In"));
UiObject emailField = new UiObject(selector
.className("android.widget.EditText").index(1));
emailField.clearTextField();
emailField.setText("abkksathe@gmail.com");
UiObject passwordField = new UiObject(selector
.className("android.widget.EditText").index(2));
passwordField.clearTextField();
passwordField.setText("highelymotivated");
logInButton.clickAndWaitForNewWindow(timeout);
sleep(timeout);
//Click on message logo
UiObject messageLogo = new UiObject(new UiSelector()
.className("android.widget.RelativeLayout").index(0)
.childSelector(new UiSelector()
.className("android.widget.LinearLayout").index(3)
.childSelector(new UiSelector()
.className("android.widget.RelativeLayout").index(1)
.childSelector(new UiSelector()
.className("android.widget.ImageButton").index(0)))));
messageLogo.clickAndWaitForNewWindow(timeout);
//send message
UiObject clickMessage = new UiObject(new UiSelector()
.className("android.support.v4.view.ViewPager").index(0)
.childSelector(new UiSelector()
.className("android.widget.RelativeLayout").index(1)));
clickMessage.clickAndWaitForNewWindow(timeout);
sleep(timeout);
UiObject sendMessage = new UiObject(new UiSelector()
.className("android.widget.FrameLayout").index(4)
.childSelector(new UiSelector()
.className("android.widget.LinearLayout").index(2))
.childSelector(new UiSelector()
.className("android.widget.EditText").index(0)
.text("Write a message")));
sendMessage.click();
sleep(timeout);
UiObject editMessage = new UiObject(new UiSelector()
.className("android.widget.EditText").text("Write a message"));
editMessage.setText("Hi how are you?????");
UiObject sendButton = new UiObject(new UiSelector()
.className("android.widget.TextView").text("Send"));
sendButton.click();
getUiDevice().pressDPadDown();
sleep(timeout);
getUiDevice().pressBack();
sleep(timeout);
getUiDevice().pressBack();
//Check for notifications
UiObject clickNotificationsLogo = new UiObject(new UiSelector()
.className("android.widget.RelativeLayout").index(0)
.childSelector(new UiSelector()
.className("android.widget.LinearLayout").index(3)
.childSelector(new UiSelector()
.className("android.widget.RelativeLayout").index(2)
.childSelector(new UiSelector()
.className("android.widget.ImageButton").index(0)))));
clickNotificationsLogo.clickAndWaitForNewWindow(timeout);
//Click on latest notification
UiObject clickNotify = new UiObject(new UiSelector()
.className("android.support.v4.view.ViewPager").index(0)
.childSelector(new UiSelector()
.className("android.widget.LinearLayout").index(1)));
clickNotify.clickAndWaitForNewWindow(timeout);
sleep(timeout);
getUiDevice().pressBack();
sleep(timeout);
getUiDevice().pressBack();
//Search for the facebook account
UiObject clickBar = new UiObject(new UiSelector()
.className("android.view.View").index(0)
.childSelector(new UiSelector()
.className("android.widget.ImageButton").index(0)
.description("Main navigation menu")));
clickBar.clickAndWaitForNewWindow(timeout);
UiObject clickSearch = new UiObject(new UiSelector()
.className("android.widget.FrameLayout").index(0)
.childSelector(new UiSelector()
.className("android.widget.LinearLayout").index(0)
.childSelector(new UiSelector()
.className("android.widget.FrameLayout").index(0)
.childSelector(new UiSelector()
.className("android.widget.FrameLayout").index(1)
.childSelector(new UiSelector()
.className("android.widget.EditText").index(1)
.text("Search"))))));
clickSearch.clickAndWaitForNewWindow(timeout);
UiObject editSearch = new UiObject(new UiSelector()
.className("android.widget.EditText").index(0).text("Search"));
editSearch.clearTextField();
editSearch.setText("amol kamble");
sleep(timeout);
UiObject clickOnSearchResult = new UiObject(new UiSelector()
.className("android.webkit.WebView").index(0));
clickOnSearchResult.clickTopLeft();
sleep(2 * timeout);
getUiDevice().pressBack();
sleep(timeout);
getUiDevice().pressBack();
clickBar.click();
sleep(timeout);
//Click on find friends
UiObject clickFriends = new UiObject(new UiSelector()
.className("android.widget.FrameLayout").index(0)
.childSelector(new UiSelector()
.className("android.widget.LinearLayout").index(0)
.childSelector(new UiSelector()
.className("android.widget.FrameLayout").index(0)
.childSelector(new UiSelector()
.className("android.widget.FrameLayout").index(1)
.childSelector(new UiSelector()
.className("android.widget.RelativeLayout").index(0)
.childSelector(new UiSelector()
.className("android.widget.ListView").index(2)))))));
UiObject friends = clickFriends.getChild(new UiSelector()
.className("android.widget.RelativeLayout").index(3));
friends.click();
sleep(timeout);
getUiDevice().pressBack();
//Update the status
UiObject updateStatus = new UiObject(new UiSelector()
.className("android.widget.FrameLayout").index(1)
.childSelector(new UiSelector()
.className("android.widget.FrameLayout").index(1)
.childSelector(new UiSelector()
.className("android.widget.RelativeLayout").index(1)
.childSelector(new UiSelector()
.className("android.widget.LinearLayout").index(0)
.childSelector(new UiSelector()
.className("android.widget.LinearLayout").index(0)
.childSelector(new UiSelector()
.className("android.widget.LinearLayout").index(0)))))));
updateStatus.clickAndWaitForNewWindow(timeout);
UiObject editUpdateStatus = new UiObject(new UiSelector()
.className("android.widget.EditText")
.text("What's on your mind?"));
editUpdateStatus.clearTextField();
editUpdateStatus.setText("hellllooooooo its done!!");
UiObject clickPost = new UiObject(new UiSelector()
.className("android.widget.RelativeLayout").index(0)
.childSelector(new UiSelector()
.className("android.widget.LinearLayout").index(3)));
clickPost.clickAndWaitForNewWindow(timeout);
getUiDevice().pressHome();
}
//disable update using playstore
public void disableUpdate() throws UiObjectNotFoundException {
UiObject accountSelect = new UiObject(new UiSelector()
.className("android.widget.Button").text("Accept"));
if (accountSelect.exists())
accountSelect.click();
UiObject moreOptions = new UiObject(new UiSelector()
.className("android.widget.ImageButton")
.description("More options"));
moreOptions.click();
UiObject settings = new UiObject(new UiSelector()
.className("android.widget.TextView").text("Settings"));
settings.clickAndWaitForNewWindow();
UiObject autoUpdate = new UiObject(new UiSelector()
.className("android.widget.TextView")
.text("Auto-update apps"));
autoUpdate.clickAndWaitForNewWindow();
UiObject clickAutoUpdate = new UiObject(new UiSelector()
.className("android.widget.CheckedTextView")
.text("Do not auto-update apps"));
clickAutoUpdate.clickAndWaitForNewWindow();
getUiDevice().pressBack();
getUiDevice().pressHome();
}
}

View File

@@ -0,0 +1,351 @@
# 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
import os
import re
import tempfile
import json
from collections import defaultdict
from wlauto import AndroidUiAutoBenchmark, Parameter, Artifact
from wlauto.exceptions import ConfigError, WorkloadError
from wlauto.utils.misc import capitalize
import wlauto.common.android.resources
class Geekbench(AndroidUiAutoBenchmark):
name = 'geekbench'
description = """
Geekbench provides a comprehensive set of benchmarks engineered to quickly
and accurately measure processor and memory performance.
http://www.primatelabs.com/geekbench/
From the website:
Designed to make benchmarks easy to run and easy to understand, Geekbench
takes the guesswork out of producing robust and reliable benchmark results.
Geekbench scores are calibrated against a baseline score of 1,000 (which is
the score of a single-processor Power Mac G5 @ 1.6GHz). Higher scores are
better, with double the score indicating double the performance.
The benchmarks fall into one of four categories:
- integer performance.
- floating point performance.
- memory performance.
- stream performance.
Geekbench benchmarks: http://www.primatelabs.com/geekbench/doc/benchmarks.html
Geekbench scoring methedology:
http://support.primatelabs.com/kb/geekbench/interpreting-geekbench-scores
"""
summary_metrics = ['score', 'multicore_score']
versions = {
'3': {
'package': 'com.primatelabs.geekbench3',
'activity': '.HomeActivity',
},
'2': {
'package': 'ca.primatelabs.geekbench2',
'activity': '.HomeActivity',
},
}
begin_regex = re.compile(r'^\s*D/WebViewClassic.loadDataWithBaseURL\(\s*\d+\s*\)'
r'\s*:\s*(?P<content>\<.*)\s*$')
replace_regex = re.compile(r'<[^>]*>')
parameters = [
Parameter('version', default=sorted(versions.keys())[-1], allowed_values=sorted(versions.keys()),
description='Specifies which version of the workload should be run.'),
Parameter('times', kind=int, default=1,
description=('Specfies the number of times the benchmark will be run in a "tight '
'loop", i.e. without performaing setup/teardown inbetween.')),
]
@property
def activity(self):
return self.versions[self.version]['activity']
@property
def package(self):
return self.versions[self.version]['package']
def __init__(self, device, **kwargs):
super(Geekbench, self).__init__(device, **kwargs)
self.uiauto_params['version'] = self.version
self.uiauto_params['times'] = self.times
self.run_timeout = 3 * 60 * self.times
def init_resources(self, context):
self.apk_file = context.resolver.get(wlauto.common.android.resources.ApkFile(self), version=self.version)
self.uiauto_file = context.resolver.get(wlauto.common.android.resources.JarFile(self))
self.device_uiauto_file = self.device.path.join(self.device.working_directory,
os.path.basename(self.uiauto_file))
if not self.uiauto_package:
self.uiauto_package = os.path.splitext(os.path.basename(self.uiauto_file))[0]
def update_result(self, context):
super(Geekbench, self).update_result(context)
update_method = getattr(self, 'update_result_{}'.format(self.version))
update_method(context)
def validate(self):
if (self.times > 1) and (self.version == '2'):
raise ConfigError('times parameter is not supported for version 2 of Geekbench.')
def update_result_2(self, context):
score_calculator = GBScoreCalculator()
score_calculator.parse(self.logcat_log)
score_calculator.update_results(context)
def update_result_3(self, context):
outfile_glob = self.device.path.join(self.device.package_data_directory, self.package, 'files', '*gb3')
on_device_output_files = [f.strip() for f in
self.device.execute('ls {}'.format(outfile_glob), as_root=True).split('\n')]
for i, on_device_output_file in enumerate(on_device_output_files):
host_temp_file = tempfile.mktemp()
self.device.pull_file(on_device_output_file, host_temp_file)
host_output_file = os.path.join(context.output_directory, os.path.basename(on_device_output_file))
with open(host_temp_file) as fh:
data = json.load(fh)
os.remove(host_temp_file)
with open(host_output_file, 'w') as wfh:
json.dump(data, wfh, indent=4)
context.iteration_artifacts.append(Artifact('geekout', path=os.path.basename(on_device_output_file),
kind='data',
description='Geekbench 3 output from device.'))
context.result.add_metric(namemify('score', i), data['score'])
context.result.add_metric(namemify('multicore_score', i), data['multicore_score'])
for section in data['sections']:
context.result.add_metric(namemify(section['name'] + '_score', i), section['score'])
context.result.add_metric(namemify(section['name'] + '_multicore_score', i),
section['multicore_score'])
class GBWorkload(object):
"""
Geekbench workload (not to be confused with WA's workloads). This is a single test run by
geek bench, such as preforming compression or generating Madelbrot.
"""
# Index maps onto the hundreds digit of the ID.
categories = [None, 'integer', 'float', 'memory', 'stream']
# 2003 entry-level Power Mac G5 is considered to have a baseline score of
# 1000 for every category.
pmac_g5_base_score = 1000
units_conversion_map = {
'K': 1,
'M': 1000,
'G': 1000000,
}
def __init__(self, wlid, name, pmac_g5_st_score, pmac_g5_mt_score):
"""
:param wlid: A three-digit workload ID. Uniquely identifies a workload and also
determines the category a workload belongs to.
:param name: The name of the workload.
:param pmac_g5_st_score: Score achieved for this workload on 2003 entry-level
Power Mac G5 running in a single thread.
:param pmac_g5_mt_score: Score achieved for this workload on 2003 entry-level
Power Mac G5 running in multiple threads.
"""
self.wlid = wlid
self.name = name
self.pmac_g5_st_score = pmac_g5_st_score
self.pmac_g5_mt_score = pmac_g5_mt_score
self.category = self.categories[int(wlid) // 100]
self.collected_results = []
def add_result(self, value, units):
self.collected_results.append(self.convert_to_kilo(value, units))
def convert_to_kilo(self, value, units):
return value * self.units_conversion_map[units[0]]
def clear(self):
self.collected_results = []
def get_scores(self):
"""
Returns a tuple (single-thraded score, multi-threaded score) for this workload.
Some workloads only have a single-threaded score, in which case multi-threaded
score will be ``None``.
Geekbench will perform four iterations of each workload in single-threaded and,
for some workloads, multi-threaded configurations. Thus there should always be
either four or eight scores collected for each workload. Single-threaded iterations
are always done before multi-threaded, so the ordering of the scores can be used
to determine which configuration they belong to.
This method should not be called before score collection has finished.
"""
no_of_results = len(self.collected_results)
if no_of_results == 4:
return (self._calculate(self.collected_results[:4], self.pmac_g5_st_score), None)
if no_of_results == 8:
return (self._calculate(self.collected_results[:4], self.pmac_g5_st_score),
self._calculate(self.collected_results[4:], self.pmac_g5_mt_score))
else:
msg = 'Collected {} results for Geekbench {} workload;'.format(no_of_results, self.name)
msg += ' expecting either 4 or 8.'
raise WorkloadError(msg)
def _calculate(self, values, scale_factor):
return max(values) * self.pmac_g5_base_score / scale_factor
def __str__(self):
return self.name
__repr__ = __str__
class GBScoreCalculator(object):
"""
Parses logcat output to extract raw Geekbench workload values and converts them into
category and overall scores.
"""
result_regex = re.compile(r'workload (?P<id>\d+) (?P<value>[0-9.]+) '
r'(?P<units>[a-zA-Z/]+) (?P<time>[0-9.]+)s')
# Indicates contribution to the overall score.
category_weights = {
'integer': 0.3357231,
'float': 0.3594,
'memory': 0.1926489,
'stream': 0.1054738,
}
#pylint: disable=C0326
workloads = [
# ID Name Power Mac ST Power Mac MT
GBWorkload(101, 'Blowfish', 43971, 40979),
GBWorkload(102, 'Text Compress', 3202, 3280),
GBWorkload(103, 'Text Decompress', 4112, 3986),
GBWorkload(104, 'Image Compress', 8272, 8412),
GBWorkload(105, 'Image Decompress', 16800, 16330),
GBWorkload(107, 'Lua', 385, 385),
GBWorkload(201, 'Mandelbrot', 665589, 653746),
GBWorkload(202, 'Dot Product', 481449, 455422),
GBWorkload(203, 'LU Decomposition', 889933, 877657),
GBWorkload(204, 'Primality Test', 149394, 185502),
GBWorkload(205, 'Sharpen Image', 2340, 2304),
GBWorkload(206, 'Blur Image', 791, 787),
GBWorkload(302, 'Read Sequential', 1226708, None),
GBWorkload(304, 'Write Sequential', 683782, None),
GBWorkload(306, 'Stdlib Allocate', 3739, None),
GBWorkload(307, 'Stdlib Write', 2070681, None),
GBWorkload(308, 'Stdlib Copy', 1030360, None),
GBWorkload(401, 'Stream Copy', 1367892, None),
GBWorkload(402, 'Stream Scale', 1296053, None),
GBWorkload(403, 'Stream Add', 1507115, None),
GBWorkload(404, 'Stream Triad', 1384526, None),
]
def __init__(self):
self.workload_map = {wl.wlid: wl for wl in self.workloads}
def parse(self, filepath):
"""
Extract results from the specified file. The file should contain a logcat log of Geekbench execution.
Iteration results in the log appear as 'I/geekbench' category entries in the following format::
| worklod ID value units timing
| \------------- | ----/ ---/
| | | | |
| I/geekbench(29026): [....] workload 101 132.9 MB/sec 0.0300939s
| | |
| | -----\
| label random crap we don't care about
"""
for wl in self.workloads:
wl.clear()
with open(filepath) as fh:
for line in fh:
match = self.result_regex.search(line)
if match:
wkload = self.workload_map[int(match.group('id'))]
wkload.add_result(float(match.group('value')), match.group('units'))
def update_results(self, context):
"""
http://support.primatelabs.com/kb/geekbench/interpreting-geekbench-2-scores
From the website:
Each workload's performance is compared against a baseline to determine a score. These
scores are averaged together to determine an overall, or Geekbench, score for the system.
Geekbench uses the 2003 entry-level Power Mac G5 as the baseline with a score of 1,000
points. Higher scores are better, with double the score indicating double the performance.
Geekbench provides three different kinds of scores:
:Workload Scores: Each time a workload is executed Geekbench calculates a score based
on the computer's performance compared to the baseline
performance. There can be multiple workload scores for the
same workload as Geekbench can execute each workload multiple
times with different settings. For example, the "Dot Product"
workload is executed four times (single-threaded scalar code,
multi-threaded scalar code, single-threaded vector code, and
multi-threaded vector code) producing four "Dot Product" scores.
:Section Scores: A section score is the average of all the workload scores for
workloads that are part of the section. These scores are useful
for determining the performance of the computer in a particular
area. See the section descriptions above for a summary on what
each section measures.
:Geekbench Score: The Geekbench score is the weighted average of the four section
scores. The Geekbench score provides a way to quickly compare
performance across different computers and different platforms
without getting bogged down in details.
"""
scores_by_category = defaultdict(list)
for wkload in self.workloads:
st_score, mt_score = wkload.get_scores()
scores_by_category[wkload.category].append(st_score)
context.result.add_metric(wkload.name + ' (single-threaded)', int(st_score))
if mt_score is not None:
scores_by_category[wkload.category].append(mt_score)
context.result.add_metric(wkload.name + ' (multi-threaded)', int(mt_score))
overall_score = 0
for category in scores_by_category:
scores = scores_by_category[category]
category_score = sum(scores) / len(scores)
overall_score += category_score * self.category_weights[category]
context.result.add_metric(capitalize(category) + ' Score', int(category_score))
context.result.add_metric('Geekbench Score', int(overall_score))
def namemify(basename, i):
return basename + (' {}'.format(i) if i else '')

View File

@@ -0,0 +1,28 @@
#!/bin/bash
# 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.
#
class_dir=bin/classes/com/arm/wlauto/uiauto
base_class=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', 'BaseUiAutomation.class')"`
mkdir -p $class_dir
cp $base_class $class_dir
ant build
if [[ -f bin/com.arm.wlauto.uiauto.geekbench.jar ]]; then
cp bin/com.arm.wlauto.uiauto.geekbench.jar ..
fi

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="com.arm.wlauto.uiauto.geekbench" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: VERSION_TAG -->
<import file="${sdk.dir}/tools/ant/uibuild.xml" />
</project>

View File

@@ -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-17

View File

@@ -0,0 +1,121 @@
/* 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.
*/
package com.arm.wlauto.uiauto.geekbench;
import java.util.concurrent.TimeUnit;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
// Import the uiautomator libraries
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import com.arm.wlauto.uiauto.BaseUiAutomation;
public class UiAutomation extends BaseUiAutomation {
public static String TAG = "geekbench";
public void runUiAutomation() throws Exception {
Bundle params = getParams();
int version = Integer.parseInt(params.getString("version"));
int times = Integer.parseInt(params.getString("times"));
for (int i = 0; i < times; i++) {
runBenchmarks();
switch(version) {
case 2:
// In version 2, we scroll through the results WebView to make sure
// all results appear on the screen, which causes them to be dumped into
// logcat by the Linaro hacks.
waitForResultsv2();
scrollThroughResults();
break;
case 3:
// Attempting to share the results will generate the .gb3 file with
// results that can then be pulled from the device. This is not possible
// in verison 2 of Geekbench (Share option was added later).
waitForResultsv3();
shareResults();
break;
}
if (i < (times - 1)) {
getUiDevice().pressBack();
getUiDevice().pressBack(); // twice
}
}
Bundle status = new Bundle();
getAutomationSupport().sendStatus(Activity.RESULT_OK, status);
}
public void runBenchmarks() throws Exception {
UiSelector selector = new UiSelector();
UiObject runButton = new UiObject(selector.text("Run Benchmarks")
.className("android.widget.Button"));
if (!runButton.exists()) {
getUiDevice().pressBack();
}
runButton.click();
}
public void waitForResultsv2() throws Exception {
UiSelector selector = new UiSelector();
UiObject resultsWebview = new UiObject(selector.className("android.webkit.WebView"));
if (!resultsWebview.waitForExists(TimeUnit.SECONDS.toMillis(200))) {
throw new UiObjectNotFoundException("Did not see Geekbench results screen.");
}
}
public void waitForResultsv3() throws Exception {
UiSelector selector = new UiSelector();
UiObject runningTextView = new UiObject(selector.text("Running Benchmarks...")
.className("android.widget.TextView"));
runningTextView.waitForExists(TimeUnit.SECONDS.toMillis(2));
if (!runningTextView.waitUntilGone(TimeUnit.SECONDS.toMillis(200))) {
throw new UiObjectNotFoundException("Did not get to Geekbench results screen.");
}
}
public void scrollThroughResults() throws Exception {
UiSelector selector = new UiSelector();
getUiDevice().pressKeyCode(KeyEvent.KEYCODE_PAGE_DOWN);
sleep(1);
getUiDevice().pressKeyCode(KeyEvent.KEYCODE_PAGE_DOWN);
sleep(1);
getUiDevice().pressKeyCode(KeyEvent.KEYCODE_PAGE_DOWN);
sleep(1);
getUiDevice().pressKeyCode(KeyEvent.KEYCODE_PAGE_DOWN);
}
public void shareResults() throws Exception {
sleep(2); // transition
UiSelector selector = new UiSelector();
getUiDevice().pressMenu();
UiObject runButton = new UiObject(selector.text("Share")
.className("android.widget.TextView"));
runButton.waitForExists(500);
runButton.click();
}
}

View File

@@ -0,0 +1,209 @@
# 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,W0201,E0203
from __future__ import division
import os
import re
import time
import select
import json
import threading
import subprocess
from wlauto import ApkWorkload, Parameter, Alias
from wlauto.exceptions import WorkloadError
DELAY = 2
class GlbCorp(ApkWorkload):
name = 'glb_corporate'
description = """
GFXBench GL (a.k.a. GLBench) v3.0 Corporate version.
This is a version of GLBench available through a corporate license (distinct
from the version available in Google Play store).
"""
package = 'net.kishonti.gfxbench'
activity = 'net.kishonti.benchui.TestActivity'
result_start_regex = re.compile(r'I/TfwActivity\s*\(\s*\d+\):\s+\S+\s+result: {')
preamble_regex = re.compile(r'I/TfwActivity\s*\(\s*\d+\):\s+')
valid_test_ids = [
'gl_alu',
'gl_alu_off',
'gl_blending',
'gl_blending_off',
'gl_driver',
'gl_driver_off',
'gl_fill',
'gl_fill_off',
'gl_manhattan',
'gl_manhattan_off',
'gl_trex',
'gl_trex_battery',
'gl_trex_off',
'gl_trex_qmatch',
'gl_trex_qmatch_highp',
]
supported_resolutions = {
'720p': {
'-ei -w': 1280,
'-ei -h': 720,
},
'1080p': {
'-ei -w': 1920,
'-ei -h': 1080,
}
}
run_timeout = 3 * 60
parameters = [
Parameter('times', kind=int, default=1, constraint=lambda x: x > 0,
description=('Specifies the number of times the benchmark will be run in a "tight '
'loop", i.e. without performaing setup/teardown inbetween.')),
Parameter('resolution', default=None, allowed_values=['720p', '1080p', '720', '1080'],
description=('Explicitly specifies the resultion under which the benchmark will '
'be run. If not specfied, device\'s native resoution will used.')),
Parameter('test_id', default='gl_manhattan_off', allowed_values=valid_test_ids,
description='ID of the GFXBench test to be run.')
]
aliases = [
Alias('manhattan', test_id='gl_manhattan'),
Alias('manhattan_off', test_id='gl_manhattan_off'),
Alias('manhattan_offscreen', test_id='gl_manhattan_off'),
]
def setup(self, context):
super(GlbCorp, self).setup(context)
self.command = self._build_command()
self.monitor = GlbRunMonitor(self.device)
self.monitor.start()
def start_activity(self):
# Unlike with most other APK workloads, we're invoking the use case
# directly by starting the activity with appropriate parameters on the
# command line during execution, so we dont' need to start activity
# during setup.
pass
def run(self, context):
for _ in xrange(self.times):
result = self.device.execute(self.command, timeout=self.run_timeout)
if 'FAILURE' in result:
raise WorkloadError(result)
else:
self.logger.debug(result)
time.sleep(DELAY)
self.monitor.wait_for_run_end(self.run_timeout)
def update_result(self, context): # NOQA
super(GlbCorp, self).update_result(context)
self.monitor.stop()
iteration = 0
results = []
with open(self.logcat_log) as fh:
try:
line = fh.next()
result_lines = []
while True:
if self.result_start_regex.search(line):
result_lines.append('{')
line = fh.next()
while self.preamble_regex.search(line):
result_lines.append(self.preamble_regex.sub('', line))
line = fh.next()
try:
result = json.loads(''.join(result_lines))
results.append(result)
if iteration:
suffix = '_{}'.format(iteration)
else:
suffix = ''
for sub_result in result['results']:
frames = sub_result['score']
elapsed_time = sub_result['elapsed_time'] / 1000
fps = frames / elapsed_time
context.result.add_metric('score' + suffix, frames, 'frames')
context.result.add_metric('fps' + suffix, fps)
except ValueError:
self.logger.warning('Could not parse result for iteration {}'.format(iteration))
result_lines = []
iteration += 1
line = fh.next()
except StopIteration:
pass # EOF
if results:
outfile = os.path.join(context.output_directory, 'glb-results.json')
with open(outfile, 'wb') as wfh:
json.dump(results, wfh, indent=4)
def _build_command(self):
command_params = []
command_params.append('-e test_ids "{}"'.format(self.test_id))
if self.resolution:
if not self.resolution.endswith('p'):
self.resolution += 'p'
for k, v in self.supported_resolutions[self.resolution].iteritems():
command_params.append('{} {}'.format(k, v))
return 'am start -W -S -n {}/{} {}'.format(self.package,
self.activity,
' '.join(command_params))
class GlbRunMonitor(threading.Thread):
regex = re.compile(r'I/Runner\s+\(\s*\d+\): finished:')
def __init__(self, device):
super(GlbRunMonitor, self).__init__()
self.device = device
self.daemon = True
self.run_ended = threading.Event()
self.stop_event = threading.Event()
if self.device.adb_name:
self.command = ['adb', '-s', self.device.adb_name, 'logcat']
else:
self.command = ['adb', 'logcat']
def run(self):
proc = subprocess.Popen(self.command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while not self.stop_event.is_set():
if self.run_ended.is_set():
time.sleep(DELAY)
else:
ready, _, _ = select.select([proc.stdout, proc.stderr], [], [], 2)
if ready:
line = ready[0].readline()
if self.regex.search(line):
self.run_ended.set()
def stop(self):
self.stop_event.set()
self.join()
def wait_for_run_end(self, timeout):
self.run_ended.wait(timeout)
self.run_ended.clear()

View File

@@ -0,0 +1,158 @@
# 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,E0203
import re
import os
from wlauto import AndroidUiAutoBenchmark, Parameter, Alias
from wlauto.exceptions import ConfigError
import wlauto.common.android.resources
# These maps provide use-friendly aliases for the most common options.
USE_CASE_MAP = {
'egypt': 'GLBenchmark 2.5 Egypt HD',
'egypt-classic': 'GLBenchmark 2.1 Egypt Classic',
't-rex': 'GLBenchmark 2.7 T-Rex HD',
}
VARIANT_MAP = {
'onscreen': 'C24Z16 Onscreen Auto',
'offscreen': 'C24Z16 Offscreen Auto',
}
class Glb(AndroidUiAutoBenchmark):
name = 'glbenchmark'
description = """
Measures the graphics performance of Android devices by testing
the underlying OpenGL (ES) implementation.
http://gfxbench.com/about-gfxbench.jsp
From the website:
The benchmark includes console-quality high-level 3D animations
(T-Rex HD and Egypt HD) and low-level graphics measurements.
With high vertex count and complex effects such as motion blur, parallax
mapping and particle systems, the engine of GFXBench stresses GPUs in order
provide users a realistic feedback on their device.
"""
activity = 'com.glbenchmark.activities.GLBenchmarkDownloaderActivity'
view = 'com.glbenchmark.glbenchmark27/com.glbenchmark.activities.GLBRender'
packages = {
'2.7.0': 'com.glbenchmark.glbenchmark27',
'2.5.1': 'com.glbenchmark.glbenchmark25',
}
# If usecase is not specified the default usecase is the first supported usecase alias
# for the specified version.
supported_usecase_aliases = {
'2.7.0': ['t-rex', 'egypt'],
'2.5.1': ['egypt-classic', 'egypt'],
}
default_iterations = 1
install_timeout = 500
regex = re.compile(r'GLBenchmark (metric|FPS): (.*)')
parameters = [
Parameter('version', default='2.7.0', allowed_values=['2.7.0', '2.5.1'],
description=('Specifies which version of the benchmark to run (different versions '
'support different use cases).')),
Parameter('use_case', default=None,
description="""Specifies which usecase to run, as listed in the benchmark menu; e.g.
``'GLBenchmark 2.5 Egypt HD'``. For convenience, two aliases are provided
for the most common use cases: ``'egypt'`` and ``'t-rex'``. These could
be use instead of the full use case title. For version ``'2.7.0'`` it defaults
to ``'t-rex'``, for version ``'2.5.1'`` it defaults to ``'egypt-classic'``.
"""),
Parameter('variant', default='onscreen',
description="""Specifies which variant of the use case to run, as listed in the benchmarks
menu (small text underneath the use case name); e.g. ``'C24Z16 Onscreen Auto'``.
For convenience, two aliases are provided for the most common variants:
``'onscreen'`` and ``'offscreen'``. These may be used instead of full variant
names.
"""),
Parameter('times', kind=int, default=1,
description=('Specfies the number of times the benchmark will be run in a "tight '
'loop", i.e. without performaing setup/teardown inbetween.')),
Parameter('timeout', kind=int, default=200,
description="""Specifies how long, in seconds, UI automation will wait for results screen to
appear before assuming something went wrong.
"""),
]
aliases = [
Alias('glbench'),
Alias('egypt', use_case='egypt'),
Alias('t-rex', use_case='t-rex'),
Alias('egypt_onscreen', use_case='egypt', variant='onscreen'),
Alias('t-rex_onscreen', use_case='t-rex', variant='onscreen'),
Alias('egypt_offscreen', use_case='egypt', variant='offscreen'),
Alias('t-rex_offscreen', use_case='t-rex', variant='offscreen'),
]
def __init__(self, device, **kwargs):
super(Glb, self).__init__(device, **kwargs)
self.uiauto_params['version'] = self.version
if self.use_case is None:
self.use_case = self.supported_usecase_aliases[self.version][0]
if self.use_case.lower() in USE_CASE_MAP:
if self.use_case not in self.supported_usecase_aliases[self.version]:
raise ConfigError('usecases {} is not supported in version {}'.format(self.use_case, self.version))
self.use_case = USE_CASE_MAP[self.use_case.lower()]
self.uiauto_params['use_case'] = self.use_case.replace(' ', '_')
if self.variant.lower() in VARIANT_MAP:
self.variant = VARIANT_MAP[self.variant.lower()]
self.uiauto_params['variant'] = self.variant.replace(' ', '_')
self.uiauto_params['iterations'] = self.times
self.run_timeout = 4 * 60 * self.times
self.uiauto_params['timeout'] = self.timeout
self.package = self.packages[self.version]
def init_resources(self, context):
self.apk_file = context.resolver.get(wlauto.common.android.resources.ApkFile(self), version=self.version)
self.uiauto_file = context.resolver.get(wlauto.common.android.resources.JarFile(self))
self.device_uiauto_file = self.device.path.join(self.device.working_directory,
os.path.basename(self.uiauto_file))
if not self.uiauto_package:
self.uiauto_package = os.path.splitext(os.path.basename(self.uiauto_file))[0]
def update_result(self, context):
super(Glb, self).update_result(context)
match_count = 0
with open(self.logcat_log) as fh:
for line in fh:
match = self.regex.search(line)
if match:
metric = match.group(1)
value, units = match.group(2).split()
value = value.replace('*', '')
if metric == 'metric':
metric = 'Frames'
units = 'frames'
metric = metric + '_' + str(match_count // 2)
context.result.add_metric(metric, value, units)
match_count += 1

Some files were not shown because too many files have changed in this diff Show More