1 /* 2 * Copyright (C) 2011, 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.bandwidthtest.util; 18 19 import android.app.DownloadManager; 20 import android.app.DownloadManager.Query; 21 import android.app.DownloadManager.Request; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.content.pm.ApplicationInfo; 27 import android.content.pm.PackageManager; 28 import android.content.pm.PackageManager.NameNotFoundException; 29 import android.database.Cursor; 30 import android.net.ConnectivityManager; 31 import android.net.NetworkInfo; 32 import android.net.NetworkInfo.State; 33 import android.net.Uri; 34 import android.net.wifi.ScanResult; 35 import android.net.wifi.WifiConfiguration; 36 import android.net.wifi.WifiConfiguration.KeyMgmt; 37 import android.net.wifi.WifiManager; 38 import android.os.Handler; 39 import android.os.Message; 40 import android.provider.Settings; 41 import android.util.Log; 42 43 import com.android.bandwidthtest.NetworkState; 44 import com.android.bandwidthtest.NetworkState.StateTransitionDirection; 45 import com.android.internal.util.AsyncChannel; 46 47 import java.io.IOException; 48 import java.net.UnknownHostException; 49 import java.util.List; 50 51 /* 52 * Utility class used to set the connectivity of the device and to download files. 53 */ 54 public class ConnectionUtil { 55 private static final String LOG_TAG = "ConnectionUtil"; 56 private static final String DOWNLOAD_MANAGER_PKG_NAME = "com.android.providers.downloads"; 57 private static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; // 10 seconds 58 private static final int WIFI_SCAN_TIMEOUT = 50 * 1000; 59 public static final int SHORT_TIMEOUT = 5 * 1000; 60 public static final int LONG_TIMEOUT = 5 * 60 * 1000; // 5 minutes 61 private ConnectivityReceiver mConnectivityReceiver = null; 62 private WifiReceiver mWifiReceiver = null; 63 private DownloadReceiver mDownloadReceiver = null; 64 private DownloadManager mDownloadManager; 65 private NetworkInfo mNetworkInfo; 66 private NetworkInfo mOtherNetworkInfo; 67 private boolean mScanResultIsAvailable = false; 68 private ConnectivityManager mCM; 69 private Object mWifiMonitor = new Object(); 70 private Object mConnectivityMonitor = new Object(); 71 private Object mDownloadMonitor = new Object(); 72 private int mWifiState; 73 private NetworkInfo mWifiNetworkInfo; 74 private WifiManager mWifiManager; 75 private Context mContext; 76 // Verify connectivity state 77 // ConnectivityManager.TYPE_* is deprecated and no longer extended, so use the max public 78 // network type - TYPE_VPN should be enough. 79 // TODO: Replace registering CONNECTIVITY_ACTION with registering NetworkCallback and check 80 // network by NetworkCapabilities.TRANSPORT_* and NetworkCapabilities.hasTransport() instead. 81 private static final int NUM_NETWORK_TYPES = ConnectivityManager.TYPE_VPN + 1; 82 private NetworkState[] mConnectivityState = new NetworkState[NUM_NETWORK_TYPES]; 83 ConnectionUtil(Context context)84 public ConnectionUtil(Context context) { 85 mContext = context; 86 } 87 88 /** 89 * Initialize the class. Needs to be called before any other methods in {@link ConnectionUtil} 90 * 91 * @throws Exception 92 */ initialize()93 public void initialize() throws Exception { 94 // Register a connectivity receiver for CONNECTIVITY_ACTION 95 mConnectivityReceiver = new ConnectivityReceiver(); 96 mContext.registerReceiver(mConnectivityReceiver, 97 new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); 98 99 // Register a download receiver for ACTION_DOWNLOAD_COMPLETE 100 mDownloadReceiver = new DownloadReceiver(); 101 mContext.registerReceiver(mDownloadReceiver, 102 new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); 103 104 // Register a wifi receiver 105 mWifiReceiver = new WifiReceiver(); 106 IntentFilter mIntentFilter = new IntentFilter(); 107 mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 108 mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 109 mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 110 mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 111 mIntentFilter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 112 mContext.registerReceiver(mWifiReceiver, mIntentFilter); 113 114 // Get an instance of ConnectivityManager 115 mCM = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 116 117 // Get an instance of WifiManager 118 mWifiManager =(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE); 119 120 mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE); 121 122 initializeNetworkStates(); 123 124 125 } 126 127 /** 128 * Additional initialization needed for wifi related tests. 129 */ wifiTestInit()130 public void wifiTestInit() { 131 mWifiManager.setWifiEnabled(true); 132 Log.v(LOG_TAG, "Clear Wifi before we start the test."); 133 sleep(SHORT_TIMEOUT); 134 removeConfiguredNetworksAndDisableWifi(); 135 } 136 137 138 /** 139 * A wrapper of a broadcast receiver which provides network connectivity information 140 * for all kinds of network: wifi, mobile, etc. 141 */ 142 private class ConnectivityReceiver extends BroadcastReceiver { 143 /** 144 * {@inheritDoc} 145 */ 146 @Override onReceive(Context context, Intent intent)147 public void onReceive(Context context, Intent intent) { 148 if (isInitialStickyBroadcast()) { 149 Log.d(LOG_TAG, "This is a sticky broadcast don't do anything."); 150 return; 151 } 152 Log.v(LOG_TAG, "ConnectivityReceiver: onReceive() is called with " + intent); 153 String action = intent.getAction(); 154 if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 155 Log.v("ConnectivityReceiver", "onReceive() called with " + intent); 156 return; 157 } 158 159 final ConnectivityManager connManager = (ConnectivityManager) context 160 .getSystemService(Context.CONNECTIVITY_SERVICE); 161 mNetworkInfo = connManager.getActiveNetworkInfo(); 162 163 if (intent.hasExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO)) { 164 mOtherNetworkInfo = (NetworkInfo) 165 intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO); 166 } 167 168 Log.v(LOG_TAG, "mNetworkInfo: " + mNetworkInfo.toString()); 169 recordNetworkState(mNetworkInfo.getType(), mNetworkInfo.getState()); 170 if (mOtherNetworkInfo != null) { 171 Log.v(LOG_TAG, "mOtherNetworkInfo: " + mOtherNetworkInfo.toString()); 172 recordNetworkState(mOtherNetworkInfo.getType(), mOtherNetworkInfo.getState()); 173 } 174 notifyNetworkConnectivityChange(); 175 } 176 } 177 178 /** 179 * A wrapper of a broadcast receiver which provides wifi information. 180 */ 181 private class WifiReceiver extends BroadcastReceiver { 182 /** 183 * {@inheritDoc} 184 */ 185 @Override onReceive(Context context, Intent intent)186 public void onReceive(Context context, Intent intent) { 187 String action = intent.getAction(); 188 Log.v("WifiReceiver", "onReceive() is calleld with " + intent); 189 if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { 190 Log.v(LOG_TAG, "Scan results are available"); 191 notifyScanResult(); 192 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 193 mWifiNetworkInfo = 194 (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 195 Log.v(LOG_TAG, "mWifiNetworkInfo: " + mWifiNetworkInfo.toString()); 196 if (mWifiNetworkInfo.getState() == State.CONNECTED) { 197 intent.getStringExtra(WifiManager.EXTRA_BSSID); 198 } 199 notifyWifiState(); 200 } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 201 mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 202 WifiManager.WIFI_STATE_UNKNOWN); 203 notifyWifiState(); 204 } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) { 205 notifyWifiAPState(); 206 } else { 207 return; 208 } 209 } 210 } 211 212 /** 213 * A wrapper of a broadcast receiver which provides download manager information. 214 */ 215 private class DownloadReceiver extends BroadcastReceiver { 216 /** 217 * {@inheritDoc} 218 */ 219 @Override onReceive(Context context, Intent intent)220 public void onReceive(Context context, Intent intent) { 221 String action = intent.getAction(); 222 Log.v("DownloadReceiver", "onReceive() is called with " + intent); 223 // Download complete 224 if (action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) { 225 notifiyDownloadState(); 226 } 227 } 228 } 229 230 private class WifiServiceHandler extends Handler { 231 /** 232 * {@inheritDoc} 233 */ 234 @Override handleMessage(Message msg)235 public void handleMessage(Message msg) { 236 switch (msg.what) { 237 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 238 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 239 // AsyncChannel in msg.obj 240 } else { 241 Log.v(LOG_TAG, "Failed to establish AsyncChannel connection"); 242 } 243 break; 244 default: 245 // Ignore 246 break; 247 } 248 } 249 } 250 251 /** 252 * Initialize all the network states. 253 */ initializeNetworkStates()254 public void initializeNetworkStates() { 255 // For each network type, initialize network states to UNKNOWN, and no verification 256 // flag is set. 257 for (int networkType = NUM_NETWORK_TYPES - 1; networkType >= 0; networkType--) { 258 mConnectivityState[networkType] = new NetworkState(); 259 Log.v(LOG_TAG, "Initialize network state for " + networkType + ": " + 260 mConnectivityState[networkType].toString()); 261 } 262 } 263 recordNetworkState(int networkType, State networkState)264 public void recordNetworkState(int networkType, State networkState) { 265 // deposit a network state 266 Log.v(LOG_TAG, "record network state for network " + networkType + 267 ", state is " + networkState); 268 mConnectivityState[networkType].recordState(networkState); 269 } 270 271 /** 272 * Set the state transition criteria 273 * 274 * @param networkType 275 * @param initState 276 * @param transitionDir 277 * @param targetState 278 */ setStateTransitionCriteria(int networkType, State initState, StateTransitionDirection transitionDir, State targetState)279 public void setStateTransitionCriteria(int networkType, State initState, 280 StateTransitionDirection transitionDir, State targetState) { 281 mConnectivityState[networkType].setStateTransitionCriteria( 282 initState, transitionDir, targetState); 283 } 284 285 /** 286 * Validate the states recorded. 287 * @param networkType 288 * @return 289 */ validateNetworkStates(int networkType)290 public boolean validateNetworkStates(int networkType) { 291 Log.v(LOG_TAG, "validate network state for " + networkType + ": "); 292 return mConnectivityState[networkType].validateStateTransition(); 293 } 294 295 /** 296 * Fetch the failure reason for the transition. 297 * @param networkType 298 * @return result from network state validation 299 */ getTransitionFailureReason(int networkType)300 public String getTransitionFailureReason(int networkType) { 301 Log.v(LOG_TAG, "get network state transition failure reason for " + networkType + ": " + 302 mConnectivityState[networkType].toString()); 303 return mConnectivityState[networkType].getFailureReason(); 304 } 305 306 /** 307 * Send a notification via the mConnectivityMonitor when the network connectivity changes. 308 */ notifyNetworkConnectivityChange()309 private void notifyNetworkConnectivityChange() { 310 synchronized(mConnectivityMonitor) { 311 Log.v(LOG_TAG, "notify network connectivity changed"); 312 mConnectivityMonitor.notifyAll(); 313 } 314 } 315 316 /** 317 * Send a notification when a scan for the wifi network is done. 318 */ notifyScanResult()319 private void notifyScanResult() { 320 synchronized (this) { 321 Log.v(LOG_TAG, "notify that scan results are available"); 322 this.notify(); 323 } 324 } 325 326 /** 327 * Send a notification via the mWifiMonitor when the wifi state changes. 328 */ notifyWifiState()329 private void notifyWifiState() { 330 synchronized (mWifiMonitor) { 331 Log.v(LOG_TAG, "notify wifi state changed."); 332 mWifiMonitor.notify(); 333 } 334 } 335 336 /** 337 * Send a notification via the mDownloadMonitor when a download is complete. 338 */ notifiyDownloadState()339 private void notifiyDownloadState() { 340 synchronized (mDownloadMonitor) { 341 Log.v(LOG_TAG, "notifiy download manager state changed."); 342 mDownloadMonitor.notify(); 343 } 344 } 345 346 /** 347 * Send a notification when the wifi ap state changes. 348 */ notifyWifiAPState()349 private void notifyWifiAPState() { 350 synchronized (this) { 351 Log.v(LOG_TAG, "notify wifi AP state changed."); 352 this.notify(); 353 } 354 } 355 356 /** 357 * Start a download on a given url and wait for completion. 358 * 359 * @param targetUrl the target to download.x 360 * @param timeout to wait for download to finish 361 * @return true if we successfully downloaded the requestedUrl, false otherwise. 362 */ startDownloadAndWait(String targetUrl, long timeout)363 public boolean startDownloadAndWait(String targetUrl, long timeout) { 364 if (targetUrl.length() == 0 || targetUrl == null) { 365 Log.v(LOG_TAG, "Empty or Null target url requested to DownloadManager"); 366 return true; 367 } 368 Request request = new Request(Uri.parse(targetUrl)); 369 long enqueue = mDownloadManager.enqueue(request); 370 Log.v(LOG_TAG, "Sending download request of " + targetUrl + " to DownloadManager"); 371 long startTime = System.currentTimeMillis(); 372 while (true) { 373 if ((System.currentTimeMillis() - startTime) > timeout) { 374 Log.v(LOG_TAG, "startDownloadAndWait timed out, failed to fetch " + targetUrl + 375 " within " + timeout); 376 return downloadSuccessful(enqueue); 377 } 378 Log.v(LOG_TAG, "Waiting for the download to finish " + targetUrl); 379 synchronized (mDownloadMonitor) { 380 try { 381 mDownloadMonitor.wait(SHORT_TIMEOUT); 382 } catch (InterruptedException e) { 383 e.printStackTrace(); 384 } 385 if (!downloadSuccessful(enqueue)) { 386 continue; 387 } 388 return true; 389 } 390 } 391 } 392 393 /** 394 * Fetch the Download Manager's UID. 395 * @return the Download Manager's UID 396 */ downloadManagerUid()397 public int downloadManagerUid() { 398 try { 399 PackageManager pm = mContext.getPackageManager(); 400 ApplicationInfo appInfo = pm.getApplicationInfo(DOWNLOAD_MANAGER_PKG_NAME, 401 PackageManager.GET_META_DATA); 402 return appInfo.uid; 403 } catch (NameNotFoundException e) { 404 Log.d(LOG_TAG, "Did not find the package for the download service."); 405 return -1; 406 } 407 } 408 409 /** 410 * Determines if a given download was successful by querying the DownloadManager. 411 * 412 * @param enqueue the id used to identify/query the DownloadManager with. 413 * @return true if download was successful, false otherwise. 414 */ downloadSuccessful(long enqueue)415 private boolean downloadSuccessful(long enqueue) { 416 Query query = new Query(); 417 query.setFilterById(enqueue); 418 Cursor c = mDownloadManager.query(query); 419 if (c.moveToFirst()) { 420 int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS); 421 if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) { 422 Log.v(LOG_TAG, "Successfully downloaded file!"); 423 return true; 424 } 425 } 426 return false; 427 } 428 429 /** 430 * Wait for network connectivity state. 431 * @param networkType the network to check for 432 * @param expectedState the desired state 433 * @param timeout in milliseconds 434 * @return true if the network connectivity state matched what was expected 435 */ waitForNetworkState(int networkType, State expectedState, long timeout)436 public boolean waitForNetworkState(int networkType, State expectedState, long timeout) { 437 long startTime = System.currentTimeMillis(); 438 while (true) { 439 if ((System.currentTimeMillis() - startTime) > timeout) { 440 Log.v(LOG_TAG, "waitForNetworkState time out, the state of network type " + networkType + 441 " is: " + mCM.getNetworkInfo(networkType).getState()); 442 if (mCM.getNetworkInfo(networkType).getState() != expectedState) { 443 return false; 444 } else { 445 // the broadcast has been sent out. the state has been changed. 446 Log.v(LOG_TAG, "networktype: " + networkType + " state: " + 447 mCM.getNetworkInfo(networkType)); 448 return true; 449 } 450 } 451 Log.v(LOG_TAG, "Wait for the connectivity state for network: " + networkType + 452 " to be " + expectedState.toString()); 453 synchronized (mConnectivityMonitor) { 454 try { 455 mConnectivityMonitor.wait(SHORT_TIMEOUT); 456 } catch (InterruptedException e) { 457 e.printStackTrace(); 458 } 459 if (mNetworkInfo == null) { 460 Log.v(LOG_TAG, "Do not have networkInfo! Force fetch of network info."); 461 mNetworkInfo = mCM.getActiveNetworkInfo(); 462 } 463 // Still null after force fetch? Maybe the network did not have time to be brought 464 // up yet. 465 if (mNetworkInfo == null) { 466 Log.v(LOG_TAG, "Failed to force fetch networkInfo. " + 467 "The network is still not ready. Wait for the next broadcast"); 468 continue; 469 } 470 if ((mNetworkInfo.getType() != networkType) || 471 (mNetworkInfo.getState() != expectedState)) { 472 Log.v(LOG_TAG, "network state for " + mNetworkInfo.getType() + 473 "is: " + mNetworkInfo.getState()); 474 continue; 475 } 476 return true; 477 } 478 } 479 } 480 481 /** 482 * Wait for a given wifi state to occur within a given timeout. 483 * @param expectedState the expected wifi state. 484 * @param timeout for the state to be set in milliseconds. 485 * @return true if the state was achieved within the timeout, false otherwise. 486 */ waitForWifiState(int expectedState, long timeout)487 public boolean waitForWifiState(int expectedState, long timeout) { 488 // Wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED, 489 // WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN 490 long startTime = System.currentTimeMillis(); 491 while (true) { 492 if ((System.currentTimeMillis() - startTime) > timeout) { 493 if (mWifiState != expectedState) { 494 return false; 495 } else { 496 return true; 497 } 498 } 499 Log.v(LOG_TAG, "Wait for wifi state to be: " + expectedState); 500 synchronized (mWifiMonitor) { 501 try { 502 mWifiMonitor.wait(SHORT_TIMEOUT); 503 } catch (InterruptedException e) { 504 e.printStackTrace(); 505 } 506 if (mWifiState != expectedState) { 507 Log.v(LOG_TAG, "Wifi state is: " + mWifiState); 508 continue; 509 } 510 return true; 511 } 512 } 513 } 514 515 /** 516 * Convenience method to determine if we are connected to a mobile network. 517 * @return true if connected to a mobile network, false otherwise. 518 */ isConnectedToMobile()519 public boolean isConnectedToMobile() { 520 NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); 521 return networkInfo.isConnected(); 522 } 523 524 /** 525 * Convenience method to determine if we are connected to wifi. 526 * @return true if connected to wifi, false otherwise. 527 */ isConnectedToWifi()528 public boolean isConnectedToWifi() { 529 NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 530 return networkInfo.isConnected(); 531 } 532 533 /** 534 * Associate the device to given SSID 535 * If the device is already associated with a WiFi, disconnect and forget it, 536 * We don't verify whether the connection is successful or not, leave this to the test 537 */ connectToWifi(String knownSSID)538 public boolean connectToWifi(String knownSSID) { 539 WifiConfiguration config = new WifiConfiguration(); 540 config.SSID = knownSSID; 541 config.allowedKeyManagement.set(KeyMgmt.NONE); 542 return connectToWifiWithConfiguration(config); 543 } 544 545 /** 546 * Connect to Wi-Fi with the given configuration. 547 * @param config 548 * @return true if we are connected to a given AP. 549 */ connectToWifiWithConfiguration(WifiConfiguration config)550 public boolean connectToWifiWithConfiguration(WifiConfiguration config) { 551 // The SSID in the configuration is a pure string, need to convert it to a quoted string. 552 String ssid = config.SSID; 553 config.SSID = convertToQuotedString(ssid); 554 555 // If wifi is not enabled, enable it 556 if (!mWifiManager.isWifiEnabled()) { 557 Log.v(LOG_TAG, "Wifi is not enabled, enable it"); 558 mWifiManager.setWifiEnabled(true); 559 // wait for the wifi state change before start scanning. 560 if (!waitForWifiState(WifiManager.WIFI_STATE_ENABLED, 2 * SHORT_TIMEOUT)) { 561 Log.v(LOG_TAG, "Wait for WIFI_STATE_ENABLED failed"); 562 return false; 563 } 564 } 565 566 boolean foundApInScanResults = false; 567 for (int retry = 0; retry < 5; retry++) { 568 List<ScanResult> netList = mWifiManager.getScanResults(); 569 if (netList != null) { 570 Log.v(LOG_TAG, "size of scan result list: " + netList.size()); 571 for (int i = 0; i < netList.size(); i++) { 572 ScanResult sr= netList.get(i); 573 if (sr.SSID.equals(ssid)) { 574 Log.v(LOG_TAG, "Found " + ssid + " in the scan result list."); 575 Log.v(LOG_TAG, "Retry: " + retry); 576 foundApInScanResults = true; 577 mWifiManager.connect(config, new WifiManager.ActionListener() { 578 public void onSuccess() { 579 } 580 public void onFailure(int reason) { 581 Log.e(LOG_TAG, "connect failed " + reason); 582 } 583 }); 584 585 break; 586 } 587 } 588 } 589 if (foundApInScanResults) { 590 return true; 591 } else { 592 // Start an active scan 593 mWifiManager.startScan(); 594 mScanResultIsAvailable = false; 595 long startTime = System.currentTimeMillis(); 596 while (!mScanResultIsAvailable) { 597 if ((System.currentTimeMillis() - startTime) > WIFI_SCAN_TIMEOUT) { 598 Log.v(LOG_TAG, "wait for scan results timeout"); 599 return false; 600 } 601 // wait for the scan results to be available 602 synchronized (this) { 603 // wait for the scan result to be available 604 try { 605 this.wait(WAIT_FOR_SCAN_RESULT); 606 } catch (InterruptedException e) { 607 e.printStackTrace(); 608 } 609 if ((mWifiManager.getScanResults() == null) || 610 (mWifiManager.getScanResults().size() <= 0)) { 611 continue; 612 } 613 mScanResultIsAvailable = true; 614 } 615 } 616 } 617 } 618 return false; 619 } 620 621 /* 622 * Disconnect from the current AP and remove configured networks. 623 */ disconnectAP()624 public boolean disconnectAP() { 625 // remove saved networks 626 List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks(); 627 Log.v(LOG_TAG, "size of wifiConfigList: " + wifiConfigList.size()); 628 for (WifiConfiguration wifiConfig: wifiConfigList) { 629 Log.v(LOG_TAG, "Remove wifi configuration: " + wifiConfig.networkId); 630 int netId = wifiConfig.networkId; 631 mWifiManager.forget(netId, new WifiManager.ActionListener() { 632 public void onSuccess() { 633 } 634 public void onFailure(int reason) { 635 Log.e(LOG_TAG, "forget failed " + reason); 636 } 637 }); 638 } 639 return true; 640 } 641 642 /** 643 * Enable Wifi 644 * @return true if Wifi is enabled successfully 645 */ enableWifi()646 public boolean enableWifi() { 647 return mWifiManager.setWifiEnabled(true); 648 } 649 650 /** 651 * Disable Wifi 652 * @return true if Wifi is disabled successfully 653 */ disableWifi()654 public boolean disableWifi() { 655 return mWifiManager.setWifiEnabled(false); 656 } 657 658 /** 659 * Remove configured networks and disable wifi 660 */ removeConfiguredNetworksAndDisableWifi()661 public boolean removeConfiguredNetworksAndDisableWifi() { 662 if (!disconnectAP()) { 663 return false; 664 } 665 sleep(SHORT_TIMEOUT); 666 if (!mWifiManager.setWifiEnabled(false)) { 667 return false; 668 } 669 sleep(SHORT_TIMEOUT); 670 return true; 671 } 672 673 /** 674 * Make the current thread sleep. 675 * @param sleeptime the time to sleep in milliseconds 676 */ sleep(long sleeptime)677 private void sleep(long sleeptime) { 678 try { 679 Thread.sleep(sleeptime); 680 } catch (InterruptedException e) {} 681 } 682 683 /** 684 * Set airplane mode on device, caller is responsible to ensuring correct state. 685 * @param context {@link Context} 686 * @param enableAM to enable or disable airplane mode. 687 */ setAirplaneMode(Context context, boolean enableAM)688 public void setAirplaneMode(Context context, boolean enableAM) { 689 //set the airplane mode 690 Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 691 enableAM ? 1 : 0); 692 // Post the intent 693 Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 694 intent.putExtra("state", enableAM); 695 context.sendBroadcast(intent); 696 } 697 698 /** 699 * Add quotes around the string. 700 * @param string to convert 701 * @return string with quotes around it 702 */ convertToQuotedString(String string)703 protected static String convertToQuotedString(String string) { 704 return "\"" + string + "\""; 705 } 706 cleanUp()707 public void cleanUp() { 708 // Unregister receivers if defined. 709 if (mConnectivityReceiver != null) { 710 mContext.unregisterReceiver(mConnectivityReceiver); 711 } 712 if (mWifiReceiver != null) { 713 mContext.unregisterReceiver(mWifiReceiver); 714 } 715 if (mDownloadReceiver != null) { 716 mContext.unregisterReceiver(mDownloadReceiver); 717 } 718 Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode())); 719 } 720 721 /** 722 * Helper method used to test data connectivity by pinging a series of popular sites. 723 * @return true if device has data connectivity, false otherwise. 724 */ hasData()725 public boolean hasData() { 726 String[] hostList = {"www.google.com", "www.yahoo.com", 727 "www.bing.com", "www.facebook.com", "www.ask.com"}; 728 try { 729 for (int i = 0; i < hostList.length; ++i) { 730 String host = hostList[i]; 731 Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host); 732 int status = p.waitFor(); 733 if (status == 0) { 734 return true; 735 } 736 } 737 } catch (UnknownHostException e) { 738 Log.e(LOG_TAG, "Ping test Failed: Unknown Host"); 739 } catch (IOException e) { 740 Log.e(LOG_TAG, "Ping test Failed: IOException"); 741 } catch (InterruptedException e) { 742 Log.e(LOG_TAG, "Ping test Failed: InterruptedException"); 743 } 744 return false; 745 } 746 } 747