1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.test.tilebenchmark; 18 19 import android.content.Context; 20 import android.os.CountDownTimer; 21 import android.util.AttributeSet; 22 import android.util.Log; 23 import android.webkit.WebView; 24 25 import com.test.tilebenchmark.ProfileActivity.ProfileCallback; 26 import com.test.tilebenchmark.RunData.TileData; 27 28 public class ProfiledWebView extends WebView { 29 private int mSpeed; 30 31 private boolean mIsTesting = false; 32 private boolean mIsScrolling = false; 33 private ProfileCallback mCallback; 34 private long mContentInvalMillis; 35 private boolean mHadToBeForced = false; 36 private int mTestCount = 0; 37 private static final int LOAD_STALL_MILLIS = 5000; // nr of millis after load, 38 // before test is forced 39 40 public ProfiledWebView(Context context) { 41 super(context); 42 } 43 44 public ProfiledWebView(Context context, AttributeSet attrs) { 45 super(context, attrs); 46 } 47 48 public ProfiledWebView(Context context, AttributeSet attrs, int defStyle) { 49 super(context, attrs, defStyle); 50 } 51 52 public ProfiledWebView(Context context, AttributeSet attrs, int defStyle, 53 boolean privateBrowsing) { 54 super(context, attrs, defStyle, privateBrowsing); 55 } 56 57 @Override 58 protected void onDraw(android.graphics.Canvas canvas) { 59 if (mIsTesting && mIsScrolling) { 60 if (canScrollVertically(1)) { 61 scrollBy(0, mSpeed); 62 } else { 63 stopScrollTest(); 64 mIsScrolling = false; 65 } 66 } 67 super.onDraw(canvas); 68 } 69 70 /* 71 * Called once the page is loaded to start scrolling for evaluating tiles. 72 * If autoScrolling isn't set, stop must be called manually. Before 73 * scrolling, invalidate all content and redraw it, measuring time taken. 74 */ 75 public void startScrollTest(ProfileCallback callback, boolean autoScrolling) { 76 mIsScrolling = autoScrolling; 77 mCallback = callback; 78 mIsTesting = false; 79 mContentInvalMillis = System.currentTimeMillis(); 80 registerPageSwapCallback(); 81 contentInvalidateAll(); 82 invalidate(); 83 84 mTestCount++; 85 final int testCount = mTestCount; 86 87 if (autoScrolling) { 88 // after a while, force it to start even if the pages haven't swapped 89 new CountDownTimer(LOAD_STALL_MILLIS, LOAD_STALL_MILLIS) { 90 @Override 91 public void onTick(long millisUntilFinished) { 92 } 93 94 @Override 95 public void onFinish() { 96 if (testCount == mTestCount && !mIsTesting) { 97 mHadToBeForced = true; 98 Log.d("ProfiledWebView", "num " + testCount 99 + " forcing a page swap with a scroll..."); 100 scrollBy(0, 1); 101 invalidate(); // ensure a redraw so that auto-scrolling can occur 102 } 103 } 104 }.start(); 105 } 106 } 107 108 /* 109 * Called after the manual contentInvalidateAll, after the tiles have all 110 * been redrawn. 111 */ 112 @Override 113 protected void pageSwapCallback() { 114 mContentInvalMillis = System.currentTimeMillis() - mContentInvalMillis; 115 super.pageSwapCallback(); 116 Log.d("ProfiledWebView", "REDRAW TOOK " + mContentInvalMillis 117 + "millis"); 118 mIsTesting = true; 119 invalidate(); // ensure a redraw so that auto-scrolling can occur 120 tileProfilingStart(); 121 } 122 123 /* 124 * Called once the page has stopped scrolling 125 */ 126 public void stopScrollTest() { 127 tileProfilingStop(); 128 mIsTesting = false; 129 130 if (mCallback == null) { 131 tileProfilingClear(); 132 return; 133 } 134 135 RunData data = new RunData(super.tileProfilingNumFrames()); 136 // record the time spent (before scrolling) rendering the page 137 data.singleStats.put(getResources().getString(R.string.render_millis), 138 (double)mContentInvalMillis); 139 // record if the page render timed out 140 Log.d("ProfiledWebView", "hadtobeforced = " + mHadToBeForced); 141 data.singleStats.put(getResources().getString(R.string.render_stalls), 142 mHadToBeForced ? 1.0 : 0.0); 143 mHadToBeForced = false; 144 145 for (int frame = 0; frame < data.frames.length; frame++) { 146 data.frames[frame] = new TileData[ 147 tileProfilingNumTilesInFrame(frame)]; 148 for (int tile = 0; tile < data.frames[frame].length; tile++) { 149 int left = tileProfilingGetInt(frame, tile, "left"); 150 int top = tileProfilingGetInt(frame, tile, "top"); 151 int right = tileProfilingGetInt(frame, tile, "right"); 152 int bottom = tileProfilingGetInt(frame, tile, "bottom"); 153 154 boolean isReady = super.tileProfilingGetInt( 155 frame, tile, "isReady") == 1; 156 int level = tileProfilingGetInt(frame, tile, "level"); 157 158 float scale = tileProfilingGetFloat(frame, tile, "scale"); 159 160 data.frames[frame][tile] = data.new TileData(left, top, right, bottom, 161 isReady, level, scale); 162 } 163 } 164 tileProfilingClear(); 165 166 mCallback.profileCallback(data); 167 } 168 169 @Override 170 public void loadUrl(String url) { 171 if (!url.startsWith("http://") && !url.startsWith("file://")) { 172 url = "http://" + url; 173 } 174 super.loadUrl(url); 175 } 176 177 public void setAutoScrollSpeed(int speedInt) { 178 mSpeed = speedInt; 179 } 180 } 181