| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.net; | 5 package org.chromium.net; |
| 6 | 6 |
| 7 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; | 7 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; |
| 8 | 8 |
| 9 import android.Manifest.permission; | 9 import android.Manifest.permission; |
| 10 import android.annotation.SuppressLint; | 10 import android.annotation.SuppressLint; |
| 11 import android.content.BroadcastReceiver; | 11 import android.content.BroadcastReceiver; |
| 12 import android.content.Context; | 12 import android.content.Context; |
| 13 import android.content.Intent; | 13 import android.content.Intent; |
| 14 import android.content.IntentFilter; | 14 import android.content.IntentFilter; |
| 15 import android.content.pm.PackageManager; | 15 import android.content.pm.PackageManager; |
| 16 import android.net.ConnectivityManager; | 16 import android.net.ConnectivityManager; |
| 17 import android.net.ConnectivityManager.NetworkCallback; | 17 import android.net.ConnectivityManager.NetworkCallback; |
| 18 import android.net.Network; | 18 import android.net.Network; |
| 19 import android.net.NetworkCapabilities; | 19 import android.net.NetworkCapabilities; |
| 20 import android.net.NetworkInfo; | 20 import android.net.NetworkInfo; |
| 21 import android.net.NetworkRequest; | 21 import android.net.NetworkRequest; |
| 22 import android.net.wifi.WifiInfo; | 22 import android.net.wifi.WifiInfo; |
| 23 import android.net.wifi.WifiManager; | 23 import android.net.wifi.WifiManager; |
| 24 import android.os.Build; | 24 import android.os.Build; |
| 25 import android.telephony.TelephonyManager; | 25 import android.telephony.TelephonyManager; |
| 26 import android.util.Log; | 26 import android.util.Log; |
| 27 | 27 |
| 28 import org.chromium.base.ApplicationState; | |
| 29 import org.chromium.base.ApplicationStatus; | |
| 30 import org.chromium.base.ThreadUtils; | 28 import org.chromium.base.ThreadUtils; |
| 31 import org.chromium.base.VisibleForTesting; | 29 import org.chromium.base.VisibleForTesting; |
| 32 | 30 |
| 33 /** | 31 /** |
| 34 * Used by the NetworkChangeNotifier to listens to platform changes in connectiv
ity. | 32 * Used by the NetworkChangeNotifier to listens to platform changes in connectiv
ity. |
| 35 * Note that use of this class requires that the app have the platform | 33 * Note that use of this class requires that the app have the platform |
| 36 * ACCESS_NETWORK_STATE permission. | 34 * ACCESS_NETWORK_STATE permission. |
| 37 */ | 35 */ |
| 38 public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver | 36 public class NetworkChangeNotifierAutoDetect extends BroadcastReceiver { |
| 39 implements ApplicationStatus.ApplicationStateListener { | |
| 40 | |
| 41 static class NetworkState { | 37 static class NetworkState { |
| 42 private final boolean mConnected; | 38 private final boolean mConnected; |
| 43 private final int mType; | 39 private final int mType; |
| 44 private final int mSubtype; | 40 private final int mSubtype; |
| 45 | 41 |
| 46 public NetworkState(boolean connected, int type, int subtype) { | 42 public NetworkState(boolean connected, int type, int subtype) { |
| 47 mConnected = connected; | 43 mConnected = connected; |
| 48 mType = type; | 44 mType = type; |
| 49 mSubtype = subtype; | 45 mSubtype = subtype; |
| 50 } | 46 } |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 final int netId = networkToNetId(network); | 289 final int netId = networkToNetId(network); |
| 294 ThreadUtils.postOnUiThread(new Runnable() { | 290 ThreadUtils.postOnUiThread(new Runnable() { |
| 295 @Override | 291 @Override |
| 296 public void run() { | 292 public void run() { |
| 297 mObserver.onNetworkDisconnect(netId); | 293 mObserver.onNetworkDisconnect(netId); |
| 298 } | 294 } |
| 299 }); | 295 }); |
| 300 } | 296 } |
| 301 } | 297 } |
| 302 | 298 |
| 299 /** |
| 300 * Abstract class for providing a policy regarding when the NetworkChangeNot
ifier |
| 301 * should listen for network changes. |
| 302 */ |
| 303 public abstract static class RegistrationPolicy { |
| 304 private NetworkChangeNotifierAutoDetect mNotifier; |
| 305 |
| 306 /** |
| 307 * Start listening for network changes. |
| 308 */ |
| 309 protected final void register() { |
| 310 assert mNotifier != null; |
| 311 mNotifier.register(); |
| 312 } |
| 313 |
| 314 /** |
| 315 * Stop listening for network changes. |
| 316 */ |
| 317 protected final void unregister() { |
| 318 assert mNotifier != null; |
| 319 mNotifier.unregister(); |
| 320 } |
| 321 |
| 322 /** |
| 323 * Initializes the policy with the notifier, overriding subclasses shoul
d always |
| 324 * call this method. |
| 325 */ |
| 326 protected void init(NetworkChangeNotifierAutoDetect notifier) { |
| 327 mNotifier = notifier; |
| 328 } |
| 329 |
| 330 protected abstract void destroy(); |
| 331 } |
| 332 |
| 303 private static final String TAG = "NetworkChangeNotifierAutoDetect"; | 333 private static final String TAG = "NetworkChangeNotifierAutoDetect"; |
| 304 private static final int UNKNOWN_LINK_SPEED = -1; | 334 private static final int UNKNOWN_LINK_SPEED = -1; |
| 335 |
| 305 private final NetworkConnectivityIntentFilter mIntentFilter; | 336 private final NetworkConnectivityIntentFilter mIntentFilter; |
| 337 private final Observer mObserver; |
| 338 private final Context mContext; |
| 339 private final RegistrationPolicy mRegistrationPolicy; |
| 306 | 340 |
| 307 private final Observer mObserver; | |
| 308 | |
| 309 private final Context mContext; | |
| 310 // mConnectivityManagerDelegates and mWifiManagerDelegate are only non-final
for testing. | 341 // mConnectivityManagerDelegates and mWifiManagerDelegate are only non-final
for testing. |
| 311 private ConnectivityManagerDelegate mConnectivityManagerDelegate; | 342 private ConnectivityManagerDelegate mConnectivityManagerDelegate; |
| 312 private WifiManagerDelegate mWifiManagerDelegate; | 343 private WifiManagerDelegate mWifiManagerDelegate; |
| 313 // mNetworkCallback and mNetworkRequest are only non-null in Android L and a
bove. | 344 // mNetworkCallback and mNetworkRequest are only non-null in Android L and a
bove. |
| 314 private final NetworkCallback mNetworkCallback; | 345 private final NetworkCallback mNetworkCallback; |
| 315 private final NetworkRequest mNetworkRequest; | 346 private final NetworkRequest mNetworkRequest; |
| 316 private boolean mRegistered; | 347 private boolean mRegistered; |
| 317 private final boolean mApplicationStateRegistered; | |
| 318 private int mConnectionType; | 348 private int mConnectionType; |
| 319 private String mWifiSSID; | 349 private String mWifiSSID; |
| 320 private double mMaxBandwidthMbps; | 350 private double mMaxBandwidthMbps; |
| 321 | 351 |
| 322 /** | 352 /** |
| 323 * Observer interface by which observer is notified of network changes. | 353 * Observer interface by which observer is notified of network changes. |
| 324 */ | 354 */ |
| 325 public static interface Observer { | 355 public static interface Observer { |
| 326 /** | 356 /** |
| 327 * Called when default network changes. | 357 * Called when default network changes. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 public void updateActiveNetworkList(int[] activeNetIds); | 392 public void updateActiveNetworkList(int[] activeNetIds); |
| 363 } | 393 } |
| 364 | 394 |
| 365 /** | 395 /** |
| 366 * Constructs a NetworkChangeNotifierAutoDetect. Should only be called on UI
thread. | 396 * Constructs a NetworkChangeNotifierAutoDetect. Should only be called on UI
thread. |
| 367 * @param alwaysWatchForChanges If true, always watch for network changes. | 397 * @param alwaysWatchForChanges If true, always watch for network changes. |
| 368 * Otherwise, only watch if app is in foreground. | 398 * Otherwise, only watch if app is in foreground. |
| 369 */ | 399 */ |
| 370 @SuppressLint("NewApi") | 400 @SuppressLint("NewApi") |
| 371 public NetworkChangeNotifierAutoDetect( | 401 public NetworkChangeNotifierAutoDetect( |
| 372 Observer observer, Context context, boolean alwaysWatchForChanges) { | 402 Observer observer, Context context, RegistrationPolicy policy) { |
| 373 // Since BroadcastReceiver is always called back on UI thread, ensure | 403 // Since BroadcastReceiver is always called back on UI thread, ensure |
| 374 // running on UI thread so notification logic can be single-threaded. | 404 // running on UI thread so notification logic can be single-threaded. |
| 375 ThreadUtils.assertOnUiThread(); | 405 ThreadUtils.assertOnUiThread(); |
| 376 mObserver = observer; | 406 mObserver = observer; |
| 377 mContext = context.getApplicationContext(); | 407 mContext = context.getApplicationContext(); |
| 378 mConnectivityManagerDelegate = new ConnectivityManagerDelegate(context); | 408 mConnectivityManagerDelegate = new ConnectivityManagerDelegate(context); |
| 379 mWifiManagerDelegate = new WifiManagerDelegate(context); | 409 mWifiManagerDelegate = new WifiManagerDelegate(context); |
| 380 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | 410 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { |
| 381 mNetworkCallback = new MyNetworkCallback(); | 411 mNetworkCallback = new MyNetworkCallback(); |
| 382 mNetworkRequest = | 412 mNetworkRequest = |
| 383 new NetworkRequest.Builder().addCapability(NET_CAPABILITY_IN
TERNET).build(); | 413 new NetworkRequest.Builder().addCapability(NET_CAPABILITY_IN
TERNET).build(); |
| 384 } else { | 414 } else { |
| 385 mNetworkCallback = null; | 415 mNetworkCallback = null; |
| 386 mNetworkRequest = null; | 416 mNetworkRequest = null; |
| 387 } | 417 } |
| 388 final NetworkState networkState = mConnectivityManagerDelegate.getNetwor
kState(); | 418 final NetworkState networkState = mConnectivityManagerDelegate.getNetwor
kState(); |
| 389 mConnectionType = getCurrentConnectionType(networkState); | 419 mConnectionType = getCurrentConnectionType(networkState); |
| 390 mWifiSSID = getCurrentWifiSSID(networkState); | 420 mWifiSSID = getCurrentWifiSSID(networkState); |
| 391 mMaxBandwidthMbps = getCurrentMaxBandwidthInMbps(networkState); | 421 mMaxBandwidthMbps = getCurrentMaxBandwidthInMbps(networkState); |
| 392 mIntentFilter = | 422 mIntentFilter = |
| 393 new NetworkConnectivityIntentFilter(mWifiManagerDelegate.getHasW
ifiPermission()); | 423 new NetworkConnectivityIntentFilter(mWifiManagerDelegate.getHasW
ifiPermission()); |
| 394 | 424 mRegistrationPolicy = policy; |
| 395 if (alwaysWatchForChanges) { | 425 mRegistrationPolicy.init(this); |
| 396 registerReceiver(); | |
| 397 mApplicationStateRegistered = false; | |
| 398 } else { | |
| 399 ApplicationStatus.registerApplicationStateListener(this); | |
| 400 onApplicationStateChange(getApplicationState()); | |
| 401 mApplicationStateRegistered = true; | |
| 402 } | |
| 403 } | 426 } |
| 404 | 427 |
| 405 /** | 428 /** |
| 406 * Allows overriding the ConnectivityManagerDelegate for tests. | 429 * Allows overriding the ConnectivityManagerDelegate for tests. |
| 407 */ | 430 */ |
| 408 void setConnectivityManagerDelegateForTests(ConnectivityManagerDelegate dele
gate) { | 431 void setConnectivityManagerDelegateForTests(ConnectivityManagerDelegate dele
gate) { |
| 409 mConnectivityManagerDelegate = delegate; | 432 mConnectivityManagerDelegate = delegate; |
| 410 } | 433 } |
| 411 | 434 |
| 412 /** | 435 /** |
| 413 * Allows overriding the WifiManagerDelegate for tests. | 436 * Allows overriding the WifiManagerDelegate for tests. |
| 414 */ | 437 */ |
| 415 void setWifiManagerDelegateForTests(WifiManagerDelegate delegate) { | 438 void setWifiManagerDelegateForTests(WifiManagerDelegate delegate) { |
| 416 mWifiManagerDelegate = delegate; | 439 mWifiManagerDelegate = delegate; |
| 417 } | 440 } |
| 418 | 441 |
| 419 /** | |
| 420 * Returns the activity's status. | |
| 421 * @return an {@code int} that is one of {@code ApplicationState.HAS_*_ACTIV
ITIES}. | |
| 422 */ | |
| 423 @VisibleForTesting | 442 @VisibleForTesting |
| 424 int getApplicationState() { | 443 RegistrationPolicy getRegistrationPolicy() { |
| 425 return ApplicationStatus.getStateForApplication(); | 444 return mRegistrationPolicy; |
| 426 } | 445 } |
| 427 | 446 |
| 428 /** | 447 /** |
| 429 * Returns whether the object has registered to receive network connectivity
intents. | 448 * Returns whether the object has registered to receive network connectivity
intents. |
| 430 */ | 449 */ |
| 431 @VisibleForTesting | 450 @VisibleForTesting |
| 432 boolean isReceiverRegisteredForTesting() { | 451 boolean isReceiverRegisteredForTesting() { |
| 433 return mRegistered; | 452 return mRegistered; |
| 434 } | 453 } |
| 435 | 454 |
| 436 public void destroy() { | 455 public void destroy() { |
| 437 if (mApplicationStateRegistered) ApplicationStatus.unregisterApplication
StateListener(this); | 456 mRegistrationPolicy.destroy(); |
| 438 unregisterReceiver(); | 457 unregister(); |
| 439 } | 458 } |
| 440 | 459 |
| 441 /** | 460 /** |
| 442 * Registers a BroadcastReceiver in the given context. | 461 * Registers a BroadcastReceiver in the given context. |
| 443 */ | 462 */ |
| 444 private void registerReceiver() { | 463 public void register() { |
| 445 if (!mRegistered) { | 464 if (mRegistered) return; |
| 446 mRegistered = true; | 465 |
| 447 mContext.registerReceiver(this, mIntentFilter); | 466 final NetworkState networkState = getCurrentNetworkState(); |
| 448 if (mNetworkCallback != null) { | 467 connectionTypeChanged(networkState); |
| 449 mConnectivityManagerDelegate.registerNetworkCallback( | 468 maxBandwidthChanged(networkState); |
| 450 mNetworkRequest, mNetworkCallback); | 469 mContext.registerReceiver(this, mIntentFilter); |
| 451 // registerNetworkCallback() will rematch our NetworkRequest | 470 mRegistered = true; |
| 452 // against active networks, so a cached list of active networks | 471 |
| 453 // will be repopulated immediatly after this. However we need to | 472 if (mNetworkCallback != null) { |
| 454 // purge any cached networks as they may have been disconnected | 473 mConnectivityManagerDelegate.registerNetworkCallback(mNetworkRequest
, mNetworkCallback); |
| 455 // while mNetworkCallback was unregistered. | 474 // registerNetworkCallback() will rematch our NetworkRequest |
| 456 final Network[] networks = mConnectivityManagerDelegate.getAllNe
tworks(); | 475 // against active networks, so a cached list of active networks |
| 457 // Convert Networks to NetIDs. | 476 // will be repopulated immediatly after this. However we need to |
| 458 final int[] netIds = new int[networks.length]; | 477 // purge any cached networks as they may have been disconnected |
| 459 for (int i = 0; i < networks.length; i++) { | 478 // while mNetworkCallback was unregistered. |
| 460 netIds[i] = networkToNetId(networks[i]); | 479 final Network[] networks = mConnectivityManagerDelegate.getAllNetwor
ks(); |
| 461 } | 480 // Convert Networks to NetIDs. |
| 462 mObserver.updateActiveNetworkList(netIds); | 481 final int[] netIds = new int[networks.length]; |
| 482 for (int i = 0; i < networks.length; i++) { |
| 483 netIds[i] = networkToNetId(networks[i]); |
| 463 } | 484 } |
| 485 mObserver.updateActiveNetworkList(netIds); |
| 464 } | 486 } |
| 465 } | 487 } |
| 466 | 488 |
| 467 /** | 489 /** |
| 468 * Unregisters the BroadcastReceiver in the given context. | 490 * Unregisters a BroadcastReceiver in the given context. |
| 469 */ | 491 */ |
| 470 private void unregisterReceiver() { | 492 public void unregister() { |
| 471 if (mRegistered) { | 493 if (!mRegistered) return; |
| 472 mRegistered = false; | 494 mContext.unregisterReceiver(this); |
| 473 mContext.unregisterReceiver(this); | 495 mRegistered = false; |
| 474 if (mNetworkCallback != null) { | 496 if (mNetworkCallback != null) { |
| 475 mConnectivityManagerDelegate.unregisterNetworkCallback(mNetworkC
allback); | 497 mConnectivityManagerDelegate.unregisterNetworkCallback(mNetworkCallb
ack); |
| 476 } | |
| 477 } | 498 } |
| 478 } | 499 } |
| 479 | 500 |
| 480 public NetworkState getCurrentNetworkState() { | 501 public NetworkState getCurrentNetworkState() { |
| 481 return mConnectivityManagerDelegate.getNetworkState(); | 502 return mConnectivityManagerDelegate.getNetworkState(); |
| 482 } | 503 } |
| 483 | 504 |
| 484 /** | 505 /** |
| 485 * Returns an array of all of the device's currently connected | 506 * Returns an array of all of the device's currently connected |
| 486 * networks and ConnectionTypes. Array elements are a repeated sequence of: | 507 * networks and ConnectionTypes. Array elements are a repeated sequence of: |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 public void onReceive(Context context, Intent intent) { | 666 public void onReceive(Context context, Intent intent) { |
| 646 final NetworkState networkState = getCurrentNetworkState(); | 667 final NetworkState networkState = getCurrentNetworkState(); |
| 647 if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction()))
{ | 668 if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction()))
{ |
| 648 connectionTypeChanged(networkState); | 669 connectionTypeChanged(networkState); |
| 649 maxBandwidthChanged(networkState); | 670 maxBandwidthChanged(networkState); |
| 650 } else if (WifiManager.RSSI_CHANGED_ACTION.equals(intent.getAction())) { | 671 } else if (WifiManager.RSSI_CHANGED_ACTION.equals(intent.getAction())) { |
| 651 maxBandwidthChanged(networkState); | 672 maxBandwidthChanged(networkState); |
| 652 } | 673 } |
| 653 } | 674 } |
| 654 | 675 |
| 655 // ApplicationStatus.ApplicationStateListener | |
| 656 @Override | |
| 657 public void onApplicationStateChange(int newState) { | |
| 658 final NetworkState networkState = getCurrentNetworkState(); | |
| 659 if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES) { | |
| 660 connectionTypeChanged(networkState); | |
| 661 maxBandwidthChanged(networkState); | |
| 662 registerReceiver(); | |
| 663 } else if (newState == ApplicationState.HAS_PAUSED_ACTIVITIES) { | |
| 664 unregisterReceiver(); | |
| 665 } | |
| 666 } | |
| 667 | |
| 668 private void connectionTypeChanged(NetworkState networkState) { | 676 private void connectionTypeChanged(NetworkState networkState) { |
| 669 int newConnectionType = getCurrentConnectionType(networkState); | 677 int newConnectionType = getCurrentConnectionType(networkState); |
| 670 String newWifiSSID = getCurrentWifiSSID(networkState); | 678 String newWifiSSID = getCurrentWifiSSID(networkState); |
| 671 if (newConnectionType == mConnectionType && newWifiSSID.equals(mWifiSSID
)) return; | 679 if (newConnectionType == mConnectionType && newWifiSSID.equals(mWifiSSID
)) return; |
| 672 | 680 |
| 673 mConnectionType = newConnectionType; | 681 mConnectionType = newConnectionType; |
| 674 mWifiSSID = newWifiSSID; | 682 mWifiSSID = newWifiSSID; |
| 675 Log.d(TAG, "Network connectivity changed, type is: " + mConnectionType); | 683 Log.d(TAG, "Network connectivity changed, type is: " + mConnectionType); |
| 676 mObserver.onConnectionTypeChanged(newConnectionType); | 684 mObserver.onConnectionTypeChanged(newConnectionType); |
| 677 } | 685 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 694 * Extracts NetID of network. Only available on Lollipop and newer releases. | 702 * Extracts NetID of network. Only available on Lollipop and newer releases. |
| 695 */ | 703 */ |
| 696 @SuppressLint("NewApi") | 704 @SuppressLint("NewApi") |
| 697 private static int networkToNetId(Network network) { | 705 private static int networkToNetId(Network network) { |
| 698 // NOTE(pauljensen): This depends on Android framework implementation de
tails. | 706 // NOTE(pauljensen): This depends on Android framework implementation de
tails. |
| 699 // Fortunately this functionality is unlikely to ever change. | 707 // Fortunately this functionality is unlikely to ever change. |
| 700 // TODO(pauljensen): When we update to Android M SDK, use Network.getNet
workHandle(). | 708 // TODO(pauljensen): When we update to Android M SDK, use Network.getNet
workHandle(). |
| 701 return Integer.parseInt(network.toString()); | 709 return Integer.parseInt(network.toString()); |
| 702 } | 710 } |
| 703 } | 711 } |
| OLD | NEW |