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.Activity; 20 import android.content.Context; 21 import android.content.BroadcastReceiver; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.os.Bundle; 25 import android.provider.Settings; 26 import android.util.Log; 27 import java.util.List; 28 import android.widget.LinearLayout; 29 import android.net.ConnectivityManager; 30 import android.net.NetworkInfo; 31 import android.net.NetworkInfo.State; 32 33 import android.net.wifi.WifiConfiguration; 34 import android.net.wifi.WifiManager; 35 import android.net.wifi.WifiInfo; 36 import android.net.wifi.ScanResult; 37 import android.net.wifi.WifiConfiguration.KeyMgmt; 38 39 40 /** 41 * An activity registered with connectivity manager broadcast 42 * provides network connectivity information and 43 * can be used to set device states: Cellular, Wifi, Airplane mode. 44 */ 45 public class ConnectivityManagerTestActivity extends Activity { 46 47 public static final String LOG_TAG = "ConnectivityManagerTestActivity"; 48 public static final int WAIT_FOR_SCAN_RESULT = 5 * 1000; //5 seconds 49 public static final int WIFI_SCAN_TIMEOUT = 20 * 1000; 50 public ConnectivityReceiver mConnectivityReceiver = null; 51 public WifiReceiver mWifiReceiver = null; 52 /* 53 * Track network connectivity information 54 */ 55 public State mState; 56 public NetworkInfo mNetworkInfo; 57 public NetworkInfo mOtherNetworkInfo; 58 public boolean mIsFailOver; 59 public String mReason; 60 public boolean mScanResultIsAvailable = false; 61 public ConnectivityManager mCM; 62 public Object wifiObject = new Object(); 63 public Object connectivityObject = new Object(); 64 public int mWifiState; 65 public NetworkInfo mWifiNetworkInfo; 66 public String mBssid; 67 68 /* 69 * Control Wifi States 70 */ 71 public WifiManager mWifiManager; 72 73 /* 74 * Verify connectivity state 75 */ 76 public static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE + 1; 77 NetworkState[] connectivityState = new NetworkState[NUM_NETWORK_TYPES]; 78 79 /** 80 * A wrapper of a broadcast receiver which provides network connectivity information 81 * for all kinds of network: wifi, mobile, etc. 82 */ 83 private class ConnectivityReceiver extends BroadcastReceiver { 84 @Override 85 public void onReceive(Context context, Intent intent) { 86 Log.v(LOG_TAG, "ConnectivityReceiver: onReceive() is called with " + intent); 87 String action = intent.getAction(); 88 if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 89 Log.v("ConnectivityReceiver", "onReceive() called with " + intent); 90 return; 91 } 92 93 boolean noConnectivity = 94 intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); 95 96 if (noConnectivity) { 97 mState = State.DISCONNECTED; 98 } else { 99 mState = State.CONNECTED; 100 } 101 102 mNetworkInfo = (NetworkInfo) 103 intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO); 104 105 mOtherNetworkInfo = (NetworkInfo) 106 intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO); 107 108 mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON); 109 mIsFailOver = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false); 110 111 Log.v(LOG_TAG, "mNetworkInfo: " + mNetworkInfo.toString()); 112 if (mOtherNetworkInfo != null) { 113 Log.v(LOG_TAG, "mOtherNetworkInfo: " + mOtherNetworkInfo.toString()); 114 } 115 recordNetworkState(mNetworkInfo.getType(), mNetworkInfo.getState()); 116 if (mOtherNetworkInfo != null) { 117 recordNetworkState(mOtherNetworkInfo.getType(), mOtherNetworkInfo.getState()); 118 } 119 notifyNetworkConnectivityChange(); 120 } 121 } 122 123 private class WifiReceiver extends BroadcastReceiver { 124 @Override 125 public void onReceive(Context context, Intent intent) { 126 String action = intent.getAction(); 127 Log.v("WifiReceiver", "onReceive() is calleld with " + intent); 128 if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { 129 notifyScanResult(); 130 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 131 mWifiNetworkInfo = 132 (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 133 Log.v(LOG_TAG, "mWifiNetworkInfo: " + mWifiNetworkInfo.toString()); 134 if (mWifiNetworkInfo.getState() == State.CONNECTED) { 135 mBssid = intent.getStringExtra(WifiManager.EXTRA_BSSID); 136 } 137 notifyWifiState(); 138 } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 139 mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 140 WifiManager.WIFI_STATE_UNKNOWN); 141 notifyWifiState(); 142 } 143 else { 144 return; 145 } 146 } 147 } 148 149 public ConnectivityManagerTestActivity() { 150 mState = State.UNKNOWN; 151 } 152 153 @Override 154 protected void onCreate(Bundle savedInstanceState) { 155 super.onCreate(savedInstanceState); 156 Log.v(LOG_TAG, "onCreate, inst=" + Integer.toHexString(hashCode())); 157 158 // Create a simple layout 159 LinearLayout contentView = new LinearLayout(this); 160 contentView.setOrientation(LinearLayout.VERTICAL); 161 setContentView(contentView); 162 setTitle("ConnectivityManagerTestActivity"); 163 164 165 // register a connectivity receiver for CONNECTIVITY_ACTION; 166 mConnectivityReceiver = new ConnectivityReceiver(); 167 registerReceiver(mConnectivityReceiver, 168 new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); 169 170 mWifiReceiver = new WifiReceiver(); 171 IntentFilter mIntentFilter = new IntentFilter(); 172 mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 173 mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 174 mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 175 registerReceiver(mWifiReceiver, mIntentFilter); 176 177 // Get an instance of ConnectivityManager 178 mCM = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); 179 // Get an instance of WifiManager 180 mWifiManager =(WifiManager)getSystemService(Context.WIFI_SERVICE); 181 initializeNetworkStates(); 182 183 if (mWifiManager.isWifiEnabled()) { 184 Log.v(LOG_TAG, "Clear Wifi before we start the test."); 185 clearWifi(); 186 } 187 } 188 189 // for each network type, initialize network states to UNKNOWN, and no verification flag is set 190 public void initializeNetworkStates() { 191 for (int networkType = NUM_NETWORK_TYPES - 1; networkType >=0; networkType--) { 192 connectivityState[networkType] = new NetworkState(); 193 Log.v(LOG_TAG, "Initialize network state for " + networkType + ": " + 194 connectivityState[networkType].toString()); 195 } 196 } 197 198 // deposit a network state 199 public void recordNetworkState(int networkType, State networkState) { 200 Log.v(LOG_TAG, "record network state for network " + networkType + 201 ", state is " + networkState); 202 connectivityState[networkType].recordState(networkState); 203 } 204 205 // set the state transition criteria 206 public void setStateTransitionCriteria(int networkType, State initState, 207 int transitionDir, State targetState) { 208 connectivityState[networkType].setStateTransitionCriteria( 209 initState, transitionDir, targetState); 210 } 211 212 // Validate the states recorded 213 public boolean validateNetworkStates(int networkType) { 214 Log.v(LOG_TAG, "validate network state for " + networkType + ": "); 215 return connectivityState[networkType].validateStateTransition(); 216 } 217 218 // return result from network state validation 219 public String getTransitionFailureReason(int networkType) { 220 Log.v(LOG_TAG, "get network state transition failure reason for " + networkType + ": " + 221 connectivityState[networkType].toString()); 222 return connectivityState[networkType].getReason(); 223 } 224 225 private void notifyNetworkConnectivityChange() { 226 synchronized(connectivityObject) { 227 Log.v(LOG_TAG, "notify network connectivity changed"); 228 connectivityObject.notifyAll(); 229 } 230 } 231 private void notifyScanResult() { 232 synchronized (this) { 233 Log.v(LOG_TAG, "notify that scan results are available"); 234 this.notify(); 235 } 236 } 237 238 public void notifyWifiState() { 239 synchronized (wifiObject) { 240 Log.v(LOG_TAG, "notify wifi state changed"); 241 wifiObject.notify(); 242 } 243 } 244 245 // Return true if device is currently connected to mobile network 246 public boolean isConnectedToMobile() { 247 return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE); 248 } 249 250 // Return true if device is currently connected to Wifi 251 public boolean isConnectedToWifi() { 252 return (mNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI); 253 } 254 255 public boolean enableWifi() { 256 return mWifiManager.setWifiEnabled(true); 257 } 258 259 /** 260 * Associate the device to given SSID 261 * If the device is already associated with a WiFi, disconnect and forget it, 262 * We don't verify whether the connection is successful or not, leave this to the test 263 */ 264 public boolean connectToWifi(String knownSSID) { 265 //If Wifi is not enabled, enable it 266 if (!mWifiManager.isWifiEnabled()) { 267 Log.v(LOG_TAG, "Wifi is not enabled, enable it"); 268 mWifiManager.setWifiEnabled(true); 269 } 270 271 List<ScanResult> netList = mWifiManager.getScanResults(); 272 if (netList == null) { 273 // if no scan results are available, start active scan 274 mWifiManager.startScanActive(); 275 mScanResultIsAvailable = false; 276 long startTime = System.currentTimeMillis(); 277 while (!mScanResultIsAvailable) { 278 if ((System.currentTimeMillis() - startTime) > WIFI_SCAN_TIMEOUT) { 279 return false; 280 } 281 // wait for the scan results to be available 282 synchronized (this) { 283 // wait for the scan result to be available 284 try { 285 this.wait(WAIT_FOR_SCAN_RESULT); 286 } catch (InterruptedException e) { 287 e.printStackTrace(); 288 } 289 if ((mWifiManager.getScanResults() == null) || 290 (mWifiManager.getScanResults().size() <= 0)) { 291 continue; 292 } 293 mScanResultIsAvailable = true; 294 } 295 } 296 } 297 298 netList = mWifiManager.getScanResults(); 299 for (int i = 0; i < netList.size(); i++) { 300 ScanResult sr= netList.get(i); 301 if (sr.SSID.equals(knownSSID)) { 302 Log.v(LOG_TAG, "found " + knownSSID + " in the scan result list"); 303 WifiConfiguration config = new WifiConfiguration(); 304 config.SSID = convertToQuotedString(sr.SSID); 305 config.allowedKeyManagement.set(KeyMgmt.NONE); 306 int networkId = mWifiManager.addNetwork(config); 307 // Connect to network by disabling others. 308 mWifiManager.enableNetwork(networkId, true); 309 mWifiManager.saveConfiguration(); 310 mWifiManager.reconnect(); 311 break; 312 } 313 } 314 315 List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks(); 316 if (netConfList.size() <= 0) { 317 Log.v(LOG_TAG, knownSSID + " is not available"); 318 return false; 319 } 320 return true; 321 } 322 323 /* 324 * Disconnect from the current AP 325 */ 326 public boolean disconnectAP() { 327 if (mWifiManager.isWifiEnabled()) { 328 //remove the current network Id 329 WifiInfo curWifi = mWifiManager.getConnectionInfo(); 330 if (curWifi == null) { 331 return false; 332 } 333 int curNetworkId = curWifi.getNetworkId(); 334 mWifiManager.removeNetwork(curNetworkId); 335 mWifiManager.saveConfiguration(); 336 337 // remove other saved networks 338 List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks(); 339 if (netConfList != null) { 340 Log.v(LOG_TAG, "remove configured network ids"); 341 for (int i = 0; i < netConfList.size(); i++) { 342 WifiConfiguration conf = new WifiConfiguration(); 343 conf = netConfList.get(i); 344 mWifiManager.removeNetwork(conf.networkId); 345 } 346 } 347 } 348 mWifiManager.saveConfiguration(); 349 return true; 350 } 351 /** 352 * Disable Wifi 353 * @return true if Wifi is disabled successfully 354 */ 355 public boolean disableWifi() { 356 return mWifiManager.setWifiEnabled(false); 357 } 358 359 /** 360 * Disconnect from the current Wifi and clear the configuration list 361 */ 362 public boolean clearWifi() { 363 if (!disconnectAP()) { 364 return false; 365 } 366 // Disable Wifi 367 if (!mWifiManager.setWifiEnabled(false)) { 368 return false; 369 } 370 // Wait for the actions to be completed 371 try { 372 Thread.sleep(5*1000); 373 } catch (InterruptedException e) {} 374 return true; 375 } 376 377 /** 378 * Set airplane mode 379 */ 380 public void setAirplaneMode(Context context, boolean enableAM) { 381 //set the airplane mode 382 Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 383 enableAM ? 1 : 0); 384 // Post the intent 385 Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 386 intent.putExtra("state", enableAM); 387 context.sendBroadcast(intent); 388 } 389 390 protected static String convertToQuotedString(String string) { 391 return "\"" + string + "\""; 392 } 393 394 @Override 395 protected void onDestroy() { 396 super.onDestroy(); 397 398 //Unregister receiver 399 if (mConnectivityReceiver != null) { 400 unregisterReceiver(mConnectivityReceiver); 401 } 402 if (mWifiReceiver != null) { 403 unregisterReceiver(mWifiReceiver); 404 } 405 Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode())); 406 } 407 } 408