Home | History | Annotate | Download | only in connectivitymanagertest
      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 
     17 package com.android.connectivitymanagertest;
     18 
     19 import android.app.KeyguardManager;
     20 import android.content.BroadcastReceiver;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentFilter;
     24 import android.net.ConnectivityManager;
     25 import android.net.NetworkInfo;
     26 import android.net.NetworkInfo.State;
     27 import android.net.wifi.ScanResult;
     28 import android.net.wifi.WifiConfiguration;
     29 import android.net.wifi.WifiManager;
     30 import android.os.PowerManager;
     31 import android.os.SystemClock;
     32 import android.test.InstrumentationTestCase;
     33 import android.util.Log;
     34 import android.view.KeyEvent;
     35 
     36 import java.io.IOException;
     37 import java.net.UnknownHostException;
     38 import java.util.List;
     39 
     40 
     41 /**
     42  * Base InstrumentationTestCase for Connectivity Manager (CM) test suite
     43  *
     44  * It registers connectivity manager broadcast and WiFi broadcast to provide
     45  * network connectivity information, also provides a set of utility functions
     46  * to modify and verify connectivity states.
     47  *
     48  * A CM test case should extend this base class.
     49  */
     50 public class ConnectivityManagerTestBase extends InstrumentationTestCase {
     51 
     52     private static final String[] PING_HOST_LIST = {
     53         "www.google.com", "www.yahoo.com", "www.bing.com", "www.facebook.com", "www.ask.com"};
     54 
     55     protected static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
     56     protected static final int WIFI_SCAN_TIMEOUT = 50 * 1000; // 50 seconds
     57     protected static final int SHORT_TIMEOUT = 5 * 1000; // 5 seconds
     58     protected static final long LONG_TIMEOUT = 2 * 60 * 1000;  // 2 minutes
     59     protected static final long WIFI_CONNECTION_TIMEOUT = 5 * 60 * 1000; // 5 minutes
     60     // 2 minutes timer between wifi stop and start
     61     protected static final long  WIFI_STOP_START_INTERVAL = 2 * 60 * 1000; // 2 minutes
     62     // Set ping test timer to be 3 minutes
     63     protected static final long PING_TIMER = 3 * 60 *1000; // 3 minutes
     64     protected static final int SUCCESS = 0;  // for Wifi tethering state change
     65     protected static final int FAILURE = 1;
     66     protected static final int INIT = -1;
     67 
     68     protected final String mLogTag;
     69 
     70     private ConnectivityReceiver mConnectivityReceiver = null;
     71     private WifiReceiver mWifiReceiver = null;
     72 
     73     private long mLastConnectivityChangeTime = -1;
     74     protected ConnectivityManager mCm;
     75     private Context mContext;
     76     protected List<ScanResult> mLastScanResult;
     77     protected Object mWifiScanResultLock = new Object();
     78 
     79     /* Control Wifi States */
     80     public WifiManager mWifiManager;
     81 
     82     public ConnectivityManagerTestBase(String logTag) {
     83         super();
     84         mLogTag = logTag;
     85     }
     86 
     87     protected long getLastConnectivityChangeTime() {
     88         return mLastConnectivityChangeTime;
     89     }
     90 
     91     /**
     92      * A wrapper of a broadcast receiver which provides network connectivity information
     93      * for all kinds of network: wifi, mobile, etc.
     94      */
     95     private class ConnectivityReceiver extends BroadcastReceiver {
     96         @Override
     97         public void onReceive(Context context, Intent intent) {
     98             mLastConnectivityChangeTime = SystemClock.uptimeMillis();
     99             logv("ConnectivityReceiver: " + intent);
    100             String action = intent.getAction();
    101             if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
    102                 Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
    103             }
    104         }
    105     }
    106 
    107     private class WifiReceiver extends BroadcastReceiver {
    108         @Override
    109         public void onReceive(Context context, Intent intent) {
    110             String action = intent.getAction();
    111             Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
    112             if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
    113                 logv("scan results are available");
    114                 synchronized (mWifiScanResultLock) {
    115                     mLastScanResult = mWifiManager.getScanResults();
    116                     mWifiScanResultLock.notifyAll();
    117                 }
    118             }
    119         }
    120     }
    121 
    122     @Override
    123     protected void setUp() throws Exception {
    124         mLastScanResult = null;
    125         mContext = getInstrumentation().getContext();
    126 
    127         // Get an instance of ConnectivityManager
    128         mCm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
    129         // Get an instance of WifiManager
    130         mWifiManager =(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
    131 
    132         if (mWifiManager.isWifiApEnabled()) {
    133             // if soft AP is enabled, disable it
    134             mWifiManager.setWifiApEnabled(null, false);
    135             logv("Disable soft ap");
    136         }
    137 
    138         // register a connectivity receiver for CONNECTIVITY_ACTION;
    139         mConnectivityReceiver = new ConnectivityReceiver();
    140         mContext.registerReceiver(mConnectivityReceiver,
    141                 new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
    142 
    143         mWifiReceiver = new WifiReceiver();
    144         IntentFilter mIntentFilter = new IntentFilter();
    145         mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
    146         mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
    147         mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
    148         mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
    149         mIntentFilter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
    150         mIntentFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
    151         mContext.registerReceiver(mWifiReceiver, mIntentFilter);
    152 
    153         logv("Clear Wifi before we start the test.");
    154         removeConfiguredNetworksAndDisableWifi();
    155      }
    156 
    157     // wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING,
    158     //                                      DISCONNECTED, UNKNOWN
    159     protected boolean waitForNetworkState(int networkType, State expectedState, long timeout) {
    160         long startTime = SystemClock.uptimeMillis();
    161         while (true) {
    162             NetworkInfo ni = mCm.getNetworkInfo(networkType);
    163             if (ni != null && expectedState.equals(ni.getState())) {
    164                 logv("waitForNetworkState success: %s", ni);
    165                 return true;
    166             }
    167             if ((SystemClock.uptimeMillis() - startTime) > timeout) {
    168                 logv("waitForNetworkState timeout: %s", ni);
    169                 return false;
    170             }
    171             logv("waitForNetworkState interim: %s", ni);
    172             SystemClock.sleep(SHORT_TIMEOUT);
    173         }
    174     }
    175 
    176     // wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED,
    177     //                      WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
    178     protected boolean waitForWifiState(int expectedState, long timeout) {
    179         long startTime = SystemClock.uptimeMillis();
    180         while (true) {
    181             int state = mWifiManager.getWifiState();
    182             if (state == expectedState) {
    183                 logv("waitForWifiState success: state=" + state);
    184                 return true;
    185             }
    186             if ((SystemClock.uptimeMillis() - startTime) > timeout) {
    187                 logv("waitForWifiState timeout: expected=%d, actual=%d", expectedState, state);
    188                 return false;
    189             }
    190             logv("waitForWifiState interim: expected=%d, actual=%d", expectedState, state);
    191             SystemClock.sleep(SHORT_TIMEOUT);
    192         }
    193     }
    194 
    195     // Wait for Wifi AP state: WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING,
    196     //                         WIFI_AP_STATE_ENABLED, WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
    197     protected boolean waitForWifiApState(int expectedState, long timeout) {
    198         long startTime = SystemClock.uptimeMillis();
    199         while (true) {
    200             int state = mWifiManager.getWifiApState();
    201             if (state == expectedState) {
    202                 logv("waitForWifiAPState success: state=" + state);
    203                 return true;
    204             }
    205             if ((SystemClock.uptimeMillis() - startTime) > timeout) {
    206                 logv(String.format("waitForWifiAPState timeout: expected=%d, actual=%d",
    207                         expectedState, state));
    208                 return false;
    209             }
    210             logv(String.format("waitForWifiAPState interim: expected=%d, actual=%d",
    211                     expectedState, state));
    212             SystemClock.sleep(SHORT_TIMEOUT);
    213         }
    214     }
    215 
    216     /**
    217      * Wait for the wifi tethering result:
    218      * @param timeout is the maximum waiting time
    219      * @return SUCCESS if tethering result is successful
    220      *         FAILURE if tethering result returns error.
    221      */
    222     protected boolean waitForTetherStateChange(long timeout) {
    223         long startTime = SystemClock.uptimeMillis();
    224         String[] wifiRegexes = mCm.getTetherableWifiRegexs();
    225         while (true) {
    226             if ((SystemClock.uptimeMillis() - startTime) > timeout) {
    227                 return false;
    228             }
    229             String[] active = mCm.getTetheredIfaces();
    230             String[] error = mCm.getTetheringErroredIfaces();
    231             for (String iface: active) {
    232                 for (String regex: wifiRegexes) {
    233                     if (iface.matches(regex)) {
    234                         return true;
    235                     }
    236                 }
    237             }
    238             for (String iface: error) {
    239                 for (String regex: wifiRegexes) {
    240                     if (iface.matches(regex)) {
    241                         return false;
    242                     }
    243                 }
    244             }
    245             SystemClock.sleep(SHORT_TIMEOUT);
    246         }
    247     }
    248 
    249     // Return true if device is currently connected to mobile network
    250     protected boolean isConnectedToMobile() {
    251         return (mCm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_MOBILE);
    252     }
    253 
    254     // Return true if device is currently connected to Wifi
    255     protected boolean isConnectedToWifi() {
    256         return (mCm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI);
    257     }
    258 
    259     protected boolean enableWifi() {
    260         return mWifiManager.setWifiEnabled(true);
    261     }
    262 
    263     // Turn screen off
    264     protected void turnScreenOff() {
    265         logv("Turn screen off");
    266         PowerManager pm =
    267             (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    268         pm.goToSleep(SystemClock.uptimeMillis());
    269     }
    270 
    271     // Turn screen on
    272     protected void turnScreenOn() {
    273         logv("Turn screen on");
    274         PowerManager pm =
    275                 (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    276         pm.wakeUp(SystemClock.uptimeMillis());
    277         // disable lock screen
    278         KeyguardManager km = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
    279         if (km.inKeyguardRestrictedInputMode()) {
    280             sendKeys(KeyEvent.KEYCODE_MENU);
    281         }
    282     }
    283 
    284     /**
    285      * @return true if the ping test is successful, false otherwise.
    286      */
    287     protected boolean pingTest() {
    288         long startTime = System.currentTimeMillis();
    289         while ((System.currentTimeMillis() - startTime) < PING_TIMER) {
    290             try {
    291                 // assume the chance that all servers are down is very small
    292                 for (String host : PING_HOST_LIST) {
    293                     logv("Start ping test, ping " + host);
    294                     Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
    295                     int status = p.waitFor();
    296                     if (status == 0) {
    297                         // if any of the ping test is successful, return true
    298                         return true;
    299                     }
    300                 }
    301             } catch (UnknownHostException e) {
    302                 logv("Ping test Fail: Unknown Host");
    303             } catch (IOException e) {
    304                 logv("Ping test Fail:  IOException");
    305             } catch (InterruptedException e) {
    306                 logv("Ping test Fail: InterruptedException");
    307             }
    308             SystemClock.sleep(SHORT_TIMEOUT);
    309         }
    310         // ping test timeout
    311         return false;
    312     }
    313 
    314     /**
    315      * Associate the device to given SSID
    316      * If the device is already associated with a WiFi, disconnect and forget it,
    317      * We don't verify whether the connection is successful or not, leave this to the test
    318      */
    319     protected boolean connectToWifi(String ssid, String password) {
    320         WifiConfiguration config;
    321         if (password == null) {
    322             config = WifiConfigurationHelper.createOpenConfig(ssid);
    323         } else {
    324             config = WifiConfigurationHelper.createPskConfig(ssid, password);
    325         }
    326         return connectToWifiWithConfiguration(config);
    327     }
    328 
    329     /**
    330      * Connect to Wi-Fi with the given configuration. Note the SSID in the configuration
    331      * is pure string, we need to convert it to quoted string.
    332      */
    333     protected boolean connectToWifiWithConfiguration(WifiConfiguration config) {
    334         // If Wifi is not enabled, enable it
    335         if (!mWifiManager.isWifiEnabled()) {
    336             logv("Wifi is not enabled, enable it");
    337             mWifiManager.setWifiEnabled(true);
    338             // wait for the wifi state change before start scanning.
    339             if (!waitForWifiState(WifiManager.WIFI_STATE_ENABLED, LONG_TIMEOUT)) {
    340                 logv("wait for WIFI_STATE_ENABLED failed");
    341                 return false;
    342             }
    343         }
    344 
    345         // Save network configuration and connect to network without scanning
    346         mWifiManager.connect(config,
    347             new WifiManager.ActionListener() {
    348                 @Override
    349                 public void onSuccess() {
    350                 }
    351 
    352                 @Override
    353                 public void onFailure(int reason) {
    354                     logv("connect failure " + reason);
    355                 }
    356             });
    357         return true;
    358     }
    359 
    360     /*
    361      * Disconnect from the current AP and remove configured networks.
    362      */
    363     protected boolean disconnectAP() {
    364         // remove saved networks
    365         if (!mWifiManager.isWifiEnabled()) {
    366             logv("Enabled wifi before remove configured networks");
    367             mWifiManager.setWifiEnabled(true);
    368             SystemClock.sleep(SHORT_TIMEOUT);
    369         }
    370 
    371         List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks();
    372         if (wifiConfigList == null) {
    373             logv("no configuration list is null");
    374             return true;
    375         }
    376         logv("size of wifiConfigList: " + wifiConfigList.size());
    377         for (WifiConfiguration wifiConfig: wifiConfigList) {
    378             logv("remove wifi configuration: " + wifiConfig.networkId);
    379             int netId = wifiConfig.networkId;
    380             mWifiManager.forget(netId, new WifiManager.ActionListener() {
    381                     @Override
    382                     public void onSuccess() {
    383                     }
    384 
    385                     @Override
    386                     public void onFailure(int reason) {
    387                         logv("Failed to forget " + reason);
    388                     }
    389                 });
    390         }
    391         return true;
    392     }
    393     /**
    394      * Disable Wifi
    395      * @return true if Wifi is disabled successfully
    396      */
    397     protected boolean disableWifi() {
    398         return mWifiManager.setWifiEnabled(false);
    399     }
    400 
    401     /**
    402      * Remove configured networks and disable wifi
    403      */
    404     protected boolean removeConfiguredNetworksAndDisableWifi() {
    405         if (!disconnectAP()) {
    406            return false;
    407         }
    408         SystemClock.sleep(SHORT_TIMEOUT);
    409         if (!mWifiManager.setWifiEnabled(false)) {
    410             return false;
    411         }
    412         SystemClock.sleep(SHORT_TIMEOUT);
    413         return true;
    414     }
    415 
    416     protected static String convertToQuotedString(String string) {
    417         return "\"" + string + "\"";
    418     }
    419 
    420     protected boolean waitForActiveNetworkConnection(long timeout) {
    421         long startTime = SystemClock.uptimeMillis();
    422         while (true) {
    423             NetworkInfo ni = mCm.getActiveNetworkInfo();
    424             if (ni != null && ni.isConnected()) {
    425                 return true;
    426             }
    427             if ((SystemClock.uptimeMillis() - startTime) > timeout) {
    428                 logv("waitForActiveNetworkConnection timeout: %s", ni);
    429                 return false;
    430             }
    431             logv("waitForActiveNetworkConnection interim: %s", ni);
    432             SystemClock.sleep(SHORT_TIMEOUT);
    433         }
    434     }
    435 
    436     protected boolean waitUntilNoActiveNetworkConnection(long timeout) {
    437         long startTime = SystemClock.uptimeMillis();
    438         while (true) {
    439             NetworkInfo ni = mCm.getActiveNetworkInfo();
    440             if (ni == null) {
    441                 return true;
    442             }
    443             if ((SystemClock.uptimeMillis() - startTime) > timeout) {
    444                 logv("waitForActiveNetworkConnection timeout: %s", ni);
    445                 return false;
    446             }
    447             logv("waitForActiveNetworkConnection interim: %s", ni);
    448             SystemClock.sleep(SHORT_TIMEOUT);
    449         }
    450     }
    451 
    452     // use ping request against Google public DNS to verify connectivity
    453     protected boolean checkNetworkConnectivity() {
    454         assertTrue("no active network connection", waitForActiveNetworkConnection(LONG_TIMEOUT));
    455         return pingTest();
    456     }
    457 
    458     @Override
    459     protected void tearDown() throws Exception{
    460         //Unregister receiver
    461         if (mConnectivityReceiver != null) {
    462           mContext.unregisterReceiver(mConnectivityReceiver);
    463         }
    464         if (mWifiReceiver != null) {
    465           mContext.unregisterReceiver(mWifiReceiver);
    466         }
    467         super.tearDown();
    468     }
    469 
    470     protected void logv(String format, Object... args) {
    471         Log.v(mLogTag, String.format(format, args));
    472     }
    473 
    474     /**
    475      * Connect to the provided Wi-Fi network
    476      * @param config is the network configuration
    477      * @throws AssertionError if fails to associate and connect to wifi ap
    478      */
    479     protected void connectToWifi(WifiConfiguration config) {
    480         // step 1: connect to the test access point
    481         assertTrue("failed to associate with " + config.SSID,
    482                 connectToWifiWithConfiguration(config));
    483 
    484         // step 2: verify Wifi state and network state;
    485         assertTrue("wifi state not connected with " + config.SSID,
    486                 waitForNetworkState(ConnectivityManager.TYPE_WIFI,
    487                 State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
    488 
    489         // step 3: verify the current connected network is the given SSID
    490         assertNotNull("no active wifi info", mWifiManager.getConnectionInfo());
    491         assertEquals("SSID mismatch", config.SSID, mWifiManager.getConnectionInfo().getSSID());
    492     }
    493 }
    494