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