Merge "Port wi-fi stress test into GB DO NOT MERGE" into gingerbread
diff --git a/core/tests/ConnectivityManagerTest/Android.mk b/core/tests/ConnectivityManagerTest/Android.mk
index a1546fa..56011f7 100644
--- a/core/tests/ConnectivityManagerTest/Android.mk
+++ b/core/tests/ConnectivityManagerTest/Android.mk
@@ -25,6 +25,6 @@
 
 LOCAL_PACKAGE_NAME := ConnectivityManagerTest
 
-#LOCAL_INSTRUMENTATION_FOR := connectivitymanagertest
+LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
index b116bea..05f8b39 100644
--- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml
+++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
@@ -16,7 +16,8 @@
 
 <!-- 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.connectivitymanagertest">
+  package="com.android.connectivitymanagertest"
+  android:sharedUserId="com.android.uid.test">
 
     <!-- We add an application tag here just so that we can indicate that
          this package needs to link against the android.test library,
@@ -67,5 +68,9 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.DEVICE_POWER" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
 </manifest>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
index 47f208a..5b76e39 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerStressTestRunner.java
@@ -19,8 +19,8 @@
 import android.os.Bundle;
 import android.test.InstrumentationTestRunner;
 import android.test.InstrumentationTestSuite;
-import android.util.Log;
 import com.android.connectivitymanagertest.stress.WifiApStress;
+import com.android.connectivitymanagertest.stress.WifiStressTest;
 
 import junit.framework.TestSuite;
 
@@ -34,10 +34,18 @@
  */
 
 public class ConnectivityManagerStressTestRunner extends InstrumentationTestRunner {
+    public int mSoftapIterations = 100;
+    public int mScanIterations = 100;
+    public int mReconnectIterations = 100;
+    public int mSleepTime = 30 * 1000;  // default sleep time is 30 seconds
+    public String mReconnectSsid = "securenetdhcp";
+    public String mReconnectPassword = "androidwifi";
+
     @Override
     public TestSuite getAllTests() {
         TestSuite suite = new InstrumentationTestSuite(this);
         suite.addTestSuite(WifiApStress.class);
+        suite.addTestSuite(WifiStressTest.class);
         return suite;
     }
 
@@ -49,14 +57,46 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        String stressValue = (String) icicle.get("stressnum");
-        if (stressValue != null) {
-            int iteration = Integer.parseInt(stressValue);
+        String valueStr = (String) icicle.get("softap_iterations");
+        if (valueStr != null) {
+            int iteration = Integer.parseInt(valueStr);
             if (iteration > 0) {
-                numStress = iteration;
+                mSoftapIterations = iteration;
+            }
+        }
+
+        String scanIterationStr = (String) icicle.get("scan_iterations");
+        if (scanIterationStr != null) {
+            int scanIteration = Integer.parseInt(scanIterationStr);
+            if (scanIteration > 0) {
+                mScanIterations = scanIteration;
+            }
+        }
+
+        String ssidStr= (String) icicle.get("reconnect_ssid");
+        if (ssidStr != null) {
+            mReconnectSsid = ssidStr;
+        }
+
+        String passwordStr = (String) icicle.get("reconnect_password");
+        if (passwordStr != null) {
+            mReconnectPassword = passwordStr;
+        }
+
+        String reconnectStr = (String) icicle.get("reconnect_iterations");
+        if (reconnectStr != null) {
+            int iteration = Integer.parseInt(reconnectStr);
+            if (iteration > 0) {
+                mReconnectIterations = iteration;
+            }
+        }
+
+        String sleepTimeStr = (String) icicle.get("sleep_time");
+        if (sleepTimeStr != null) {
+            int sleepTime = Integer.parseInt(sleepTimeStr);
+            if (sleepTime > 0) {
+                mSleepTime = 1000 * sleepTime;
             }
         }
     }
-
-    public int numStress = 100;
 }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index 0807706..7aa0afd 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -24,11 +24,17 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Bundle;
+import android.os.IPowerManager;
+import android.os.PowerManager;
+import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.Log;
 import android.view.KeyEvent;
 
