Merge "Javadoc cleanup."
diff --git a/prod-tests/src/com/android/media/tests/CameraLatencyTest.java b/prod-tests/src/com/android/media/tests/CameraLatencyTest.java
index 6f24f7f..13fa66f 100644
--- a/prod-tests/src/com/android/media/tests/CameraLatencyTest.java
+++ b/prod-tests/src/com/android/media/tests/CameraLatencyTest.java
@@ -111,6 +111,7 @@
         t.mTestName = "latency";
         t.mClassName = "com.android.camera.stress.CameraLatency";
         t.mTestMetricsName = "CameraLatency";
+        map = t.mPatternMap;
         map.put("AutoFocus", "^Avg AutoFocus = (\\d+)");
         map.put("ShutterLag", "^Avg mShutterLag = (\\d+)");
         map.put("Preview", "^Avg mShutterToPictureDisplayedTime = (\\d+)");
diff --git a/prod-tests/src/com/android/wireless/tests/RadioStressTest.java b/prod-tests/src/com/android/wireless/tests/RadioStressTest.java
index 0da8e1e..2c7b2ed 100644
--- a/prod-tests/src/com/android/wireless/tests/RadioStressTest.java
+++ b/prod-tests/src/com/android/wireless/tests/RadioStressTest.java
@@ -46,7 +46,7 @@
     /* Maxium time to wait for SETUP_DATA_CALL */
     private static int MAX_DATA_SETUP_TIME = 5 * 60 * 1000;
     /* Time to wait for framework to bootup */
-    private static final int BOOTING_TIME = 2 * 60 * 1000;
+    private static final int BOOTING_TIME = 5 * 60 * 1000;
 
     // Define instrumentation test package and runner.
     private static final String TEST_PACKAGE_NAME = "com.android.phonetests";
@@ -72,9 +72,15 @@
     private String mPhoneNumber = null;
 
     @Option(name="voice",
-            description="to verify the voice call")
+            description="To verify the voice call")
     private boolean mVoiceVerificationFlag = true;
 
