| /* |
| * 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; |
| |
| import android.app.KeyguardManager; |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.net.ConnectivityManager; |
| import android.net.NetworkInfo; |
| import android.net.NetworkInfo.State; |
| import android.net.wifi.ScanResult; |
| import android.net.wifi.WifiConfiguration; |
| import android.net.wifi.WifiManager; |
| import android.os.PowerManager; |
| import android.os.SystemClock; |
| import android.test.InstrumentationTestCase; |
| import android.util.Log; |
| import android.view.KeyEvent; |
| |
| import java.io.IOException; |
| import java.net.UnknownHostException; |
| import java.util.List; |
| |
| |
| /** |
| * Base InstrumentationTestCase for Connectivity Manager (CM) test suite |
| * |
| * It registers connectivity manager broadcast and WiFi broadcast to provide |
| * network connectivity information, also provides a set of utility functions |
| * to modify and verify connectivity states. |
| * |
| * A CM test case should extend this base class. |
| */ |
| public class ConnectivityManagerTestBase extends InstrumentationTestCase { |
| |
| private static final String[] PING_HOST_LIST = { |
| "www.google.com", "www.yahoo.com", "www.bing.com", "www.facebook.com", "www.ask.com"}; |
| |
| protected static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds |
| protected static final int WIFI_SCAN_TIMEOUT = 50 * 1000; // 50 seconds |
| protected static final int SHORT_TIMEOUT = 5 * 1000; // 5 seconds |
| protected static final long LONG_TIMEOUT = 2 * 60 * 1000; // 2 minutes |
| protected static final long WIFI_CONNECTION_TIMEOUT = 5 * 60 * 1000; // 5 minutes |
| // 2 minutes timer between wifi stop and start |
| protected static final long WIFI_STOP_START_INTERVAL = 2 * 60 * 1000; // 2 minutes |
| // Set ping test timer to be 3 minutes |
| protected static final long PING_TIMER = 3 * 60 *1000; // 3 minutes |
| protected static final int SUCCESS = 0; // for Wifi tethering state change |
| protected static final int FAILURE = 1; |
| protected static final int INIT = -1; |
| |
| protected final String mLogTag; |
| |
| private ConnectivityReceiver mConnectivityReceiver = null; |
| private WifiReceiver mWifiReceiver = null; |
| |
| private long mLastConnectivityChangeTime = -1; |
| protected ConnectivityManager mCm; |
| private Context mContext; |
| protected List<ScanResult> mLastScanResult; |
| protected Object mWifiScanResultLock = new Object(); |
| |
| /* Control Wifi States */ |
| public WifiManager mWifiManager; |
| |
| public ConnectivityManagerTestBase(String logTag) { |
| super(); |
| mLogTag = logTag; |
| } |
| |
| protected long getLastConnectivityChangeTime() { |
| return mLastConnectivityChangeTime; |
| } |
| |
| /** |
| * A wrapper of a broadcast receiver which provides network connectivity information |
| * for all kinds of network: wifi, mobile, etc. |
| */ |
| private class ConnectivityReceiver extends BroadcastReceiver { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| mLastConnectivityChangeTime = SystemClock.uptimeMillis(); |
| logv("ConnectivityReceiver: " + intent); |
| String action = intent.getAction(); |
| if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { |
| Log.v("ConnectivityReceiver", "onReceive() called with " + intent); |
| } |
| } |
| } |
| |
| private class WifiReceiver extends BroadcastReceiver { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| String action = intent.getAction(); |
| Log.v("WifiReceiver", "onReceive() is calleld with " + intent); |
| if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { |
| logv("scan results are available"); |
| synchronized (mWifiScanResultLock) { |
| mLastScanResult = mWifiManager.getScanResults(); |
| mWifiScanResultLock.notifyAll(); |
| } |
| } |
| } |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| mLastScanResult = null; |
| mContext = getInstrumentation().getContext(); |
| |
| // Get an instance of ConnectivityManager |
| mCm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); |
| // Get an instance of WifiManager |
| mWifiManager =(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE); |
| |
| if (mWifiManager.isWifiApEnabled()) { |
| // if soft AP is enabled, disable it |
| mWifiManager.setWifiApEnabled(null, false); |
| logv("Disable soft ap"); |
| } |
| |
| // register a connectivity receiver for CONNECTIVITY_ACTION; |
| mConnectivityReceiver = new ConnectivityReceiver(); |
| mContext.registerReceiver(mConnectivityReceiver, |
| new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); |
| |
| mWifiReceiver = new WifiReceiver(); |
| IntentFilter mIntentFilter = new IntentFilter(); |
| mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); |
| mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); |
| mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); |
| mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); |
| mIntentFilter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); |
| mIntentFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); |
| mContext.registerReceiver(mWifiReceiver, mIntentFilter); |
| |
| logv("Clear Wifi before we start the test."); |
| removeConfiguredNetworksAndDisableWifi(); |
| } |
| |
| // wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING, |
| // DISCONNECTED, UNKNOWN |
| protected boolean waitForNetworkState(int networkType, State expectedState, long timeout) { |
| long startTime = SystemClock.uptimeMillis(); |
| while (true) { |
| NetworkInfo ni = mCm.getNetworkInfo(networkType); |
| if (ni != null && expectedState.equals(ni.getState())) { |
| logv("waitForNetworkState success: %s", ni); |
| return true; |
| } |
| if ((SystemClock.uptimeMillis() - startTime) > timeout) { |
| logv("waitForNetworkState timeout: %s", ni); |
| return false; |
| } |
| logv("waitForNetworkState interim: %s", ni); |
| SystemClock.sleep(SHORT_TIMEOUT); |
| } |
| } |
| |
| // wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED, |
| // WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN |
| protected boolean waitForWifiState(int expectedState, long timeout) { |
| long startTime = SystemClock.uptimeMillis(); |
| while (true) { |
| int state = mWifiManager.getWifiState(); |
| if (state == expectedState) { |
| logv("waitForWifiState success: state=" + state); |
| return true; |
| } |
| if ((SystemClock.uptimeMillis() - startTime) > timeout) { |
| logv("waitForWifiState timeout: expected=%d, actual=%d", expectedState, state); |
| return false; |
| } |
| logv("waitForWifiState interim: expected=%d, actual=%d", expectedState, state); |
| SystemClock.sleep(SHORT_TIMEOUT); |
| } |
| } |
| |
| // Wait for Wifi AP state: WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, |
| // WIFI_AP_STATE_ENABLED, WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN |
| protected boolean waitForWifiApState(int expectedState, long timeout) { |
| long startTime = SystemClock.uptimeMillis(); |
| while (true) { |
| int state = mWifiManager.getWifiApState(); |
| if (state == expectedState) { |
| logv("waitForWifiAPState success: state=" + state); |
| return true; |
| } |
| if ((SystemClock.uptimeMillis() - startTime) > timeout) { |
| logv(String.format("waitForWifiAPState timeout: expected=%d, actual=%d", |
| expectedState, state)); |
| return false; |
| } |
| logv(String.format("waitForWifiAPState interim: expected=%d, actual=%d", |
| expectedState, state)); |
| SystemClock.sleep(SHORT_TIMEOUT); |
| } |
| } |
| |
| /** |
| * Wait for the wifi tethering result: |
| * @param timeout is the maximum waiting time |
| * @return SUCCESS if tethering result is successful |
| * FAILURE if tethering result returns error. |
| */ |
| protected boolean waitForTetherStateChange(long timeout) { |
| long startTime = SystemClock.uptimeMillis(); |
| String[] wifiRegexes = mCm.getTetherableWifiRegexs(); |
| while (true) { |
| if ((SystemClock.uptimeMillis() - startTime) > timeout) { |
| return false; |
| } |
| String[] active = mCm.getTetheredIfaces(); |
| String[] error = mCm.getTetheringErroredIfaces(); |
| for (String iface: active) { |
| for (String regex: wifiRegexes) { |
| if (iface.matches(regex)) { |
| return true; |
| } |
| } |
| } |
| for (String iface: error) { |
| for (String regex: wifiRegexes) { |
| if (iface.matches(regex)) { |
| return false; |
| } |
| } |
| } |
| SystemClock.sleep(SHORT_TIMEOUT); |
| } |
| } |
| |
| // Return true if device is currently connected to mobile network |
| protected boolean isConnectedToMobile() { |
| return (mCm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_MOBILE); |
| } |
| |
| // Return true if device is currently connected to Wifi |
| protected boolean isConnectedToWifi() { |
| return (mCm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI); |
| } |
| |
| protected boolean enableWifi() { |
| return mWifiManager.setWifiEnabled(true); |
| } |
| |
| // Turn screen off |
| protected void turnScreenOff() { |
| logv("Turn screen off"); |
| PowerManager pm = |
| (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); |
| pm.goToSleep(SystemClock.uptimeMillis()); |
| } |
| |
| // Turn screen on |
| protected void turnScreenOn() { |
| logv("Turn screen on"); |
| PowerManager pm = |
| (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); |
| pm.wakeUp(SystemClock.uptimeMillis()); |
| // disable lock screen |
| KeyguardManager km = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); |
| if (km.inKeyguardRestrictedInputMode()) { |
| sendKeys(KeyEvent.KEYCODE_MENU); |
| } |
| } |
| |
| /** |
| * @return true if the ping test is successful, false otherwise. |
| */ |
| protected boolean pingTest() { |
| long startTime = System.currentTimeMillis(); |
| while ((System.currentTimeMillis() - startTime) < PING_TIMER) { |
| try { |
| // assume the chance that all servers are down is very small |
| for (String host : PING_HOST_LIST) { |
| logv("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 |
| return true; |
| } |
| } |
| } catch (UnknownHostException e) { |
| logv("Ping test Fail: Unknown Host"); |
| } catch (IOException e) { |
| logv("Ping test Fail: IOException"); |
| } catch (InterruptedException e) { |
| logv("Ping test Fail: InterruptedException"); |
| } |
| SystemClock.sleep(SHORT_TIMEOUT); |
| } |
| // ping test timeout |
| return false; |
| } |
| |
| /** |
| * Associate the device to given SSID |
| * If the device is already associated with a WiFi, disconnect and forget it, |
| * We don't verify whether the connection is successful or not, leave this to the test |
| */ |
| protected boolean connectToWifi(String ssid, String password) { |
| WifiConfiguration config; |
| if (password == null) { |
| config = WifiConfigurationHelper.createOpenConfig(ssid); |
| } else { |
| config = WifiConfigurationHelper.createPskConfig(ssid, password); |
| } |
| return connectToWifiWithConfiguration(config); |
| } |
| |
| /** |
| * Connect to Wi-Fi with the given configuration. Note the SSID in the configuration |
| * is pure string, we need to convert it to quoted string. |
| */ |
| protected boolean connectToWifiWithConfiguration(WifiConfiguration config) { |
| // If Wifi is not enabled, enable it |
| if (!mWifiManager.isWifiEnabled()) { |
| logv("Wifi is not enabled, enable it"); |
| mWifiManager.setWifiEnabled(true); |
| // wait for the wifi state change before start scanning. |
| if (!waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT)) { |
| logv("wait for WIFI_STATE_ENABLED failed"); |
| return false; |
| } |
| } |
| |
| // Save network configuration and connect to network without scanning |
| mWifiManager.connect(config, |
| new WifiManager.ActionListener() { |
| @Override |
| public void onSuccess() { |
| } |
| |
| @Override |
| public void onFailure(int reason) { |
| logv("connect failure " + reason); |
| } |
| }); |
| return true; |
| } |
| |
| /* |
| * Disconnect from the current AP and remove configured networks. |
| */ |
| protected boolean disconnectAP() { |
| // remove saved networks |
| if (!mWifiManager.isWifiEnabled()) { |
| logv("Enabled wifi before remove configured networks"); |
| mWifiManager.setWifiEnabled(true); |
| SystemClock.sleep(SHORT_TIMEOUT); |
| } |
| |
| List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks(); |
| if (wifiConfigList == null) { |
| logv("no configuration list is null"); |
| return true; |
| } |
| logv("size of wifiConfigList: " + wifiConfigList.size()); |
| for (WifiConfiguration wifiConfig: wifiConfigList) { |
| logv("remove wifi configuration: " + wifiConfig.networkId); |
| int netId = wifiConfig.networkId; |
| mWifiManager.forget(netId, new WifiManager.ActionListener() { |
| @Override |
| public void onSuccess() { |
| } |
| |
| @Override |
| public void onFailure(int reason) { |
| logv("Failed to forget " + reason); |
| } |
| }); |
| } |
| return true; |
| } |
| /** |
| * Disable Wifi |
| * @return true if Wifi is disabled successfully |
| */ |
| protected boolean disableWifi() { |
| return mWifiManager.setWifiEnabled(false); |
| } |
| |
| /** |
| * Remove configured networks and disable wifi |
| */ |
| protected boolean removeConfiguredNetworksAndDisableWifi() { |
| if (!disconnectAP()) { |
| return false; |
| } |
| SystemClock.sleep(SHORT_TIMEOUT); |
| if (!mWifiManager.setWifiEnabled(false)) { |
| return false; |
| } |
| SystemClock.sleep(SHORT_TIMEOUT); |
| return true; |
| } |
| |
| protected static String convertToQuotedString(String string) { |
| return "\"" + string + "\""; |
| } |
| |
| protected boolean waitForActiveNetworkConnection(long timeout) { |
| long startTime = SystemClock.uptimeMillis(); |
| while (true) { |
| NetworkInfo ni = mCm.getActiveNetworkInfo(); |
| if (ni != null && ni.isConnected()) { |
| return true; |
| } |
| if ((SystemClock.uptimeMillis() - startTime) > timeout) { |
| logv("waitForActiveNetworkConnection timeout: %s", ni); |
| return false; |
| } |
| logv("waitForActiveNetworkConnection interim: %s", ni); |
| SystemClock.sleep(SHORT_TIMEOUT); |
| } |
| } |
| |
| protected boolean waitUntilNoActiveNetworkConnection(long timeout) { |
| long startTime = SystemClock.uptimeMillis(); |
| while (true) { |
| NetworkInfo ni = mCm.getActiveNetworkInfo(); |
| if (ni == null) { |
| return true; |
| } |
| if ((SystemClock.uptimeMillis() - startTime) > timeout) { |
| logv("waitForActiveNetworkConnection timeout: %s", ni); |
| return false; |
| } |
| logv("waitForActiveNetworkConnection interim: %s", ni); |
| SystemClock.sleep(SHORT_TIMEOUT); |
| } |
| } |
| |
| // use ping request against Google public DNS to verify connectivity |
| protected boolean checkNetworkConnectivity() { |
| assertTrue("no active network connection", waitForActiveNetworkConnection(LONG_TIMEOUT)); |
| return pingTest(); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception{ |
| //Unregister receiver |
| if (mConnectivityReceiver != null) { |
| mContext.unregisterReceiver(mConnectivityReceiver); |
| } |
| if (mWifiReceiver != null) { |
| mContext.unregisterReceiver(mWifiReceiver); |
| } |
| super.tearDown(); |
| } |
| |
| protected void logv(String format, Object... args) { |
| Log.v(mLogTag, String.format(format, args)); |
| } |
| |
| /** |
| * Connect to the provided Wi-Fi network |
| * @param config is the network configuration |
| * @throws AssertionError if fails to associate and connect to wifi ap |
| */ |
| protected void connectToWifi(WifiConfiguration config) { |
| // step 1: connect to the test access point |
| assertTrue("failed to associate with " + config.SSID, |
| connectToWifiWithConfiguration(config)); |
| |
| // step 2: verify Wifi state and network state; |
| assertTrue("wifi state not connected with " + config.SSID, |
| waitForNetworkState(ConnectivityManager.TYPE_WIFI, |
| State.CONNECTED, WIFI_CONNECTION_TIMEOUT)); |
| |
| // step 3: verify the current connected network is the given SSID |
| assertNotNull("no active wifi info", mWifiManager.getConnectionInfo()); |
| assertEquals("SSID mismatch", config.SSID, mWifiManager.getConnectionInfo().getSSID()); |
| } |
| } |