2727import android .os .Environment ;
2828import android .test .ActivityInstrumentationTestCase2 ;
2929import android .util .Log ;
30+ import android .webkit .WebSettings ;
31+ import android .widget .Spinner ;
3032
3133public class PerformanceTest extends
3234 ActivityInstrumentationTestCase2 <ProfileActivity > {
3335
36+ public static class AnimStat {
37+ double aggVal = 0 ;
38+ double aggSqrVal = 0 ;
39+ double count = 0 ;
40+ }
41+
3442 private class StatAggregator extends PlaybackGraphs {
3543 private HashMap <String , Double > mDataMap = new HashMap <String , Double >();
44+ private HashMap <String , AnimStat > mAnimDataMap = new HashMap <String , AnimStat >();
3645 private int mCount = 0 ;
3746
47+
3848 public void aggregate () {
49+ boolean inAnimTests = mAnimTests != null ;
50+ Resources resources = mWeb .getResources ();
51+ String animFramerateString = resources .getString (R .string .animation_framerate );
52+ for (Map .Entry <String , Double > e : mSingleStats .entrySet ()) {
53+ String name = e .getKey ();
54+ if (inAnimTests ) {
55+ if (name .equals (animFramerateString )) {
56+ // in animation testing phase, record animation framerate and aggregate
57+ // stats, differentiating on values of mAnimTestNr and mDoubleBuffering
58+ String fullName = ANIM_TEST_NAMES [mAnimTestNr ] + " " + name ;
59+ fullName += mDoubleBuffering ? " tiled" : " webkit" ;
60+
61+ if (!mAnimDataMap .containsKey (fullName )) {
62+ mAnimDataMap .put (fullName , new AnimStat ());
63+ }
64+ AnimStat statVals = mAnimDataMap .get (fullName );
65+ statVals .aggVal += e .getValue ();
66+ statVals .aggSqrVal += e .getValue () * e .getValue ();
67+ statVals .count += 1 ;
68+ }
69+ } else {
70+ double aggVal = mDataMap .containsKey (name )
71+ ? mDataMap .get (name ) : 0 ;
72+ mDataMap .put (name , aggVal + e .getValue ());
73+ }
74+ }
75+
76+ if (inAnimTests ) {
77+ return ;
78+ }
79+
3980 mCount ++;
40- Resources resources = mView .getResources ();
4181 for (int metricIndex = 0 ; metricIndex < Metrics .length ; metricIndex ++) {
4282 for (int statIndex = 0 ; statIndex < Stats .length ; statIndex ++) {
4383 String metricLabel = resources .getString (
@@ -53,34 +93,47 @@ public void aggregate() {
5393 mDataMap .put (label , aggVal );
5494 }
5595 }
56- for (Map .Entry <String , Double > e : mSingleStats .entrySet ()) {
57- double aggVal = mDataMap .containsKey (e .getKey ())
58- ? mDataMap .get (e .getKey ()) : 0 ;
59- mDataMap .put (e .getKey (), aggVal + e .getValue ());
60- }
96+
6197 }
6298
99+ // build the final bundle of results
63100 public Bundle getBundle () {
64101 Bundle b = new Bundle ();
65- int count = 0 == mCount ? Integer .MAX_VALUE : mCount ;
102+ int count = ( 0 == mCount ) ? Integer .MAX_VALUE : mCount ;
66103 for (Map .Entry <String , Double > e : mDataMap .entrySet ()) {
67104 b .putDouble (e .getKey (), e .getValue () / count );
68105 }
106+
107+ for (Map .Entry <String , AnimStat > e : mAnimDataMap .entrySet ()) {
108+ String statName = e .getKey ();
109+ AnimStat statVals = e .getValue ();
110+
111+ double avg = statVals .aggVal /statVals .count ;
112+ double stdDev = Math .sqrt ((statVals .aggSqrVal / statVals .count ) - avg * avg );
113+
114+ b .putDouble (statName , avg );
115+ b .putDouble (statName + " STD DEV" , stdDev );
116+ }
117+
69118 return b ;
70119 }
71120 }
72121
73122 ProfileActivity mActivity ;
74- ProfiledWebView mView ;
75- StatAggregator mStats = new StatAggregator ();
123+ ProfiledWebView mWeb ;
124+ Spinner mMovementSpinner ;
125+ StatAggregator mStats ;
76126
77127 private static final String LOGTAG = "PerformanceTest" ;
78128 private static final String TEST_LOCATION = "webkit/page_cycler" ;
79129 private static final String URL_PREFIX = "file://" ;
80130 private static final String URL_POSTFIX = "/index.html?skip=true" ;
81131 private static final int MAX_ITERATIONS = 4 ;
82- private static final String TEST_DIRS [] = {
83- "alexa25_2011" //, "alexa_us", "android", "dom", "intl2", "moz", "moz2"
132+ private static final String SCROLL_TEST_DIRS [] = {
133+ "alexa25_2011"
134+ };
135+ private static final String ANIM_TEST_DIRS [] = {
136+ "dhtml"
84137 };
85138
86139 public PerformanceTest () {
@@ -91,7 +144,22 @@ public PerformanceTest() {
91144 protected void setUp () throws Exception {
92145 super .setUp ();
93146 mActivity = getActivity ();
94- mView = (ProfiledWebView ) mActivity .findViewById (R .id .web );
147+ mWeb = (ProfiledWebView ) mActivity .findViewById (R .id .web );
148+ mMovementSpinner = (Spinner ) mActivity .findViewById (R .id .movement );
149+ mStats = new StatAggregator ();
150+
151+ // use mStats as a condition variable between the UI thread and
152+ // this(the testing) thread
153+ mActivity .setCallback (new ProfileCallback () {
154+ @ Override
155+ public void profileCallback (RunData data ) {
156+ mStats .setData (data );
157+ synchronized (mStats ) {
158+ mStats .notify ();
159+ }
160+ }
161+ });
162+
95163 }
96164
97165 private boolean loadUrl (final String url ) {
@@ -100,12 +168,13 @@ private boolean loadUrl(final String url) {
100168 mActivity .runOnUiThread (new Runnable () {
101169 @ Override
102170 public void run () {
103- mView .loadUrl (url );
171+ mWeb .loadUrl (url );
104172 }
105173 });
106174 synchronized (mStats ) {
107175 mStats .wait ();
108176 }
177+
109178 mStats .aggregate ();
110179 } catch (InterruptedException e ) {
111180 e .printStackTrace ();
@@ -114,15 +183,30 @@ public void run() {
114183 return true ;
115184 }
116185
117- private boolean runIteration () {
186+ private boolean validTest (String nextTest ) {
187+ // if testing animations, test must be in mAnimTests
188+ if (mAnimTests == null )
189+ return true ;
190+
191+ for (String test : mAnimTests ) {
192+ if (test .equals (nextTest )) {
193+ return true ;
194+ }
195+ }
196+ return false ;
197+ }
198+
199+ private boolean runIteration (String [] testDirs ) {
118200 File sdFile = Environment .getExternalStorageDirectory ();
119- for (String testDirName : TEST_DIRS ) {
201+ for (String testDirName : testDirs ) {
120202 File testDir = new File (sdFile , TEST_LOCATION + "/" + testDirName );
121203 Log .d (LOGTAG , "Testing dir: '" + testDir .getAbsolutePath ()
122204 + "', exists=" + testDir .exists ());
205+
123206 for (File siteDir : testDir .listFiles ()) {
124- if (!siteDir .isDirectory ())
207+ if (!siteDir .isDirectory () || ! validTest ( siteDir . getName ())) {
125208 continue ;
209+ }
126210
127211 if (!loadUrl (URL_PREFIX + siteDir .getAbsolutePath ()
128212 + URL_POSTFIX )) {
@@ -133,35 +217,88 @@ private boolean runIteration() {
133217 return true ;
134218 }
135219
136- public void testMetrics () {
220+ private boolean runTestDirs (String [] testDirs ) {
221+ for (int i = 0 ; i < MAX_ITERATIONS ; i ++)
222+ if (!runIteration (testDirs )) {
223+ return false ;
224+ }
225+ return true ;
226+ }
227+
228+ private void pushDoubleBuffering () {
229+ getInstrumentation ().runOnMainSync (new Runnable () {
230+ public void run () {
231+ mWeb .setDoubleBuffering (mDoubleBuffering );
232+ }
233+ });
234+ }
235+
236+ private void setScrollingTestingMode (final boolean scrolled ) {
237+ getInstrumentation ().runOnMainSync (new Runnable () {
238+ public void run () {
239+ mMovementSpinner .setSelection (scrolled ? 0 : 2 );
240+ }
241+ });
242+ }
243+
244+
245+ private String [] mAnimTests = null ;
246+ private int mAnimTestNr = -1 ;
247+ private boolean mDoubleBuffering = true ;
248+ private static final String [] ANIM_TEST_NAMES = {
249+ "slow" , "fast"
250+ };
251+ private static final String [][] ANIM_TESTS = {
252+ {"scrolling" , "replaceimages" , "layers5" , "layers1" },
253+ {"slidingballs" , "meter" , "slidein" , "fadespacing" , "colorfade" ,
254+ "mozilla" , "movingtext" , "diagball" , "zoom" , "imageslide" },
255+ };
256+
257+ private boolean checkMedia () {
137258 String state = Environment .getExternalStorageState ();
138259
139260 if (!Environment .MEDIA_MOUNTED .equals (state )
140261 && !Environment .MEDIA_MOUNTED_READ_ONLY .equals (state )) {
141262 Log .d (LOGTAG , "ARG Can't access sd card!" );
142263 // Can't read the SD card, fail and die!
143264 getInstrumentation ().sendStatus (1 , null );
144- return ;
265+ return false ;
145266 }
267+ return true ;
268+ }
146269
147- // use mGraphs as a condition variable between the UI thread and
148- // this(the testing) thread
149- mActivity .setCallback (new ProfileCallback () {
150- @ Override
151- public void profileCallback (RunData data ) {
152- Log .d (LOGTAG , "test completion callback" );
153- mStats .setData (data );
154- synchronized (mStats ) {
155- mStats .notify ();
270+ public void testMetrics () {
271+ setScrollingTestingMode (true );
272+ if (checkMedia () && runTestDirs (SCROLL_TEST_DIRS )) {
273+ getInstrumentation ().sendStatus (0 , mStats .getBundle ());
274+ } else {
275+ getInstrumentation ().sendStatus (1 , null );
276+ }
277+ }
278+
279+ private boolean runAnimationTests () {
280+ for (int doubleBuffer = 0 ; doubleBuffer <= 1 ; doubleBuffer ++) {
281+ mDoubleBuffering = doubleBuffer == 1 ;
282+ pushDoubleBuffering ();
283+ for (mAnimTestNr = 0 ; mAnimTestNr < ANIM_TESTS .length ; mAnimTestNr ++) {
284+ mAnimTests = ANIM_TESTS [mAnimTestNr ];
285+ if (!runTestDirs (ANIM_TEST_DIRS )) {
286+ return false ;
156287 }
157288 }
158- });
289+ }
290+ return true ;
291+ }
159292
160- for (int i = 0 ; i < MAX_ITERATIONS ; i ++)
161- if (!runIteration ()) {
162- getInstrumentation ().sendStatus (1 , null );
163- return ;
164- }
165- getInstrumentation ().sendStatus (0 , mStats .getBundle ());
293+ public void testAnimations () {
294+ // instead of autoscrolling, load each page until either an timer fires,
295+ // or the animation signals complete via javascript
296+ setScrollingTestingMode (false );
297+
298+ if (checkMedia () && runAnimationTests ()) {
299+ getInstrumentation ().sendStatus (0 , mStats .getBundle ());
300+ } else {
301+ getInstrumentation ().sendStatus (1 , null );
302+ }
166303 }
167304}
0 commit comments