+    // From the past test, if there are too many failures, they are similar
+    // set the threshold so that the test won't drag too long
+    @Option(name="threshold",
+            description="Threshold to stop the test")
+    private int mThreshold = 10;
+
     /**
      * Run radio startup stress test, capture bugreport if the test failed.
      * Report results to dashboard after the test
@@ -94,6 +100,10 @@
         for (int i = 0; i < mIteration; i++) {
             // reset device before rebooting
             CLog.d("Radio startup test iteration : %d, success runs: %d", i, mSuccessRun);
+            if ((i + 1) - mSuccessRun > mThreshold) {
+                CLog.d("Too many failures, stop the test");
+                break;
+            }
             mRadioHelper.resetBootComplete();
 
             // run-time reboot device
@@ -107,27 +117,29 @@
             mTestDevice.postBootSetup();
             mTestDevice.clearErrorDialogs();
 
-            // Wait 2 minutes for the device to fully booting up
+            // Wait for the device to fully booting up and connect to mobile network
             getRunUtil().sleep(BOOTING_TIME);
 
+            // verify data connection first
+            boolean dataFlag = false;
+            if (verifyDataConnection()) {
+                dataFlag = true;
+            } else {
+                getBugReport(listener, i);
+            }
+
             // verify voice connection
             if (mVoiceVerificationFlag) {
-                boolean voiceRes = verifyVoiceConnection(listener);
+                boolean voiceFlag = verifyVoiceConnection(listener);
                 getRunUtil().sleep(MAX_DATA_SETUP_TIME);
-                boolean dataRes = verifyDataConnection();
-                if (voiceRes && dataRes) {
+                // after the voice call, phone app is reset
+                dataFlag = verifyDataConnection();
+                if (voiceFlag && dataFlag) {
                     mSuccessRun++;
                 }
-                if (!dataRes) {
-                    // Take a bugreport if data verification failed. A bugreport should be captured
-                    // if voice verification failed in the instrumentation test.
-                    getBugReport(listener, i);
-                }
             } else {
-                if (verifyDataConnection()) {
+                if (dataFlag) {
                     mSuccessRun++;
-                } else {
-                    getBugReport(listener, i);
                 }
             }
         }
diff --git a/prod-tests/src/com/android/wireless/tests/TelephonyStabilityTest.java b/prod-tests/src/com/android/wireless/tests/TelephonyStabilityTest.java
index b5adbc7..e00acec 100644
--- a/prod-tests/src/com/android/wireless/tests/TelephonyStabilityTest.java
+++ b/prod-tests/src/com/android/wireless/tests/TelephonyStabilityTest.java
@@ -29,6 +29,8 @@
 import com.android.tradefed.testtype.IDeviceTest;
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.util.RegexTrie;
+import com.android.tradefed.util.IRunUtil;
+import com.android.tradefed.util.RunUtil;
 
 import junit.framework.Assert;
 
@@ -120,6 +122,7 @@
         mRunMetrics.put(VOICE_CONNECTION_KEY, value);
         mRunMetrics.put(DATA_REGISTRATION_KEY, value);
         mRunMetrics.put(DATA_CONNECTION_KEY, value);
+        getRunUtil().sleep(3*60*1000);  // wait for 3 minutes for device to set up data connection
     }
 
     /**
@@ -174,7 +177,12 @@
         resFile = mTestDevice.pullFile(OUTPUT_FILE);
         int testRun = 0;
         try {
-            Assert.assertNotNull("no output file", resFile);
+            if (resFile == null) {
+                // If the result file is empty, either system crash or there are other fails
+                // (e.g. failed to connect to mobile network after bootup), count as a failed
+                // iteration
+                return 1;
+            }
             // Save a copy of the output file
             CLog.d("Sending %d byte file %s into the logosphere!",
                    resFile.length(), resFile);
@@ -241,4 +249,11 @@
     public ITestDevice getDevice() {
         return mTestDevice;
     }
+
+    /**
+     * Gets the {@link IRunUtil} instance to use.
+     */
+    IRunUtil getRunUtil() {
+        return RunUtil.getDefault();
+    }
 }
diff --git a/prod-tests/src/com/android/wireless/tests/TelephonyTest.java b/prod-tests/src/com/android/wireless/tests/TelephonyTest.java
index 9a9f7fb..7016635 100644
--- a/prod-tests/src/com/android/wireless/tests/TelephonyTest.java
+++ b/prod-tests/src/com/android/wireless/tests/TelephonyTest.java
@@ -26,6 +26,8 @@
 import com.android.tradefed.result.ITestInvocationListener;
 import com.android.tradefed.testtype.IDeviceTest;
 import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.util.IRunUtil;
+import com.android.tradefed.util.RunUtil;
 
 import junit.framework.Assert;
 
@@ -86,6 +88,8 @@
 
         Assert.assertNotNull(mTestDevice);
         Assert.assertNotNull(mPhoneNumber);
+        // wait for 3 minutes for fully booting up and data connection
+        getRunUtil().sleep(3*60*1000);
 
         IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(TEST_PACKAGE_NAME,
                 TEST_RUNNER_NAME, mTestDevice.getIDevice());
@@ -132,7 +136,11 @@
         int calls = 0;
         resFile = mTestDevice.pullFile(mOutputFile);
         try {
-            Assert.assertNotNull("no output file", resFile);
+            if (resFile == null) {
+                // test failed without writing any results
+                // either system crash, or other fails, treat as one failed iteration
+                return 1;
+            }
             BufferedReader br= new BufferedReader(new FileReader(resFile));
             String line = br.readLine();
 
@@ -192,4 +200,11 @@
     public ITestDevice getDevice() {
         return mTestDevice;
     }
+
+    /**
+     * Gets the {@link IRunUtil} instance to use.
+     */
+    IRunUtil getRunUtil() {
+        return RunUtil.getDefault();
+    }
 }
