Add a "sign into network" button to the wifi details page.

Bug: 36203355
Test: manually signed into captive portal
Test: make -j64 RunSettingsRoboTests
Change-Id: I3242ef30125ddfdaaac9b80ead4f8ac14ea6d364
This commit is contained in:
Lorenzo Colitti
2017-04-27 00:56:39 +09:00
parent d51b94b042
commit b6245156f6
6 changed files with 255 additions and 43 deletions

View File

@@ -28,9 +28,9 @@
android:key="general_details_category" > android:key="general_details_category" >
<!-- Buttons --> <!-- Buttons -->
<com.android.settings.applications.LayoutPreference <com.android.settings.applications.LayoutPreference
android:key="forget_button" android:key="buttons"
android:selectable="false" android:layout="@layout/two_buttons_panel"
android:layout="@layout/single_button_panel" /> android:selectable="false" />
<com.android.settings.wifi.WifiDetailPreference <com.android.settings.wifi.WifiDetailPreference
android:key="signal_strength" android:key="signal_strength"

View File

@@ -16,6 +16,11 @@
package com.android.settings.vpn2; package com.android.settings.vpn2;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkRequest;
import android.os.Handler;
import android.net.ProxyInfo; import android.net.ProxyInfo;
/** /**
@@ -26,6 +31,11 @@ import android.net.ProxyInfo;
*/ */
public interface ConnectivityManagerWrapper { public interface ConnectivityManagerWrapper {
/**
* Returns the real ConnectivityManager object wrapped by this wrapper.
*/
public ConnectivityManager getConnectivityManager();
/** /**
* Calls {@code ConnectivityManager.getAlwaysOnVpnPackageForUser()}. * Calls {@code ConnectivityManager.getAlwaysOnVpnPackageForUser()}.
* *
@@ -39,4 +49,27 @@ public interface ConnectivityManagerWrapper {
* @see android.net.ConnectivityManager#getGlobalProxy * @see android.net.ConnectivityManager#getGlobalProxy
*/ */
ProxyInfo getGlobalProxy(); ProxyInfo getGlobalProxy();
/**
* Calls {@code ConnectivityManager.registerNetworkCallback()}.
*
* This is part of the ConnectivityManager public API in SDK 26 or above, but is not yet visible
* to the robolectric tests, which currently build with SDK 23.
* TODO: delete this once the robolectric tests build with SDK 26 or above.
*
* @see android.net.ConnectivityManager#registerNetworkCallback(NetworkRequest,NetworkCallback,Handler)
*/
public void registerNetworkCallback(NetworkRequest request, NetworkCallback callback,
Handler handler);
/**
* Calls {@code ConnectivityManager.startCaptivePortalApp()}.
*
* This is part of the ConnectivityManager public API in SDK 26 or above, but is not yet visible
* to the robolectric tests, which currently build with SDK 23.
* TODO: delete this once the robolectric tests build with SDK 26 or above.
*
* @see android.net.ConnectivityManager#startCaptivePortalApp(Network)
*/
public void startCaptivePortalApp(Network network);
} }

View File

@@ -17,6 +17,10 @@
package com.android.settings.vpn2; package com.android.settings.vpn2;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkRequest;
import android.os.Handler;
import android.net.ProxyInfo; import android.net.ProxyInfo;
public class ConnectivityManagerWrapperImpl implements ConnectivityManagerWrapper { public class ConnectivityManagerWrapperImpl implements ConnectivityManagerWrapper {
@@ -27,6 +31,11 @@ public class ConnectivityManagerWrapperImpl implements ConnectivityManagerWrappe
mCm = cm; mCm = cm;
} }
@Override
public ConnectivityManager getConnectivityManager() {
return mCm;
}
@Override @Override
public String getAlwaysOnVpnPackageForUser(int userId) { public String getAlwaysOnVpnPackageForUser(int userId) {
return mCm.getAlwaysOnVpnPackageForUser(userId); return mCm.getAlwaysOnVpnPackageForUser(userId);
@@ -36,4 +45,15 @@ public class ConnectivityManagerWrapperImpl implements ConnectivityManagerWrappe
public ProxyInfo getGlobalProxy() { public ProxyInfo getGlobalProxy() {
return mCm.getGlobalProxy(); return mCm.getGlobalProxy();
} }
@Override
public void registerNetworkCallback(NetworkRequest request, NetworkCallback callback,
Handler handler) {
mCm.registerNetworkCallback(request, callback, handler);
}
@Override
public void startCaptivePortalApp(Network network) {
mCm.startCaptivePortalApp(network);
}
} }

