Add subtext for Wi-Fi items on Wi-Fi slice

- Sync the Wi-Fi slice items subtexts with Wi-Fi page, and add
  "Not connected" when the returned subtext is empty
- Wi-Fi slice header subtext just simply reveals on/off state
- Add a placeholder to the loading row to sync its height with other
  rows
- Show contextual Wi-Fi slice when the connected network is captive
  portal, is invalidated, or has limited connectivity

Bug: 130751985
Test: make RunSettingsRoboTests -j ROBOTEST_FILTER=com.android.settings.wifi
Change-Id: I0b2715295f00edc8dd7d6d75b7fdc18263675797
This commit is contained in:
Jason Chiu
2019-05-02 12:22:22 +08:00
parent 0ea58e740d
commit 6a6787cdc0
7 changed files with 146 additions and 180 deletions

View File

@@ -25,7 +25,6 @@ import androidx.preference.PreferenceViewHolder;
import com.android.settings.R; import com.android.settings.R;
import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint;
import com.android.settingslib.wifi.AccessPointPreference;
/** /**
* An AP preference for the currently connected AP * An AP preference for the currently connected AP

View File

@@ -17,7 +17,10 @@
package com.android.settings.wifi.slice; package com.android.settings.wifi.slice;
import android.content.Context; import android.content.Context;
import android.net.NetworkCapabilities;
import android.net.Uri; import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiSsid; import android.net.wifi.WifiSsid;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@@ -69,6 +72,22 @@ public class ContextualWifiSlice extends WifiSlice {
} }
private boolean hasWorkingNetwork() { private boolean hasWorkingNetwork() {
return !TextUtils.equals(getActiveSSID(), WifiSsid.NONE) && !isCaptivePortal(); return !TextUtils.equals(getActiveSSID(), WifiSsid.NONE) && hasInternetAccess();
}
private String getActiveSSID() {
if (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED) {
return WifiSsid.NONE;
}
return WifiInfo.removeDoubleQuotes(mWifiManager.getConnectionInfo().getSSID());
}
private boolean hasInternetAccess() {
final NetworkCapabilities nc = mConnectivityManager.getNetworkCapabilities(
mWifiManager.getCurrentNetwork());
return nc != null
&& !nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)
&& !nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY)
&& nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
} }
} }

View File

@@ -16,7 +16,11 @@
package com.android.settings.wifi.slice; package com.android.settings.wifi.slice;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT; import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT;
import android.content.Context; import android.content.Context;
@@ -25,7 +29,6 @@ import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback; import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network; import android.net.Network;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest; import android.net.NetworkRequest;
import android.net.Uri; import android.net.Uri;
import android.net.wifi.WifiInfo; import android.net.wifi.WifiInfo;
@@ -40,7 +43,6 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.util.Preconditions; import com.android.internal.util.Preconditions;
import com.android.settings.slices.SliceBackgroundWorker; import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settings.wifi.WifiUtils;
import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint;
import com.android.settingslib.wifi.WifiTracker; import com.android.settingslib.wifi.WifiTracker;
@@ -56,7 +58,7 @@ public class WifiScanWorker extends SliceBackgroundWorker<AccessPoint> implement
private static final String TAG = "WifiScanWorker"; private static final String TAG = "WifiScanWorker";
@VisibleForTesting @VisibleForTesting
CaptivePortalNetworkCallback mCaptivePortalNetworkCallback; WifiNetworkCallback mNetworkCallback;
private final Context mContext; private final Context mContext;
private final ConnectivityManager mConnectivityManager; private final ConnectivityManager mConnectivityManager;
@@ -81,7 +83,7 @@ public class WifiScanWorker extends SliceBackgroundWorker<AccessPoint> implement
@Override @Override
protected void onSliceUnpinned() { protected void onSliceUnpinned() {
mWifiTracker.onStop(); mWifiTracker.onStop();
unregisterCaptivePortalNetworkCallback(); unregisterNetworkCallback();
clearClickedWifi(); clearClickedWifi();
} }
@@ -135,21 +137,13 @@ public class WifiScanWorker extends SliceBackgroundWorker<AccessPoint> implement
// compare access point states one by one // compare access point states one by one
final int listSize = a.size(); final int listSize = a.size();
for (int i = 0; i < listSize; i++) { for (int i = 0; i < listSize; i++) {
if (getState(a.get(i)) != getState(b.get(i))) { if (a.get(i).getDetailedState() != b.get(i).getDetailedState()) {
return false; return false;
} }
} }
return true; return true;
} }
private NetworkInfo.State getState(AccessPoint accessPoint) {
final NetworkInfo networkInfo = accessPoint.getNetworkInfo();
if (networkInfo != null) {
return networkInfo.getState();
}
return null;
}
static void saveClickedWifi(AccessPoint accessPoint) { static void saveClickedWifi(AccessPoint accessPoint) {
sClickedWifiSsid = accessPoint.getSsidStr(); sClickedWifiSsid = accessPoint.getSsidStr();
} }
@@ -163,69 +157,74 @@ public class WifiScanWorker extends SliceBackgroundWorker<AccessPoint> implement
return !TextUtils.isEmpty(ssid) && TextUtils.equals(ssid, sClickedWifiSsid); return !TextUtils.isEmpty(ssid) && TextUtils.equals(ssid, sClickedWifiSsid);
} }
public void registerCaptivePortalNetworkCallback(Network wifiNetwork) { public void registerNetworkCallback(Network wifiNetwork) {
if (wifiNetwork == null) { if (wifiNetwork == null) {
return; return;
} }
if (mCaptivePortalNetworkCallback != null if (mNetworkCallback != null && mNetworkCallback.isSameNetwork(wifiNetwork)) {
&& mCaptivePortalNetworkCallback.isSameNetwork(wifiNetwork)) {
return; return;
} }
unregisterCaptivePortalNetworkCallback(); unregisterNetworkCallback();
mCaptivePortalNetworkCallback = new CaptivePortalNetworkCallback(wifiNetwork); mNetworkCallback = new WifiNetworkCallback(wifiNetwork);
mConnectivityManager.registerNetworkCallback( mConnectivityManager.registerNetworkCallback(
new NetworkRequest.Builder() new NetworkRequest.Builder()
.clearCapabilities() .clearCapabilities()
.addTransportType(TRANSPORT_WIFI) .addTransportType(TRANSPORT_WIFI)
.build(), .build(),
mCaptivePortalNetworkCallback, mNetworkCallback,
new Handler(Looper.getMainLooper())); new Handler(Looper.getMainLooper()));
} }
public void unregisterCaptivePortalNetworkCallback() { public void unregisterNetworkCallback() {
if (mCaptivePortalNetworkCallback != null) { if (mNetworkCallback != null) {
try { try {
mConnectivityManager.unregisterNetworkCallback(mCaptivePortalNetworkCallback); mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
} catch (RuntimeException e) { } catch (RuntimeException e) {
Log.e(TAG, "Unregistering CaptivePortalNetworkCallback failed.", e); Log.e(TAG, "Unregistering CaptivePortalNetworkCallback failed.", e);
} }
mCaptivePortalNetworkCallback = null; mNetworkCallback = null;
} }
} }
class CaptivePortalNetworkCallback extends NetworkCallback { class WifiNetworkCallback extends NetworkCallback {
private final Network mNetwork; private final Network mNetwork;
private boolean mIsCaptivePortal; private boolean mIsCaptivePortal;
private boolean mHasPartialConnectivity;
private boolean mIsValidated;
CaptivePortalNetworkCallback(Network network) { WifiNetworkCallback(Network network) {
mNetwork = Preconditions.checkNotNull(network); mNetwork = Preconditions.checkNotNull(network);
} }
@Override @Override
public void onCapabilitiesChanged(Network network, public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
NetworkCapabilities networkCapabilities) {
if (!isSameNetwork(network)) { if (!isSameNetwork(network)) {
return; return;
} }
final boolean isCaptivePortal = WifiUtils.canSignIntoNetwork(networkCapabilities); final boolean prevIsCaptivePortal = mIsCaptivePortal;
if (mIsCaptivePortal == isCaptivePortal) { final boolean prevHasPartialConnectivity = mHasPartialConnectivity;
final boolean prevIsValidated = mIsValidated;
mIsCaptivePortal = nc.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
mHasPartialConnectivity = nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
mIsValidated = nc.hasCapability(NET_CAPABILITY_VALIDATED);
if (prevIsCaptivePortal == mIsCaptivePortal
&& prevHasPartialConnectivity == mHasPartialConnectivity
&& prevIsValidated == mIsValidated) {
return; return;
} }
mIsCaptivePortal = isCaptivePortal;
notifySliceChange(); notifySliceChange();
// Automatically start captive portal // Automatically start captive portal
if (mIsCaptivePortal) { if (!prevIsCaptivePortal && mIsCaptivePortal
if (!isWifiClicked(mWifiTracker.getManager().getConnectionInfo())) { && isWifiClicked(mWifiTracker.getManager().getConnectionInfo())) {
return;
}
final Intent intent = new Intent(mContext, ConnectToWifiHandler.class) final Intent intent = new Intent(mContext, ConnectToWifiHandler.class)
.putExtra(ConnectivityManager.EXTRA_NETWORK, network) .putExtra(ConnectivityManager.EXTRA_NETWORK, network)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

View File

@@ -34,17 +34,10 @@ import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.net.NetworkInfo.DetailedState;
import android.net.Uri; import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.net.wifi.WifiSsid;
import android.os.Bundle; import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
@@ -99,16 +92,16 @@ public class WifiSlice implements CustomSliceable {
mContext.getTheme().applyStyle(R.style.Theme_Settings_Home, true /* force */); mContext.getTheme().applyStyle(R.style.Theme_Settings_Home, true /* force */);
final boolean isWifiEnabled = isWifiEnabled(); final boolean isWifiEnabled = isWifiEnabled();
ListBuilder listBuilder = getListBuilder(isWifiEnabled, null /* accessPoint */); ListBuilder listBuilder = getHeaderRow(isWifiEnabled);
if (!isWifiEnabled) { if (!isWifiEnabled) {
return listBuilder.build(); return listBuilder.build();
} }
final WifiScanWorker worker = SliceBackgroundWorker.getInstance(getUri()); final WifiScanWorker worker = SliceBackgroundWorker.getInstance(getUri());
final List<AccessPoint> results = worker != null ? worker.getResults() : null; final List<AccessPoint> apList = worker != null ? worker.getResults() : null;
final int apCount = results == null ? 0 : results.size(); final int apCount = apList == null ? 0 : apList.size();
final boolean isFirstApActive = apCount > 0 && results.get(0).isActive(); final boolean isFirstApActive = apCount > 0 && apList.get(0).isActive();
handleCaptivePortalCallback(worker, isFirstApActive); handleNetworkCallback(worker, isFirstApActive);
// Need a loading text when results are not ready or out of date. // Need a loading text when results are not ready or out of date.
boolean needLoadingRow = true; boolean needLoadingRow = true;
@@ -117,7 +110,7 @@ public class WifiSlice implements CustomSliceable {
// This loop checks the existence of reachable APs to determine the validity of the current // This loop checks the existence of reachable APs to determine the validity of the current
// AP list. // AP list.
for (; index < apCount; index++) { for (; index < apCount; index++) {
if (results.get(index).isReachable()) { if (apList.get(index).isReachable()) {
needLoadingRow = false; needLoadingRow = false;
break; break;
} }
@@ -127,28 +120,24 @@ public class WifiSlice implements CustomSliceable {
final CharSequence placeholder = mContext.getText(R.string.summary_placeholder); final CharSequence placeholder = mContext.getText(R.string.summary_placeholder);
for (int i = 0; i < DEFAULT_EXPANDED_ROW_COUNT; i++) { for (int i = 0; i < DEFAULT_EXPANDED_ROW_COUNT; i++) {
if (i < apCount) { if (i < apCount) {
final AccessPoint accessPoint = results.get(i); listBuilder.addRow(getAccessPointRow(apList.get(i)));
if (accessPoint.isActive()) {
// update summary
listBuilder = getListBuilder(isWifiEnabled, accessPoint);
}
listBuilder.addRow(getAccessPointRow(accessPoint));
} else if (needLoadingRow) { } else if (needLoadingRow) {
listBuilder.addRow(getLoadingRow()); listBuilder.addRow(getLoadingRow(placeholder));
needLoadingRow = false; needLoadingRow = false;
} else { } else {
listBuilder.addRow(new ListBuilder.RowBuilder() listBuilder.addRow(new ListBuilder.RowBuilder()
.setTitle(placeholder)); .setTitle(placeholder)
.setSubtitle(placeholder));
} }
} }
return listBuilder.build(); return listBuilder.build();
} }
private ListBuilder getListBuilder(boolean isWifiEnabled, AccessPoint accessPoint) { private ListBuilder getHeaderRow(boolean isWifiEnabled) {
final IconCompat icon = IconCompat.createWithResource(mContext, final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_settings_wireless); R.drawable.ic_settings_wireless);
final String title = mContext.getString(R.string.wifi_settings); final String title = mContext.getString(R.string.wifi_settings);
final CharSequence summary = getSummary(accessPoint); final CharSequence summary = getSummary();
final PendingIntent toggleAction = getBroadcastIntent(mContext); final PendingIntent toggleAction = getBroadcastIntent(mContext);
final PendingIntent primaryAction = getPrimaryAction(); final PendingIntent primaryAction = getPrimaryAction();
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon, final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
@@ -166,24 +155,26 @@ public class WifiSlice implements CustomSliceable {
.setPrimaryAction(primarySliceAction)); .setPrimaryAction(primarySliceAction));
} }
private void handleCaptivePortalCallback(WifiScanWorker worker, boolean isFirstApActive) { private void handleNetworkCallback(WifiScanWorker worker, boolean isFirstApActive) {
if (worker == null) { if (worker == null) {
return; return;
} }
if (isFirstApActive) { if (isFirstApActive) {
worker.registerCaptivePortalNetworkCallback(mWifiManager.getCurrentNetwork()); worker.registerNetworkCallback(mWifiManager.getCurrentNetwork());
} else { } else {
worker.unregisterCaptivePortalNetworkCallback(); worker.unregisterNetworkCallback();
} }
} }
private ListBuilder.RowBuilder getAccessPointRow(AccessPoint accessPoint) { private ListBuilder.RowBuilder getAccessPointRow(AccessPoint accessPoint) {
final CharSequence title = getAccessPointName(accessPoint);
final IconCompat levelIcon = getAccessPointLevelIcon(accessPoint);
final boolean isCaptivePortal = accessPoint.isActive() && isCaptivePortal(); final boolean isCaptivePortal = accessPoint.isActive() && isCaptivePortal();
final CharSequence title = accessPoint.getTitle();
final CharSequence summary = getAccessPointSummary(accessPoint, isCaptivePortal);
final IconCompat levelIcon = getAccessPointLevelIcon(accessPoint);
final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder() final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
.setTitleItem(levelIcon, ListBuilder.ICON_IMAGE) .setTitleItem(levelIcon, ListBuilder.ICON_IMAGE)
.setSubtitle(title) .setTitle(title)
.setSubtitle(summary)
.setPrimaryAction(SliceAction.createDeeplink( .setPrimaryAction(SliceAction.createDeeplink(
getAccessPointAction(accessPoint, isCaptivePortal), levelIcon, getAccessPointAction(accessPoint, isCaptivePortal), levelIcon,
ListBuilder.ICON_IMAGE, title)); ListBuilder.ICON_IMAGE, title));
@@ -199,14 +190,13 @@ public class WifiSlice implements CustomSliceable {
return rowBuilder; return rowBuilder;
} }
private CharSequence getAccessPointName(AccessPoint accessPoint) { private CharSequence getAccessPointSummary(AccessPoint accessPoint, boolean isCaptivePortal) {
final CharSequence name = accessPoint.getTitle(); if (isCaptivePortal) {
final Spannable span = new SpannableString(name); return mContext.getText(R.string.wifi_tap_to_sign_in);
@ColorInt final int color = Utils.getColorAttrDefaultColor(mContext, }
android.R.attr.textColorPrimary);
span.setSpan(new ForegroundColorSpan(color), 0, name.length(), final CharSequence summary = accessPoint.getSettingsSummary();
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); return TextUtils.isEmpty(summary) ? mContext.getText(R.string.disconnected) : summary;
return span;
} }
private IconCompat getAccessPointLevelIcon(AccessPoint accessPoint) { private IconCompat getAccessPointLevelIcon(AccessPoint accessPoint) {
@@ -274,7 +264,7 @@ public class WifiSlice implements CustomSliceable {
intent, 0 /* flags */); intent, 0 /* flags */);
} }
private ListBuilder.RowBuilder getLoadingRow() { private ListBuilder.RowBuilder getLoadingRow(CharSequence placeholder) {
final CharSequence title = mContext.getText(R.string.wifi_empty_list_wifi_on); final CharSequence title = mContext.getText(R.string.wifi_empty_list_wifi_on);
// for aligning to the Wi-Fi AP's name // for aligning to the Wi-Fi AP's name
@@ -283,6 +273,7 @@ public class WifiSlice implements CustomSliceable {
return new ListBuilder.RowBuilder() return new ListBuilder.RowBuilder()
.setTitleItem(emptyIcon, ListBuilder.ICON_IMAGE) .setTitleItem(emptyIcon, ListBuilder.ICON_IMAGE)
.setTitle(placeholder)
.setSubtitle(title); .setSubtitle(title);
} }
@@ -319,13 +310,6 @@ public class WifiSlice implements CustomSliceable {
return intent; return intent;
} }
protected String getActiveSSID() {
if (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED) {
return WifiSsid.NONE;
}
return WifiInfo.removeDoubleQuotes(mWifiManager.getConnectionInfo().getSSID());
}
private boolean isWifiEnabled() { private boolean isWifiEnabled() {
switch (mWifiManager.getWifiState()) { switch (mWifiManager.getWifiState()) {
case WifiManager.WIFI_STATE_ENABLED: case WifiManager.WIFI_STATE_ENABLED:
@@ -339,13 +323,8 @@ public class WifiSlice implements CustomSliceable {
private CharSequence getSummary() { private CharSequence getSummary() {
switch (mWifiManager.getWifiState()) { switch (mWifiManager.getWifiState()) {
case WifiManager.WIFI_STATE_ENABLED: case WifiManager.WIFI_STATE_ENABLED:
final String ssid = getActiveSSID();
if (TextUtils.equals(ssid, WifiSsid.NONE)) {
return mContext.getText(R.string.disconnected);
}
return ssid;
case WifiManager.WIFI_STATE_ENABLING: case WifiManager.WIFI_STATE_ENABLING:
return mContext.getText(R.string.disconnected); return mContext.getText(R.string.switch_on_text);
case WifiManager.WIFI_STATE_DISABLED: case WifiManager.WIFI_STATE_DISABLED:
case WifiManager.WIFI_STATE_DISABLING: case WifiManager.WIFI_STATE_DISABLING:
return mContext.getText(R.string.switch_off_text); return mContext.getText(R.string.switch_off_text);
@@ -355,38 +334,6 @@ public class WifiSlice implements CustomSliceable {
} }
} }
private CharSequence getSummary(AccessPoint accessPoint) {
if (isCaptivePortal()) {
final int id = mContext.getResources()
.getIdentifier("network_available_sign_in", "string", "android");
return mContext.getText(id);
}
if (accessPoint == null) {
return getSummary();
}
final NetworkInfo networkInfo = accessPoint.getNetworkInfo();
if (networkInfo == null) {
return getSummary();
}
final State state = networkInfo.getState();
DetailedState detailedState;
if (state == State.CONNECTING) {
detailedState = DetailedState.CONNECTING;
} else if (state == State.CONNECTED) {
detailedState = DetailedState.CONNECTED;
} else {
return getSummary();
}
final String[] formats = mContext.getResources().getStringArray(
R.array.wifi_status_with_ssid);
final int index = detailedState.ordinal();
return String.format(formats[index], accessPoint.getTitle());
}
private PendingIntent getPrimaryAction() { private PendingIntent getPrimaryAction() {
final Intent intent = getIntent(); final Intent intent = getIntent();
return PendingIntent.getActivity(mContext, 0 /* requestCode */, return PendingIntent.getActivity(mContext, 0 /* requestCode */,

View File

@@ -16,7 +16,6 @@
package com.android.settings.wifi.slice; package com.android.settings.wifi.slice;
import static org.mockito.ArgumentMatchers.any;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
@@ -25,7 +24,7 @@ import static org.mockito.Mockito.spy;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.net.ConnectivityManager; import android.net.NetworkCapabilities;
import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
@@ -40,22 +39,24 @@ import com.android.settings.R;
import com.android.settings.slices.CustomSliceRegistry; import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SlicesFeatureProviderImpl; import com.android.settings.slices.SlicesFeatureProviderImpl;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowConnectivityManager;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.List; import java.util.List;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowConnectivityManager.class)
public class ContextualWifiSliceTest { public class ContextualWifiSliceTest {
private Context mContext; private Context mContext;
private ContentResolver mResolver; private ContentResolver mResolver;
private WifiManager mWifiManager; private WifiManager mWifiManager;
private ConnectivityManager mConnectivityManager;
private ContextualWifiSlice mWifiSlice; private ContextualWifiSlice mWifiSlice;
private FakeFeatureFactory mFeatureFactory; private FakeFeatureFactory mFeatureFactory;
@@ -73,9 +74,6 @@ public class ContextualWifiSliceTest {
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
mWifiManager.setWifiEnabled(true); mWifiManager.setWifiEnabled(true);
mConnectivityManager = spy(mContext.getSystemService(ConnectivityManager.class));
doReturn(mConnectivityManager).when(mContext).getSystemService(ConnectivityManager.class);
mWifiSlice = new ContextualWifiSlice(mContext); mWifiSlice = new ContextualWifiSlice(mContext);
mWifiSlice.sPreviouslyDisplayed = false; mWifiSlice.sPreviouslyDisplayed = false;
} }
@@ -83,9 +81,7 @@ public class ContextualWifiSliceTest {
@Test @Test
public void getWifiSlice_hasActiveConnection_shouldReturnNull() { public void getWifiSlice_hasActiveConnection_shouldReturnNull() {
mWifiSlice.sPreviouslyDisplayed = false; mWifiSlice.sPreviouslyDisplayed = false;
final WifiConfiguration config = new WifiConfiguration(); connectToWifi(makeValidatedNetworkCapabilities());
config.SSID = "123";
mWifiManager.connect(config, null /* listener */);
final Slice wifiSlice = mWifiSlice.getSlice(); final Slice wifiSlice = mWifiSlice.getSlice();
@@ -98,10 +94,7 @@ public class ContextualWifiSliceTest {
// previous displayed: yes // previous displayed: yes
mWifiSlice.sPreviouslyDisplayed = true; mWifiSlice.sPreviouslyDisplayed = true;
mWifiSlice.sActiveUiSession = ~mFeatureFactory.slicesFeatureProvider.getUiSessionToken(); mWifiSlice.sActiveUiSession = ~mFeatureFactory.slicesFeatureProvider.getUiSessionToken();
connectToWifi(makeValidatedNetworkCapabilities());
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "123";
mWifiManager.connect(config, null /* listener */);
final Slice wifiSlice = mWifiSlice.getSlice(); final Slice wifiSlice = mWifiSlice.getSlice();
@@ -112,9 +105,7 @@ public class ContextualWifiSliceTest {
public void getWifiSlice_previousDisplayed_hasActiveConnection_shouldHaveTitleAndToggle() { public void getWifiSlice_previousDisplayed_hasActiveConnection_shouldHaveTitleAndToggle() {
mWifiSlice.sActiveUiSession = mFeatureFactory.slicesFeatureProvider.getUiSessionToken(); mWifiSlice.sActiveUiSession = mFeatureFactory.slicesFeatureProvider.getUiSessionToken();
mWifiSlice.sPreviouslyDisplayed = true; mWifiSlice.sPreviouslyDisplayed = true;
final WifiConfiguration config = new WifiConfiguration(); connectToWifi(makeValidatedNetworkCapabilities());
config.SSID = "123";
mWifiManager.connect(config, null /* listener */);
final Slice wifiSlice = mWifiSlice.getSlice(); final Slice wifiSlice = mWifiSlice.getSlice();
@@ -133,11 +124,7 @@ public class ContextualWifiSliceTest {
@Test @Test
public void getWifiSlice_isCaptivePortal_shouldHaveTitleAndToggle() { public void getWifiSlice_isCaptivePortal_shouldHaveTitleAndToggle() {
mWifiSlice.sPreviouslyDisplayed = false; mWifiSlice.sPreviouslyDisplayed = false;
final WifiConfiguration config = new WifiConfiguration(); connectToWifi(WifiSliceTest.makeCaptivePortalNetworkCapabilities());
config.SSID = "123";
mWifiManager.connect(config, null /* listener */);
doReturn(WifiSliceTest.makeCaptivePortalNetworkCapabilities()).when(mConnectivityManager)
.getNetworkCapabilities(any());
final Slice wifiSlice = mWifiSlice.getSlice(); final Slice wifiSlice = mWifiSlice.getSlice();
@@ -162,4 +149,20 @@ public class ContextualWifiSliceTest {
assertThat(wifiSlice.getUri()).isEqualTo(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI); assertThat(wifiSlice.getUri()).isEqualTo(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI);
} }
private void connectToWifi(NetworkCapabilities nc) {
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "123";
mWifiManager.connect(config, null /* listener */);
ShadowConnectivityManager.getShadow().setNetworkCapabilities(
mWifiManager.getCurrentNetwork(), nc);
}
private NetworkCapabilities makeValidatedNetworkCapabilities() {
final NetworkCapabilities nc = new NetworkCapabilities();
nc.clearAll();
nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
nc.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
return nc;
}
} }

View File

@@ -32,9 +32,10 @@ import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network; import android.net.Network;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.NetworkInfo.State; import android.net.NetworkInfo.DetailedState;
import android.net.wifi.WifiInfo; import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.net.wifi.WifiSsid; import android.net.wifi.WifiSsid;
@@ -62,6 +63,7 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements; import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowNetworkInfo;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = { @Config(shadows = {
@@ -70,8 +72,6 @@ import org.robolectric.annotation.Implements;
}) })
public class WifiScanWorkerTest { public class WifiScanWorkerTest {
private static final String AP_NAME = "ap";
private Context mContext; private Context mContext;
private ContentResolver mResolver; private ContentResolver mResolver;
private WifiManager mWifiManager; private WifiManager mWifiManager;
@@ -107,20 +107,10 @@ public class WifiScanWorkerTest {
verify(mResolver).notifyChange(WIFI_SLICE_URI, null); verify(mResolver).notifyChange(WIFI_SLICE_URI, null);
} }
private AccessPoint createAccessPoint(String name, State state) {
final NetworkInfo info = mock(NetworkInfo.class);
doReturn(state).when(info).getState();
final Bundle savedState = new Bundle();
savedState.putString("key_ssid", name);
savedState.putParcelable("key_networkinfo", info);
return new AccessPoint(mContext, savedState);
}
@Test @Test
public void AccessPointList_sameState_shouldBeTheSame() { public void AccessPointList_sameState_shouldBeTheSame() {
final AccessPoint ap1 = createAccessPoint(AP_NAME, State.CONNECTED); final AccessPoint ap1 = createAccessPoint(DetailedState.CONNECTED);
final AccessPoint ap2 = createAccessPoint(AP_NAME, State.CONNECTED); final AccessPoint ap2 = createAccessPoint(DetailedState.CONNECTED);
assertThat(mWifiScanWorker.areListsTheSame(Arrays.asList(ap1), Arrays.asList(ap2))) assertThat(mWifiScanWorker.areListsTheSame(Arrays.asList(ap1), Arrays.asList(ap2)))
.isTrue(); .isTrue();
@@ -128,17 +118,17 @@ public class WifiScanWorkerTest {
@Test @Test
public void AccessPointList_differentState_shouldBeDifferent() { public void AccessPointList_differentState_shouldBeDifferent() {
final AccessPoint ap1 = createAccessPoint(AP_NAME, State.CONNECTING); final AccessPoint ap1 = createAccessPoint(DetailedState.CONNECTING);
final AccessPoint ap2 = createAccessPoint(AP_NAME, State.CONNECTED); final AccessPoint ap2 = createAccessPoint(DetailedState.CONNECTED);
assertThat(mWifiScanWorker.areListsTheSame(Arrays.asList(ap1), Arrays.asList(ap2))) assertThat(mWifiScanWorker.areListsTheSame(Arrays.asList(ap1), Arrays.asList(ap2)))
.isFalse(); .isFalse();
} }
@Test @Test
public void AccessPointList_differentLength_shouldBeDifferent() { public void AccessPointList_differentListLength_shouldBeDifferent() {
final AccessPoint ap1 = createAccessPoint(AP_NAME, State.CONNECTED); final AccessPoint ap1 = createAccessPoint(DetailedState.CONNECTED);
final AccessPoint ap2 = createAccessPoint(AP_NAME, State.CONNECTED); final AccessPoint ap2 = createAccessPoint(DetailedState.CONNECTED);
final List<AccessPoint> list = new ArrayList<>(); final List<AccessPoint> list = new ArrayList<>();
list.add(ap1); list.add(ap1);
list.add(ap2); list.add(ap2);
@@ -149,20 +139,14 @@ public class WifiScanWorkerTest {
@Test @Test
public void NetworkCallback_onCapabilitiesChanged_shouldNotifyChange() { public void NetworkCallback_onCapabilitiesChanged_shouldNotifyChange() {
final Network network = mConnectivityManager.getActiveNetwork(); final Network network = mConnectivityManager.getActiveNetwork();
mWifiScanWorker.registerCaptivePortalNetworkCallback(network); mWifiScanWorker.registerNetworkCallback(network);
mWifiScanWorker.mCaptivePortalNetworkCallback.onCapabilitiesChanged(network, mWifiScanWorker.mNetworkCallback.onCapabilitiesChanged(network,
WifiSliceTest.makeCaptivePortalNetworkCapabilities()); WifiSliceTest.makeCaptivePortalNetworkCapabilities());
verify(mResolver).notifyChange(WIFI_SLICE_URI, null); verify(mResolver).notifyChange(WIFI_SLICE_URI, null);
} }
private AccessPoint createAccessPoint(String ssid) {
final AccessPoint accessPoint = mock(AccessPoint.class);
doReturn(ssid).when(accessPoint).getSsidStr();
return accessPoint;
}
private void setConnectionInfoSSID(String ssid) { private void setConnectionInfoSSID(String ssid) {
final WifiInfo wifiInfo = new WifiInfo(); final WifiInfo wifiInfo = new WifiInfo();
wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(ssid)); wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(ssid));
@@ -174,10 +158,10 @@ public class WifiScanWorkerTest {
final AccessPoint accessPoint = createAccessPoint("ap1"); final AccessPoint accessPoint = createAccessPoint("ap1");
setConnectionInfoSSID("ap1"); setConnectionInfoSSID("ap1");
final Network network = mConnectivityManager.getActiveNetwork(); final Network network = mConnectivityManager.getActiveNetwork();
mWifiScanWorker.registerCaptivePortalNetworkCallback(network); mWifiScanWorker.registerNetworkCallback(network);
mConnectToWifiHandler.connect(accessPoint); mConnectToWifiHandler.connect(accessPoint);
mWifiScanWorker.mCaptivePortalNetworkCallback.onCapabilitiesChanged(network, mWifiScanWorker.mNetworkCallback.onCapabilitiesChanged(network,
WifiSliceTest.makeCaptivePortalNetworkCapabilities()); WifiSliceTest.makeCaptivePortalNetworkCapabilities());
verify(mContext).startActivityAsUser(any(Intent.class), eq(UserHandle.CURRENT)); verify(mContext).startActivityAsUser(any(Intent.class), eq(UserHandle.CURRENT));
@@ -188,10 +172,10 @@ public class WifiScanWorkerTest {
final AccessPoint accessPoint = createAccessPoint("ap1"); final AccessPoint accessPoint = createAccessPoint("ap1");
setConnectionInfoSSID("ap2"); setConnectionInfoSSID("ap2");
final Network network = mConnectivityManager.getActiveNetwork(); final Network network = mConnectivityManager.getActiveNetwork();
mWifiScanWorker.registerCaptivePortalNetworkCallback(network); mWifiScanWorker.registerNetworkCallback(network);
mConnectToWifiHandler.connect(accessPoint); mConnectToWifiHandler.connect(accessPoint);
mWifiScanWorker.mCaptivePortalNetworkCallback.onCapabilitiesChanged(network, mWifiScanWorker.mNetworkCallback.onCapabilitiesChanged(network,
WifiSliceTest.makeCaptivePortalNetworkCapabilities()); WifiSliceTest.makeCaptivePortalNetworkCapabilities());
verify(mContext, never()).startActivityAsUser(any(Intent.class), eq(UserHandle.CURRENT)); verify(mContext, never()).startActivityAsUser(any(Intent.class), eq(UserHandle.CURRENT));
@@ -201,9 +185,9 @@ public class WifiScanWorkerTest {
public void NetworkCallback_onCapabilitiesChanged_neverClickWifi_shouldNotStartActivity() { public void NetworkCallback_onCapabilitiesChanged_neverClickWifi_shouldNotStartActivity() {
setConnectionInfoSSID("ap1"); setConnectionInfoSSID("ap1");
final Network network = mConnectivityManager.getActiveNetwork(); final Network network = mConnectivityManager.getActiveNetwork();
mWifiScanWorker.registerCaptivePortalNetworkCallback(network); mWifiScanWorker.registerNetworkCallback(network);
mWifiScanWorker.mCaptivePortalNetworkCallback.onCapabilitiesChanged(network, mWifiScanWorker.mNetworkCallback.onCapabilitiesChanged(network,
WifiSliceTest.makeCaptivePortalNetworkCapabilities()); WifiSliceTest.makeCaptivePortalNetworkCapabilities());
verify(mContext, never()).startActivityAsUser(any(Intent.class), eq(UserHandle.CURRENT)); verify(mContext, never()).startActivityAsUser(any(Intent.class), eq(UserHandle.CURRENT));
@@ -214,9 +198,8 @@ public class WifiScanWorkerTest {
final AccessPoint accessPoint = createAccessPoint("ap1"); final AccessPoint accessPoint = createAccessPoint("ap1");
setConnectionInfoSSID("ap1"); setConnectionInfoSSID("ap1");
final Network network = mConnectivityManager.getActiveNetwork(); final Network network = mConnectivityManager.getActiveNetwork();
mWifiScanWorker.registerCaptivePortalNetworkCallback(network); mWifiScanWorker.registerNetworkCallback(network);
final WifiScanWorker.CaptivePortalNetworkCallback callback = final NetworkCallback callback = mWifiScanWorker.mNetworkCallback;
mWifiScanWorker.mCaptivePortalNetworkCallback;
mWifiScanWorker.onSlicePinned(); mWifiScanWorker.onSlicePinned();
mConnectToWifiHandler.connect(accessPoint); mConnectToWifiHandler.connect(accessPoint);
@@ -227,6 +210,23 @@ public class WifiScanWorkerTest {
verify(mContext, never()).startActivityAsUser(any(Intent.class), eq(UserHandle.CURRENT)); verify(mContext, never()).startActivityAsUser(any(Intent.class), eq(UserHandle.CURRENT));
} }
private AccessPoint createAccessPoint(String ssid, DetailedState detailedState) {
final NetworkInfo info = ShadowNetworkInfo.newInstance(detailedState, 1 /* type */,
0 /*subType */, true /* isAvailable */, true /* isConnected */);
final Bundle savedState = new Bundle();
savedState.putString("key_ssid", ssid);
savedState.putParcelable("key_networkinfo", info);
return new AccessPoint(mContext, savedState);
}
private AccessPoint createAccessPoint(DetailedState detailedState) {
return createAccessPoint("ap", detailedState);
}
private AccessPoint createAccessPoint(String ssid) {
return createAccessPoint(ssid, DetailedState.DISCONNECTED);
}
@Implements(WifiTracker.class) @Implements(WifiTracker.class)
public static class ShadowWifiTracker { public static class ShadowWifiTracker {
@Implementation @Implementation

View File

@@ -247,8 +247,7 @@ public class WifiSliceTest {
} }
private void assertCaptivePortalItems(List<SliceItem> sliceItems) { private void assertCaptivePortalItems(List<SliceItem> sliceItems) {
final String expectedSummary = mContext.getString(mContext.getResources() final String expectedSummary = mContext.getString(R.string.switch_on_text);
.getIdentifier("network_available_sign_in", "string", "android"));
SliceTester.assertAnySliceItemContainsSubtitle(sliceItems, expectedSummary); SliceTester.assertAnySliceItemContainsSubtitle(sliceItems, expectedSummary);
final IconCompat expectedIcon = IconCompat.createWithResource(mContext, final IconCompat expectedIcon = IconCompat.createWithResource(mContext,