diff --git a/src/com/android/tradefed/command/CommandScheduler.java b/src/com/android/tradefed/command/CommandScheduler.java
index d91cb7b..3b6f8df 100644
--- a/src/com/android/tradefed/command/CommandScheduler.java
+++ b/src/com/android/tradefed/command/CommandScheduler.java
@@ -35,8 +35,8 @@
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.util.ConditionPriorityBlockingQueue;
 
-import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
@@ -58,7 +58,6 @@
  */
 public class CommandScheduler extends Thread implements ICommandScheduler {
 
-    private static final String LOG_TAG = "CommandScheduler";
     /** the queue of commands ready to be executed. */
     private ConditionPriorityBlockingQueue<ExecutableCommand> mCommandQueue;
     /**
@@ -239,26 +238,26 @@
                 mCmd.commandStarted();
                 instance.invoke(mDevice, config, new Rescheduler(mCmd.getCommandTracker()));
             } catch (DeviceUnresponsiveException e) {
-                Log.w(LOG_TAG, String.format("Device %s is unresponsive",
-                        mDevice.getSerialNumber()));
+                CLog.w("Device %s is unresponsive. Reason: %s", mDevice.getSerialNumber(),
+                        e.getMessage());
                 deviceState = FreeDeviceState.UNRESPONSIVE;
             } catch (DeviceNotAvailableException e) {
-                Log.w(LOG_TAG, String.format("Device %s is not available",
-                        mDevice.getSerialNumber()));
+                CLog.w("Device %s is not available. Reason: %s", mDevice.getSerialNumber(),
+                        e.getMessage());
                 deviceState = FreeDeviceState.UNAVAILABLE;
             } catch (FatalHostError e) {
-                Log.logAndDisplay(LogLevel.ERROR, LOG_TAG, String.format(
-                        "Fatal error occurred: %s, shutting down", e.getMessage()));
+                CLog.logAndDisplay(LogLevel.ERROR, "Fatal error occurred: %s, shutting down",
+                        e.getMessage());
                 if (e.getCause() != null) {
-                    Log.e(LOG_TAG, e.getCause());
+                    CLog.e(e.getCause());
                 }
                 shutdown();
             } catch (Throwable e) {
-                Log.e(LOG_TAG, e);
+                CLog.e(e);
             } finally {
                 long elapsedTime = System.currentTimeMillis() - mStartTime;
-                Log.i(LOG_TAG, String.format("Updating command '%s' with elapsed time %d ms",
-                        getArgString(mCmd.getCommandTracker().getArgs()), elapsedTime));
+                CLog.i("Updating command '%s' with elapsed time %d ms",
+                        getArgString(mCmd.getCommandTracker().getArgs()), elapsedTime);
                 mCmd.getCommandTracker().incrementExecTime(elapsedTime);
                 if (!mCmd.getCommandTracker().getCommandOptions().isLoopMode()) {
                     mAllCommands.remove(mCmd.getCommandTracker());
@@ -352,7 +351,7 @@
                 }
             }
         }
-        Log.i(LOG_TAG, "Waiting for invocation threads to complete");
+        CLog.i("Waiting for invocation threads to complete");
         List<InvocationThread> threadListCopy;
         synchronized (this) {
             threadListCopy = new ArrayList<InvocationThread>(
@@ -362,7 +361,7 @@
         for (Thread thread : threadListCopy) {
             waitForThread(thread);
         }
-        Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "All done");
+        CLog.logAndDisplay(LogLevel.INFO, "All done");
         exit(manager);
         cleanUp();
     }
@@ -432,7 +431,7 @@
             // poll for a command, rather than block indefinitely, to handle shutdown case
             return mCommandQueue.poll(getCommandPollTimeMs(), TimeUnit.MILLISECONDS);
         } catch (InterruptedException e) {
-            Log.i(LOG_TAG, "Waiting for command interrupted");
+            CLog.i("Waiting for command interrupted");
         }
         return null;
     }
@@ -458,7 +457,7 @@
             ExecutableCommand execCmd = new ExecutableCommand(commandTracker, config);
             addExecCommandToQueue(execCmd, commandTracker.getCommandOptions().getMinLoopTime());
         } catch (ConfigurationException e) {
-            Log.e(LOG_TAG, e);
+            CLog.e(e);
         }
     }
 
@@ -558,7 +557,7 @@
      */
     public synchronized void shutdownHard() {
         shutdown();
-        Log.logAndDisplay(LogLevel.WARN, LOG_TAG, "Force killing adb connection");
+        CLog.logAndDisplay(LogLevel.WARN, "Force killing adb connection");
         getDeviceManager().terminateHard();
     }
 
diff --git a/src/com/android/tradefed/invoker/TestInvocation.java b/src/com/android/tradefed/invoker/TestInvocation.java
index d86fd6e..fc979fc 100644
--- a/src/com/android/tradefed/invoker/TestInvocation.java
+++ b/src/com/android/tradefed/invoker/TestInvocation.java
@@ -15,7 +15,6 @@
  */
 package com.android.tradefed.invoker;
 
-import com.android.ddmlib.Log;
 import com.android.ddmlib.Log.LogLevel;
 import com.android.tradefed.build.BuildInfo;
 import com.android.tradefed.build.BuildRetrievalError;
@@ -62,7 +61,6 @@
  */
 public class TestInvocation implements ITestInvocation {
 
-    private static final String LOG_TAG = "TestInvocation";
     static final String TRADEFED_LOG_NAME = "host_log";
     static final String DEVICE_LOG_NAME = "device_logcat";
 
@@ -249,7 +247,7 @@
         }
         msg.append(" on device ");
         msg.append(device.getSerialNumber());
-        Log.logAndDisplay(LogLevel.INFO, LOG_TAG, msg.toString());
+        CLog.logAndDisplay(LogLevel.INFO, msg.toString());
         mStatus = String.format("running %s on build %s", info.getTestTag(), info.getBuildId());
     }
 
