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 com.android.connectivitymanagertest.R;
     20 import android.app.Activity;
     21 import android.content.Context;
     22 import android.content.res.Resources;
     23 import android.content.BroadcastReceiver;
     24 import android.content.Intent;
     25 import android.content.IntentFilter;
     26 import android.os.Bundle;
     27 import android.provider.Settings;
     28 import android.util.Log;
     29 import android.view.KeyEvent;
     30 
     31 import java.io.InputStream;
     32 import java.util.ArrayList;
     33 import java.util.List;
     34 import android.widget.LinearLayout;
     35 import android.net.ConnectivityManager;
     36 import android.net.NetworkInfo;
     37 import android.net.NetworkInfo.State;
     38 
     39 import android.net.wifi.SupplicantState;
     40 import android.net.wifi.WifiConfiguration;
     41 import android.net.wifi.WifiManager;
     42 import android.net.wifi.WifiInfo;
     43 import android.net.wifi.ScanResult;
     44 import android.net.wifi.WifiConfiguration.KeyMgmt;
     45 
     46 /**
     47  * An activity registered with connectivity manager broadcast
     48  * provides network connectivity information and
     49  * can be used to set device states: Cellular, Wifi, Airplane mode.
     50  */
     51 public class ConnectivityManagerTestActivity extends Activity {
     52 
     53     public static final String LOG_TAG = "ConnectivityManagerTestActivity";
     54     public static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
     55     public static final int WIFI_SCAN_TIMEOUT = 20 * 1000;
     56     public static final int SHORT_TIMEOUT = 5 * 1000;
     57     public static final long LONG_TIMEOUT = 50 * 1000;
     58     private static final String ACCESS_POINT_FILE = "accesspoints.xml";
     59     public ConnectivityReceiver mConnectivityReceiver = null;
     60     public WifiReceiver mWifiReceiver = null;
     61     /*
     62      * Track network connectivity information
     63      */
     64     public State mState;
     65     public NetworkInfo mNetworkInfo;
     66     public NetworkInfo mOtherNetworkInfo;
     67     public boolean mIsFailOver;
     68     public String mReason;
     69     public boolean mScanResultIsAvailable = false;
     70     public ConnectivityManager mCM;
     71     public Object wifiObject = new Object();
     72     public Object connectivityObject = new Object();
     73     public int mWifiState;
     74     public NetworkInfo mWifiNetworkInfo;
     75     public String mBssid;
     76     public String mPowerSsid = "GoogleGuest"; //Default power SSID
     77     private Context mContext;
     78 
     79     /*
     80      * Control Wifi States
     81      */
     82     public WifiManager mWifiManager;
     83 
     84     /*
     85      * Verify connectivity state
     86      */
     87     public static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE + 1;
     88     NetworkState[] connectivityState = new NetworkState[NUM_NETWORK_TYPES];
     89 
     90     /**
     91      * A wrapper of a broadcast receiver which provides network connectivity information
     92      * for all kinds of network: wifi, mobile, etc.
     93      */
     94     private class ConnectivityReceiver extends BroadcastReceiver {
     95         @Override
     96         public void onReceive(Context context, Intent intent) {
     97             Log.v(LOG_TAG, "ConnectivityReceiver: onReceive() is called with " + intent);
     98             String action = intent.getAction();
     99             if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
    100                 Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
    101                 return;
    102             }
    103 
    104             boolean noConnectivity =
    105                 intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
    106 
    107             if (noConnectivity) {
    108                 mState = State.DISCONNECTED;
    109             } else {
    110                 mState = State.CONNECTED;
    111             }
    112 
    113             mNetworkInfo = (NetworkInfo)
    114                 intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
    115 
    116             mOtherNetworkInfo = (NetworkInfo)
    117                 intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
    118 
    119             mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
    120             mIsFailOver = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
    121 
    122             Log.v(LOG_TAG, "mNetworkInfo: " + mNetworkInfo.toString());
    123             if (mOtherNetworkInfo != null) {
    124                 Log.v(LOG_TAG, "mOtherNetworkInfo: " + mOtherNetworkInfo.toString());
    125             }
    126             recordNetworkState(mNetworkInfo.getType(), mNetworkInfo.getState());
    127             if (mOtherNetworkInfo != null) {
    128                 recordNetworkState(mOtherNetworkInfo.getType(), mOtherNetworkInfo.getState());
    129             }
    130             notifyNetworkConnectivityChange();
    131         }
    132     }
    133 
    134     private class WifiReceiver extends BroadcastReceiver {
    135         @Override
    136         public void onReceive(Context context, Intent intent) {
    137             String action = intent.getAction();
    138             Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
    139             if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
    140                 notifyScanResult();
    141             } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
    142                 mWifiNetworkInfo =
    143                     (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    144                 Log.v(LOG_TAG, "mWifiNetworkInfo: " + mWifiNetworkInfo.toString());
    145                 if (mWifiNetworkInfo.getState() == State.CONNECTED) {
    146                     mBssid = intent.getStringExtra(WifiManager.EXTRA_BSSID);
    147                 }
    148                 notifyWifiState();
    149             } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
    150                 mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
    151                                                 WifiManager.WIFI_STATE_UNKNOWN);
    152                 notifyWifiState();
    153             }
    154             else {
    155                 return;
    156             }
    157         }
    158     }
    159 
    160     public ConnectivityManagerTestActivity() {
    161         mState = State.UNKNOWN;
    162     }
    163 
    164     @Override
    165     protected void onCreate(Bundle savedInstanceState) {
    166         super.onCreate(savedInstanceState);
    167         Log.v(LOG_TAG, "onCreate, inst=" + Integer.toHexString(hashCode()));
    168 
    169         // Create a simple layout
    170         LinearLayout contentView = new LinearLayout(this);
    171         contentView.setOrientation(LinearLayout.VERTICAL);
    172         setContentView(contentView);
    173         setTitle("ConnectivityManagerTestActivity");
    174 
    175 
    176         // register a connectivity receiver for CONNECTIVITY_ACTION;
    177         mConnectivityReceiver = new ConnectivityReceiver();
    178         registerReceiver(mConnectivityReceiver,
    179                 new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
    180 
    181         mWifiReceiver = new WifiReceiver();
    182         IntentFilter mIntentFilter = new IntentFilter();
    183         mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
    184         mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
    185         mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
    186         mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
    187         registerReceiver(mWifiReceiver, mIntentFilter);
    188 
    189         // Get an instance of ConnectivityManager
    190         mCM = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
    191         // Get an instance of WifiManager
    192         mWifiManager =(WifiManager)getSystemService(Context.WIFI_SERVICE);
    193         initializeNetworkStates();
    194 
    195         if (mWifiManager.isWifiEnabled()) {
    196             Log.v(LOG_TAG, "Clear Wifi before we start the test.");
    197             removeConfiguredNetworksAndDisableWifi();
    198         }
    199      }
    200 
    201     public List<WifiConfiguration> loadNetworkConfigurations() throws Exception {
    202         InputStream in = getAssets().open(ACCESS_POINT_FILE);
    203         AccessPointParserHelper parseHelper = new AccessPointParserHelper();
    204         return parseHelper.processAccessPoint(in);
    205     }
    206 
    207     private void printNetConfig(String[] configuration) {
    208         for (int i = 0; i < configuration.length; i++) {
    209             if (i == 0) {
    210                 Log.v(LOG_TAG, "SSID: " + configuration[0]);
    211             } else {
    212                 Log.v(LOG_TAG, "      " + configuration[i]);
    213             }
    214         }
    215     }
    216 
    217     // for each network type, initialize network states to UNKNOWN, and no verification flag is set
    218     public void initializeNetworkStates() {
    219         for (int networkType = NUM_NETWORK_TYPES - 1; networkType >=0; networkType--) {
    220             connectivityState[networkType] =  new NetworkState();
    221             Log.v(LOG_TAG, "Initialize network state for " + networkType + ": " +
    222                     connectivityState[networkType].toString());
    223         }
    224     }
    225 
    226     // deposit a network state
    227     public void recordNetworkState(int networkType, State networkState) {
    228         Log.v(LOG_TAG, "record network state for network " +  networkType +
    229                 ", state is " + networkState);
    230         connectivityState[networkType].recordState(networkState);
    231     }
    232 
    233     // set the state transition criteria
    234     public void setStateTransitionCriteria(int networkType, State initState,
    235             int transitionDir, State targetState) {
    236         connectivityState[networkType].setStateTransitionCriteria(
    237                 initState, transitionDir, targetState);
    238     }
    239 
    240     // Validate the states recorded
    241     public boolean validateNetworkStates(int networkType) {
    242         Log.v(LOG_TAG, "validate network state for " + networkType + ": ");
    243         return connectivityState[networkType].validateStateTransition();
    244     }
    245 
    246     // return result from network state validation
    247     public String getTransitionFailureReason(int networkType) {
    248         Log.v(LOG_TAG, "get network state transition failure reason for " + networkType + ": " +
    249                 connectivityState[networkType].toString());
    250         return connectivityState[networkType].getReason();
    251     }
    252 
    253     private void notifyNetworkConnectivityChange() {
    254         synchronized(connectivityObject) {
    255             Log.v(LOG_TAG, "notify network connectivity changed");
    256             connectivityObject.notifyAll();
    257         }
    258     }
    259     private void notifyScanResult() {
    260         synchronized (this) {
    261             Log.v(LOG_TAG, "notify that scan results are available");
    262             this.notify();
    263         }
    264     }
    265 
    266     public void notifyWifiState() {
    267         synchronized (wifiObject) {
    268             Log.v(LOG_TAG, "notify wifi state changed");
    269             wifiObject.notify();
    270         }
    271     }
    272 
    273     // Wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED,
    274     //                                      DISCONNECTING, DISCONNECTED, UNKNOWN
    275     public boolean waitForNetworkState(int networkType, State expectedState, long timeout) {
    276         long startTime = System.currentTimeMillis();
    277         while (true) {
    278             if ((System.currentTimeMillis() - startTime) > timeout) {
    279                 if (mCM.getNetworkInfo(networkType).getState() != expectedState) {
    280                     return false;
    281                 } else {
    282                     // the broadcast has been sent out. the state has been changed.
    283                     Log.v(LOG_TAG, "networktype: " + networkType + " state: " +
    284                             mCM.getNetworkInfo(networkType));
    285                     return true;
    286                 }
    287             }
    288             Log.v(LOG_TAG, "Wait for the connectivity state for network: " + networkType +
    289                     " to be " + expectedState.toString());
    290             synchronized (connectivityObject) {
    291                 try {
    292                     connectivityObject.wait(SHORT_TIMEOUT);
    293                 } catch (InterruptedException e) {
    294                     e.printStackTrace();
    295                 }
    296                 if ((mNetworkInfo.getType() != networkType) ||
    297                     (mNetworkInfo.getState() != expectedState)) {
    298                     Log.v(LOG_TAG, "network state for " + mNetworkInfo.getType() +
    299                             "is: " + mNetworkInfo.getState());
    300                     continue;
    301                 }
    302                 return true;
    303             }
    304         }
    305     }
    306 
    307     // Wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED,
    308     //                      WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
    309     public boolean waitForWifiState(int expectedState, long timeout) {
    310         long startTime = System.currentTimeMillis();
    311         while (true) {
    312             if ((System.currentTimeMillis() - startTime) > timeout) {
    313                 if (mWifiState != expectedState) {
    314                     return false;
    315                 } else {
    316                     return true;
    317                 }
    318             }
    319             Log.v(LOG_TAG, "Wait for wifi state to be: " + expectedState);
    320             synchronized (wifiObject) {
    321                 try {
    322                     wifiObject.wait(SHORT_TIMEOUT);
    323                 } catch (InterruptedException e) {
    324                     e.printStackTrace();
    325                 }
    326                 if (mWifiState != expectedState) {
    327                     Log.v(LOG_TAG, "Wifi state is: " + mWifiNetworkInfo.getState());
    328                     continue;
    329                 }
    330                 return true;
    331             }
    332         }
    333     }
    334 
    335     // Return true if device is currently connected to mobile network
    336     public boolean isConnectedToMobile() {
    337         return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
    338     }
    339 
    340     // Return true if device is currently connected to Wifi
    341     public boolean isConnectedToWifi() {
    342         return (mNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI);
    343     }
    344 
    345     public boolean enableWifi() {
    346         return mWifiManager.setWifiEnabled(true);
    347     }
    348 
    349     /**
    350      * Associate the device to given SSID
    351      * If the device is already associated with a WiFi, disconnect and forget it,
    352      * We don't verify whether the connection is successful or not, leave this to the test
    353      */
    354     public boolean connectToWifi(String knownSSID) {
    355         WifiConfiguration config = new WifiConfiguration();
    356         config.SSID = knownSSID;
    357         config.allowedKeyManagement.set(KeyMgmt.NONE);
    358         return connectToWifiWithConfiguration(config);
    359     }
    360 
    361     /**
    362      * Connect to Wi-Fi with the given configuration. Note the SSID in the configuration
    363      * is pure string, we need to convert it to quoted string.
    364      * @param config
    365      * @return
    366      */
    367     public boolean connectToWifiWithConfiguration(WifiConfiguration config) {
    368         String ssid = config.SSID;
    369         config.SSID = convertToQuotedString(ssid);
    370 
    371         //If Wifi is not enabled, enable it
    372         if (!mWifiManager.isWifiEnabled()) {
    373             Log.v(LOG_TAG, "Wifi is not enabled, enable it");
    374             mWifiManager.setWifiEnabled(true);
    375         }
    376 
    377         List<ScanResult> netList = mWifiManager.getScanResults();
    378         if (netList == null) {
    379             Log.v(LOG_TAG, "scan results are null");
    380             // if no scan results are available, start active scan
    381             mWifiManager.startScanActive();
    382             mScanResultIsAvailable = false;
    383             long startTime = System.currentTimeMillis();
    384             while (!mScanResultIsAvailable) {
    385                 if ((System.currentTimeMillis() - startTime) > WIFI_SCAN_TIMEOUT) {
    386                     return false;
    387                 }
    388                 // wait for the scan results to be available
    389                 synchronized (this) {
    390                     // wait for the scan result to be available
    391                     try {
    392                         this.wait(WAIT_FOR_SCAN_RESULT);
    393                     } catch (InterruptedException e) {
    394                         e.printStackTrace();
    395                     }
    396                     if ((mWifiManager.getScanResults() == null) ||
    397                             (mWifiManager.getScanResults().size() <= 0)) {
    398                         continue;
    399                     }
    400                     mScanResultIsAvailable = true;
    401                 }
    402             }
    403         }
    404 
    405         netList = mWifiManager.getScanResults();
    406 
    407         for (int i = 0; i < netList.size(); i++) {
    408             ScanResult sr= netList.get(i);
    409             if (sr.SSID.equals(ssid)) {
    410                 Log.v(LOG_TAG, "found " + ssid + " in the scan result list");
    411                 int networkId = mWifiManager.addNetwork(config);
    412                 // Connect to network by disabling others.
    413                 mWifiManager.enableNetwork(networkId, true);
    414                 mWifiManager.saveConfiguration();
    415                 List<WifiConfiguration> wifiNetworks = mWifiManager.getConfiguredNetworks();
    416                 for (WifiConfiguration netConfig : wifiNetworks) {
    417                     Log.v(LOG_TAG, netConfig.toString());
    418                 }
    419 
    420                 mWifiManager.reconnect();
    421                 break;
    422            }
    423         }
    424 
    425         List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
    426         if (netConfList.size() <= 0) {
    427             Log.v(LOG_TAG, ssid + " is not available");
    428             return false;
    429         }
    430         return true;
    431     }
    432 
    433     /*
    434      * Disconnect from the current AP and remove configured networks.
    435      */
    436     public boolean disconnectAP() {
    437         if (mWifiManager.isWifiEnabled()) {
    438             //remove the current network Id
    439             WifiInfo curWifi = mWifiManager.getConnectionInfo();
    440             if (curWifi == null) {
    441                 return false;
    442             }
    443             int curNetworkId = curWifi.getNetworkId();
    444             mWifiManager.removeNetwork(curNetworkId);
    445             mWifiManager.saveConfiguration();
    446 
    447             // remove other saved networks
    448             List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
    449             if (netConfList != null) {
    450                 Log.v(LOG_TAG, "remove configured network ids");
    451                 for (int i = 0; i < netConfList.size(); i++) {
    452                     WifiConfiguration conf = new WifiConfiguration();
    453                     conf = netConfList.get(i);
    454                     mWifiManager.removeNetwork(conf.networkId);
    455                 }
    456             }
    457         }
    458         mWifiManager.saveConfiguration();
    459         return true;
    460     }
    461     /**
    462      * Disable Wifi
    463      * @return true if Wifi is disabled successfully
    464      */
    465     public boolean disableWifi() {
    466         return mWifiManager.setWifiEnabled(false);
    467     }
    468 
    469     /**
    470      * Remove configured networks and disable wifi
    471      */
    472     public boolean removeConfiguredNetworksAndDisableWifi() {
    473             if (!disconnectAP()) {
    474                 return false;
    475             }
    476             // Disable Wifi
    477             if (!mWifiManager.setWifiEnabled(false)) {
    478                 return false;
    479             }
    480             // Wait for the actions to be completed
    481             try {
    482                 Thread.sleep(5*1000);
    483             } catch (InterruptedException e) {}
    484         return true;
    485     }
    486 
    487     /**
    488      * Set airplane mode
    489      */
    490     public void setAirplaneMode(Context context, boolean enableAM) {
    491         //set the airplane mode
    492         Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
    493                 enableAM ? 1 : 0);
    494         // Post the intent
    495         Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
    496         intent.putExtra("state", enableAM);
    497         context.sendBroadcast(intent);
    498     }
    499 
    500     protected static String convertToQuotedString(String string) {
    501         return "\"" + string + "\"";
    502     }
    503 
    504     @Override
    505     protected void onDestroy() {
    506         super.onDestroy();
    507 
    508         //Unregister receiver
    509         if (mConnectivityReceiver != null) {
    510             unregisterReceiver(mConnectivityReceiver);
    511         }
    512         if (mWifiReceiver != null) {
    513             unregisterReceiver(mWifiReceiver);
    514         }
    515         Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
    516     }
    517 
    518     @Override
    519     public void onStart() {
    520         super.onStart();
    521         mContext = this;
    522         Bundle bundle = this.getIntent().getExtras();
    523         if (bundle != null){
    524             mPowerSsid = bundle.getString("power_ssid");
    525         }
    526     }
    527     //A thread to set the device into airplane mode then turn on wifi.
    528     Thread setDeviceWifiAndAirplaneThread = new Thread(new Runnable() {
    529         public void run() {
    530             setAirplaneMode(mContext, true);
    531             connectToWifi(mPowerSsid);
    532         }
    533     });
    534 
    535     //A thread to set the device into wifi
    536     Thread setDeviceInWifiOnlyThread = new Thread(new Runnable() {
    537         public void run() {
    538             connectToWifi(mPowerSsid);
    539         }
    540     });
    541 
    542     @Override
    543     public boolean onKeyDown(int keyCode, KeyEvent event) {
    544         switch (keyCode) {
    545             //This is a tricky way for the scripted monkey to
    546             //set the device in wifi and wifi in airplane mode.
    547             case KeyEvent.KEYCODE_1:
    548                 setDeviceWifiAndAirplaneThread.start();
    549                 break;
    550 
    551             case KeyEvent.KEYCODE_2:
    552                 setDeviceInWifiOnlyThread.start();
    553                 break;
    554         }
    555         return super.onKeyDown(keyCode, event);
    556     }
    557 }
    558