View File

@@ -22,30 +22,38 @@ import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.IpPrefix; import android.net.IpPrefix;
import android.net.LinkProperties; import android.net.LinkProperties;
import android.net.Network; import android.net.Network;
import android.net.NetworkBadging; import android.net.NetworkBadging;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.NetworkUtils; import android.net.NetworkUtils;
import android.net.RouteInfo; import android.net.RouteInfo;
import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo; import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.Handler;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory; import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen; import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.widget.Button;
import android.view.View;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.PreferenceController; import com.android.settings.core.PreferenceController;
import com.android.settings.core.lifecycle.Lifecycle; import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.core.lifecycle.LifecycleObserver; import com.android.settings.core.lifecycle.LifecycleObserver;
import com.android.settings.core.lifecycle.events.OnPause; import com.android.settings.core.lifecycle.events.OnPause;
import com.android.settings.core.lifecycle.events.OnResume; import com.android.settings.core.lifecycle.events.OnResume;
import com.android.settings.wifi.WifiDetailPreference; import com.android.settings.wifi.WifiDetailPreference;
import com.android.settings.vpn2.ConnectivityManagerWrapper;
import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint;
import java.net.Inet4Address; import java.net.Inet4Address;
@@ -55,6 +63,9 @@ import java.net.UnknownHostException;
import java.util.List; import java.util.List;
import java.util.StringJoiner; import java.util.StringJoiner;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
/** /**
* Controller for logic pertaining to displaying Wifi information for the * Controller for logic pertaining to displaying Wifi information for the
* {@link WifiNetworkDetailsFragment}. * {@link WifiNetworkDetailsFragment}.
@@ -67,6 +78,8 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
@VisibleForTesting @VisibleForTesting
static final String KEY_CONNECTION_DETAIL_PREF = "connection_detail"; static final String KEY_CONNECTION_DETAIL_PREF = "connection_detail";
@VisibleForTesting @VisibleForTesting
static final String KEY_BUTTONS_PREF = "buttons";
@VisibleForTesting
static final String KEY_SIGNAL_STRENGTH_PREF = "signal_strength"; static final String KEY_SIGNAL_STRENGTH_PREF = "signal_strength";
@VisibleForTesting @VisibleForTesting
static final String KEY_LINK_SPEED = "link_speed"; static final String KEY_LINK_SPEED = "link_speed";
@@ -88,9 +101,14 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
static final String KEY_IPV6_ADDRESS_CATEGORY = "ipv6_details_category"; static final String KEY_IPV6_ADDRESS_CATEGORY = "ipv6_details_category";
private AccessPoint mAccessPoint; private AccessPoint mAccessPoint;
private final ConnectivityManagerWrapper mConnectivityManagerWrapper;
private final ConnectivityManager mConnectivityManager; private final ConnectivityManager mConnectivityManager;
private final Fragment mFragment; private final Fragment mFragment;
private final Handler mHandler;
private LinkProperties mLinkProperties;
private Network mNetwork;
private NetworkInfo mNetworkInfo; private NetworkInfo mNetworkInfo;
private NetworkCapabilities mNetworkCapabilities;
private Context mPrefContext; private Context mPrefContext;
private int mRssi; private int mRssi;
private String[] mSignalStr; private String[] mSignalStr;
@@ -98,8 +116,10 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
private WifiInfo mWifiInfo; private WifiInfo mWifiInfo;
private final WifiManager mWifiManager; private final WifiManager mWifiManager;
// Preferences - in order of appearance // UI elements - in order of appearance
private Preference mConnectionDetailPref; private Preference mConnectionDetailPref;
private LayoutPreference mButtonsPref;
private Button mSignInButton;
private WifiDetailPreference mSignalStrengthPref; private WifiDetailPreference mSignalStrengthPref;
private WifiDetailPreference mLinkSpeedPref; private WifiDetailPreference mLinkSpeedPref;
private WifiDetailPreference mFrequencyPref; private WifiDetailPreference mFrequencyPref;
@@ -123,18 +143,50 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
} }
}; };
private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
.clearCapabilities().addTransportType(TRANSPORT_WIFI).build();
// Must be run on the UI thread since it directly manipulates UI state.
private final NetworkCallback mNetworkCallback = new NetworkCallback() {
@Override
public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
if (network.equals(mNetwork) && !lp.equals(mLinkProperties)) {
mLinkProperties = lp;
updateIpLayerInfo();
}
}
@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
if (network.equals(mNetwork) && !nc.equals(mNetworkCapabilities)) {
mNetworkCapabilities = nc;
updateIpLayerInfo();
}
}
@Override
public void onLost(Network network) {
if (network.equals(mNetwork)) {
exitActivity();
}
}
};
public WifiDetailPreferenceController( public WifiDetailPreferenceController(
AccessPoint accessPoint, AccessPoint accessPoint,
ConnectivityManager connectivityManager, ConnectivityManagerWrapper connectivityManagerWrapper,
Context context, Context context,
Fragment fragment, Fragment fragment,
Handler handler,
Lifecycle lifecycle, Lifecycle lifecycle,
WifiManager wifiManager) { WifiManager wifiManager) {
super(context); super(context);
mAccessPoint = accessPoint; mAccessPoint = accessPoint;
mConnectivityManager = connectivityManager; mConnectivityManager = connectivityManagerWrapper.getConnectivityManager();
mConnectivityManagerWrapper = connectivityManagerWrapper;
mFragment = fragment; mFragment = fragment;
mHandler = handler;
mNetworkInfo = accessPoint.getNetworkInfo(); mNetworkInfo = accessPoint.getNetworkInfo();
mRssi = accessPoint.getRssi(); mRssi = accessPoint.getRssi();
mSignalStr = context.getResources().getStringArray(R.array.wifi_signal); mSignalStr = context.getResources().getStringArray(R.array.wifi_signal);
@@ -167,6 +219,12 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
mConnectionDetailPref = screen.findPreference(KEY_CONNECTION_DETAIL_PREF); mConnectionDetailPref = screen.findPreference(KEY_CONNECTION_DETAIL_PREF);
mButtonsPref = (LayoutPreference) screen.findPreference(KEY_BUTTONS_PREF);
mSignInButton = (Button) mButtonsPref.findViewById(R.id.right_button);
mSignInButton.setText(com.android.internal.R.string.network_available_sign_in);
mSignInButton.setOnClickListener(
view -> mConnectivityManagerWrapper.startCaptivePortalApp(mNetwork));
mSignalStrengthPref = mSignalStrengthPref =
(WifiDetailPreference) screen.findPreference(KEY_SIGNAL_STRENGTH_PREF); (WifiDetailPreference) screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
mLinkSpeedPref = (WifiDetailPreference) screen.findPreference(KEY_LINK_SPEED); mLinkSpeedPref = (WifiDetailPreference) screen.findPreference(KEY_LINK_SPEED);
@@ -191,6 +249,12 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
@Override @Override
public void onResume() { public void onResume() {
mConnectivityManagerWrapper.registerNetworkCallback(mNetworkRequest, mNetworkCallback,
mHandler);
mNetwork = mWifiManager.getCurrentNetwork();
mLinkProperties = mConnectivityManager.getLinkProperties(mNetwork);
mNetworkCapabilities = mConnectivityManager.getNetworkCapabilities(mNetwork);
updateInfo(); updateInfo();
mContext.registerReceiver(mReceiver, mFilter); mContext.registerReceiver(mReceiver, mFilter);
@@ -198,13 +262,17 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
@Override @Override
public void onPause() { public void onPause() {
mNetwork = null;
mLinkProperties = null;
mNetworkCapabilities = null;
mContext.unregisterReceiver(mReceiver); mContext.unregisterReceiver(mReceiver);
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
} }
private void updateInfo() { private void updateInfo() {
mNetworkInfo = mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork()); mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
mWifiInfo = mWifiManager.getConnectionInfo(); mWifiInfo = mWifiManager.getConnectionInfo();
if (mNetworkInfo == null || mWifiInfo == null) { if (mNetwork == null || mNetworkInfo == null || mWifiInfo == null) {
exitActivity(); exitActivity();
return; return;
} }
@@ -238,7 +306,7 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
} }
mFrequencyPref.setDetailText(band); mFrequencyPref.setDetailText(band);
setIpText(); updateIpLayerInfo();
} }
private void exitActivity() { private void exitActivity() {
@@ -270,7 +338,9 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
mSignalStrengthPref.setDetailText(mSignalStr[summarySignalLevel]); mSignalStrengthPref.setDetailText(mSignalStr[summarySignalLevel]);
} }
private void setIpText() { private void updateIpLayerInfo() {
mSignInButton.setVisibility(canSignIntoNetwork() ? View.VISIBLE : View.INVISIBLE);
// Reset all fields // Reset all fields
mIpv6AddressCategory.removeAll(); mIpv6AddressCategory.removeAll();
mIpv6AddressCategory.setVisible(false); mIpv6AddressCategory.setVisible(false);
@@ -279,18 +349,12 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
mGatewayPref.setVisible(false); mGatewayPref.setVisible(false);
mDnsPref.setVisible(false); mDnsPref.setVisible(false);
Network currentNetwork = mWifiManager.getCurrentNetwork(); if (mNetwork == null || mLinkProperties == null) {
if (currentNetwork == null) {
return; return;
} }
List<InetAddress> addresses = mLinkProperties.getAddresses();
LinkProperties linkProperties = mConnectivityManager.getLinkProperties(currentNetwork); // Set IPv4 and IPv6 addresses
if (linkProperties == null) {
return;
}
List<InetAddress> addresses = linkProperties.getAddresses();
// Set IPv4 and Ipv6 addresses
for (int i = 0; i < addresses.size(); i++) { for (int i = 0; i < addresses.size(); i++) {
InetAddress addr = addresses.get(i); InetAddress addr = addresses.get(i);
if (addr instanceof Inet4Address) { if (addr instanceof Inet4Address) {
@@ -310,7 +374,7 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
// Set up IPv4 gateway and subnet mask // Set up IPv4 gateway and subnet mask
String gateway = null; String gateway = null;
String subnet = null; String subnet = null;
for (RouteInfo routeInfo : linkProperties.getRoutes()) { for (RouteInfo routeInfo : mLinkProperties.getRoutes()) {
if (routeInfo.hasGateway() && routeInfo.getGateway() instanceof Inet4Address) { if (routeInfo.hasGateway() && routeInfo.getGateway() instanceof Inet4Address) {
gateway = routeInfo.getGateway().getHostAddress(); gateway = routeInfo.getGateway().getHostAddress();
} }
@@ -333,7 +397,7 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
// Set IPv4 DNS addresses // Set IPv4 DNS addresses
StringJoiner stringJoiner = new StringJoiner(","); StringJoiner stringJoiner = new StringJoiner(",");
for (InetAddress dnsServer : linkProperties.getDnsServers()) { for (InetAddress dnsServer : mLinkProperties.getDnsServers()) {
if (dnsServer instanceof Inet4Address) { if (dnsServer instanceof Inet4Address) {
stringJoiner.add(dnsServer.getHostAddress()); stringJoiner.add(dnsServer.getHostAddress());
} }
@@ -362,6 +426,14 @@ public class WifiDetailPreferenceController extends PreferenceController impleme
return mWifiInfo != null && mWifiInfo.isEphemeral() || mWifiConfig != null; return mWifiInfo != null && mWifiInfo.isEphemeral() || mWifiConfig != null;
} }
/**
* Returns whether the user can sign into the network represented by this preference.
*/
private boolean canSignIntoNetwork() {
return mNetworkCapabilities != null && mNetworkCapabilities.hasCapability(
NET_CAPABILITY_CAPTIVE_PORTAL);
}
/** /**
* Forgets the wifi network associated with this preference. * Forgets the wifi network associated with this preference.
*/ */