@@ -288,7 +286,9 @@
             CLog.e(e);
             reportFailure(e, config.getTestInvocationListeners(), config.getBuildProvider(), info);
         } catch (DeviceNotAvailableException e) {
-            // rely on caller to log thrown exceptions
+            // log a warning here so its captured before reportLogs is called
+            CLog.w("Invocation did not complete due to device %s becoming not available. " +
+                    "Reason: %s", device.getSerialNumber(), e.getMessage());
             resumed = resume(config, info, rescheduler, System.currentTimeMillis() - startTime);
             if (!resumed) {
                 reportFailure(e, config.getTestInvocationListeners(), config.getBuildProvider(),
@@ -298,7 +298,8 @@
             }
             throw e;
         } catch (RuntimeException e) {
-            // rely on caller to log thrown exceptions
+            // log a warning here so its captured before reportLogs is called
+            CLog.w("Unexpected exception when running invocation: %s", e.toString());
             reportFailure(e, config.getTestInvocationListeners(), config.getBuildProvider(), info);
             throw e;
         } finally {
diff --git a/src/com/android/tradefed/log/LogUtil.java b/src/com/android/tradefed/log/LogUtil.java
index a066466..0ed1ee3 100644
--- a/src/com/android/tradefed/log/LogUtil.java
+++ b/src/com/android/tradefed/log/LogUtil.java
@@ -184,6 +184,18 @@
         }
 
         /**
+         * The shim version of {@link Log#logAndDisplay(LogLevel, String, String)}.
+         *
+         * @param logLevel the {@link LogLevel}
+         * @param format A format string for the message to log
+         * @param args The format string arguments
+         */
+        public static void logAndDisplay(LogLevel logLevel, String format, Object... args) {
+            // frame 2: skip frames 0 (#getClassName) and 1 (this method)
+            Log.logAndDisplay(logLevel, getClassName(2), String.format(format, args));
+        }
+
+        /**
          * Return the simple classname from the {@code frame}th stack frame in the call path.
          * Note: this method does <emph>not</emph> check array bounds for the stack trace length.
          *