Added TileBenchmark
Adds TileBenchmark app, which loads pages in webview and scrolls through them automatically, measuring rendering and allocation information. Change-Id: Ieaf5bbcec604c99aaf16822915e58bfc495011ec
This commit is contained in:
32
tests/TileBenchmark/Android.mk
Normal file
32
tests/TileBenchmark/Android.mk
Normal file
@@ -0,0 +1,32 @@
|
||||
# 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.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := TileBenchmark
|
||||
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
##################################################
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
include $(BUILD_MULTI_PREBUILT)
|
||||
|
||||
# Use the folloing include to make our test apk.
|
||||
include $(call all-makefiles-under,$(LOCAL_PATH))
|
||||
20
tests/TileBenchmark/AndroidManifest.xml
Normal file
20
tests/TileBenchmark/AndroidManifest.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" package="com.test.tilebenchmark">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<application android:icon="@drawable/icon"
|
||||
android:label="@string/app_name"
|
||||
android:hardwareAccelerated="true">
|
||||
<activity android:name=".ProfileActivity"
|
||||
android:label="@string/profile_activity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".PlaybackActivity"
|
||||
android:label="@string/playback_activity">
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
BIN
tests/TileBenchmark/res/drawable-hdpi/icon.png
Normal file
BIN
tests/TileBenchmark/res/drawable-hdpi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
BIN
tests/TileBenchmark/res/drawable-ldpi/icon.png
Normal file
BIN
tests/TileBenchmark/res/drawable-ldpi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
tests/TileBenchmark/res/drawable-mdpi/icon.png
Normal file
BIN
tests/TileBenchmark/res/drawable-mdpi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
53
tests/TileBenchmark/res/layout/main.xml
Normal file
53
tests/TileBenchmark/res/layout/main.xml
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
>
|
||||
<LinearLayout
|
||||
android:id="@+id/top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
<Button
|
||||
android:id="@+id/inspect"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/inspect_log"
|
||||
/>
|
||||
<Spinner
|
||||
android:id="@+id/velocity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:prompt="@string/desired_scroll_velocity"
|
||||
/>
|
||||
<EditText
|
||||
android:id="@+id/url"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textUri"
|
||||
android:imeOptions="actionGo"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<com.test.tilebenchmark.ProfiledWebView
|
||||
android:id="@+id/web"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
</LinearLayout>
|
||||
58
tests/TileBenchmark/res/layout/playback.xml
Normal file
58
tests/TileBenchmark/res/layout/playback.xml
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
>
|
||||
<LinearLayout
|
||||
android:id="@+id/top"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
<Button
|
||||
android:id="@+id/backward"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/backward"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/frame_display"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
<Button
|
||||
android:id="@+id/forward"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/forward"
|
||||
/>
|
||||
<SeekBar
|
||||
android:id="@+id/seek_bar"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="10"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<com.test.tilebenchmark.PlaybackView
|
||||
android:id="@+id/playback"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
</LinearLayout>
|
||||
25
tests/TileBenchmark/res/values/colors.xml
Normal file
25
tests/TileBenchmark/res/values/colors.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
<resources>
|
||||
<!-- The color of tiles with valid textures -->
|
||||
<color name="ready_tile">#ff4ac230</color>
|
||||
<!-- The color of tiles with stale / invalid textures -->
|
||||
<color name="unready_tile">#ff744400</color>
|
||||
<!-- Background color for logged URLs -->
|
||||
<color name="finished_url">#ff004000</color>
|
||||
<!-- Background color for URLs with logging in progress -->
|
||||
<color name="unfinished_url">#ff400000</color>
|
||||
</resources>
|
||||
67
tests/TileBenchmark/res/values/strings.xml
Normal file
67
tests/TileBenchmark/res/values/strings.xml
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
<resources>
|
||||
<!-- Button, steps back a single frame [CHAR LIMIT=15] -->
|
||||
<string name="backward">Backward</string>
|
||||
<!-- Button, steps forward a single frame [CHAR LIMIT=15] -->
|
||||
<string name="forward">Forward</string>
|
||||
<!-- The name of the application [CHAR LIMIT=20] -->
|
||||
<string name="app_name">TileBenchmark</string>
|
||||
<!-- name of the auto-scroller / tile logger activity [CHAR LIMIT=100] -->
|
||||
<string name="profile_activity">Webview Profiler</string>
|
||||
<!-- name of the tile log playback activity [CHAR LIMIT=100] -->
|
||||
<string name="playback_activity">Webview Tile Playback</string>
|
||||
<!-- Button, loads another tile log [CHAR LIMIT=30] -->
|
||||
<string name="loadbutton">Load</string>
|
||||
<!-- Button, opens the playback activity [CHAR LIMIT=20] -->
|
||||
<string name="inspect_log">Inspect Log</string>
|
||||
<!-- The speed of auto-scrolling [CHAR LIMIT=30] -->
|
||||
<string name="desired_scroll_velocity">Choose Scroll Velocity</string>
|
||||
<!-- Pixels moved per frame [CHAR LIMIT=10] -->
|
||||
<string-array name="velocity_array">
|
||||
<item>1</item>
|
||||
<item>25</item>
|
||||
<item>50</item>
|
||||
<item>100</item>
|
||||
<item>200</item>
|
||||
<item>400</item>
|
||||
</string-array>
|
||||
<!-- 25th percentile - 25% of frames fall below this value [CHAR LIMIT=12]
|
||||
-->
|
||||
<string name="percentile_25">25%ile</string>
|
||||
<!-- 50th percentile - 50% of frames fall below this value (aka median)
|
||||
[CHAR LIMIT=12] -->
|
||||
<string name="percentile_50">median</string>
|
||||
<!-- 75th percentile - 75% of frames fall below this value [CHAR LIMIT=12]
|
||||
-->
|
||||
<string name="percentile_75">75%ile</string>
|
||||
<!-- Frame rate [CHAR LIMIT=15] -->
|
||||
<string name="frames_per_second">Frames/sec</string>
|
||||
<!-- Portion of viewport covered by good tiles [CHAR LIMIT=15] -->
|
||||
<string name="viewport_coverage">Coverage</string>
|
||||
<!-- Format string for stat value overlay [CHAR LIMIT=15] -->
|
||||
<string name="format_stat">%4.4f</string>
|
||||
<!-- Format string for displaying aggregate stats+values (nr of valid tiles,
|
||||
etc.) [CHAR LIMIT=20] -->
|
||||
<string name="format_stat_name">%1$9s %2$3d</string>
|
||||
<!-- Text hovering over canvas, number of tiles ready [CHAR LIMIT=15] -->
|
||||
<string name="ready_tiles">Ready Tiles</string>
|
||||
<!-- Text hovering over canvas, number tiles not ready [CHAR LIMIT=15] -->
|
||||
<string name="unready_tiles">Unready Tiles</string>
|
||||
<!-- Text hovering over canvas, number of tiles that haven't been
|
||||
allocated to a place on the page [CHAR LIMIT=15] -->
|
||||
<string name="unplaced_tiles">Unplaced Tiles</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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 android.app.Activity;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.GestureDetector.SimpleOnGestureListener;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.SeekBar.OnSeekBarChangeListener;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
|
||||
/**
|
||||
* Interface for playing back WebView tile rendering status. Draws viewport and
|
||||
* states of tiles and statistics for off-line analysis.
|
||||
*/
|
||||
public class PlaybackActivity extends Activity {
|
||||
private static final float SCROLL_SCALER = 0.125f;
|
||||
|
||||
PlaybackView mPlaybackView;
|
||||
SeekBar mSeekBar;
|
||||
Button mForward;
|
||||
Button mBackward;
|
||||
TextView mFrameDisplay;
|
||||
|
||||
private int mFrame = -1;
|
||||
private int mFrameMax;
|
||||
|
||||
private class TouchFrameChangeListener extends SimpleOnGestureListener {
|
||||
float mDist = 0;
|
||||
|
||||
@Override
|
||||
public boolean onScroll(MotionEvent e1, MotionEvent e2,
|
||||
float distanceX, float distanceY) {
|
||||
// aggregate scrolls so that small ones can add up
|
||||
mDist += distanceY * SCROLL_SCALER;
|
||||
int intComponent = (int) Math.floor(Math.abs(mDist));
|
||||
if (intComponent >= 1) {
|
||||
int scrollDist = (mDist > 0) ? intComponent : -intComponent;
|
||||
setFrame(null, mFrame + scrollDist);
|
||||
mDist -= scrollDist;
|
||||
}
|
||||
return super.onScroll(e1, e2, distanceX, distanceY);
|
||||
}
|
||||
};
|
||||
|
||||
private class SeekFrameChangeListener implements OnSeekBarChangeListener {
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress,
|
||||
boolean fromUser) {
|
||||
setFrame(seekBar, progress);
|
||||
}
|
||||
};
|
||||
|
||||
private class LoadFileTask extends AsyncTask<String, Void, TileData[][]> {
|
||||
@Override
|
||||
protected TileData[][] doInBackground(String... params) {
|
||||
TileData[][] data = null;
|
||||
try {
|
||||
FileInputStream fis = openFileInput(params[0]);
|
||||
ObjectInputStream in = new ObjectInputStream(fis);
|
||||
data = (TileData[][]) in.readObject();
|
||||
in.close();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
} catch (ClassNotFoundException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(TileData data[][]) {
|
||||
if (data == null) {
|
||||
data = genTestPattern();
|
||||
}
|
||||
mPlaybackView.setData(data);
|
||||
|
||||
mFrameMax = data.length - 1;
|
||||
mSeekBar.setMax(mFrameMax);
|
||||
|
||||
setFrame(null, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void setFrame(View changer, int f) {
|
||||
if (f < 0) {
|
||||
f = 0;
|
||||
} else if (f > mFrameMax) {
|
||||
f = mFrameMax;
|
||||
}
|
||||
|
||||
if (mFrame == f) {
|
||||
return;
|
||||
}
|
||||
|
||||
mFrame = f;
|
||||
mForward.setEnabled(mFrame != mFrameMax);
|
||||
mBackward.setEnabled(mFrame != 0);
|
||||
if (changer != mSeekBar) {
|
||||
mSeekBar.setProgress(mFrame);
|
||||
}
|
||||
mFrameDisplay.setText(Integer.toString(mFrame));
|
||||
mPlaybackView.setFrame(mFrame);
|
||||
};
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.playback);
|
||||
|
||||
mPlaybackView = (PlaybackView) findViewById(R.id.playback);
|
||||
mSeekBar = (SeekBar) findViewById(R.id.seek_bar);
|
||||
mForward = (Button) findViewById(R.id.forward);
|
||||
mBackward = (Button) findViewById(R.id.backward);
|
||||
mFrameDisplay = (TextView) findViewById(R.id.frame_display);
|
||||
|
||||
mForward.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
setFrame(v, mFrame + 1);
|
||||
}
|
||||
});
|
||||
|
||||
mBackward.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
setFrame(v, mFrame - 1);
|
||||
}
|
||||
});
|
||||
|
||||
mSeekBar.setOnSeekBarChangeListener(new SeekFrameChangeListener());
|
||||
|
||||
mPlaybackView.setOnGestureListener(new TouchFrameChangeListener());
|
||||
|
||||
new LoadFileTask().execute(ProfileActivity.TEMP_FILENAME);
|
||||
}
|
||||
|
||||
private TileData[][] genTestPattern() {
|
||||
final int XMAX = 5;
|
||||
final int FRAMEMAX = 99;
|
||||
|
||||
TileData example[][] = new TileData[FRAMEMAX][];
|
||||
for (int frame = 0; frame < FRAMEMAX; frame++) {
|
||||
int numTiles = frame + 10;
|
||||
|
||||
example[frame] = new TileData[numTiles];
|
||||
for (int t = 0; t < numTiles; t++) {
|
||||
int x = t % XMAX;
|
||||
int y = t / XMAX;
|
||||
boolean isReady = y * 10 < frame;
|
||||
example[frame][t] = new TileData(x, y, isReady, 0);
|
||||
}
|
||||
}
|
||||
return example;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* 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 android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class PlaybackGraphs {
|
||||
private static final int BAR_WIDTH = PlaybackView.TILEX * 3;
|
||||
private static final float CANVAS_SCALE = 0.2f;
|
||||
private static final double IDEAL_FRAMES = 60;
|
||||
private static final int LABELOFFSET = 100;
|
||||
private static Paint whiteLabels;
|
||||
|
||||
private static double viewportCoverage(int l, int b, int r, int t,
|
||||
int tileIndexX,
|
||||
int tileIndexY) {
|
||||
if (tileIndexX * PlaybackView.TILEX < r
|
||||
&& (tileIndexX + 1) * PlaybackView.TILEX >= l
|
||||
&& tileIndexY * PlaybackView.TILEY < t
|
||||
&& (tileIndexY + 1) * PlaybackView.TILEY >= b) {
|
||||
return 1.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
private interface MetricGen {
|
||||
public double getValue(TileData[] frame);
|
||||
|
||||
public double getMax();
|
||||
|
||||
public int getLabelId();
|
||||
};
|
||||
|
||||
private static MetricGen[] Metrics = new MetricGen[] {
|
||||
new MetricGen() {
|
||||
// framerate graph
|
||||
@Override
|
||||
public double getValue(TileData[] frame) {
|
||||
int renderTimeUS = frame[0].level;
|
||||
return 1.0e6f / renderTimeUS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMax() {
|
||||
return IDEAL_FRAMES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLabelId() {
|
||||
return R.string.frames_per_second;
|
||||
}
|
||||
}, new MetricGen() {
|
||||
// coverage graph
|
||||
@Override
|
||||
public double getValue(TileData[] frame) {
|
||||
int l = frame[0].x, b = frame[0].y;
|
||||
int r = frame[1].x, t = frame[1].y;
|
||||
double total = 0, totalCount = 0;
|
||||
for (int tileID = 2; tileID < frame.length; tileID++) {
|
||||
TileData data = frame[tileID];
|
||||
double coverage = viewportCoverage(l, b, r, t, data.x,
|
||||
data.y);
|
||||
total += coverage * (data.isReady ? 1 : 0);
|
||||
totalCount += coverage;
|
||||
}
|
||||
if (totalCount == 0) {
|
||||
return -1;
|
||||
}
|
||||
return total / totalCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMax() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLabelId() {
|
||||
return R.string.viewport_coverage;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private interface StatGen {
|
||||
public double getValue(double sortedValues[]);
|
||||
|
||||
public int getLabelId();
|
||||
}
|
||||
|
||||
public static double getPercentile(double sortedValues[], double ratioAbove) {
|
||||
double index = ratioAbove * (sortedValues.length - 1);
|
||||
int intIndex = (int) Math.floor(index);
|
||||
if (index == intIndex) {
|
||||
return sortedValues[intIndex];
|
||||
}
|
||||
double alpha = index - intIndex;
|
||||
return sortedValues[intIndex] * (1 - alpha)
|
||||
+ sortedValues[intIndex + 1] * (alpha);
|
||||
}
|
||||
|
||||
private static StatGen[] Stats = new StatGen[] {
|
||||
new StatGen() {
|
||||
@Override
|
||||
public double getValue(double[] sortedValues) {
|
||||
return getPercentile(sortedValues, 0.25);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLabelId() {
|
||||
return R.string.percentile_25;
|
||||
}
|
||||
}, new StatGen() {
|
||||
@Override
|
||||
public double getValue(double[] sortedValues) {
|
||||
return getPercentile(sortedValues, 0.5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLabelId() {
|
||||
return R.string.percentile_50;
|
||||
}
|
||||
}, new StatGen() {
|
||||
@Override
|
||||
public double getValue(double[] sortedValues) {
|
||||
return getPercentile(sortedValues, 0.75);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLabelId() {
|
||||
return R.string.percentile_75;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
public PlaybackGraphs() {
|
||||
whiteLabels = new Paint();
|
||||
whiteLabels.setColor(Color.WHITE);
|
||||
whiteLabels.setTextSize(PlaybackView.TILEY / 3);
|
||||
}
|
||||
|
||||
private ArrayList<ShapeDrawable> mShapes = new ArrayList<ShapeDrawable>();
|
||||
private double[][] mStats = new double[Metrics.length][Stats.length];
|
||||
|
||||
public void setData(TileData[][] tileProfilingData) {
|
||||
mShapes.clear();
|
||||
double metricValues[] = new double[tileProfilingData.length];
|
||||
|
||||
if (tileProfilingData.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];
|
||||
int newBar = (frame[0].y + frame[1].y) / 2;
|
||||
|
||||
MetricGen s = Metrics[metricIndex];
|
||||
double absoluteValue = s.getValue(frame);
|
||||
double relativeValue = absoluteValue / s.getMax();
|
||||
int rightPos = (int) (-BAR_WIDTH * metricIndex);
|
||||
int leftPos = (int) (-BAR_WIDTH * (metricIndex + relativeValue));
|
||||
|
||||
ShapeDrawable graphBar = new ShapeDrawable();
|
||||
graphBar.getPaint().setColor(Color.BLUE);
|
||||
graphBar.setBounds(leftPos, lastBar, rightPos, newBar);
|
||||
|
||||
mShapes.add(graphBar);
|
||||
metricValues[frameIndex] = absoluteValue;
|
||||
lastBar = newBar;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drawVerticalShiftedShapes(Canvas canvas,
|
||||
ArrayList<ShapeDrawable> shapes) {
|
||||
// Shapes drawn here are drawn relative to the viewRect
|
||||
Rect viewRect = shapes.get(shapes.size() - 1).getBounds();
|
||||
canvas.translate(0, 5 * PlaybackView.TILEY - viewRect.top);
|
||||
|
||||
for (ShapeDrawable shape : mShapes) {
|
||||
shape.draw(canvas);
|
||||
}
|
||||
for (ShapeDrawable shape : shapes) {
|
||||
shape.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas, ArrayList<ShapeDrawable> shapes,
|
||||
String[] strings, Resources resources) {
|
||||
canvas.scale(CANVAS_SCALE, CANVAS_SCALE);
|
||||
|
||||
canvas.translate(BAR_WIDTH * Metrics.length, 0);
|
||||
|
||||
canvas.save();
|
||||
drawVerticalShiftedShapes(canvas, shapes);
|
||||
canvas.restore();
|
||||
|
||||
for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) {
|
||||
String label = resources.getString(
|
||||
Metrics[metricIndex].getLabelId());
|
||||
int xPos = (metricIndex + 1) * -BAR_WIDTH;
|
||||
int yPos = LABELOFFSET;
|
||||
canvas.drawText(label, xPos, yPos, whiteLabels);
|
||||
for (int statIndex = 0; statIndex < Stats.length; statIndex++) {
|
||||
label = resources.getString(R.string.format_stat, mStats[metricIndex][statIndex]);
|
||||
yPos = LABELOFFSET + (1 + statIndex) * PlaybackView.TILEY / 2;
|
||||
canvas.drawText(label, xPos, yPos, whiteLabels);
|
||||
}
|
||||
}
|
||||
for (int stringIndex = 0; stringIndex < strings.length; stringIndex++) {
|
||||
int yPos = LABELOFFSET + stringIndex * PlaybackView.TILEY / 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);
|
||||
}
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
}
|
||||
159
tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java
Normal file
159
tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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 android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.GestureDetector.OnGestureListener;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class PlaybackView extends View {
|
||||
public static final int TILEX = 300;
|
||||
public static final int TILEY = 300;
|
||||
|
||||
private Paint levelPaint = null, coordPaint = null, goldPaint = null;
|
||||
private PlaybackGraphs mGraphs;
|
||||
|
||||
private ArrayList<ShapeDrawable> mTempShapes = new ArrayList<ShapeDrawable>();
|
||||
private TileData mProfData[][] = null;
|
||||
private GestureDetector mGestureDetector = null;
|
||||
private String mRenderStrings[] = new String[3];
|
||||
|
||||
private class TileDrawable extends ShapeDrawable {
|
||||
TileData tile;
|
||||
|
||||
public TileDrawable(TileData t) {
|
||||
int tileColorId = t.isReady ? R.color.ready_tile
|
||||
: R.color.unready_tile;
|
||||
getPaint().setColor(getResources().getColor(tileColorId));
|
||||
|
||||
setBounds(t.x * TILEX, t.y * TILEY, (t.x + 1) * TILEX, (t.y + 1)
|
||||
* TILEY);
|
||||
this.tile = t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
super.draw(canvas);
|
||||
canvas.drawText(Integer.toString(tile.level), getBounds().left,
|
||||
getBounds().bottom, levelPaint);
|
||||
canvas.drawText(tile.x + "," + tile.y, getBounds().left,
|
||||
((getBounds().bottom + getBounds().top) / 2), coordPaint);
|
||||
}
|
||||
}
|
||||
|
||||
public PlaybackView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public PlaybackView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public PlaybackView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
public void setOnGestureListener(OnGestureListener gl) {
|
||||
mGestureDetector = new GestureDetector(getContext(), gl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
mGestureDetector.onTouchEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void init() {
|
||||
levelPaint = new Paint();
|
||||
levelPaint.setColor(Color.WHITE);
|
||||
levelPaint.setTextSize(TILEY / 2);
|
||||
coordPaint = new Paint();
|
||||
coordPaint.setColor(Color.BLACK);
|
||||
coordPaint.setTextSize(TILEY / 3);
|
||||
goldPaint = new Paint();
|
||||
goldPaint.setColor(0xffa0e010);
|
||||
mGraphs = new PlaybackGraphs();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
if (mTempShapes == null || mTempShapes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mGraphs.draw(canvas, mTempShapes, mRenderStrings, getResources());
|
||||
}
|
||||
|
||||
public int setFrame(int frame) {
|
||||
if (mProfData == null || mProfData.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int readyTiles = 0, unreadyTiles = 0, unplacedTiles = 0;
|
||||
mTempShapes.clear();
|
||||
|
||||
// draw actual tiles
|
||||
for (int tileID = 2; tileID < mProfData[frame].length; tileID++) {
|
||||
TileData t = mProfData[frame][tileID];
|
||||
mTempShapes.add(new TileDrawable(t));
|
||||
if (t.isReady) {
|
||||
readyTiles++;
|
||||
} else {
|
||||
unreadyTiles++;
|
||||
}
|
||||
if (t.x < 0 || t.y < 0) {
|
||||
unplacedTiles++;
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
// draw view rect (using first two TileData objects)
|
||||
ShapeDrawable viewShape = new ShapeDrawable();
|
||||
viewShape.getPaint().setColor(0xff0000ff);
|
||||
viewShape.setAlpha(64);
|
||||
viewShape.setBounds(mProfData[frame][0].x, mProfData[frame][0].y,
|
||||
mProfData[frame][1].x, mProfData[frame][1].y);
|
||||
mTempShapes.add(viewShape);
|
||||
this.invalidate();
|
||||
return frame;
|
||||
}
|
||||
|
||||
public void setData(TileData[][] tileProfilingData) {
|
||||
mProfData = tileProfilingData;
|
||||
|
||||
mGraphs.setData(mProfData);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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 android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.util.Pair;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemSelectedListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
/**
|
||||
* Interface for profiling the webview's scrolling, with simple controls on how
|
||||
* to scroll, and what content to load.
|
||||
*/
|
||||
public class ProfileActivity extends Activity {
|
||||
|
||||
public interface ProfileCallback {
|
||||
public void profileCallback(TileData data[][]);
|
||||
}
|
||||
|
||||
public static final String TEMP_FILENAME = "profile.tiles";
|
||||
private static final int LOAD_TEST_DELAY = 2000; // nr of millis after load,
|
||||
// before test
|
||||
|
||||
Button mInspectButton;
|
||||
Spinner mVelocitySpinner;
|
||||
EditText mUrl;
|
||||
ProfiledWebView mWeb;
|
||||
ProfileCallback mCallback;
|
||||
|
||||
private class VelocitySelectedListener implements OnItemSelectedListener {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view,
|
||||
int position, long id) {
|
||||
String speedStr = parent.getItemAtPosition(position).toString();
|
||||
int speedInt = Integer.parseInt(speedStr);
|
||||
mWeb.setAutoScrollSpeed(speedInt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
}
|
||||
}
|
||||
|
||||
private class LoggingWebViewClient extends WebViewClient {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
||||
super.onPageStarted(view, url, favicon);
|
||||
mUrl.setText(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
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) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
mWeb.startScrollTest(mCallback);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
||||
private class StoreFileTask extends
|
||||
AsyncTask<Pair<String, TileData[][]>, Void, Void> {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Pair<String, TileData[][]>... params) {
|
||||
try {
|
||||
FileOutputStream fos = openFileOutput(params[0].first,
|
||||
Context.MODE_PRIVATE);
|
||||
ObjectOutputStream out = new ObjectOutputStream(fos);
|
||||
out.writeObject(params[0].second);
|
||||
out.close();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
mUrl.setBackgroundResource(R.color.finished_url);
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
mInspectButton = (Button) findViewById(R.id.inspect);
|
||||
mVelocitySpinner = (Spinner) findViewById(R.id.velocity);
|
||||
mUrl = (EditText) findViewById(R.id.url);
|
||||
mWeb = (ProfiledWebView) findViewById(R.id.web);
|
||||
mCallback = new ProfileCallback() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void profileCallback(TileData[][] data) {
|
||||
new StoreFileTask().execute(new Pair<String, TileData[][]>(TEMP_FILENAME, data));
|
||||
}
|
||||
};
|
||||
|
||||
// Inspect button (opens PlaybackActivity)
|
||||
mInspectButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
startActivity(new Intent(ProfileActivity.this,
|
||||
PlaybackActivity.class));
|
||||
}
|
||||
});
|
||||
|
||||
// Velocity spinner
|
||||
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
|
||||
this, R.array.velocity_array,
|
||||
android.R.layout.simple_spinner_item);
|
||||
adapter.setDropDownViewResource(
|
||||
android.R.layout.simple_spinner_dropdown_item);
|
||||
mVelocitySpinner.setAdapter(adapter);
|
||||
mVelocitySpinner.setOnItemSelectedListener(
|
||||
new VelocitySelectedListener());
|
||||
mVelocitySpinner.setSelection(3);
|
||||
|
||||
// Custom profiling WebView
|
||||
WebSettings settings = mWeb.getSettings();
|
||||
settings.setJavaScriptEnabled(true);
|
||||
settings.setSupportZoom(true);
|
||||
settings.setEnableSmoothTransition(true);
|
||||
settings.setBuiltInZoomControls(true);
|
||||
settings.setLoadWithOverviewMode(true);
|
||||
mWeb.setWebViewClient(new LoggingWebViewClient());
|
||||
|
||||
// URL text entry
|
||||
mUrl.setOnEditorActionListener(new OnEditorActionListener() {
|
||||
public boolean onEditorAction(TextView v, int actionId,
|
||||
KeyEvent event) {
|
||||
String url = mUrl.getText().toString();
|
||||
mUrl.setBackgroundResource(R.color.unfinished_url);
|
||||
mWeb.loadUrl(url);
|
||||
mWeb.requestFocus();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setCallback(ProfileCallback callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWeb.canGoBack()) {
|
||||
mWeb.goBack();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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 android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.test.tilebenchmark.ProfileActivity.ProfileCallback;
|
||||
|
||||
public class ProfiledWebView extends WebView {
|
||||
private int mSpeed;
|
||||
|
||||
private boolean isScrolling = false;
|
||||
private ProfileCallback mCallback;
|
||||
|
||||
public ProfiledWebView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public ProfiledWebView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public ProfiledWebView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public ProfiledWebView(Context context, AttributeSet attrs, int defStyle,
|
||||
boolean privateBrowsing) {
|
||||
super(context, attrs, defStyle, privateBrowsing);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(android.graphics.Canvas canvas) {
|
||||
if (isScrolling) {
|
||||
if (canScrollVertically(1)) {
|
||||
scrollBy(0, mSpeed);
|
||||
} else {
|
||||
stopScrollTest();
|
||||
isScrolling = false;
|
||||
}
|
||||
}
|
||||
super.onDraw(canvas);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called once the page is loaded to start scrolling for evaluating tiles
|
||||
*/
|
||||
public void startScrollTest(ProfileCallback callback) {
|
||||
isScrolling = true;
|
||||
mCallback = callback;
|
||||
super.tileProfilingStart();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called once the page has stopped scrolling
|
||||
*/
|
||||
public void stopScrollTest() {
|
||||
float testRatio = super.tileProfilingStop();
|
||||
|
||||
TileData data[][] = new TileData[super.tileProfilingNumFrames()][];
|
||||
for (int frame = 0; frame < data.length; frame++) {
|
||||
data[frame] = new TileData[
|
||||
super.tileProfilingNumTilesInFrame(frame)];
|
||||
for (int tile = 0; tile < data[frame].length; tile++) {
|
||||
int x = super.tileProfilingGetX(frame, tile);
|
||||
int y = super.tileProfilingGetY(frame, tile);
|
||||
boolean isReady = super.tileProfilingGetReady(frame, tile);
|
||||
int level = super.tileProfilingGetLevel(frame, tile);
|
||||
|
||||
data[frame][tile] = new TileData(x, y, isReady, level);
|
||||
}
|
||||
}
|
||||
super.tileProfilingClear();
|
||||
|
||||
mCallback.profileCallback(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadUrl(String url) {
|
||||
if (!url.startsWith("http://")) {
|
||||
url = "http://" + url;
|
||||
}
|
||||
super.loadUrl(url);
|
||||
}
|
||||
|
||||
public void setAutoScrollSpeed(int speedInt) {
|
||||
mSpeed = speedInt;
|
||||
}
|
||||
}
|
||||
32
tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java
Normal file
32
tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 {
|
||||
public int x, y;
|
||||
public boolean isReady;
|
||||
public int level;
|
||||
|
||||
public TileData(int x, int y, boolean isReady, int level) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.isReady = isReady;
|
||||
this.level = level;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user