diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 52d6b56609def..b9e9b283106f9 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -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}. + * + *
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
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index d48c155986f3f..4aabda9eb09d2 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -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);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 25f1f3c9ed04f..61715aacfa765 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7489,6 +7489,13 @@ public final class Settings {
/**
* Whether to automatically switch away from wifi networks that lose Internet access.
+ * Only meaningful if config_networkAvoidBadWifi is set to 0, otherwise the system always
+ * avoids such networks. Valid values are:
+ *
+ * 0: Don't avoid bad wifi, don't prompt the user. Get stuck on bad wifi like it's 2013.
+ * null: Ask the user whether to switch away from bad wifi.
+ * 1: Avoid bad wifi.
+ *
* @hide
*/
public static final String NETWORK_AVOID_BAD_WIFI = "network_avoid_bad_wifi";
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index ae61a7e10dd02..58e54f5f68896 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -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;
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index cb4bb8840b5a0..2a618bcc2eac0 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -140,12 +140,14 @@ public class NetworkAgentInfo implements Comparable