blob: 5763ad3903c17202f66b619e5333f1d6427717a3 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* 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.test.tilebenchmark;
import com.test.tilebenchmark.ProfileActivity.ProfileCallback;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Environment;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import android.webkit.WebSettings;
import android.widget.Spinner;
public class PerformanceTest extends
ActivityInstrumentationTestCase2<ProfileActivity> {
public static class AnimStat {
double aggVal = 0;
double aggSqrVal = 0;
double count = 0;
}
private class StatAggregator extends PlaybackGraphs {
private HashMap<String, Double> mDataMap = new HashMap<String, Double>();
private HashMap<String, AnimStat> mAnimDataMap = new HashMap<String, AnimStat>();
private int mCount = 0;
public void aggregate() {
boolean inAnimTests = mAnimTests != null;
Resources resources = mWeb.getResources();
String animFramerateString = resources.getString(R.string.animation_framerate);
for (Map.Entry<String, Double> e : mSingleStats.entrySet()) {
String name = e.getKey();
if (inAnimTests) {
if (name.equals(animFramerateString)) {
// in animation testing phase, record animation framerate and aggregate
// stats, differentiating on values of mAnimTestNr and mDoubleBuffering
String fullName = ANIM_TEST_NAMES[mAnimTestNr] + " " + name;
fullName += mDoubleBuffering ? " tiled" : " webkit";
if (!mAnimDataMap.containsKey(fullName)) {
mAnimDataMap.put(fullName, new AnimStat());
}
AnimStat statVals = mAnimDataMap.get(fullName);
statVals.aggVal += e.getValue();
statVals.aggSqrVal += e.getValue() * e.getValue();
statVals.count += 1;
}
} else {
double aggVal = mDataMap.containsKey(name)
? mDataMap.get(name) : 0;
mDataMap.put(name, aggVal + e.getValue());
}
}
if (inAnimTests) {
return;
}
mCount++;
for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) {
for (int statIndex = 0; statIndex < Stats.length; statIndex++) {
String metricLabel = resources.getString(
Metrics[metricIndex].getLabelId());
String statLabel = resources.getString(
Stats[statIndex].getLabelId());
String label = metricLabel + " " + statLabel;
double aggVal = mDataMap.containsKey(label) ? mDataMap
.get(label) : 0;
aggVal += mStats[metricIndex][statIndex];
mDataMap.put(label, aggVal);
}
}
}
// build the final bundle of results
public Bundle getBundle() {
Bundle b = new Bundle();
int count = (0 == mCount) ? Integer.MAX_VALUE : mCount;
for (Map.Entry<String, Double> e : mDataMap.entrySet()) {
b.putDouble(e.getKey(), e.getValue() / count);
}
for (Map.Entry<String, AnimStat> e : mAnimDataMap.entrySet()) {
String statName = e.getKey();
AnimStat statVals = e.getValue();
double avg = statVals.aggVal/statVals.count;
double stdDev = Math.sqrt((statVals.aggSqrVal / statVals.count) - avg * avg);
b.putDouble(statName, avg);
b.putDouble(statName + " STD DEV", stdDev);
}
return b;
}
}
ProfileActivity mActivity;
ProfiledWebView mWeb;
Spinner mMovementSpinner;
StatAggregator mStats;
private static final String LOGTAG = "PerformanceTest";
private static final String TEST_LOCATION = "webkit/page_cycler";
private static final String URL_PREFIX = "file://";
private static final String URL_POSTFIX = "/index.html?skip=true";
private static final int MAX_ITERATIONS = 4;
private static final String SCROLL_TEST_DIRS[] = {
"alexa25_2011"
};
private static final String ANIM_TEST_DIRS[] = {
"dhtml"
};
public PerformanceTest() {
super(ProfileActivity.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
mActivity = getActivity();
mWeb = (ProfiledWebView) mActivity.findViewById(R.id.web);
mMovementSpinner = (Spinner) mActivity.findViewById(R.id.movement);
mStats = new StatAggregator();
// use mStats as a condition variable between the UI thread and
// this(the testing) thread
mActivity.setCallback(new ProfileCallback() {
@Override
public void profileCallback(RunData data) {
mStats.setData(data);
synchronized (mStats) {
mStats.notify();
}
}
});
}
private boolean loadUrl(final String url) {
try {
Log.d(LOGTAG, "test starting for url " + url);
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mWeb.loadUrl(url);
}
});
synchronized (mStats) {
mStats.wait();
}
mStats.aggregate();
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
return true;
}
private boolean validTest(String nextTest) {
// if testing animations, test must be in mAnimTests
if (mAnimTests == null)
return true;
for (String test : mAnimTests) {
if (test.equals(nextTest)) {
return true;
}
}
return false;
}
private boolean runIteration(String[] testDirs) {
File sdFile = Environment.getExternalStorageDirectory();
for (String testDirName : testDirs) {
File testDir = new File(sdFile, TEST_LOCATION + "/" + testDirName);
Log.d(LOGTAG, "Testing dir: '" + testDir.getAbsolutePath()
+ "', exists=" + testDir.exists());
for (File siteDir : testDir.listFiles()) {
if (!siteDir.isDirectory() || !validTest(siteDir.getName())) {
continue;
}
if (!loadUrl(URL_PREFIX + siteDir.getAbsolutePath()
+ URL_POSTFIX)) {
return false;
}
}
}
return true;
}
private boolean runTestDirs(String[] testDirs) {
for (int i = 0; i < MAX_ITERATIONS; i++)
if (!runIteration(testDirs)) {
return false;
}
return true;
}
private void pushDoubleBuffering() {
getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
mWeb.setDoubleBuffering(mDoubleBuffering);
}
});
}
private void setScrollingTestingMode(final boolean scrolled) {
getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
mMovementSpinner.setSelection(scrolled ? 0 : 2);
}
});
}
private String[] mAnimTests = null;
private int mAnimTestNr = -1;
private boolean mDoubleBuffering = true;
private static final String[] ANIM_TEST_NAMES = {
"slow", "fast"
};
private static final String[][] ANIM_TESTS = {
{"scrolling", "replaceimages", "layers5", "layers1"},
{"slidingballs", "meter", "slidein", "fadespacing", "colorfade",
"mozilla", "movingtext", "diagball", "zoom", "imageslide"},
};
private boolean checkMedia() {
String state = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(state)
&& !Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
Log.d(LOGTAG, "ARG Can't access sd card!");
// Can't read the SD card, fail and die!
getInstrumentation().sendStatus(1, null);
return false;
}
return true;
}
public void testMetrics() {
setScrollingTestingMode(true);
if (checkMedia() && runTestDirs(SCROLL_TEST_DIRS)) {
getInstrumentation().sendStatus(0, mStats.getBundle());
} else {
getInstrumentation().sendStatus(1, null);
}
}
public void testMetricsMinimalMemory() {
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mWeb.setUseMinimalMemory(true);
}
});
setScrollingTestingMode(true);
if (checkMedia() && runTestDirs(SCROLL_TEST_DIRS)) {
getInstrumentation().sendStatus(0, mStats.getBundle());
} else {
getInstrumentation().sendStatus(1, null);
}
}
private boolean runAnimationTests() {
for (int doubleBuffer = 0; doubleBuffer <= 1; doubleBuffer++) {
mDoubleBuffering = doubleBuffer == 1;
pushDoubleBuffering();
for (mAnimTestNr = 0; mAnimTestNr < ANIM_TESTS.length; mAnimTestNr++) {
mAnimTests = ANIM_TESTS[mAnimTestNr];
if (!runTestDirs(ANIM_TEST_DIRS)) {
return false;
}
}
}
return true;
}
public void testAnimations() {
// instead of autoscrolling, load each page until either an timer fires,
// or the animation signals complete via javascript
setScrollingTestingMode(false);
if (checkMedia() && runAnimationTests()) {
getInstrumentation().sendStatus(0, mStats.getBundle());
} else {
getInstrumentation().sendStatus(1, null);
}
}
}