blob: 064bfc8173f6a989dbf0654e1bb044918509a63c [file] [log] [blame]
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.net;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.telephony.TelephonyManager;
import android.test.InstrumentationTestCase;
import android.test.UiThreadTest;
import android.test.suitebuilder.annotation.MediumTest;
import org.chromium.base.ApplicationState;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.test.util.Feature;
import org.chromium.net.NetworkChangeNotifierAutoDetect.NetworkState;
/**
* Tests for org.chromium.net.NetworkChangeNotifier.
*/
public class NetworkChangeNotifierTest extends InstrumentationTestCase {
/**
* Listens for alerts fired by the NetworkChangeNotifier when network status changes.
*/
private static class NetworkChangeNotifierTestObserver
implements NetworkChangeNotifier.ConnectionTypeObserver {
private boolean mReceivedNotification = false;
@Override
public void onConnectionTypeChanged(int connectionType) {
mReceivedNotification = true;
}
public boolean hasReceivedNotification() {
return mReceivedNotification;
}
public void resetHasReceivedNotification() {
mReceivedNotification = false;
}
}
/**
* Mocks out calls to the ConnectivityManager.
*/
class MockConnectivityManagerDelegate
extends NetworkChangeNotifierAutoDetect.ConnectivityManagerDelegate {
private boolean mActiveNetworkExists;
private int mNetworkType;
private int mNetworkSubtype;
@Override
NetworkState getNetworkState() {
return new NetworkState(mActiveNetworkExists, mNetworkType, mNetworkSubtype);
}
void setActiveNetworkExists(boolean networkExists) {
mActiveNetworkExists = networkExists;
}
void setNetworkType(int networkType) {
mNetworkType = networkType;
}
void setNetworkSubtype(int networkSubtype) {
mNetworkSubtype = networkSubtype;
}
}
/**
* Mocks out calls to the WifiManager.
*/
class MockWifiManagerDelegate
extends NetworkChangeNotifierAutoDetect.WifiManagerDelegate {
private String mWifiSSID;
private int mLinkSpeedMbps;
@Override
String getWifiSSID() {
return mWifiSSID;
}
void setWifiSSID(String wifiSSID) {
mWifiSSID = wifiSSID;
}
@Override
int getLinkSpeedInMbps() {
return mLinkSpeedMbps;
}
void setLinkSpeedInMbps(int linkSpeedInMbps) {
mLinkSpeedMbps = linkSpeedInMbps;
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized();
createTestNotifier(WatchForChanges.ONLY_WHEN_APP_IN_FOREGROUND);
}
private NetworkChangeNotifierAutoDetect mReceiver;
private MockConnectivityManagerDelegate mConnectivityDelegate;
private MockWifiManagerDelegate mWifiDelegate;
private static enum WatchForChanges {
ALWAYS,
ONLY_WHEN_APP_IN_FOREGROUND,
}
/**
* Helper method to create a notifier and delegates for testing.
* @param watchForChanges indicates whether app wants to watch for changes always or only when
* it is in the foreground.
*/
private void createTestNotifier(WatchForChanges watchForChanges) {
Context context = getInstrumentation().getTargetContext();
NetworkChangeNotifier.resetInstanceForTests(context);
if (watchForChanges == WatchForChanges.ALWAYS) {
NetworkChangeNotifier.registerToReceiveNotificationsAlways();
} else {
NetworkChangeNotifier.setAutoDetectConnectivityState(true);
}
mReceiver = NetworkChangeNotifier.getAutoDetectorForTest();
assertNotNull(mReceiver);
mConnectivityDelegate =
new MockConnectivityManagerDelegate();
mConnectivityDelegate.setActiveNetworkExists(true);
mReceiver.setConnectivityManagerDelegateForTests(mConnectivityDelegate);
mWifiDelegate = new MockWifiManagerDelegate();
mReceiver.setWifiManagerDelegateForTests(mWifiDelegate);
mWifiDelegate.setWifiSSID("foo");
}
private double getCurrentMaxBandwidthInMbps() {
final NetworkChangeNotifierAutoDetect.NetworkState networkState =
mReceiver.getCurrentNetworkState();
return mReceiver.getCurrentMaxBandwidthInMbps(networkState);
}
private int getCurrentConnectionType() {
final NetworkChangeNotifierAutoDetect.NetworkState networkState =
mReceiver.getCurrentNetworkState();
return mReceiver.getCurrentConnectionType(networkState);
}
/**
* Tests that changing the RSSI_CHANGED_ACTION intent updates MaxBandwidth.
*/
@UiThreadTest
@MediumTest
@Feature({"Android-AppBase"})
public void testNetworkChangeNotifierRSSIEventUpdatesMaxBandwidthForWiFi()
throws InterruptedException {
NetworkChangeNotifier notifier = NetworkChangeNotifier.getInstance();
mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI);
mWifiDelegate.setLinkSpeedInMbps(42);
Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION);
mReceiver.onReceive(getInstrumentation().getTargetContext(), intent);
assertEquals(42.0, notifier.getCurrentMaxBandwidthInMbps());
// Changing the link speed has no effect until the intent fires.
mWifiDelegate.setLinkSpeedInMbps(80);
assertEquals(42.0, notifier.getCurrentMaxBandwidthInMbps());
// Fire the intent.
mReceiver.onReceive(getInstrumentation().getTargetContext(), intent);
assertEquals(80.0, notifier.getCurrentMaxBandwidthInMbps());
// Firing a network type change intent also causes max bandwidth to update.
mWifiDelegate.setLinkSpeedInMbps(20);
intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
mReceiver.onReceive(getInstrumentation().getTargetContext(), intent);
assertEquals(20.0, notifier.getCurrentMaxBandwidthInMbps());
}
/**
* Tests that changing the network type changes the maxBandwidth.
*/
@UiThreadTest
@MediumTest
@Feature({"Android-AppBase"})
public void testNetworkChangeNotifierMaxBandwidthEthernet() throws InterruptedException {
// Show that for Ethernet the link speed is unknown (+Infinity).
mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_ETHERNET);
assertEquals(ConnectionType.CONNECTION_ETHERNET, getCurrentConnectionType());
assertEquals(Double.POSITIVE_INFINITY, getCurrentMaxBandwidthInMbps());
}
@UiThreadTest
@MediumTest
@Feature({"Android-AppBase"})
public void testNetworkChangeNotifierMaxBandwidthWifi() throws InterruptedException {
// Test that for wifi types the link speed is read from the WifiManager.
mWifiDelegate.setLinkSpeedInMbps(42);
mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI);
assertEquals(ConnectionType.CONNECTION_WIFI, getCurrentConnectionType());
assertEquals(42.0, getCurrentMaxBandwidthInMbps());
}
@UiThreadTest
@MediumTest
@Feature({"Android-AppBase"})
public void testNetworkChangeNotifierMaxBandwidthWiMax() throws InterruptedException {
// Show that for WiMax the link speed is unknown (+Infinity), although the type is 4g.
// TODO(jkarlin): Add support for CONNECTION_WIMAX as specified in
// http://w3c.github.io/netinfo/.
mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIMAX);
assertEquals(ConnectionType.CONNECTION_4G, getCurrentConnectionType());
assertEquals(Double.POSITIVE_INFINITY, getCurrentMaxBandwidthInMbps());
}
@UiThreadTest
@MediumTest
@Feature({"Android-AppBase"})
public void testNetworkChangeNotifierMaxBandwidthBluetooth() throws InterruptedException {
// Show that for bluetooth the link speed is unknown (+Infinity).
mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_BLUETOOTH);
assertEquals(ConnectionType.CONNECTION_BLUETOOTH, getCurrentConnectionType());
assertEquals(Double.POSITIVE_INFINITY, getCurrentMaxBandwidthInMbps());
}
@UiThreadTest
@MediumTest
@Feature({"Android-AppBase"})
public void testNetworkChangeNotifierMaxBandwidthMobile() throws InterruptedException {
// Test that for mobile types the subtype is used to determine the maxBandwidth.
mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_MOBILE);
mConnectivityDelegate.setNetworkSubtype(TelephonyManager.NETWORK_TYPE_LTE);
assertEquals(ConnectionType.CONNECTION_4G, getCurrentConnectionType());
assertEquals(100.0, getCurrentMaxBandwidthInMbps());
}
/**
* Tests that when Chrome gets an intent indicating a change in network connectivity, it sends a
* notification to Java observers.
*/
@UiThreadTest
@MediumTest
@Feature({"Android-AppBase"})
public void testNetworkChangeNotifierJavaObservers() throws InterruptedException {
// Initialize the NetworkChangeNotifier with a connection.
Intent connectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
mReceiver.onReceive(getInstrumentation().getTargetContext(), connectivityIntent);
// We shouldn't be re-notified if the connection hasn't actually changed.
NetworkChangeNotifierTestObserver observer = new NetworkChangeNotifierTestObserver();
NetworkChangeNotifier.addConnectionTypeObserver(observer);
mReceiver.onReceive(getInstrumentation().getTargetContext(), connectivityIntent);
assertFalse(observer.hasReceivedNotification());
// We shouldn't be notified if we're connected to non-Wifi and the Wifi SSID changes.
mWifiDelegate.setWifiSSID("bar");
mReceiver.onReceive(getInstrumentation().getTargetContext(), connectivityIntent);
assertFalse(observer.hasReceivedNotification());
// We should be notified when we change to Wifi.
mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI);
mReceiver.onReceive(getInstrumentation().getTargetContext(), connectivityIntent);
assertTrue(observer.hasReceivedNotification());
observer.resetHasReceivedNotification();
// We should be notified when the Wifi SSID changes.
mWifiDelegate.setWifiSSID("foo");
mReceiver.onReceive(getInstrumentation().getTargetContext(), connectivityIntent);
assertTrue(observer.hasReceivedNotification());
observer.resetHasReceivedNotification();
// We shouldn't be re-notified if the Wifi SSID hasn't actually changed.
mReceiver.onReceive(getInstrumentation().getTargetContext(), connectivityIntent);
assertFalse(observer.hasReceivedNotification());
// Mimic that connectivity has been lost and ensure that Chrome notifies our observer.
mConnectivityDelegate.setActiveNetworkExists(false);
Intent noConnectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
mReceiver.onReceive(getInstrumentation().getTargetContext(), noConnectivityIntent);
assertTrue(observer.hasReceivedNotification());
observer.resetHasReceivedNotification();
// Pretend we got moved to the background.
mReceiver.onApplicationStateChange(ApplicationState.HAS_PAUSED_ACTIVITIES);
// Change the state.
mConnectivityDelegate.setActiveNetworkExists(true);
mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI);
// The NetworkChangeNotifierAutoDetect doesn't receive any notification while we are in the
// background, but when we get back to the foreground the state changed should be detected
// and a notification sent.
mReceiver.onApplicationStateChange(ApplicationState.HAS_RUNNING_ACTIVITIES);
assertTrue(observer.hasReceivedNotification());
}
/**
* Tests that when setting {@code registerToReceiveNotificationsAlways()},
* a NetworkChangeNotifierAutoDetect object is successfully created.
*/
@UiThreadTest
@MediumTest
@Feature({"Android-AppBase"})
public void testCreateNetworkChangeNotifierAlwaysWatchForChanges() throws InterruptedException {
createTestNotifier(WatchForChanges.ALWAYS);
// Make sure notifications can be received.
NetworkChangeNotifierTestObserver observer = new NetworkChangeNotifierTestObserver();
NetworkChangeNotifier.addConnectionTypeObserver(observer);
Intent connectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
mReceiver.onReceive(getInstrumentation().getTargetContext(), connectivityIntent);
assertTrue(observer.hasReceivedNotification());
}
}