1/*
2 * Copyright (C) 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.connectivitymanagertest.stress;
18
19import android.content.Context;
20import android.net.ConnectivityManager;
21import android.net.NetworkInfo.State;
22import android.net.wifi.ScanResult;
23import android.net.wifi.WifiConfiguration;
24import android.net.wifi.WifiConfiguration.IpAssignment;
25import android.net.wifi.WifiConfiguration.KeyMgmt;
26import android.net.wifi.WifiConfiguration.ProxySettings;
27import android.net.wifi.WifiManager;
28import android.os.Environment;
29import android.os.PowerManager;
30import android.provider.Settings;
31import android.view.KeyEvent;
32import android.test.ActivityInstrumentationTestCase2;
33import android.test.suitebuilder.annotation.LargeTest;
34import android.util.Log;
35
36import com.android.connectivitymanagertest.ConnectivityManagerStressTestRunner;
37import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
38
39import java.io.BufferedWriter;
40import java.io.File;
41import java.io.FileWriter;
42import java.io.IOException;
43import java.util.List;
44
45/**
46 * Stress Wi-Fi connection, scanning and reconnection after sleep.
47 *
48 * To run this stress test suite, type
49 * adb shell am instrument -e class com.android.connectivitymanagertest.stress.WifiStressTest
50 *                  -w com.android.connectivitymanagertest/.ConnectivityManagerStressTestRunner
51 */
52public class WifiStressTest
53    extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
54    private final static String TAG = "WifiStressTest";
55
56    /**
57     * Wi-Fi idle time for default sleep policy
58     */
59    private final static long WIFI_IDLE_MS = 60 * 1000;
60
61    /**
62     * Delay after issuing wifi shutdown.
63     * The framework keep driver up for at leat 2 minutes to avoid problems
64     * that a quick shutdown could cause on wext driver and protentially
65     * on cfg based driver
66     */
67    private final static long WIFI_SHUTDOWN_DELAY = 2 * 60 * 1000;
68
69    private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
70    private ConnectivityManagerTestActivity mAct;
71    private int mReconnectIterations;
72    private int mWifiSleepTime;
73    private int mScanIterations;
74    private String mSsid;
75    private String mPassword;
76    private ConnectivityManagerStressTestRunner mRunner;
77    private BufferedWriter mOutputWriter = null;
78    private boolean mWifiOnlyFlag;
79
80    public WifiStressTest() {
81        super(ConnectivityManagerTestActivity.class);
82    }
83
84    @Override
85    public void setUp() throws Exception {
86        super.setUp();
87
88        mAct = getActivity();
89        mRunner = (ConnectivityManagerStressTestRunner) getInstrumentation();
90        mReconnectIterations = mRunner.mReconnectIterations;
91        mSsid = mRunner.mReconnectSsid;
92        mPassword = mRunner.mReconnectPassword;
93        mScanIterations = mRunner.mScanIterations;
94        mWifiSleepTime = mRunner.mSleepTime;
95        mWifiOnlyFlag = mRunner.mWifiOnlyFlag;
96        log(String.format("mReconnectIterations(%d), mSsid(%s), mPassword(%s),"
97            + "mScanIterations(%d), mWifiSleepTime(%d)", mReconnectIterations, mSsid,
98            mPassword, mScanIterations, mWifiSleepTime));
99        mOutputWriter = new BufferedWriter(new FileWriter(new File(
100                Environment.getExternalStorageDirectory(), OUTPUT_FILE), true));
101        mAct.turnScreenOn();
102        if (!mAct.mWifiManager.isWifiEnabled()) {
103            log("Enable wi-fi before stress tests.");
104            if (!mAct.enableWifi()) {
105                tearDown();
106                fail("enable wifi failed.");
107            }
108            sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT,
109                    "Interruped while waiting for wifi on");
110        }
111    }
112
113    @Override
114    public void tearDown() throws Exception {
115        log("tearDown()");
116        if (mOutputWriter != null) {
117            mOutputWriter.close();
118        }
119        super.tearDown();
120    }
121
122    private void writeOutput(String s) {
123        log("write message: " + s);
124        if (mOutputWriter == null) {
125            log("no writer attached to file " + OUTPUT_FILE);
126            return;
127        }
128        try {
129            mOutputWriter.write(s + "\n");
130            mOutputWriter.flush();
131        } catch (IOException e) {
132            log("failed to write output.");
133        }
134    }
135
136    public void log(String message) {
137        Log.v(TAG, message);
138    }
139
140    private void sleep(long sometime, String errorMsg) {
141        try {
142            Thread.sleep(sometime);
143        } catch (InterruptedException e) {
144            fail(errorMsg);
145        }
146    }
147
148    /**
149     *  Stress Wifi Scanning
150     *  TODO: test the scanning quality for each frequency band
151     */
152    @LargeTest
153    public void testWifiScanning() {
154        int scanTimeSum = 0;
155        int i;
156        int ssidAppearInScanResultsCount = 0; // count times of given ssid appear in scan results.
157        for (i = 0; i < mScanIterations; i++) {
158            log("testWifiScanning: iteration: " + i);
159            int averageScanTime = 0;
160            if (i > 0) {
161                averageScanTime = scanTimeSum/i;
162            }
163            writeOutput(String.format("iteration %d out of %d",
164                    i, mScanIterations));
165            writeOutput(String.format("average scanning time is %d", averageScanTime));
166            writeOutput(String.format("ssid appear %d out of %d scan iterations",
167                    ssidAppearInScanResultsCount, i));
168            long startTime = System.currentTimeMillis();
169            mAct.scanResultAvailable = false;
170            assertTrue("start scan failed", mAct.mWifiManager.startScanActive());
171            while (true) {
172                if ((System.currentTimeMillis() - startTime) >
173                ConnectivityManagerTestActivity.WIFI_SCAN_TIMEOUT) {
174                    fail("Wifi scanning takes more than " +
175                            ConnectivityManagerTestActivity.WIFI_SCAN_TIMEOUT + " ms");
176                }
177                synchronized(mAct) {
178                    try {
179                        mAct.wait(ConnectivityManagerTestActivity.WAIT_FOR_SCAN_RESULT);
180                    } catch (InterruptedException e) {
181                        e.printStackTrace();
182                    }
183                    if (mAct.scanResultAvailable) {
184                        long scanTime = (System.currentTimeMillis() - startTime);
185                        scanTimeSum += scanTime;
186                        break;
187                    }
188                }
189            }
190            if ((mAct.mWifiManager.getScanResults() == null) ||
191                    (mAct.mWifiManager.getScanResults().size() <= 0)) {
192                fail("Scan results are empty ");
193            }
194
195            List<ScanResult> netList = mAct.mWifiManager.getScanResults();
196            if (netList != null) {
197                log("size of scan result list: " + netList.size());
198                for (int s = 0; s < netList.size(); s++) {
199                    ScanResult sr= netList.get(s);
200                    log(String.format("scan result for %s is: %s", sr.SSID, sr.toString()));
201                    log(String.format("signal level for %s is %d ", sr.SSID, sr.level));
202                    if (sr.SSID.equals(mSsid)) {
203                        ssidAppearInScanResultsCount += 1;
204                        log("Number of times " + mSsid + " appear in the scan list: " +
205                                ssidAppearInScanResultsCount);
206                        break;
207                    }
208                }
209            }
210        }
211        if (i == mScanIterations) {
212            writeOutput(String.format("iteration %d out of %d",
213                    i, mScanIterations));
214            writeOutput(String.format("average scanning time is %d", scanTimeSum/mScanIterations));
215            writeOutput(String.format("ssid appear %d out of %d scan iterations",
216                    ssidAppearInScanResultsCount, mScanIterations));
217        }
218    }
219
220    // Stress Wifi reconnection to secure net after sleep
221    @LargeTest
222    public void testWifiReconnectionAfterSleep() {
223        int value = Settings.Global.getInt(mRunner.getContext().getContentResolver(),
224                Settings.Global.WIFI_SLEEP_POLICY, -1);
225        log("wifi sleep policy is: " + value);
226        if (value != Settings.Global.WIFI_SLEEP_POLICY_DEFAULT) {
227            Settings.Global.putInt(mRunner.getContext().getContentResolver(),
228                    Settings.Global.WIFI_SLEEP_POLICY, Settings.Global.WIFI_SLEEP_POLICY_DEFAULT);
229            log("set wifi sleep policy to default value");
230        }
231        Settings.Global.putLong(mRunner.getContext().getContentResolver(),
232                Settings.Global.WIFI_IDLE_MS, WIFI_IDLE_MS);
233
234        // Connect to a Wi-Fi network
235        WifiConfiguration config = new WifiConfiguration();
236        config.SSID = mSsid;
237        config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
238        if (mPassword.matches("[0-9A-Fa-f]{64}")) {
239            config.preSharedKey = mPassword;
240        } else {
241            config.preSharedKey = '"' + mPassword + '"';
242        }
243        config.ipAssignment = IpAssignment.DHCP;
244        config.proxySettings = ProxySettings.NONE;
245
246        assertTrue("Failed to connect to Wi-Fi network: " + mSsid,
247                mAct.connectToWifiWithConfiguration(config));
248        assertTrue(mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
249                ConnectivityManagerTestActivity.SHORT_TIMEOUT));
250        assertTrue(mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
251                ConnectivityManagerTestActivity.LONG_TIMEOUT));
252        // Run ping test to verify the data connection
253        assertTrue("Wi-Fi is connected, but no data connection.", mAct.pingTest(null));
254
255        int i;
256        long sum = 0;
257        for (i = 0; i < mReconnectIterations; i++) {
258            // 1. Put device into sleep mode
259            // 2. Wait for the device to sleep for sometime, verify wi-fi is off and mobile is on.
260            // 3. Maintain the sleep mode for some time,
261            // 4. Verify the Wi-Fi is still off, and data is on
262            // 5. Wake up the device, verify Wi-Fi is enabled and connected.
263            writeOutput(String.format("iteration %d out of %d",
264                    i, mReconnectIterations));
265            log("iteration: " + i);
266            mAct.turnScreenOff();
267            PowerManager pm =
268                (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
269            assertFalse(pm.isScreenOn());
270            sleep(WIFI_IDLE_MS + WIFI_SHUTDOWN_DELAY, "Interruped while wait for wifi to be idle");
271            assertTrue("Wait for Wi-Fi to idle timeout",
272                    mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
273                    6 * ConnectivityManagerTestActivity.SHORT_TIMEOUT));
274            if (!mWifiOnlyFlag) {
275                // use long timeout as the pppd startup may take several retries.
276                assertTrue("Wait for cellular connection timeout",
277                        mAct.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
278                        2 * ConnectivityManagerTestActivity.LONG_TIMEOUT));
279            }
280            sleep(mWifiSleepTime, "Interrupted while device is in sleep mode");
281            // Verify the wi-fi is still off and data connection is on
282            assertEquals("Wi-Fi is reconnected", State.DISCONNECTED,
283                    mAct.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState());
284
285            if (!mWifiOnlyFlag) {
286                assertEquals("Cellular connection is down", State.CONNECTED,
287                             mAct.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState());
288                assertTrue("Mobile is connected, but no data connection.", mAct.pingTest(null));
289            }
290
291            // Turn screen on again
292            mAct.turnScreenOn();
293            // Wait for 2 seconds for the lock screen
294            sleep(2 * 1000, "wait 2 seconds for lock screen");
295            // Disable lock screen by inject menu key event
296            mRunner.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
297
298            // Measure the time for Wi-Fi to get connected
299            long startTime = System.currentTimeMillis();
300            assertTrue("Wait for Wi-Fi enable timeout after wake up",
301                    mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
302                    ConnectivityManagerTestActivity.SHORT_TIMEOUT));
303            assertTrue("Wait for Wi-Fi connection timeout after wake up",
304                    mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
305                    6 * ConnectivityManagerTestActivity.LONG_TIMEOUT));
306            long connectionTime = System.currentTimeMillis() - startTime;
307            sum += connectionTime;
308            log("average reconnection time is: " + sum/(i+1));
309
310            assertTrue("Reconnect to Wi-Fi network, but no data connection.", mAct.pingTest(null));
311        }
312        if (i == mReconnectIterations) {
313            writeOutput(String.format("iteration %d out of %d",
314                    i, mReconnectIterations));
315        }
316    }
317}
318