diff options
author | Lorenzo Colitti <lorenzo@google.com> | 2016-09-15 14:02:29 +0900 |
---|---|---|
committer | gitbuildkicker <android-build@google.com> | 2016-09-16 15:24:41 -0700 |
commit | 44b853927bd04b7d7d62bb87d612ce387169dffd (patch) | |
tree | 15d5f2bec425c40e6d31edf74d70e94b7cd3e8ba | |
parent | b66dd29dfd79098003616eabe28a70de8c279286 (diff) | |
download | base-44b853927bd04b7d7d62bb87d612ce387169dffd.tar.gz |
Support displaying a dialog when wifi becomes unvalidated.
Bug: 31075769
Change-Id: I7a6e7580769365bea930f638bd44edcaa28df134
(cherry picked from commit 9be58c55806faf3833d0288cb043d4eb9a37930d)
3 files changed, 76 insertions, 14 deletions
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 3c2ac6733c52..52d6b56609de 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -343,6 +343,15 @@ public class ConnectivityManager { public static final String ACTION_PROMPT_UNVALIDATED = "android.net.conn.PROMPT_UNVALIDATED"; /** + * Action used to display a dialog that asks the user whether to avoid a network that is no + * longer validated. This intent is used to start the dialog in settings via startActivity. + * + * @hide + */ + public static final String ACTION_PROMPT_LOST_VALIDATION = + "android.net.conn.PROMPT_LOST_VALIDATION"; + + /** * Invalid tethering type. * @see #startTethering(int, OnStartTetheringCallback, boolean) * @hide diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 4c30dc2661ec..8b1be3b607cd 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -392,6 +392,11 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final int EVENT_REQUEST_LINKPROPERTIES = 32; private static final int EVENT_REQUEST_NETCAPABILITIES = 33; + /** + * Used internally to (re)configure avoid bad wifi setting. + */ + private static final int EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI = 34; + /** Handler thread used for both of the handlers below. */ @VisibleForTesting protected final HandlerThread mHandlerThread; @@ -896,6 +901,12 @@ public class ConnectivityService extends IConnectivityManager.Stub mSettingsObserver.observe( Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON), EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON); + + // Watch for whether to automatically switch away from wifi networks that lose Internet + // access. + mSettingsObserver.observe( + Settings.Global.getUriFor(Settings.Global.NETWORK_AVOID_BAD_WIFI), + EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI); } private synchronized int nextNetworkRequestId() { @@ -2209,6 +2220,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (nai != null) { final boolean valid = (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID); + final boolean wasValidated = nai.lastValidated; if (DBG) log(nai.name() + " validation " + (valid ? "passed" : "failed") + (msg.obj == null ? "" : " with redirect to " + (String)msg.obj)); if (valid != nai.lastValidated) { @@ -2227,6 +2239,9 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkAgent.CMD_REPORT_NETWORK_STATUS, (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK), 0, redirectUrlBundle); + if (wasValidated && !nai.lastValidated) { + handleNetworkUnvalidated(nai); + } } break; } @@ -2706,6 +2721,10 @@ public class ConnectivityService extends IConnectivityManager.Stub @VisibleForTesting public boolean avoidBadWifi() { + // 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. int defaultAvoidBadWifi = mContext.getResources().getInteger(R.integer.config_networkAvoidBadWifi); int avoid = Settings.Global.getInt(mContext.getContentResolver(), @@ -2713,6 +2732,31 @@ public class ConnectivityService extends IConnectivityManager.Stub return avoid == 1; } + private void showValidationNotification(NetworkAgentInfo nai, NotificationType type) { + final String action; + switch (type) { + case NO_INTERNET: + action = ConnectivityManager.ACTION_PROMPT_UNVALIDATED; + break; + case LOST_INTERNET: + action = ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION; + break; + default: + Slog.wtf(TAG, "Unknown notification type " + type); + return; + } + + Intent intent = new Intent(action); + intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null)); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setClassName("com.android.settings", + "com.android.settings.wifi.WifiNoInternetDialog"); + + PendingIntent pendingIntent = PendingIntent.getActivityAsUser( + mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); + mNotifier.showNotification(nai.network.netId, type, nai, null, pendingIntent, true); + } + private void handlePromptUnvalidated(Network network) { if (VDBG) log("handlePromptUnvalidated " + network); NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); @@ -2724,18 +2768,16 @@ public class ConnectivityService extends IConnectivityManager.Stub !nai.networkMisc.explicitlySelected || nai.networkMisc.acceptUnvalidated) { return; } + showValidationNotification(nai, NotificationType.NO_INTERNET); + } - Intent intent = new Intent(ConnectivityManager.ACTION_PROMPT_UNVALIDATED); - intent.setData(Uri.fromParts("netId", Integer.toString(network.netId), null)); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setClassName("com.android.settings", - "com.android.settings.wifi.WifiNoInternetDialog"); - - PendingIntent pendingIntent = PendingIntent.getActivityAsUser( - mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); + private void handleNetworkUnvalidated(NetworkAgentInfo nai) { + NetworkCapabilities nc = nai.networkCapabilities; + if (DBG) log("handleNetworkUnvalidated " + nai.name() + " cap=" + nc); - mNotifier.showNotification(nai.network.netId, NotificationType.NO_INTERNET, nai, null, - pendingIntent, true); + if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && !avoidBadWifi()) { + showValidationNotification(nai, NotificationType.LOST_INTERNET); + } } private class InternalHandler extends Handler { @@ -2819,6 +2861,10 @@ public class ConnectivityService extends IConnectivityManager.Stub handleMobileDataAlwaysOn(); break; } + case EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI: { + rematchAllNetworksAndRequests(null, 0); + break; + } case EVENT_REQUEST_LINKPROPERTIES: handleRequestLinkProperties((NetworkRequest) msg.obj, msg.arg1); break; @@ -4746,7 +4792,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) { // If "newNetwork" is listed as satisfying "nri" but no longer satisfies "nri", // mark it as no longer satisfying "nri". Because networks are processed by - // rematchAllNetworkAndRequests() in descending score order, "currentNetwork" will + // rematchAllNetworksAndRequests() in descending score order, "currentNetwork" will // match "newNetwork" before this loop will encounter a "currentNetwork" with higher // score than "newNetwork" and where "currentNetwork" no longer satisfies "nri". // This means this code doesn't have to handle the case where "currentNetwork" no @@ -5280,6 +5326,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } + + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.NETWORK_AVOID_BAD_WIFI, null); } @VisibleForTesting diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 99926a971bec..f7b01be48d88 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -35,7 +35,7 @@ import static android.net.NetworkCapabilities.*; public class NetworkNotificationManager { - public static enum NotificationType { SIGN_IN, NO_INTERNET, NETWORK_SWITCH }; + public static enum NotificationType { SIGN_IN, NO_INTERNET, LOST_INTERNET, NETWORK_SWITCH }; private static final String NOTIFICATION_ID = "Connectivity.Notification"; @@ -91,8 +91,8 @@ public class NetworkNotificationManager { * @param id an identifier that uniquely identifies this notification. This must match * between show and hide calls. We use the NetID value but for legacy callers * we concatenate the range of types with the range of NetIDs. - * @param nai the network with which the notification is associated. For a SIGN_IN or - * NO_INTERNET notification, this is the network we're connecting to. For a + * @param nai the network with which the notification is associated. For a SIGN_IN, NO_INTERNET, + * or LOST_INTERNET notification, this is the network we're connecting to. For a * NETWORK_SWITCH notification it's the network that we switched from. When this network * disconnects the notification is removed. * @param switchToNai for a NETWORK_SWITCH notification, the network we are switching to. Null @@ -126,6 +126,10 @@ public class NetworkNotificationManager { if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, 0); details = r.getString(R.string.wifi_no_internet_detailed); + } else if (notifyType == NotificationType.LOST_INTERNET && + transportType == TRANSPORT_WIFI) { + title = r.getString(R.string.wifi_no_internet, 0); + details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.SIGN_IN) { switch (transportType) { case TRANSPORT_WIFI: |