View File

@@ -17,8 +17,12 @@ package com.android.settings.wifi.details;
import android.content.Context; import android.content.Context;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.NetworkRequest;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.Button; import android.widget.Button;
import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto;
@@ -26,6 +30,7 @@ import com.android.settings.R;
import com.android.settings.applications.LayoutPreference; import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.PreferenceController; import com.android.settings.core.PreferenceController;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.vpn2.ConnectivityManagerWrapperImpl;
import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint;
import java.util.ArrayList; import java.util.ArrayList;
@@ -40,9 +45,6 @@ import java.util.List;
public class WifiNetworkDetailsFragment extends DashboardFragment { public class WifiNetworkDetailsFragment extends DashboardFragment {
private static final String TAG = "WifiNetworkDetailsFrg"; private static final String TAG = "WifiNetworkDetailsFrg";
// XML KEYS
private static final String KEY_FORGET_BUTTON = "forget_button";
private AccessPoint mAccessPoint; private AccessPoint mAccessPoint;
private Button mForgetButton; private Button mForgetButton;
private WifiDetailPreferenceController mWifiDetailPreferenceController; private WifiDetailPreferenceController mWifiDetailPreferenceController;
@@ -59,9 +61,11 @@ public class WifiNetworkDetailsFragment extends DashboardFragment {
// Header Title set automatically from launching Preference // Header Title set automatically from launching Preference
LayoutPreference forgetPreference = ((LayoutPreference) findPreference(KEY_FORGET_BUTTON)); LayoutPreference buttonsPreference = ((LayoutPreference) findPreference(
forgetPreference.setVisible(mWifiDetailPreferenceController.canForgetNetwork()); WifiDetailPreferenceController.KEY_BUTTONS_PREF));
mForgetButton = (Button) forgetPreference.findViewById(R.id.button); buttonsPreference.setVisible(mWifiDetailPreferenceController.canForgetNetwork());
mForgetButton = (Button) buttonsPreference.findViewById(R.id.left_button);
mForgetButton.setText(R.string.forget); mForgetButton.setText(R.string.forget);
mForgetButton.setOnClickListener(view -> forgetNetwork()); mForgetButton.setOnClickListener(view -> forgetNetwork());
} }
@@ -88,11 +92,13 @@ public class WifiNetworkDetailsFragment extends DashboardFragment {
@Override @Override
protected List<PreferenceController> getPreferenceControllers(Context context) { protected List<PreferenceController> getPreferenceControllers(Context context) {
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
mWifiDetailPreferenceController = new WifiDetailPreferenceController( mWifiDetailPreferenceController = new WifiDetailPreferenceController(
mAccessPoint, mAccessPoint,
context.getSystemService(ConnectivityManager.class), new ConnectivityManagerWrapperImpl(cm),
context, context,
this, this,
new Handler(Looper.getMainLooper()), // UI thread.
getLifecycle(), getLifecycle(),
context.getSystemService(WifiManager.class)); context.getSystemService(WifiManager.class));

View File

@@ -18,6 +18,8 @@ package com.android.settings.wifi.details;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset; import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
@@ -29,25 +31,35 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.IpPrefix; import android.net.IpPrefix;
import android.net.LinkAddress; import android.net.LinkAddress;
import android.net.LinkProperties; import android.net.LinkProperties;
import android.net.Network; import android.net.Network;
import android.net.NetworkBadging; import android.net.NetworkBadging;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.RouteInfo; import android.net.RouteInfo;
import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo; import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.Handler;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory; import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen; import android.support.v7.preference.PreferenceScreen;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig; import com.android.settings.TestConfig;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.lifecycle.Lifecycle; import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.wifi.WifiDetailPreference; import com.android.settings.wifi.WifiDetailPreference;
import com.android.settings.vpn2.ConnectivityManagerWrapper;
import com.android.settings.vpn2.ConnectivityManagerWrapperImpl;
import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint;
import org.junit.Before; import org.junit.Before;
@@ -55,6 +67,7 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Answers; import org.mockito.Answers;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
@@ -83,6 +96,7 @@ public class WifiDetailPreferenceControllerTest {
@Mock private AccessPoint mockAccessPoint; @Mock private AccessPoint mockAccessPoint;
@Mock private Activity mockActivity; @Mock private Activity mockActivity;
@Mock private ConnectivityManager mockConnectivityManager; @Mock private ConnectivityManager mockConnectivityManager;
@Mock private ConnectivityManagerWrapperImpl mockConnectivityManagerWrapper;
@Mock private Network mockNetwork; @Mock private Network mockNetwork;
@Mock private NetworkInfo mockNetworkInfo; @Mock private NetworkInfo mockNetworkInfo;
@Mock private WifiConfiguration mockWifiConfig; @Mock private WifiConfiguration mockWifiConfig;
@@ -91,6 +105,8 @@ public class WifiDetailPreferenceControllerTest {
@Mock private WifiManager mockWifiManager; @Mock private WifiManager mockWifiManager;
@Mock private Preference mockConnectionDetailPref; @Mock private Preference mockConnectionDetailPref;
@Mock private LayoutPreference mockButtonsPref;
@Mock private Button mockSignInButton;
@Mock private WifiDetailPreference mockSignalStrengthPref; @Mock private WifiDetailPreference mockSignalStrengthPref;
@Mock private WifiDetailPreference mockLinkSpeedPref; @Mock private WifiDetailPreference mockLinkSpeedPref;
@Mock private WifiDetailPreference mockFrequencyPref; @Mock private WifiDetailPreference mockFrequencyPref;
@@ -102,9 +118,10 @@ public class WifiDetailPreferenceControllerTest {
@Mock private WifiDetailPreference mockDnsPref; @Mock private WifiDetailPreference mockDnsPref;
@Mock private PreferenceCategory mockIpv6AddressCategory; @Mock private PreferenceCategory mockIpv6AddressCategory;
private LinkProperties mLinkProperties; private ArgumentCaptor<NetworkCallback> mCallbackCaptor;
private Context mContext = RuntimeEnvironment.application; private Context mContext = RuntimeEnvironment.application;
private Lifecycle mLifecycle; private Lifecycle mLifecycle;
private LinkProperties mLinkProperties;
private WifiDetailPreferenceController mController; private WifiDetailPreferenceController mController;
@Before @Before
@@ -126,14 +143,20 @@ public class WifiDetailPreferenceControllerTest {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
mCallbackCaptor = ArgumentCaptor.forClass(NetworkCallback.class);
when(mockAccessPoint.getConfig()).thenReturn(mockWifiConfig); when(mockAccessPoint.getConfig()).thenReturn(mockWifiConfig);
when(mockAccessPoint.getLevel()).thenReturn(LEVEL); when(mockAccessPoint.getLevel()).thenReturn(LEVEL);
when(mockAccessPoint.getNetworkInfo()).thenReturn(mockNetworkInfo); when(mockAccessPoint.getNetworkInfo()).thenReturn(mockNetworkInfo);
when(mockAccessPoint.getRssi()).thenReturn(RSSI); when(mockAccessPoint.getRssi()).thenReturn(RSSI);
when(mockAccessPoint.getSecurityString(false)).thenReturn(SECURITY); when(mockAccessPoint.getSecurityString(false)).thenReturn(SECURITY);
when(mockConnectivityManagerWrapper.getConnectivityManager())
.thenReturn(mockConnectivityManager);
when(mockConnectivityManager.getNetworkInfo(any(Network.class))) when(mockConnectivityManager.getNetworkInfo(any(Network.class)))
.thenReturn(mockNetworkInfo); .thenReturn(mockNetworkInfo);
doNothing().when(mockConnectivityManagerWrapper).registerNetworkCallback(
any(NetworkRequest.class), mCallbackCaptor.capture(), any(Handler.class));
when(mockWifiInfo.getLinkSpeed()).thenReturn(LINK_SPEED); when(mockWifiInfo.getLinkSpeed()).thenReturn(LINK_SPEED);
when(mockWifiInfo.getRssi()).thenReturn(RSSI); when(mockWifiInfo.getRssi()).thenReturn(RSSI);
@@ -154,9 +177,10 @@ public class WifiDetailPreferenceControllerTest {
private WifiDetailPreferenceController newWifiDetailPreferenceController() { private WifiDetailPreferenceController newWifiDetailPreferenceController() {
return new WifiDetailPreferenceController( return new WifiDetailPreferenceController(
mockAccessPoint, mockAccessPoint,
mockConnectivityManager, mockConnectivityManagerWrapper,
mContext, mContext,
mockFragment, mockFragment,
null, // Handler
mLifecycle, mLifecycle,
mockWifiManager); mockWifiManager);
} }
@@ -166,6 +190,10 @@ public class WifiDetailPreferenceControllerTest {
when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_CONNECTION_DETAIL_PREF)) when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_CONNECTION_DETAIL_PREF))
.thenReturn(mockConnectionDetailPref); .thenReturn(mockConnectionDetailPref);
when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_BUTTONS_PREF))
.thenReturn(mockButtonsPref);
when(mockButtonsPref.findViewById(R.id.right_button))
.thenReturn(mockSignInButton);
when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SIGNAL_STRENGTH_PREF)) when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SIGNAL_STRENGTH_PREF))
.thenReturn(mockSignalStrengthPref); .thenReturn(mockSignalStrengthPref);
when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_LINK_SPEED)) when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_LINK_SPEED))
@@ -214,6 +242,23 @@ public class WifiDetailPreferenceControllerTest {
verify(mockConnectivityManager, times(1)).getNetworkInfo(any(Network.class)); verify(mockConnectivityManager, times(1)).getNetworkInfo(any(Network.class));
} }
@Test
public void networkCallback_shouldBeRegisteredOnResume() {
mController.onResume();
verify(mockConnectivityManagerWrapper, times(1)).registerNetworkCallback(
any(NetworkRequest.class), mCallbackCaptor.capture(), any(Handler.class));
}
@Test
public void networkCallback_shouldBeUnregisteredOnPause() {
mController.onResume();
mController.onPause();
verify(mockConnectivityManager, times(1)).unregisterNetworkCallback(
mCallbackCaptor.getValue());
}
@Test @Test
public void connectionDetailPref_shouldHaveIconSet() { public void connectionDetailPref_shouldHaveIconSet() {
Drawable expectedIcon = Drawable expectedIcon =
@@ -311,23 +356,14 @@ public class WifiDetailPreferenceControllerTest {
} }
@Test @Test
public void noCurrentNetwork_allIpDetailsHidden() { public void noCurrentNetwork_shouldFinishActivity() {
// If WifiManager#getCurrentNetwork() returns null, then the network is neither connected
// nor connecting and WifiStateMachine has not reached L2ConnectedState.
when(mockWifiManager.getCurrentNetwork()).thenReturn(null); when(mockWifiManager.getCurrentNetwork()).thenReturn(null);
reset(mockIpv6AddressCategory, mockIpAddressPref, mockSubnetPref, mockGatewayPref,
mockDnsPref);
mController.onResume(); mController.onResume();
verify(mockIpv6AddressCategory).setVisible(false); verify(mockActivity).finish();
verify(mockIpAddressPref).setVisible(false);
verify(mockSubnetPref).setVisible(false);
verify(mockGatewayPref).setVisible(false);
verify(mockDnsPref).setVisible(false);
verify(mockIpv6AddressCategory, never()).setVisible(true);
verify(mockIpAddressPref, never()).setVisible(true);
verify(mockSubnetPref, never()).setVisible(true);
verify(mockGatewayPref, never()).setVisible(true);
verify(mockDnsPref, never()).setVisible(true);
} }
@Test @Test
@@ -432,6 +468,15 @@ public class WifiDetailPreferenceControllerTest {
verify(mockActivity).finish(); verify(mockActivity).finish();
} }
@Test
public void networkOnLost_shouldFinishActivity() {
mController.onResume();
mCallbackCaptor.getValue().onLost(mockNetwork);
verify(mockActivity).finish();
}
@Test @Test
public void ipv6AddressPref_shouldHaveHostAddressTextSet() { public void ipv6AddressPref_shouldHaveHostAddressTextSet() {
LinkAddress ipv6Address = new LinkAddress(mIpv6Address, 128); LinkAddress ipv6Address = new LinkAddress(mIpv6Address, 128);
@@ -457,4 +502,40 @@ public class WifiDetailPreferenceControllerTest {
verify(mockIpv6AddressCategory).addPreference(preferenceCaptor.capture()); verify(mockIpv6AddressCategory).addPreference(preferenceCaptor.capture());
assertThat(preferenceCaptor.getValue().isSelectable()).isFalse(); assertThat(preferenceCaptor.getValue().isSelectable()).isFalse();
} }
@Test
public void captivePortal_shouldShowSignInButton() {
reset(mockSignInButton);
InOrder inOrder = inOrder(mockSignInButton);
mController.onResume();
inOrder.verify(mockSignInButton).setVisibility(View.INVISIBLE);
NetworkCapabilities nc = new NetworkCapabilities();
nc.clearAll();
nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
NetworkCallback callback = mCallbackCaptor.getValue();
callback.onCapabilitiesChanged(mockNetwork, nc);
inOrder.verify(mockSignInButton).setVisibility(View.INVISIBLE);
nc = new NetworkCapabilities(nc);
nc.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
callback.onCapabilitiesChanged(mockNetwork, nc);
inOrder.verify(mockSignInButton).setVisibility(View.VISIBLE);
nc = new NetworkCapabilities(nc);
nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
callback.onCapabilitiesChanged(mockNetwork, nc);
inOrder.verify(mockSignInButton).setVisibility(View.INVISIBLE);
}
@Test
public void testSignInButton_shouldStartCaptivePortalApp() {
mController.onResume();
ArgumentCaptor<OnClickListener> captor = ArgumentCaptor.forClass(OnClickListener.class);
verify(mockSignInButton).setOnClickListener(captor.capture());
captor.getValue().onClick(mockSignInButton);
verify(mockConnectivityManagerWrapper).startCaptivePortalApp(mockNetwork);
}
} }