+import java.io.IOException;
 import java.io.InputStream;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -54,7 +60,7 @@
 
     public static final String LOG_TAG = "ConnectivityManagerTestActivity";
     public static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
-    public static final int WIFI_SCAN_TIMEOUT = 20 * 1000;
+    public static final int WIFI_SCAN_TIMEOUT = 50 * 1000;
     public static final int SHORT_TIMEOUT = 5 * 1000;
     public static final long LONG_TIMEOUT = 50 * 1000;
     public static final int SUCCESS = 0;  // for Wifi tethering state change
@@ -64,6 +70,7 @@
     public ConnectivityReceiver mConnectivityReceiver = null;
     public WifiReceiver mWifiReceiver = null;
     private AccessPointParserHelper mParseHelper = null;
+    public boolean scanResultAvailable = false;
     /*
      * Track network connectivity information
      */
@@ -79,7 +86,7 @@
     public int mWifiState;
     public NetworkInfo mWifiNetworkInfo;
     public String mBssid;
-    public String mPowerSsid = "GoogleGuest"; //Default power SSID
+    public String mPowerSsid = "opennet"; //Default power SSID
     private Context mContext;
 
     /*
@@ -104,7 +111,7 @@
     private class ConnectivityReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
-            Log.v(LOG_TAG, "ConnectivityReceiver: onReceive() is called with " + intent);
+            log("ConnectivityReceiver: onReceive() is called with " + intent);
             String action = intent.getAction();
             if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                 Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
@@ -129,9 +136,9 @@
             mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
             mIsFailOver = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
 
-            Log.v(LOG_TAG, "mNetworkInfo: " + mNetworkInfo.toString());
+            log("mNetworkInfo: " + mNetworkInfo.toString());
             if (mOtherNetworkInfo != null) {
-                Log.v(LOG_TAG, "mOtherNetworkInfo: " + mOtherNetworkInfo.toString());
+                log("mOtherNetworkInfo: " + mOtherNetworkInfo.toString());
             }
             recordNetworkState(mNetworkInfo.getType(), mNetworkInfo.getState());
             if (mOtherNetworkInfo != null) {
@@ -151,7 +158,7 @@
             } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                 mWifiNetworkInfo =
                     (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
-                Log.v(LOG_TAG, "mWifiNetworkInfo: " + mWifiNetworkInfo.toString());
+                log("mWifiNetworkInfo: " + mWifiNetworkInfo.toString());
                 if (mWifiNetworkInfo.getState() == State.CONNECTED) {
                     mBssid = intent.getStringExtra(WifiManager.EXTRA_BSSID);
                 }
@@ -159,7 +166,7 @@
             } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
                 mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                                                 WifiManager.WIFI_STATE_UNKNOWN);
-                Log.v(LOG_TAG, "mWifiState: " + mWifiState);
+                log("mWifiState: " + mWifiState);
                 notifyWifiState();
             } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
                 notifyWifiAPState();
@@ -180,12 +187,13 @@
 
     public ConnectivityManagerTestActivity() {
         mState = State.UNKNOWN;
+        scanResultAvailable = false;
     }
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        Log.v(LOG_TAG, "onCreate, inst=" + Integer.toHexString(hashCode()));
+        log("onCreate, inst=" + Integer.toHexString(hashCode()));
 
         // Create a simple layout
         LinearLayout contentView = new LinearLayout(this);
@@ -216,7 +224,7 @@
         initializeNetworkStates();
 
         if (mWifiManager.isWifiEnabled()) {
-            Log.v(LOG_TAG, "Clear Wifi before we start the test.");
+            log("Clear Wifi before we start the test.");
             removeConfiguredNetworksAndDisableWifi();
         }
         mWifiRegexs = mCM.getTetherableWifiRegexs();
@@ -240,9 +248,9 @@
     private void printNetConfig(String[] configuration) {
         for (int i = 0; i < configuration.length; i++) {
             if (i == 0) {
-                Log.v(LOG_TAG, "SSID: " + configuration[0]);
+                log("SSID: " + configuration[0]);
             } else {
-                Log.v(LOG_TAG, "      " + configuration[i]);
+                log("      " + configuration[i]);
             }
         }
     }
@@ -251,14 +259,14 @@
     public void initializeNetworkStates() {
         for (int networkType = NUM_NETWORK_TYPES - 1; networkType >=0; networkType--) {
             connectivityState[networkType] =  new NetworkState();
-            Log.v(LOG_TAG, "Initialize network state for " + networkType + ": " +
+            log("Initialize network state for " + networkType + ": " +
                     connectivityState[networkType].toString());
         }
     }
 
     // deposit a network state
     public void recordNetworkState(int networkType, State networkState) {
-        Log.v(LOG_TAG, "record network state for network " +  networkType +
+        log("record network state for network " +  networkType +
                 ", state is " + networkState);
         connectivityState[networkType].recordState(networkState);
     }
@@ -272,40 +280,41 @@
 
     // Validate the states recorded
     public boolean validateNetworkStates(int networkType) {
-        Log.v(LOG_TAG, "validate network state for " + networkType + ": ");
+        log("validate network state for " + networkType + ": ");
         return connectivityState[networkType].validateStateTransition();
     }
 
     // return result from network state validation
     public String getTransitionFailureReason(int networkType) {
-        Log.v(LOG_TAG, "get network state transition failure reason for " + networkType + ": " +
+        log("get network state transition failure reason for " + networkType + ": " +
                 connectivityState[networkType].toString());
         return connectivityState[networkType].getReason();
     }
 
     private void notifyNetworkConnectivityChange() {
         synchronized(connectivityObject) {
-            Log.v(LOG_TAG, "notify network connectivity changed");
+            log("notify network connectivity changed");
             connectivityObject.notifyAll();
         }
     }
     private void notifyScanResult() {
         synchronized (this) {
-            Log.v(LOG_TAG, "notify that scan results are available");
+            log("notify that scan results are available");
+            scanResultAvailable = true;
             this.notify();
         }
     }
 
     private void notifyWifiState() {
         synchronized (wifiObject) {
-            Log.v(LOG_TAG, "notify wifi state changed");
+            log("notify wifi state changed");
             wifiObject.notify();
         }
     }
 
     private void notifyWifiAPState() {
         synchronized (this) {
-            Log.v(LOG_TAG, "notify wifi AP state changed");
+            log("notify wifi AP state changed");
             this.notify();
         }
     }
@@ -319,7 +328,7 @@
             for (Object obj: tethered) {
                 String str = (String)obj;
                 for (String tethRex: mWifiRegexs) {
-                    Log.v(LOG_TAG, "str: " + str +"tethRex: " + tethRex);
+                    log("str: " + str +"tethRex: " + tethRex);
                     if (str.matches(tethRex)) {
                         wifiTethered = true;
                     }
@@ -329,7 +338,7 @@
             for (Object obj: errored) {
                 String str = (String)obj;
                 for (String tethRex: mWifiRegexs) {
-                    Log.v(LOG_TAG, "error: str: " + str +"tethRex: " + tethRex);
+                    log("error: str: " + str +"tethRex: " + tethRex);
                     if (str.matches(tethRex)) {
                         wifiErrored = true;
                     }
@@ -341,7 +350,7 @@
             } else if (wifiErrored) {
                 mWifiTetherResult = FAILURE;   // wifi tethering failed
             }
-            Log.v(LOG_TAG, "mWifiTetherResult: " + mWifiTetherResult);
+            log("mWifiTetherResult: " + mWifiTetherResult);
             this.notify();
         }
     }
@@ -357,12 +366,12 @@
                     return false;
                 } else {
                     // the broadcast has been sent out. the state has been changed.
-                    Log.v(LOG_TAG, "networktype: " + networkType + " state: " +
+                    log("networktype: " + networkType + " state: " +
                             mCM.getNetworkInfo(networkType));
                     return true;
                 }
             }
-            Log.v(LOG_TAG, "Wait for the connectivity state for network: " + networkType +
+            log("Wait for the connectivity state for network: " + networkType +
                     " to be " + expectedState.toString());
             synchronized (connectivityObject) {
                 try {
@@ -372,7 +381,7 @@
                 }
                 if ((mNetworkInfo.getType() != networkType) ||
                     (mNetworkInfo.getState() != expectedState)) {
-                    Log.v(LOG_TAG, "network state for " + mNetworkInfo.getType() +
+                    log("network state for " + mNetworkInfo.getType() +
                             "is: " + mNetworkInfo.getState());
                     continue;
                 }
@@ -393,7 +402,7 @@
                     return true;
                 }
             }
-            Log.v(LOG_TAG, "Wait for wifi state to be: " + expectedState);
+            log("Wait for wifi state to be: " + expectedState);
             synchronized (wifiObject) {
                 try {
                     wifiObject.wait(SHORT_TIMEOUT);
@@ -401,7 +410,7 @@
                     e.printStackTrace();
                 }
                 if (mWifiState != expectedState) {
-                    Log.v(LOG_TAG, "Wifi state is: " + mWifiState);
+                    log("Wifi state is: " + mWifiState);
                     continue;
                 }
                 return true;
@@ -421,7 +430,7 @@
                     return true;
                 }
             }
-            Log.v(LOG_TAG, "Wait for wifi AP state to be: " + expectedState);
+            log("Wait for wifi AP state to be: " + expectedState);
             synchronized (wifiObject) {
                 try {
                     wifiObject.wait(SHORT_TIMEOUT);
@@ -429,7 +438,7 @@
                     e.printStackTrace();
                 }
                 if (mWifiManager.getWifiApState() != expectedState) {
-                    Log.v(LOG_TAG, "Wifi state is: " + mWifiManager.getWifiApState());
+                    log("Wifi state is: " + mWifiManager.getWifiApState());
                     continue;
                 }
                 return true;
@@ -449,7 +458,7 @@
             if ((System.currentTimeMillis() - startTime) > timeout) {
                 return mWifiTetherResult;
             }
-            Log.v(LOG_TAG, "Wait for wifi tethering result.");
+            log("Wait for wifi tethering result.");
             synchronized (this) {
                 try {
                     this.wait(SHORT_TIMEOUT);
@@ -479,6 +488,64 @@
         return mWifiManager.setWifiEnabled(true);
     }
 
+    // Turn screen off
+    public void turnScreenOff() {
+        log("Turn screen off");
+        PowerManager pm =
+            (PowerManager) getSystemService(Context.POWER_SERVICE);
+        pm.goToSleep(SystemClock.uptimeMillis() + 100);
+    }
+
+    // Turn screen on
+    public void turnScreenOn() {
+        log("Turn screen on");
+        IPowerManager mPowerManagerService = IPowerManager.Stub.asInterface(
+                ServiceManager.getService("power"));;
+        try {
+            mPowerManagerService.userActivityWithForce(SystemClock.uptimeMillis(), false, true);
+        } catch (Exception e) {
+            log(e.toString());
+        }
+    }
+
+    /**
+     * @param pingServerList a list of servers that can be used for ping test, can be null
+     * @return true if the ping test is successful, false otherwise.
+     */
+    public boolean pingTest(String[] pingServerList) {
+        boolean result = false;
+        String[] hostList = {"www.google.com", "www.yahoo.com",
+                "www.bing.com", "www.facebook.com", "www.ask.com"};
+        if (pingServerList != null) {
+            hostList = pingServerList;
+        }
+        try {
+            // assume the chance that all servers are down is very small
+            for (int i = 0; i < hostList.length; i++ ) {
+                String host = hostList[i];
+                log("Start ping test, ping " + host);
+                Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
+                int status = p.waitFor();
+                if (status == 0) {
+                    // if any of the ping test is successful, return true
+                    result = true;
+                    break;
+                } else {
+                    result = false;
+                    log("ping " + host + " failed.");
+                }
+            }
+        } catch (UnknownHostException e) {
+            log("Ping test Fail: Unknown Host");
+        } catch (IOException e) {
+            log("Ping test Fail:  IOException");
+        } catch (InterruptedException e) {
+            log("Ping test Fail: InterruptedException");
+        }
+        log("return");
+        return result;
+    }
+
     /**
      * Associate the device to given SSID
      * If the device is already associated with a WiFi, disconnect and forget it,
@@ -503,13 +570,13 @@
 
         //If Wifi is not enabled, enable it
         if (!mWifiManager.isWifiEnabled()) {
-            Log.v(LOG_TAG, "Wifi is not enabled, enable it");
+            log("Wifi is not enabled, enable it");
             mWifiManager.setWifiEnabled(true);
         }
 
         List<ScanResult> netList = mWifiManager.getScanResults();
         if (netList == null) {
-            Log.v(LOG_TAG, "scan results are null");
+            log("scan results are null");
             // if no scan results are available, start active scan
             mWifiManager.startScanActive();
             mScanResultIsAvailable = false;
@@ -540,7 +607,7 @@
         for (int i = 0; i < netList.size(); i++) {
             ScanResult sr= netList.get(i);
             if (sr.SSID.equals(ssid)) {
-                Log.v(LOG_TAG, "found " + ssid + " in the scan result list");
+                log("found " + ssid + " in the scan result list");
                 int networkId = mWifiManager.addNetwork(config);
                 // Connect to network by disabling others.
                 mWifiManager.enableNetwork(networkId, true);
@@ -552,7 +619,7 @@
 
         List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
         if (netConfList.size() <= 0) {
-            Log.v(LOG_TAG, ssid + " is not available");
+            log(ssid + " is not available");
             return false;
         }
         return true;
@@ -575,7 +642,7 @@
             // remove other saved networks
             List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
             if (netConfList != null) {
-                Log.v(LOG_TAG, "remove configured network ids");
+                log("remove configured network ids");
                 for (int i = 0; i < netConfList.size(); i++) {
                     WifiConfiguration conf = new WifiConfiguration();
                     conf = netConfList.get(i);
@@ -640,7 +707,7 @@
         if (mWifiReceiver != null) {
             unregisterReceiver(mWifiReceiver);
         }
-        Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
+        log("onDestroy, inst=" + Integer.toHexString(hashCode()));
     }
 
     @Override
@@ -682,5 +749,8 @@
         }
         return super.onKeyDown(keyCode, event);
     }
-}
 
+    private void log(String message) {
+        Log.v(LOG_TAG, message);
+    }
+}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
index cc53ddc..8717a12 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
@@ -19,25 +19,33 @@
 
 import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
 import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
-import com.android.connectivitymanagertest.ConnectivityManagerTestRunner;
 
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiManager;
+import android.os.Environment;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
 
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+
 /**
  * Stress the wifi driver as access point.
  */
 public class WifiApStress
     extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
     private final static String TAG = "WifiApStress";
