diff options
author | Xia Wang <xiaw@google.com> | 2009-09-02 17:52:24 -0700 |
---|---|---|
committer | Xia Wang <xiaw@google.com> | 2009-09-02 20:59:37 -0700 |
commit | 7c6efa13f129dbae5319f0981a430d4662f43354 (patch) | |
tree | c0353eedab622c39251cb2b29d6195fb09cf9771 /tests/BrowserPowerTest | |
parent | 04e1faf0f030ddb360180289fb798adbb3348dd4 (diff) | |
download | frameworks_base-7c6efa13f129dbae5319f0981a430d4662f43354.zip frameworks_base-7c6efa13f129dbae5319f0981a430d4662f43354.tar.gz frameworks_base-7c6efa13f129dbae5319f0981a430d4662f43354.tar.bz2 |
Add a test case to measure the power usage of loading a web page
Diffstat (limited to 'tests/BrowserPowerTest')
5 files changed, 411 insertions, 0 deletions
diff --git a/tests/BrowserPowerTest/Android.mk b/tests/BrowserPowerTest/Android.mk new file mode 100644 index 0000000..f2c07b3 --- /dev/null +++ b/tests/BrowserPowerTest/Android.mk @@ -0,0 +1,30 @@ +# Copyright 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. + +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 := BrowserPowerTests + +#LOCAL_INSTRUMENTATION_FOR := browserpowertest + +include $(BUILD_PACKAGE) diff --git a/tests/BrowserPowerTest/AndroidManifest.xml b/tests/BrowserPowerTest/AndroidManifest.xml new file mode 100644 index 0000000..43eeaad --- /dev/null +++ b/tests/BrowserPowerTest/AndroidManifest.xml @@ -0,0 +1,46 @@ +<?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. +--> + +<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.browserpowertest"> + + <!-- We add an application tag here just so that we can indicate that + this package needs to link against the android.test library, + which is needed when building test cases. --> + <application> + <uses-library android:name="android.test.runner" /> + <activity android:name="PowerTestActivity" android:label="Power"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.TEST" /> + </intent-filter> + </activity> + </application> + <!-- + This declares that this app uses the instrumentation test runner targeting + the package of browserpowertest. To run the tests use the command: + "adb shell am instrument -w com.android.browserpowertest/.PowerTestRunner" + --> + <instrumentation android:name=".PowerTestRunner" + android:targetPackage="com.android.browserpowertest" + android:label="Test runner for Browser Power Tests." + /> + + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.WRITE_SDCARD" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> +</manifest> diff --git a/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerMeasurement.java b/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerMeasurement.java new file mode 100644 index 0000000..74ac865 --- /dev/null +++ b/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerMeasurement.java @@ -0,0 +1,51 @@ +package com.android.browserpowertest; + +import android.content.Intent; +import android.app.Instrumentation; +import android.os.Handler; +import android.os.Message; +import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; +import junit.framework.*; + +public class PowerMeasurement extends ActivityInstrumentationTestCase2<PowerTestActivity> { + + private static final String LOGTAG = "PowerMeasurement"; + private static final String PKG_NAME = "com.android.browserpowertest"; + private static final String TESTING_URL = "http://www.espn.com"; + private static final int TIME_OUT = 2 * 60 * 1000; + private static final int DELAY = 0; + + public PowerMeasurement() { + super(PKG_NAME, PowerTestActivity.class); + } + + public void testPageLoad() throws Throwable { + Instrumentation mInst = getInstrumentation(); + PowerTestActivity act = getActivity(); + + Intent intent = new Intent(mInst.getContext(), PowerTestActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + long start = System.currentTimeMillis(); + PowerTestActivity activity = (PowerTestActivity)mInst.startActivitySync( + intent); + activity.reset(); + //send a message with the new URL + Handler handler = activity.getHandler(); + Message msg = handler.obtainMessage( + PowerTestActivity.MSG_NAVIGATE, TIME_OUT, DELAY); + msg.getData().putString(PowerTestActivity.MSG_NAV_URL, TESTING_URL); + msg.getData().putBoolean(PowerTestActivity.MSG_NAV_LOGTIME, true); + + handler.sendMessage(msg); + boolean timeoutFlag = activity.waitUntilDone(); + long end = System.currentTimeMillis(); + assertFalse(TESTING_URL + " failed to load", timeoutFlag); + boolean pageErrorFlag = activity.getPageError(); + assertFalse(TESTING_URL + " is not available, either network is down or the server is down", + pageErrorFlag); + Log.v(LOGTAG, "Page is loaded in " + activity.getPageLoadTime() + " ms."); + + activity.finish(); + } +} diff --git a/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestActivity.java b/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestActivity.java new file mode 100644 index 0000000..77e390b --- /dev/null +++ b/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestActivity.java @@ -0,0 +1,253 @@ +package com.android.browserpowertest; + +import android.app.Activity; +import android.app.ActivityThread; +import android.graphics.Bitmap; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.view.ViewGroup; +import android.webkit.WebChromeClient; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.webkit.WebSettings.LayoutAlgorithm; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; + +public class PowerTestActivity extends Activity { + + public static final String LOGTAG = "PowerTestActivity"; + public static final String PARAM_URL = "URL"; + public static final String PARAM_TIMEOUT = "Timeout"; + public static final int RESULT_TIMEOUT = 0xDEAD; + public static final int MSG_TIMEOUT = 0xC001; + public static final int MSG_NAVIGATE = 0xC002; + public static final String MSG_NAV_URL = "url"; + public static final String MSG_NAV_LOGTIME = "logtime"; + + private WebView webView; + private SimpleWebViewClient webViewClient; + private SimpleChromeClient chromeClient; + private Handler handler; + private boolean timeoutFlag; + private boolean logTime; + private boolean pageDone; + private Object pageDoneLock; + private int pageStartCount; + private int manualDelay; + private long startTime; + private long pageLoadTime; + private PageDoneRunner pageDoneRunner = new PageDoneRunner(); + + public PowerTestActivity() { + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Log.v(LOGTAG, "onCreate, inst=" + Integer.toHexString(hashCode())); + + LinearLayout contentView = new LinearLayout(this); + contentView.setOrientation(LinearLayout.VERTICAL); + setContentView(contentView); + setTitle("Idle"); + + webView = new WebView(this); + webView.getSettings().setJavaScriptEnabled(true); + webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(false); + webView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.NORMAL); + + webViewClient = new SimpleWebViewClient(); + chromeClient = new SimpleChromeClient(); + webView.setWebViewClient(webViewClient); + webView.setWebChromeClient(chromeClient); + + contentView.addView(webView, new LayoutParams( + ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.FILL_PARENT, 0.0f)); + + handler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_TIMEOUT: + handleTimeout(); + return; + case MSG_NAVIGATE: + manualDelay = msg.arg2; + navigate(msg.getData().getString(MSG_NAV_URL), msg.arg1); + logTime = msg.getData().getBoolean(MSG_NAV_LOGTIME); + return; + } + } + }; + + pageDoneLock = new Object(); + } + + public void reset() { + synchronized (pageDoneLock) { + pageDone = false; + } + timeoutFlag = false; + pageStartCount = 0; + chromeClient.resetJsTimeout(); + } + + private void navigate(String url, int timeout) { + if(url == null) { + Log.v(LOGTAG, "URL is null, cancelling..."); + finish(); + } + webView.stopLoading(); + if(logTime) { + webView.clearCache(true); + } + startTime = System.currentTimeMillis(); + Log.v(LOGTAG, "Navigating to URL: " + url); + webView.loadUrl(url); + + if(timeout != 0) { + //set a timer with specified timeout (in ms) + handler.sendMessageDelayed(handler.obtainMessage(MSG_TIMEOUT), + timeout); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + Log.v(LOGTAG, "onDestroy, inst=" + Integer.toHexString(hashCode())); + webView.clearCache(true); + webView.destroy(); + } + + private boolean isPageDone() { + synchronized (pageDoneLock) { + return pageDone; + } + } + + private void setPageDone(boolean pageDone) { + synchronized (pageDoneLock) { + this.pageDone = pageDone; + pageDoneLock.notifyAll(); + } + } + + private void handleTimeout() { + int progress = webView.getProgress(); + webView.stopLoading(); + Log.v(LOGTAG, "Page timeout triggered, progress = " + progress); + timeoutFlag = true; + handler.postDelayed(pageDoneRunner, manualDelay); + } + + public boolean waitUntilDone() { + validateNotAppThread(); + synchronized (pageDoneLock) { + while(!isPageDone()) { + try { + pageDoneLock.wait(); + } catch (InterruptedException ie) { + //no-op + } + } + } + return timeoutFlag; + } + + public Handler getHandler() { + return handler; + } + + private final void validateNotAppThread() { + if (ActivityThread.currentActivityThread() != null) { + throw new RuntimeException( + "This method can not be called from the main application thread"); + } + } + + public long getPageLoadTime() { + return pageLoadTime; + } + + public boolean getPageError() { + return webViewClient.getPageErrorFlag(); + } + + class SimpleWebViewClient extends WebViewClient { + + private boolean pageErrorFlag = false; + + @Override + public void onReceivedError(WebView view, int errorCode, String description, + String failingUrl) { + pageErrorFlag = true; + Log.v(LOGTAG, "WebCore error: code=" + errorCode + + ", description=" + description + + ", url=" + failingUrl); + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + pageStartCount++; + Log.v(LOGTAG, "onPageStarted: " + url); + } + + @Override + public void onPageFinished(WebView view, String url) { + Log.v(LOGTAG, "onPageFinished: " + url); + // let handleTimeout take care of finishing the page + if(!timeoutFlag) + handler.postDelayed(new WebViewStatusChecker(), 500); + } + + // return true if the URL is not available or the page is down + public boolean getPageErrorFlag() { + return pageErrorFlag; + } + } + + class SimpleChromeClient extends WebChromeClient { + + private int timeoutCounter = 0; + + public void resetJsTimeout() { + timeoutCounter = 0; + } + + @Override + public void onReceivedTitle(WebView view, String title) { + PowerTestActivity.this.setTitle(title); + } + } + + class WebViewStatusChecker implements Runnable { + + private int initialStartCount; + + public WebViewStatusChecker() { + initialStartCount = pageStartCount; + } + + public void run() { + if (initialStartCount == pageStartCount && !isPageDone()) { + handler.removeMessages(MSG_TIMEOUT); + webView.stopLoading(); + handler.postDelayed(pageDoneRunner, manualDelay); + } + } + } + + class PageDoneRunner implements Runnable { + + public void run() { + Log.v(LOGTAG, "Finishing URL: " + webView.getUrl()); + pageLoadTime = System.currentTimeMillis() - startTime; + setPageDone(true); + } + } +} diff --git a/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestRunner.java b/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestRunner.java new file mode 100644 index 0000000..4857209 --- /dev/null +++ b/tests/BrowserPowerTest/src/com/android/browserpowertest/PowerTestRunner.java @@ -0,0 +1,31 @@ +package com.android.browserpowertest; + +import android.test.InstrumentationTestRunner; +import android.test.InstrumentationTestSuite; + +import junit.framework.TestSuite; + + +/** + * Instrumentation Test Runner for all browser power tests. + * + * Running power tests: + * + * adb shell am instrument \ + * -w com.android.browserpowertest/.PowerTestRunner + */ + +public class PowerTestRunner extends InstrumentationTestRunner { + @Override + public TestSuite getAllTests() { + TestSuite suite = new InstrumentationTestSuite(this); + suite.addTestSuite(PowerMeasurement.class); + return suite; + } + + @Override + public ClassLoader getLoader() { + return PowerTestRunner.class.getClassLoader(); + } + +} |