diff options
author | Chris Craik <ccraik@google.com> | 2011-07-28 15:39:43 -0700 |
---|---|---|
committer | Chris Craik <ccraik@google.com> | 2011-08-02 16:47:21 -0700 |
commit | 555c55ed65056e2236430f92e81c1fb6acd05dcd (patch) | |
tree | 6764ebe79aaa1e431d8aa7c4347176cc4333d08e | |
parent | 00451ed2d1f21945766bc0c59e762ef39cb391b8 (diff) | |
download | frameworks_base-555c55ed65056e2236430f92e81c1fb6acd05dcd.zip frameworks_base-555c55ed65056e2236430f92e81c1fb6acd05dcd.tar.gz frameworks_base-555c55ed65056e2236430f92e81c1fb6acd05dcd.tar.bz2 |
Added automated performance test to TileBenchmark
bug:5062896
Depends on external/webkit change:
https://android-git.corp.google.com/g/#change,125566
Loads pages from SD card, and scrolls through them reporting results. Added
contentInvalidateAll hidden WebView method, and made pageSwapCallback
extensible.
Change-Id: I9f7377aad6fd7c101177dde552a72357c8b4e400
13 files changed, 398 insertions, 129 deletions
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index f4fd551..7620a63 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -8405,9 +8405,9 @@ public class WebView extends AbsoluteLayout } } - // Called by JNI to invalidate the View, given rectangle coordinates in - // content space - private void pageSwapCallback() { + /** @hide Called by JNI when pages are swapped (only occurs with hardware + * acceleration) */ + protected void pageSwapCallback() { if (inEditingMode()) { didUpdateWebTextViewDimensions(ANYWHERE); } @@ -8426,11 +8426,11 @@ public class WebView extends AbsoluteLayout WebViewCore.ViewState viewState = draw.mViewState; boolean isPictureAfterFirstLayout = viewState != null; - // Request a callback on pageSwap (to reposition the webtextview) - boolean registerPageSwapCallback = - !mZoomManager.isFixedLengthAnimationInProgress() && inEditingMode(); - if (updateBaseLayer) { + // Request a callback on pageSwap (to reposition the webtextview) + boolean registerPageSwapCallback = + !mZoomManager.isFixedLengthAnimationInProgress() && inEditingMode(); + setBaseLayer(draw.mBaseLayer, draw.mInvalRegion, getSettings().getShowVisualIndicator(), isPictureAfterFirstLayout, registerPageSwapCallback); @@ -9084,6 +9084,16 @@ public class WebView extends AbsoluteLayout } } + /** @hide send content invalidate */ + protected void contentInvalidateAll() { + mWebViewCore.sendMessage(EventHub.CONTENT_INVALIDATE_ALL); + } + + /** @hide call pageSwapCallback upon next page swap */ + protected void registerPageSwapCallback() { + nativeRegisterPageSwapCallback(); + } + /** * Begin collecting per-tile profiling data * @@ -9245,6 +9255,7 @@ public class WebView extends AbsoluteLayout private native void nativeStopGL(); private native Rect nativeSubtractLayers(Rect content); private native int nativeTextGeneration(); + private native void nativeRegisterPageSwapCallback(); private native void nativeTileProfilingStart(); private native float nativeTileProfilingStop(); private native void nativeTileProfilingClear(); diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 8d8023b..400cdbd 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -999,6 +999,7 @@ public final class WebViewCore { static final int DUMP_V8COUNTERS = 173; static final int SET_JS_FLAGS = 174; + static final int CONTENT_INVALIDATE_ALL = 175; // Geolocation static final int GEOLOCATION_PERMISSIONS_PROVIDE = 180; @@ -1503,6 +1504,10 @@ public final class WebViewCore { nativeSetJsFlags((String)msg.obj); break; + case CONTENT_INVALIDATE_ALL: + nativeContentInvalidateAll(); + break; + case SAVE_WEBARCHIVE: WebView.SaveWebArchiveMessage saveMessage = (WebView.SaveWebArchiveMessage)msg.obj; diff --git a/tests/TileBenchmark/res/values/strings.xml b/tests/TileBenchmark/res/values/strings.xml index 66972ac..c4fd189 100644 --- a/tests/TileBenchmark/res/values/strings.xml +++ b/tests/TileBenchmark/res/values/strings.xml @@ -71,8 +71,16 @@ <string name="frames_per_second">Frames/sec</string> <!-- Portion of viewport covered by good tiles [CHAR LIMIT=15] --> <string name="viewport_coverage">Coverage</string> + <!-- Milliseconds taken to inval, and re-render the page [CHAR LIMIT=15] --> + <string name="render_millis">RenderMillis</string> <!-- Format string for stat value overlay [CHAR LIMIT=15] --> <string name="format_stat">%4.4f</string> + + <!-- Format string for viewport position value overlay [CHAR LIMIT=25] --> + <string name="format_view_pos">View:(%1$d,%2$d)-(%3$d,%4$d)</string> + <!-- Format string for viewport position value overlay [CHAR LIMIT=25] --> + <string name="format_inval_pos">Inval:(%1$d,%2$d)-(%3$d,%4$d)</string> + <!-- Format string for displaying aggregate stats+values (nr of valid tiles, etc.) [CHAR LIMIT=20] --> <string name="format_stat_name">%1$-20s %2$3d</string> diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java index 36694a7..1eb1c00 100644 --- a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java +++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java @@ -83,14 +83,14 @@ public class PlaybackActivity extends Activity { } }; - private class LoadFileTask extends AsyncTask<String, Void, TileData[][]> { + private class LoadFileTask extends AsyncTask<String, Void, RunData> { @Override - protected TileData[][] doInBackground(String... params) { - TileData[][] data = null; + protected RunData doInBackground(String... params) { + RunData data = null; try { FileInputStream fis = openFileInput(params[0]); ObjectInputStream in = new ObjectInputStream(fis); - data = (TileData[][]) in.readObject(); + data = (RunData) in.readObject(); in.close(); } catch (IOException ex) { ex.printStackTrace(); @@ -101,7 +101,7 @@ public class PlaybackActivity extends Activity { } @Override - protected void onPostExecute(TileData data[][]) { + protected void onPostExecute(RunData data) { if (data == null) { Toast.makeText(getApplicationContext(), getResources().getString(R.string.error_no_data), @@ -110,7 +110,7 @@ public class PlaybackActivity extends Activity { } mPlaybackView.setData(data); - mFrameMax = data.length - 1; + mFrameMax = data.frames.length - 1; mSeekBar.setMax(mFrameMax); setFrame(null, 0); diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java index 35b1563..aad138c 100644 --- a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java +++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java @@ -22,10 +22,12 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.ShapeDrawable; -import android.os.Bundle; + +import com.test.tilebenchmark.RunData.TileData; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; public class PlaybackGraphs { private static final int BAR_WIDTH = PlaybackView.TILE_SCALE * 3; @@ -44,7 +46,7 @@ public class PlaybackGraphs { return 0.0f; } - private interface MetricGen { + protected interface MetricGen { public double getValue(TileData[] frame); public double getMax(); @@ -52,7 +54,7 @@ public class PlaybackGraphs { public int getLabelId(); }; - private static MetricGen[] Metrics = new MetricGen[] { + protected static MetricGen[] Metrics = new MetricGen[] { new MetricGen() { // framerate graph @Override @@ -99,7 +101,7 @@ public class PlaybackGraphs { } }; - private interface StatGen { + protected interface StatGen { public double getValue(double sortedValues[]); public int getLabelId(); @@ -116,7 +118,7 @@ public class PlaybackGraphs { + sortedValues[intIndex + 1] * (alpha); } - private static StatGen[] Stats = new StatGen[] { + protected static StatGen[] Stats = new StatGen[] { new StatGen() { @Override public double getValue(double[] sortedValues) { @@ -157,21 +159,22 @@ public class PlaybackGraphs { } private ArrayList<ShapeDrawable> mShapes = new ArrayList<ShapeDrawable>(); - private double[][] mStats = new double[Metrics.length][Stats.length]; + protected double[][] mStats = new double[Metrics.length][Stats.length]; + protected HashMap<String, Double> mSingleStats; - public void setData(TileData[][] tileProfilingData) { + public void setData(RunData data) { mShapes.clear(); - double metricValues[] = new double[tileProfilingData.length]; + double metricValues[] = new double[data.frames.length]; - if (tileProfilingData.length == 0) { + if (data.frames.length == 0) { return; } for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) { // create graph out of rectangles, one per frame int lastBar = 0; - for (int frameIndex = 0; frameIndex < tileProfilingData.length; frameIndex++) { - TileData frame[] = tileProfilingData[frameIndex]; + for (int frameIndex = 0; frameIndex < data.frames.length; frameIndex++) { + TileData frame[] = data.frames[frameIndex]; int newBar = (frame[0].top + frame[0].bottom) / 2; MetricGen s = Metrics[metricIndex]; @@ -194,9 +197,11 @@ public class PlaybackGraphs { // store aggregate statistics per metric (median, and similar) Arrays.sort(metricValues); for (int statIndex = 0; statIndex < Stats.length; statIndex++) { - mStats[metricIndex][statIndex] = Stats[statIndex] - .getValue(metricValues); + mStats[metricIndex][statIndex] = + Stats[statIndex].getValue(metricValues); } + + mSingleStats = data.singleStats; } } @@ -215,7 +220,7 @@ public class PlaybackGraphs { } public void draw(Canvas canvas, ArrayList<ShapeDrawable> shapes, - String[] strings, Resources resources) { + ArrayList<String> strings, Resources resources) { canvas.scale(CANVAS_SCALE, CANVAS_SCALE); canvas.translate(BAR_WIDTH * Metrics.length, 0); @@ -238,26 +243,9 @@ public class PlaybackGraphs { canvas.drawText(label, xPos, yPos, whiteLabels); } } - for (int stringIndex = 0; stringIndex < strings.length; stringIndex++) { + for (int stringIndex = 0; stringIndex < strings.size(); stringIndex++) { int yPos = LABELOFFSET + stringIndex * PlaybackView.TILE_SCALE / 2; - canvas.drawText(strings[stringIndex], 0, yPos, whiteLabels); - } - } - - public Bundle getStatBundle(Resources resources) { - Bundle b = new Bundle(); - - 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()); - double value = mStats[metricIndex][statIndex]; - b.putDouble(metricLabel + " " + statLabel, value); - } + canvas.drawText(strings.get(stringIndex), 0, yPos, whiteLabels); } - - return b; } } diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java index edc8643..5459c1f 100644 --- a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java +++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java @@ -30,10 +30,12 @@ import android.view.GestureDetector.OnGestureListener; import android.view.MotionEvent; import android.view.View; +import com.test.tilebenchmark.RunData.TileData; + import java.util.ArrayList; public class PlaybackView extends View { - public static final int TILE_SCALE = 300; + public static final int TILE_SCALE = 256; private static final int INVAL_FLAG = -2; private static final int INVAL_CYCLE = 250; @@ -41,9 +43,9 @@ public class PlaybackView extends View { private PlaybackGraphs mGraphs; private ArrayList<ShapeDrawable> mTempShapes = new ArrayList<ShapeDrawable>(); - private TileData mProfData[][] = null; + private RunData mProfData = null; private GestureDetector mGestureDetector = null; - private String mRenderStrings[] = new String[4]; + private ArrayList<String> mRenderStrings = new ArrayList<String>(); private class TileDrawable extends ShapeDrawable { TileData tile; @@ -135,17 +137,30 @@ public class PlaybackView extends View { invalidate(); // may have animations, force redraw } + private String statString(int labelId, int value) { + return getResources().getString(R.string.format_stat_name, + getResources().getString(labelId), value); + } + private String tileString(int formatStringId, TileData t) { + return getResources().getString(formatStringId, + t.left, t.top, t.right, t.bottom); + } + public int setFrame(int frame) { - if (mProfData == null || mProfData.length == 0) { + if (mProfData == null || mProfData.frames.length == 0) { return 0; } int readyTiles = 0, unreadyTiles = 0, unplacedTiles = 0, numInvals = 0; mTempShapes.clear(); + mRenderStrings.clear(); // create tile shapes (as they're drawn on bottom) - for (TileData t : mProfData[frame]) { - if (t.level != INVAL_FLAG && t != mProfData[frame][0]) { + for (TileData t : mProfData.frames[frame]) { + if (t == mProfData.frames[frame][0]){ + // viewport 'tile', add coords to render strings + mRenderStrings.add(tileString(R.string.format_view_pos, t)); + } else if (t.level != INVAL_FLAG) { int colorId; if (t.isReady) { readyTiles++; @@ -159,14 +174,16 @@ public class PlaybackView extends View { } mTempShapes.add(new TileDrawable(t, colorId)); } else { + // inval 'tile', count and add coords to render strings numInvals++; + mRenderStrings.add(tileString(R.string.format_inval_pos, t)); } } // create invalidate shapes (drawn above tiles) int invalId = 0; - for (TileData t : mProfData[frame]) { - if (t.level == INVAL_FLAG && t != mProfData[frame][0]) { + for (TileData t : mProfData.frames[frame]) { + if (t.level == INVAL_FLAG && t != mProfData.frames[frame][0]) { TileDrawable invalShape = new TileDrawable(t, R.color.inval_region_start); ValueAnimator tileAnimator = ObjectAnimator.ofInt(invalShape, @@ -186,26 +203,20 @@ public class PlaybackView extends View { } } - mRenderStrings[0] = getResources().getString(R.string.format_stat_name, - getResources().getString(R.string.ready_tiles), readyTiles); - mRenderStrings[1] = getResources().getString(R.string.format_stat_name, - getResources().getString(R.string.unready_tiles), unreadyTiles); - mRenderStrings[2] = getResources().getString(R.string.format_stat_name, - getResources().getString(R.string.unplaced_tiles), - unplacedTiles); - mRenderStrings[3] = getResources().getString(R.string.format_stat_name, - getResources().getString(R.string.number_invalidates), - numInvals); + mRenderStrings.add(statString(R.string.ready_tiles, readyTiles)); + mRenderStrings.add(statString(R.string.unready_tiles, unreadyTiles)); + mRenderStrings.add(statString(R.string.unplaced_tiles, unplacedTiles)); + mRenderStrings.add(statString(R.string.number_invalidates, numInvals)); // draw view rect (using first TileData object, on top) - TileDrawable viewShape = new TileDrawable(mProfData[frame][0], + TileDrawable viewShape = new TileDrawable(mProfData.frames[frame][0], R.color.view); mTempShapes.add(viewShape); this.invalidate(); return frame; } - public void setData(TileData[][] tileProfilingData) { + public void setData(RunData tileProfilingData) { mProfData = tileProfilingData; mGraphs.setData(mProfData); diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java index 1521807..a63a2f0 100644 --- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java +++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java @@ -51,11 +51,11 @@ import java.io.ObjectOutputStream; public class ProfileActivity extends Activity { public interface ProfileCallback { - public void profileCallback(TileData data[][]); + public void profileCallback(RunData data); } public static final String TEMP_FILENAME = "profile.tiles"; - private static final int LOAD_TEST_DELAY = 2000; // nr of millis after load, + private static final int LOAD_TEST_DELAY = 1000; // nr of millis after load, // before test Button mInspectButton; @@ -135,6 +135,7 @@ public class ProfileActivity extends Activity { public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); view.requestFocus(); + new CountDownTimer(LOAD_TEST_DELAY, LOAD_TEST_DELAY) { @Override public void onTick(long millisUntilFinished) { @@ -155,10 +156,10 @@ public class ProfileActivity extends Activity { } private class StoreFileTask extends - AsyncTask<Pair<String, TileData[][]>, Void, Void> { + AsyncTask<Pair<String, RunData>, Void, Void> { @Override - protected Void doInBackground(Pair<String, TileData[][]>... params) { + protected Void doInBackground(Pair<String, RunData>... params) { try { FileOutputStream fos = openFileOutput(params[0].first, Context.MODE_PRIVATE); @@ -205,10 +206,8 @@ public class ProfileActivity extends Activity { /** auto - automatically scroll. */ private void startViewProfiling(boolean auto) { - if (!auto) { - // manual, toggle capture button to indicate capture state to user - mCaptureButton.setChecked(true); - } + // toggle capture button to indicate capture state to user + mCaptureButton.setChecked(true); mWeb.startScrollTest(mCallback, auto); setTestingState(TestingState.START_TESTING); } @@ -227,8 +226,8 @@ public class ProfileActivity extends Activity { mCallback = new ProfileCallback() { @SuppressWarnings("unchecked") @Override - public void profileCallback(TileData[][] data) { - new StoreFileTask().execute(new Pair<String, TileData[][]>( + public void profileCallback(RunData data) { + new StoreFileTask().execute(new Pair<String, RunData>( TEMP_FILENAME, data)); mCaptureButton.setChecked(false); setTestingState(TestingState.STOP_TESTING); diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java index d3941be..3fc4665 100644 --- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java +++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java @@ -18,15 +18,19 @@ package com.test.tilebenchmark; import android.content.Context; import android.util.AttributeSet; +import android.util.Log; import android.webkit.WebView; import com.test.tilebenchmark.ProfileActivity.ProfileCallback; +import com.test.tilebenchmark.RunData.TileData; public class ProfiledWebView extends WebView { private int mSpeed; + private boolean isTesting = false; private boolean isScrolling = false; private ProfileCallback mCallback; + private long mContentInvalMillis; public ProfiledWebView(Context context) { super(context); @@ -47,7 +51,7 @@ public class ProfiledWebView extends WebView { @Override protected void onDraw(android.graphics.Canvas canvas) { - if (isScrolling) { + if (isTesting && isScrolling) { if (canScrollVertically(1)) { scrollBy(0, mSpeed); } else { @@ -60,31 +64,53 @@ public class ProfiledWebView extends WebView { /* * Called once the page is loaded to start scrolling for evaluating tiles. - * If autoScrolling isn't set, stop must be called manually. + * If autoScrolling isn't set, stop must be called manually. Before + * scrolling, invalidate all content and redraw it, measuring time taken. */ public void startScrollTest(ProfileCallback callback, boolean autoScrolling) { isScrolling = autoScrolling; mCallback = callback; - tileProfilingStart(); + isTesting = false; + mContentInvalMillis = System.currentTimeMillis(); + registerPageSwapCallback(); + contentInvalidateAll(); invalidate(); } /* + * Called after the manual contentInvalidateAll, after the tiles have all + * been redrawn. + */ + @Override + protected void pageSwapCallback() { + mContentInvalMillis = System.currentTimeMillis() - mContentInvalMillis; + super.pageSwapCallback(); + Log.d("ProfiledWebView", "REDRAW TOOK " + mContentInvalMillis + + "millis"); + isTesting = true; + invalidate(); // ensure a redraw so that auto-scrolling can occur + tileProfilingStart(); + } + + /* * Called once the page has stopped scrolling */ public void stopScrollTest() { - super.tileProfilingStop(); + tileProfilingStop(); + isTesting = false; if (mCallback == null) { tileProfilingClear(); return; } - TileData data[][] = new TileData[super.tileProfilingNumFrames()][]; - for (int frame = 0; frame < data.length; frame++) { - data[frame] = new TileData[ + RunData data = new RunData(super.tileProfilingNumFrames()); + data.singleStats.put(getResources().getString(R.string.render_millis), + (double)mContentInvalMillis); + for (int frame = 0; frame < data.frames.length; frame++) { + data.frames[frame] = new TileData[ tileProfilingNumTilesInFrame(frame)]; - for (int tile = 0; tile < data[frame].length; tile++) { + for (int tile = 0; tile < data.frames[frame].length; tile++) { int left = tileProfilingGetInt(frame, tile, "left"); int top = tileProfilingGetInt(frame, tile, "top"); int right = tileProfilingGetInt(frame, tile, "right"); @@ -96,18 +122,18 @@ public class ProfiledWebView extends WebView { float scale = tileProfilingGetFloat(frame, tile, "scale"); - data[frame][tile] = new TileData(left, top, right, bottom, + data.frames[frame][tile] = data.new TileData(left, top, right, bottom, isReady, level, scale); } } - super.tileProfilingClear(); + tileProfilingClear(); mCallback.profileCallback(data); } @Override public void loadUrl(String url) { - if (!url.startsWith("http://")) { + if (!url.startsWith("http://") && !url.startsWith("file://")) { url = "http://" + url; } super.loadUrl(url); diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/RunData.java b/tests/TileBenchmark/src/com/test/tilebenchmark/RunData.java new file mode 100644 index 0000000..2da61cc --- /dev/null +++ b/tests/TileBenchmark/src/com/test/tilebenchmark/RunData.java @@ -0,0 +1,53 @@ +/* + * 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 java.io.Serializable; +import java.util.HashMap; + +public class RunData implements Serializable { + public TileData[][] frames; + public HashMap<String, Double> singleStats = new HashMap<String, Double>(); + + public RunData(int frames) { + this.frames = new TileData[frames][]; + } + + public class TileData implements Serializable { + public int left, top, right, bottom; + public boolean isReady; + public int level; + public float scale; + + public TileData(int left, int top, int right, int bottom, + boolean isReady, int level, float scale) { + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; + this.isReady = isReady; + this.level = level; + this.scale = scale; + } + + public String toString() { + return "Tile (" + left + "," + top + ")->(" + + right + "," + bottom + ")"; + } + } + +} diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java b/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java deleted file mode 100644 index 3e729a6..0000000 --- a/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 java.io.Serializable; - -public class TileData implements Serializable { - int left, top, right, bottom; - public boolean isReady; - public int level; - public float scale; - - public TileData(int left, int top, int right, int bottom, boolean isReady, - int level, float scale) { - this.left = left; - this.right = right; - this.top = top; - this.bottom = bottom; - this.isReady = isReady; - this.level = level; - this.scale = scale; - } - - public String toString() { - return "Tile (" + left + "," + top + ")->(" - + right + "," + bottom + ")"; - } -} diff --git a/tests/TileBenchmark/tests/Android.mk b/tests/TileBenchmark/tests/Android.mk new file mode 100644 index 0000000..8b235ec --- /dev/null +++ b/tests/TileBenchmark/tests/Android.mk @@ -0,0 +1,16 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# We only want this apk build for tests. +LOCAL_MODULE_TAGS := tests + +LOCAL_JAVA_LIBRARIES := android.test.runner + +# Include all test java files. +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := TileBenchmarkTests + +LOCAL_INSTRUMENTATION_FOR := TileBenchmark + +include $(BUILD_PACKAGE) diff --git a/tests/TileBenchmark/tests/AndroidManifest.xml b/tests/TileBenchmark/tests/AndroidManifest.xml new file mode 100644 index 0000000..703b152 --- /dev/null +++ b/tests/TileBenchmark/tests/AndroidManifest.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2008 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.test.tilebenchmark.tests"> + + <application> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="com.test.tilebenchmark" + android:label="Tests for WebView Tiles."/> +</manifest> diff --git a/tests/TileBenchmark/tests/src/com/test/tilebenchmark/PerformanceTest.java b/tests/TileBenchmark/tests/src/com/test/tilebenchmark/PerformanceTest.java new file mode 100644 index 0000000..0f02239 --- /dev/null +++ b/tests/TileBenchmark/tests/src/com/test/tilebenchmark/PerformanceTest.java @@ -0,0 +1,167 @@ +/* + * 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; + +public class PerformanceTest extends + ActivityInstrumentationTestCase2<ProfileActivity> { + + private class StatAggregator extends PlaybackGraphs { + private HashMap<String, Double> mDataMap = new HashMap<String, Double>(); + private int mCount = 0; + + public void aggregate() { + mCount++; + Resources resources = mView.getResources(); + 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); + } + } + for (Map.Entry<String, Double> e : mSingleStats.entrySet()) { + double aggVal = mDataMap.containsKey(e.getKey()) + ? mDataMap.get(e.getKey()) : 0; + mDataMap.put(e.getKey(), aggVal + e.getValue()); + } + } + + 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); + } + return b; + } + } + + ProfileActivity mActivity; + ProfiledWebView mView; + StatAggregator mStats = new StatAggregator(); + + 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 TEST_DIRS[] = { + "alexa_us"//, "android", "dom", "intl1", "intl2", "moz", "moz2" + }; + + public PerformanceTest() { + super(ProfileActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mActivity = getActivity(); + mView = (ProfiledWebView) mActivity.findViewById(R.id.web); + } + + private boolean loadUrl(final String url) { + try { + Log.d(LOGTAG, "test starting for url " + url); + mActivity.runOnUiThread(new Runnable() { + @Override + public void run() { + mView.loadUrl(url); + } + }); + synchronized (mStats) { + mStats.wait(); + } + mStats.aggregate(); + } catch (InterruptedException e) { + e.printStackTrace(); + return false; + } + return true; + } + + private boolean runIteration() { + File sdFile = Environment.getExternalStorageDirectory(); + for (String testDirName : TEST_DIRS) { + 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()) + continue; + + if (!loadUrl(URL_PREFIX + siteDir.getAbsolutePath() + + URL_POSTFIX)) { + return false; + } + } + } + return true; + } + + public void testMetrics() { + 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; + } + + // use mGraphs as a condition variable between the UI thread and + // this(the testing) thread + mActivity.setCallback(new ProfileCallback() { + @Override + public void profileCallback(RunData data) { + Log.d(LOGTAG, "test completion callback"); + mStats.setData(data); + synchronized (mStats) { + mStats.notify(); + } + } + }); + + for (int i = 0; i < MAX_ITERATIONS; i++) + if (!runIteration()) { + getInstrumentation().sendStatus(1, null); + return; + } + getInstrumentation().sendStatus(0, mStats.getBundle()); + } +} |