Support "don't ask again" in the avoid bad wifi dialog.
am: c65750c8a0
Change-Id: Ic6a1917a83e2d847bd673790e2c36f7316ca7acd
This commit is contained in:
@@ -3197,6 +3197,27 @@ public class ConnectivityManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs the system to penalize {@code network}'s score when it becomes unvalidated. This is
|
||||
* only meaningful if the system is configured not to penalize such networks, e.g., if the
|
||||
* {@code config_networkAvoidBadWifi} configuration variable is set to 0 and the {@code
|
||||
* NETWORK_AVOID_BAD_WIFI setting is unset}.
|
||||
*
|
||||
* <p>This method requires the caller to hold the permission
|
||||
* {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}
|
||||
*
|
||||
* @param network The network to accept.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void setAvoidUnvalidated(Network network) {
|
||||
try {
|
||||
mService.setAvoidUnvalidated(network);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all connectivity manager settings back to factory defaults.
|
||||
* @hide
|
||||
|
||||
@@ -161,6 +161,7 @@ interface IConnectivityManager
|
||||
void releaseNetworkRequest(in NetworkRequest networkRequest);
|
||||
|
||||
void setAcceptUnvalidated(in Network network, boolean accept, boolean always);
|
||||
void setAvoidUnvalidated(in Network network);
|
||||
|
||||
int getRestoreDefaultNetworkDelay(int networkType);
|
||||
|
||||
|
||||
@@ -371,6 +371,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
*/
|
||||
private static final int EVENT_SET_ACCEPT_UNVALIDATED = 28;
|
||||
|
||||
/**
|
||||
* used to specify whether a network should not be penalized when it becomes unvalidated.
|
||||
*/
|
||||
private static final int EVENT_SET_AVOID_UNVALIDATED = 35;
|
||||
|
||||
/**
|
||||
* used to ask the user to confirm a connection to an unvalidated network.
|
||||
* obj = network
|
||||
@@ -2712,6 +2717,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
accept ? 1 : 0, always ? 1: 0, network));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAvoidUnvalidated(Network network) {
|
||||
enforceConnectivityInternalPermission();
|
||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_AVOID_UNVALIDATED, network));
|
||||
}
|
||||
|
||||
private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
|
||||
if (DBG) log("handleSetAcceptUnvalidated network=" + network +
|
||||
" accept=" + accept + " always=" + always);
|
||||
@@ -2752,6 +2763,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
|
||||
}
|
||||
|
||||
private void handleSetAvoidUnvalidated(Network network) {
|
||||
NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
|
||||
if (nai == null || nai.lastValidated) {
|
||||
// Nothing to do. The network either disconnected or revalidated.
|
||||
return;
|
||||
}
|
||||
if (!nai.avoidUnvalidated) {
|
||||
int oldScore = nai.getCurrentScore();
|
||||
nai.avoidUnvalidated = true;
|
||||
rematchAllNetworksAndRequests(nai, oldScore);
|
||||
sendUpdatedScoreToFactories(nai);
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) {
|
||||
if (VDBG) log("scheduleUnvalidatedPrompt " + nai.network);
|
||||
mHandler.sendMessageDelayed(
|
||||
@@ -2759,28 +2784,31 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
PROMPT_UNVALIDATED_DELAY_MS);
|
||||
}
|
||||
|
||||
private boolean mAvoidBadWifi;
|
||||
private boolean mAvoidBadWifi = true;
|
||||
|
||||
public boolean avoidBadWifi() {
|
||||
return mAvoidBadWifi;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public boolean updateAvoidBadWifi() {
|
||||
// There are two modes: either we always automatically avoid unvalidated wifi, or we show a
|
||||
// dialog and don't switch to it. The behaviour is controlled by the NETWORK_AVOID_BAD_WIFI
|
||||
// setting. If the setting has no value, then the value is taken from the config value,
|
||||
// which can be changed via OEM/carrier overlays.
|
||||
//
|
||||
// The only valid values for NETWORK_AVOID_BAD_WIFI are null and unset. Currently, the unit
|
||||
// test uses 0 in order to avoid having to mock out fetching the carrier setting.
|
||||
int defaultAvoidBadWifi =
|
||||
mContext.getResources().getInteger(R.integer.config_networkAvoidBadWifi);
|
||||
int avoid = Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.NETWORK_AVOID_BAD_WIFI, defaultAvoidBadWifi);
|
||||
/** Whether the device or carrier configuration disables avoiding bad wifi by default. */
|
||||
public boolean configRestrictsAvoidBadWifi() {
|
||||
return mContext.getResources().getInteger(R.integer.config_networkAvoidBadWifi) == 0;
|
||||
}
|
||||
|
||||
/** Whether we should display a notification when wifi becomes unvalidated. */
|
||||
public boolean shouldNotifyWifiUnvalidated() {
|
||||
return configRestrictsAvoidBadWifi() &&
|
||||
Settings.Global.getString(mContext.getContentResolver(),
|
||||
Settings.Global.NETWORK_AVOID_BAD_WIFI) == null;
|
||||
}
|
||||
|
||||
private boolean updateAvoidBadWifi() {
|
||||
boolean settingAvoidBadWifi = "1".equals(Settings.Global.getString(
|
||||
mContext.getContentResolver(), Settings.Global.NETWORK_AVOID_BAD_WIFI));
|
||||
|
||||
boolean prev = mAvoidBadWifi;
|
||||
mAvoidBadWifi = (avoid == 1);
|
||||
mAvoidBadWifi = settingAvoidBadWifi || !configRestrictsAvoidBadWifi();
|
||||
return mAvoidBadWifi != prev;
|
||||
}
|
||||
|
||||
@@ -2833,7 +2861,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
NetworkCapabilities nc = nai.networkCapabilities;
|
||||
if (DBG) log("handleNetworkUnvalidated " + nai.name() + " cap=" + nc);
|
||||
|
||||
if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && !avoidBadWifi()) {
|
||||
if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && shouldNotifyWifiUnvalidated()) {
|
||||
showValidationNotification(nai, NotificationType.LOST_INTERNET);
|
||||
}
|
||||
}
|
||||
@@ -2911,6 +2939,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
handleSetAcceptUnvalidated((Network) msg.obj, msg.arg1 != 0, msg.arg2 != 0);
|
||||
break;
|
||||
}
|
||||
case EVENT_SET_AVOID_UNVALIDATED: {
|
||||
handleSetAvoidUnvalidated((Network) msg.obj);
|
||||
break;
|
||||
}
|
||||
case EVENT_PROMPT_UNVALIDATED: {
|
||||
handlePromptUnvalidated((Network) msg.obj);
|
||||
break;
|
||||
|
||||
@@ -140,12 +140,14 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
|
||||
public boolean everValidated;
|
||||
|
||||
// The result of the last validation attempt on this network (true if validated, false if not).
|
||||
// This bit exists only because we never unvalidate a network once it's been validated, and that
|
||||
// is because the network scoring and revalidation code does not (may not?) deal properly with
|
||||
// networks becoming unvalidated.
|
||||
// TODO: Fix the network scoring code, remove this, and rename everValidated to validated.
|
||||
public boolean lastValidated;
|
||||
|
||||
// If true, becoming unvalidated will lower the network's score. This is only meaningful if the
|
||||
// system is configured not to do this for certain networks, e.g., if the
|
||||
// config_networkAvoidBadWifi option is set to 0 and the user has not overridden that via
|
||||
// Settings.Global.NETWORK_AVOID_BAD_WIFI.
|
||||
public boolean avoidUnvalidated;
|
||||
|
||||
// Whether a captive portal was ever detected on this network.
|
||||
// This is a sticky bit; once set it is never cleared.
|
||||
public boolean everCaptivePortalDetected;
|
||||
@@ -426,8 +428,10 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
|
||||
// Return true on devices configured to ignore score penalty for wifi networks
|
||||
// that become unvalidated (b/31075769).
|
||||
private boolean ignoreWifiUnvalidationPenalty() {
|
||||
boolean isWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
|
||||
return isWifi && !mConnService.avoidBadWifi() && everValidated;
|
||||
boolean isWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
|
||||
networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
|
||||
boolean avoidBadWifi = mConnService.avoidBadWifi() || avoidUnvalidated;
|
||||
return isWifi && !avoidBadWifi && everValidated;
|
||||
}
|
||||
|
||||
// Get the current score for this Network. This may be modified from what the
|
||||
|
||||
@@ -82,6 +82,7 @@ import com.android.server.net.NetworkPinner;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
@@ -601,6 +602,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
||||
|
||||
private class WrappedConnectivityService extends ConnectivityService {
|
||||
private WrappedNetworkMonitor mLastCreatedNetworkMonitor;
|
||||
public boolean configRestrictsAvoidBadWifi;
|
||||
|
||||
public WrappedConnectivityService(Context context, INetworkManagementService netManager,
|
||||
INetworkStatsService statsService, INetworkPolicyManager policyManager,
|
||||
@@ -656,6 +658,11 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
||||
return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configRestrictsAvoidBadWifi() {
|
||||
return configRestrictsAvoidBadWifi;
|
||||
}
|
||||
|
||||
public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
|
||||
return mLastCreatedNetworkMonitor;
|
||||
}
|
||||
@@ -2035,8 +2042,48 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
||||
|
||||
@SmallTest
|
||||
public void testAvoidBadWifiSetting() throws Exception {
|
||||
final ContentResolver cr = mServiceContext.getContentResolver();
|
||||
final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
|
||||
|
||||
mService.configRestrictsAvoidBadWifi = false;
|
||||
String[] values = new String[] {null, "0", "1"};
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
Settings.Global.putInt(cr, settingName, 1);
|
||||
mService.updateNetworkAvoidBadWifi();
|
||||
mService.waitForIdle();
|
||||
String msg = String.format("config=false, setting=%s", values[i]);
|
||||
assertTrue(msg, mService.avoidBadWifi());
|
||||
assertFalse(msg, mService.shouldNotifyWifiUnvalidated());
|
||||
}
|
||||
|
||||
mService.configRestrictsAvoidBadWifi = true;
|
||||
|
||||
Settings.Global.putInt(cr, settingName, 0);
|
||||
mService.updateNetworkAvoidBadWifi();
|
||||
mService.waitForIdle();
|
||||
assertFalse(mService.avoidBadWifi());
|
||||
assertFalse(mService.shouldNotifyWifiUnvalidated());
|
||||
|
||||
Settings.Global.putInt(cr, settingName, 1);
|
||||
mService.updateNetworkAvoidBadWifi();
|
||||
mService.waitForIdle();
|
||||
assertTrue(mService.avoidBadWifi());
|
||||
assertFalse(mService.shouldNotifyWifiUnvalidated());
|
||||
|
||||
Settings.Global.putString(cr, settingName, null);
|
||||
mService.updateNetworkAvoidBadWifi();
|
||||
mService.waitForIdle();
|
||||
assertFalse(mService.avoidBadWifi());
|
||||
assertTrue(mService.shouldNotifyWifiUnvalidated());
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testAvoidBadWifi() throws Exception {
|
||||
ContentResolver cr = mServiceContext.getContentResolver();
|
||||
|
||||
// Pretend we're on a carrier that restricts switching away from bad wifi.
|
||||
mService.configRestrictsAvoidBadWifi = true;
|
||||
|
||||
// File a request for cell to ensure it doesn't go down.
|
||||
final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
|
||||
final NetworkRequest cellRequest = new NetworkRequest.Builder()
|
||||
@@ -2053,8 +2100,8 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
||||
TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
|
||||
mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
|
||||
|
||||
// Takes effect on every rematch.
|
||||
Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
|
||||
mService.updateNetworkAvoidBadWifi();
|
||||
|
||||
// Bring up validated cell.
|
||||
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
|
||||
@@ -2083,7 +2130,42 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
||||
NET_CAPABILITY_VALIDATED));
|
||||
assertEquals(mCm.getActiveNetwork(), wifiNetwork);
|
||||
|
||||
// Simulate the user selecting "switch" on the dialog.
|
||||
// Simulate switching to a carrier that does not restrict avoiding bad wifi, and expect
|
||||
// that we switch back to cell.
|
||||
mService.configRestrictsAvoidBadWifi = false;
|
||||
mService.updateNetworkAvoidBadWifi();
|
||||
defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
|
||||
assertEquals(mCm.getActiveNetwork(), cellNetwork);
|
||||
|
||||
// Switch back to a restrictive carrier.
|
||||
mService.configRestrictsAvoidBadWifi = true;
|
||||
mService.updateNetworkAvoidBadWifi();
|
||||
defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
|
||||
assertEquals(mCm.getActiveNetwork(), wifiNetwork);
|
||||
|
||||
// Simulate the user selecting "switch" on the dialog, and check that we switch to cell.
|
||||
mCm.setAvoidUnvalidated(wifiNetwork);
|
||||
defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
|
||||
assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
|
||||
NET_CAPABILITY_VALIDATED));
|
||||
assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
|
||||
NET_CAPABILITY_VALIDATED));
|
||||
assertEquals(mCm.getActiveNetwork(), cellNetwork);
|
||||
|
||||
// Disconnect and reconnect wifi to clear the one-time switch above.
|
||||
mWiFiNetworkAgent.disconnect();
|
||||
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
|
||||
mWiFiNetworkAgent.connect(true);
|
||||
defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
|
||||
validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
|
||||
wifiNetwork = mWiFiNetworkAgent.getNetwork();
|
||||
|
||||
// Fail validation on wifi and expect the dialog to appear.
|
||||
mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
|
||||
mCm.reportNetworkConnectivity(wifiNetwork, false);
|
||||
validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
|
||||
|
||||
// Simulate the user selecting "switch" and checking the don't ask again checkbox.
|
||||
Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
|
||||
mService.updateNetworkAvoidBadWifi();
|
||||
|
||||
@@ -2095,6 +2177,17 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
||||
NET_CAPABILITY_VALIDATED));
|
||||
assertEquals(mCm.getActiveNetwork(), cellNetwork);
|
||||
|
||||
// Simulate the user turning the cellular fallback setting off and then on.
|
||||
// We switch to wifi and then to cell.
|
||||
Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
|
||||
mService.updateNetworkAvoidBadWifi();
|
||||
defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
|
||||
assertEquals(mCm.getActiveNetwork(), wifiNetwork);
|
||||
Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
|
||||
mService.updateNetworkAvoidBadWifi();
|
||||
defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
|
||||
assertEquals(mCm.getActiveNetwork(), cellNetwork);
|
||||
|
||||
// If cell goes down, we switch to wifi.
|
||||
mCellNetworkAgent.disconnect();
|
||||
defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
|
||||
|
||||
Reference in New Issue
Block a user