-    private ConnectivityManagerTestActivity mAct;
     private static String NETWORK_ID = "AndroidAPTest";
     private static String PASSWD = "androidwifi";
-    private int max_num;
+    private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
+    private ConnectivityManagerTestActivity mAct;
+    private int iterations;
+    private BufferedWriter mOutputWriter = null;
+    private int mLastIteration = 0;
 
     public WifiApStress() {
         super(ConnectivityManagerTestActivity.class);
@@ -47,11 +55,20 @@
     public void setUp() throws Exception {
         super.setUp();
         mAct = getActivity();
-        max_num = ((ConnectivityManagerStressTestRunner)getInstrumentation()).numStress;
+        ConnectivityManagerStressTestRunner mRunner =
+            (ConnectivityManagerStressTestRunner)getInstrumentation();
+        iterations = mRunner.mSoftapIterations;
+        mAct.turnScreenOn();
     }
 
     @Override
     public void tearDown() throws Exception {
+        // write the total number of iterations into output file
+        mOutputWriter = new BufferedWriter(new FileWriter(new File(
+                Environment.getExternalStorageDirectory(), OUTPUT_FILE)));
+        mOutputWriter.write(String.format("iteration %d out of %d\n", mLastIteration, iterations));
+        mOutputWriter.flush();
+        mOutputWriter.close();
         super.tearDown();
     }
 
@@ -67,22 +84,38 @@
         if (mAct.mWifiManager.isWifiEnabled()) {
             mAct.disableWifi();
         }
-        for (int i = 0; i < max_num; i++) {
+        int i;
+        for (i = 0; i < iterations; i++) {
             Log.v(TAG, "iteration: " + i);
+            mLastIteration = i;
             // enable Wifi tethering
             assertTrue(mAct.mWifiManager.setWifiApEnabled(config, true));
             // Wait for wifi ap state to be ENABLED
-            assertTrue(mAct.waitForWifiAPState(mAct.mWifiManager.WIFI_AP_STATE_ENABLED,
-                    mAct.LONG_TIMEOUT));
+            assertTrue(mAct.waitForWifiAPState(WifiManager.WIFI_AP_STATE_ENABLED,
+                    ConnectivityManagerTestActivity.LONG_TIMEOUT));
             // Wait for wifi tethering result
-            assertEquals(mAct.SUCCESS, mAct.waitForTetherStateChange(2*mAct.SHORT_TIMEOUT));
+            assertEquals(ConnectivityManagerTestActivity.SUCCESS,
+                    mAct.waitForTetherStateChange(2*ConnectivityManagerTestActivity.SHORT_TIMEOUT));
             // Allow the wifi tethering to be enabled for 10 seconds
             try {
                 Thread.sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
             } catch (Exception e) {
                 fail("thread in sleep is interrupted");
             }
+            assertTrue("no uplink data connection after Wi-Fi tethering", mAct.pingTest(null));
+            // Disable soft AP
             assertTrue(mAct.mWifiManager.setWifiApEnabled(config, false));
+            // Wait for 30 seconds until Wi-Fi tethering is stopped
+            try {
+                Thread.sleep(30 * 1000);
+                Log.v(TAG, "wait for Wi-Fi tethering to be disabled.");
+            } catch (Exception e) {
+                fail("thread in sleep is interrupted");
+            }
+            assertFalse("Wi-Fi AP disable failed", mAct.mWifiManager.isWifiApEnabled());
+        }
+        if (i == iterations) {
+            mLastIteration = iterations;
         }
     }
 
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
new file mode 100644
index 0000000..9adccc7
--- /dev/null
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2010, 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.android.connectivitymanagertest.stress;
+
+import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
+import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo.State;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiManager;
+import android.os.Environment;
+import android.os.PowerManager;
+import android.provider.Settings;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import android.util.Log;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Stress Wi-Fi connection, scanning and reconnection after sleep.
+ *
+ * To run this stress test suite, type
+ * adb shell am instrument -e class com.android.connectivitymanagertest.stress.WifiStressTest
+ *                  -w com.android.connectivitymanagertest/.ConnectivityManagerStressTestRunner
+ */
+public class WifiStressTest
+    extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
+    private final static String TAG = "WifiStressTest";
+
+    /**
+     * Wi-Fi idle time for default sleep policy
+     */
+    private final static long WIFI_IDLE_MS = 60 * 1000;
+
+    /**
+     * The delay for Wi-Fi to get into idle, after screen off + WIFI_IDEL_MS + WIFI_IDLE_DELAY
+     * the Wi-Fi should be in idle mode and device should be in cellular mode.
+     */
+    private final static long WIFI_IDLE_DELAY = 3 * 1000;
+
+    private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
+    private ConnectivityManagerTestActivity mAct;
+    private int mReconnectIterations;
+    private int mWifiSleepTime;
+    private int mScanIterations;
+    private String mSsid;
+    private String mPassword;
+    private ConnectivityManagerStressTestRunner mRunner;
+    private BufferedWriter mOutputWriter = null;
+
+    public WifiStressTest() {
+        super(ConnectivityManagerTestActivity.class);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mAct = getActivity();
+        mRunner = (ConnectivityManagerStressTestRunner) getInstrumentation();
+        mReconnectIterations = mRunner.mReconnectIterations;
+        mSsid = mRunner.mReconnectSsid;
+        mPassword = mRunner.mReconnectPassword;
+        mScanIterations = mRunner.mScanIterations;
+        mWifiSleepTime = mRunner.mSleepTime;
+        mOutputWriter = new BufferedWriter(new FileWriter(new File(
+                Environment.getExternalStorageDirectory(), OUTPUT_FILE), true));
+        if (!mAct.mWifiManager.isWifiEnabled()) {
+            if (!mAct.enableWifi()) {
+                tearDown();
+                fail("enable wifi failed.");
+            }
+            sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT,
+                    "Interruped while waiting for wifi on");
+        }
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        log("tearDown()");
+        if (mOutputWriter != null) {
+            mOutputWriter.close();
+        }
+        super.tearDown();
+    }
+
+    private void writeOutput(String s) {
+        log("write message: " + s);
+        if (mOutputWriter == null) {
+            log("no writer attached to file " + OUTPUT_FILE);
+            return;
+        }
+        try {
+            mOutputWriter.write(s + "\n");
+            mOutputWriter.flush();
+        } catch (IOException e) {
+            log("failed to write output.");
+        }
+    }
+
+    public void log(String message) {
+        Log.v(TAG, message);
+    }
+
+    private void sleep(long sometime, String errorMsg) {
+        try {
+            Thread.sleep(sometime);
+        } catch (InterruptedException e) {
+            fail(errorMsg);
+        }
+    }
+
+    /**
+     *  Stress Wifi Scanning
+     *  TODO: test the scanning quality for each frequency band
+     */
+    @LargeTest
+    public void testWifiScanning() {
+        int scanTimeSum = 0;
+        int i;
+        int ssidAppearInScanResultsCount = 0; // count times of given ssid appear in scan results.
+        for (i = 0; i < mScanIterations; i++) {
+            log("testWifiScanning: iteration: " + i);
+            int averageScanTime = 0;
+            if (i > 0) {
+                averageScanTime = scanTimeSum/i;
+            }
+            writeOutput(String.format("iteration %d out of %d",
+                    i, mScanIterations));
+            writeOutput(String.format("average scanning time is %d", averageScanTime));
+            writeOutput(String.format("ssid appear %d out of %d scan iterations",
+                    ssidAppearInScanResultsCount, i));
+            long startTime = System.currentTimeMillis();
+            mAct.scanResultAvailable = false;
+            assertTrue("start scan failed", mAct.mWifiManager.startScanActive());
+            while (true) {
+                if ((System.currentTimeMillis() - startTime) >
+                ConnectivityManagerTestActivity.WIFI_SCAN_TIMEOUT) {
+                    fail("Wifi scanning takes more than " +
+                            ConnectivityManagerTestActivity.WIFI_SCAN_TIMEOUT + " ms");
+                }
+                synchronized(mAct) {
+                    try {
+                        mAct.wait(ConnectivityManagerTestActivity.WAIT_FOR_SCAN_RESULT);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                    if (mAct.scanResultAvailable) {
+                        long scanTime = (System.currentTimeMillis() - startTime);
+                        scanTimeSum += scanTime;
+                        break;
+                    }
+                }
+            }
+            if ((mAct.mWifiManager.getScanResults() == null) ||
+                    (mAct.mWifiManager.getScanResults().size() <= 0)) {
+                fail("Scan results are empty ");
+            }
+
+            List<ScanResult> netList = mAct.mWifiManager.getScanResults();
+            if (netList != null) {
+                log("size of scan result list: " + netList.size());
+                for (int s = 0; s < netList.size(); s++) {
+                    ScanResult sr= netList.get(s);
+                    log(String.format("scan result for %s is: %s", sr.SSID, sr.toString()));
+                    log(String.format("signal level for %s is %d ", sr.SSID, sr.level));
+                    if (sr.SSID.equals(mSsid)) {
+                        ssidAppearInScanResultsCount += 1;
+                        log("Number of times " + mSsid + " appear in the scan list: " +
+                                ssidAppearInScanResultsCount);
+                        break;
+                    }
+                }
+            }
+        }
+        if (i == mScanIterations) {
+            writeOutput(String.format("iteration %d out of %d",
+                    i, mScanIterations));
+            writeOutput(String.format("average scanning time is %d", scanTimeSum/mScanIterations));
+            writeOutput(String.format("ssid appear %d out of %d scan iterations",
+                    ssidAppearInScanResultsCount, mScanIterations));
+        }
+    }
+
+    // Stress Wifi reconnection to secure net after sleep
+    @LargeTest
+    public void testWifiReconnectionAfterSleep() {
+        int value = Settings.System.getInt(mRunner.getContext().getContentResolver(),
+                Settings.System.WIFI_SLEEP_POLICY, -1);
+        if (value < 0) {
+            Settings.System.putInt(mRunner.getContext().getContentResolver(),
+                    Settings.System.WIFI_SLEEP_POLICY, Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
+            log("set wifi sleep policy to default value");
+        }
+        Settings.Secure.putLong(mRunner.getContext().getContentResolver(),
+                Settings.Secure.WIFI_IDLE_MS, WIFI_IDLE_MS);
+
+        // Connect to a Wi-Fi network
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = mSsid;
+        config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+        if (mPassword.matches("[0-9A-Fa-f]{64}")) {
+            config.preSharedKey = mPassword;
+        } else {
+            config.preSharedKey = '"' + mPassword + '"';
+        }
+        assertTrue("Failed to connect to Wi-Fi network: " + mSsid,
+                mAct.connectToWifiWithConfiguration(config));
+        assertTrue(mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+                ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+        assertTrue(mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                ConnectivityManagerTestActivity.LONG_TIMEOUT));
+        // Run ping test to verify the data connection
+        assertTrue("Wi-Fi is connected, but no data connection.", mAct.pingTest(null));
+
+        int i;
+        for (i = 0; i < mReconnectIterations; i++) {
+            // 1. Put device into sleep mode
+            // 2. Wait for the device to sleep for sometime, verify wi-fi is off and mobile is on.
+            // 3. Maintain the sleep mode for some time,
+            // 4. Verify the Wi-Fi is still off, and data is on
+            // 5. Wake up the device, verify Wi-Fi is enabled and connected.
+            writeOutput(String.format("iteration %d out of %d",
+                    i, mReconnectIterations));
+            log("iteration: " + i);
+            mAct.turnScreenOff();
+            PowerManager pm =
+                (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
+            assertFalse(pm.isScreenOn());
+            sleep(WIFI_IDLE_MS, "Interruped while wait for wifi to be idle");
+            assertTrue("Wait for Wi-Fi to idle timeout",
+                    mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
+                    6 * ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+            // use long timeout as the pppd startup may take several retries.
+            assertTrue("Wait for cellular connection timeout",
+                    mAct.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
+                    ConnectivityManagerTestActivity.LONG_TIMEOUT));
+            sleep(mWifiSleepTime + WIFI_IDLE_DELAY, "Interrupted while device is in sleep mode");
+            // Verify the wi-fi is still off and data connection is on
+            assertEquals("Wi-Fi is reconnected", State.DISCONNECTED,
+                    mAct.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState());
+
+            assertEquals("Cellular connection is down", State.CONNECTED,
+                         mAct.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState());
+            assertTrue("Mobile is connected, but no data connection.", mAct.pingTest(null));
+
+            // Turn screen on again
+            mAct.turnScreenOn();
+            assertTrue("Wait for Wi-Fi enable timeout after wake up",
+                    mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
+                    ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+            assertTrue("Wait for Wi-Fi connection timeout after wake up",
+                    mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
+                    ConnectivityManagerTestActivity.LONG_TIMEOUT));
+            assertTrue("Reconnect to Wi-Fi network, but no data connection.", mAct.pingTest(null));
+        }
+        if (i == mReconnectIterations) {
+            writeOutput(String.format("iteration %d out of %d",
+                    i, mReconnectIterations));
+        }
+    }
+}