Merge "BandwidthTestRunner"
diff --git a/test-runner/src/android/test/BandwidthTest.java b/test-runner/src/android/test/BandwidthTest.java
new file mode 100644
index 0000000..e02ae00
--- /dev/null
+++ b/test-runner/src/android/test/BandwidthTest.java
@@ -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 android.test;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This annotation can be used on an {@link junit.framework.TestCase}'s test methods. When the
+ * annotation is present, the test method is profiled for bandwidth metrics and the results
+ * written through instrumentation output. It can also be used on the class itself,
+ * which is equivalent to tagging all test methods with this annotation.
+ *
+ * {@hide} Pending approval for public API.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface BandwidthTest {
+}
diff --git a/test-runner/src/android/test/BandwidthTestRunner.java b/test-runner/src/android/test/BandwidthTestRunner.java
new file mode 100644
index 0000000..9c5478d
--- /dev/null
+++ b/test-runner/src/android/test/BandwidthTestRunner.java
@@ -0,0 +1,92 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+package android.test;
+
+import android.net.NetworkStats;
+import android.net.NetworkStats.Entry;
+import android.net.TrafficStats;
+import android.os.Bundle;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestListener;
+
+import java.lang.reflect.Method;
+
+/**
+ * A specialized {@link android.app.Instrumentation} that can collect Bandwidth statistics during
+ * the execution of the test.
+ * This is used in place of {@link InstrumentationTestRunner}.
+ * i.e. adb shell am instrumentation -w -e class com.android.foo.FooTest \
+ *          com.android.foo/android.test.BandwidthTestRunner
+ *
+ * @see NetworkStats and @see TrafficStats for details of the collected statistics
+ * @hide
+ */
+public class BandwidthTestRunner extends InstrumentationTestRunner implements TestListener {
+    private static final String REPORT_KEY_PACKETS_SENT = "txPackets";
+    private static final String REPORT_KEY_PACKETS_RECEIVED = "rxPackets";
+    private static final String REPORT_KEY_BYTES_SENT = "txBytes";
+    private static final String REPORT_KEY_BYTES_RECEIVED = "rxBytes";
+    private static final String REPORT_KEY_OPERATIONS = "operations";
+
+    private boolean mHasClassAnnotation;
+    private boolean mIsBandwidthTest;
+    private Bundle mTestResult;
+
+    @Override
+    public void onCreate(Bundle arguments) {
+        super.onCreate(arguments);
+        addTestListener(this);
+    }
+
+    public void addError(Test test, Throwable t) {
+    }
+
+    public void addFailure(Test test, AssertionFailedError t) {
+    }
+
+    public void startTest(Test test) {
+        String testClass = test.getClass().getName();
+        String testName = ((TestCase)test).getName();
+        Method testMethod = null;
+        try {
+            testMethod = test.getClass().getMethod(testName);
+        } catch (NoSuchMethodException e) {
+            // ignore- the test with given name does not exist. Will be handled during test
+            // execution
+        }
+        try {
+            // Look for BandwdthTest annotation on both test class and test method
+            if (testMethod != null ) {
+                if (testMethod.isAnnotationPresent(BandwidthTest.class) ){
+                    mIsBandwidthTest = true;
+                    TrafficStats.startDataProfiling(null);
+                } else if (test.getClass().isAnnotationPresent(BandwidthTest.class)){
+                    mIsBandwidthTest = true;
+                    TrafficStats.startDataProfiling(null);
+                }
+            }
+        } catch (SecurityException e) {
+            // ignore - the test with given name cannot be accessed. Will be handled during
+            // test execution
+        }
+    }
+
+    public void endTest(Test test) {
+        if (mIsBandwidthTest){
+            mTestResult = new Bundle();
+            mIsBandwidthTest=false;
+            NetworkStats stats = TrafficStats.stopDataProfiling(null);
+            Entry entry = stats.getTotal(null);
+            mTestResult.putLong(REPORT_KEY_BYTES_RECEIVED, entry.rxBytes);
+            mTestResult.putLong(REPORT_KEY_BYTES_SENT, entry.txBytes);
+            mTestResult.putLong(REPORT_KEY_PACKETS_RECEIVED, entry.rxPackets);
+            mTestResult.putLong(REPORT_KEY_PACKETS_SENT, entry.txPackets);
+            mTestResult.putLong(REPORT_KEY_OPERATIONS, entry.operations);
+            System.out.println(mTestResult.toString());
+            sendStatus(0, mTestResult);
+        }
+    }
+}
diff --git a/test-runner/src/android/test/InstrumentationTestRunner.java b/test-runner/src/android/test/InstrumentationTestRunner.java
index 43285fb..91e403e 100644
--- a/test-runner/src/android/test/InstrumentationTestRunner.java
+++ b/test-runner/src/android/test/InstrumentationTestRunner.java
@@ -399,6 +399,16 @@
         return mArguments;
     }
 
+    /**
+     * Add a {@link TestListener}
+     * @hide
+     */
+    protected void addTestListener(TestListener listener){
+        if(mTestRunner!=null && listener!=null){
+            mTestRunner.addTestListener(listener);
+        }
+    }
+
     List<Predicate<TestMethod>> getBuilderRequirements() {
         return new ArrayList<Predicate<TestMethod>>();
     }