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