Merge "When no Internet access is detected, display a notification first." into mnc-dev
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3691a3a..2f68aa8 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2027,20 +2027,22 @@
break;
}
case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
+ final int netId = msg.arg2;
if (msg.arg1 == 0) {
- setProvNotificationVisibleIntent(false, msg.arg2, 0, null, null);
+ setProvNotificationVisibleIntent(false, netId, null, 0, null, null);
} else {
final NetworkAgentInfo nai;
synchronized (mNetworkForNetId) {
- nai = mNetworkForNetId.get(msg.arg2);
+ nai = mNetworkForNetId.get(netId);
}
if (nai == null) {
loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
break;
}
nai.captivePortalDetected = true;
- setProvNotificationVisibleIntent(true, msg.arg2, nai.networkInfo.getType(),
- nai.networkInfo.getExtraInfo(), (PendingIntent)msg.obj);
+ setProvNotificationVisibleIntent(true, netId, NotificationType.SIGN_IN,
+ nai.networkInfo.getType(),nai.networkInfo.getExtraInfo(),
+ (PendingIntent)msg.obj);
}
break;
}
@@ -2397,9 +2399,7 @@
}
if (nai.everValidated) {
- // The network validated while the dialog box was up. Don't make any changes. There's a
- // TODO in the dialog code to make it go away if the network validates; once that's
- // implemented, taking action here will be confusing.
+ // The network validated while the dialog box was up. Take no action.
return;
}
@@ -2419,16 +2419,28 @@
NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED, accept ? 1 : 0);
}
- // TODO: should we also disconnect from the network if accept is false?
+ if (!accept) {
+ // Tell the NetworkAgent that the network does not have Internet access (because that's
+ // what we just told the user). This will hint to Wi-Fi not to autojoin this network in
+ // the future. We do this now because NetworkMonitor might not yet have finished
+ // validating and thus we might not yet have received an EVENT_NETWORK_TESTED.
+ nai.asyncChannel.sendMessage(NetworkAgent.CMD_REPORT_NETWORK_STATUS,
+ NetworkAgent.INVALID_NETWORK, 0, null);
+ // TODO: Tear the network down once we have determined how to tell WifiStateMachine not
+ // to reconnect to it immediately. http://b/20739299
+ }
+
}
private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) {
+ if (DBG) log("scheduleUnvalidatedPrompt " + nai.network);
mHandler.sendMessageDelayed(
mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, nai.network),
PROMPT_UNVALIDATED_DELAY_MS);
}
private void handlePromptUnvalidated(Network network) {
+ if (DBG) log("handlePromptUnvalidated " + network);
NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
// Only prompt if the network is unvalidated and was explicitly selected by the user, and if
@@ -2439,31 +2451,16 @@
return;
}
- // TODO: What should we do if we've already switched to this network because we had no
- // better option? There are two obvious alternatives.
- //
- // 1. Decide that there's no point prompting because this is our only usable network.
- // However, because we didn't prompt, if later on a validated network comes along, we'll
- // either a) silently switch to it - bad if the user wanted to connect to stay on this
- // unvalidated network - or b) prompt the user at that later time - bad because the user
- // might not understand why they are now being prompted.
- //
- // 2. Always prompt the user, even if we have no other network to use. The user could then
- // try to find an alternative network to join (remember, if we got here, then the user
- // selected this network manually). This is bad because the prompt isn't really very
- // useful.
- //
- // For now we do #1, but we can revisit that later.
- if (isDefaultNetwork(nai)) {
- return;
- }
-
Intent intent = new Intent(ConnectivityManager.ACTION_PROMPT_UNVALIDATED);
- intent.putExtra(ConnectivityManager.EXTRA_NETWORK, network);
+ 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");
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+
+ PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
+ mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
+ setProvNotificationVisibleIntent(true, nai.network.netId, NotificationType.NO_INTERNET,
+ nai.networkInfo.getType(), nai.networkInfo.getExtraInfo(), pendingIntent);
}
private class InternalHandler extends Handler {
@@ -3243,7 +3240,7 @@
}
private static final String NOTIFICATION_ID = "CaptivePortal.Notification";
- private volatile boolean mIsNotificationVisible = false;
+ private static enum NotificationType { SIGN_IN, NO_INTERNET; };
private void setProvNotificationVisible(boolean visible, int networkType, String action) {
if (DBG) {
@@ -3254,21 +3251,31 @@
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
// Concatenate the range of types onto the range of NetIDs.
int id = MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
- setProvNotificationVisibleIntent(visible, id, networkType, null, pendingIntent);
+ setProvNotificationVisibleIntent(visible, id, NotificationType.SIGN_IN,
+ networkType, null, pendingIntent);
}
/**
- * Show or hide network provisioning notificaitons.
+ * Show or hide network provisioning notifications.
+ *
+ * We use notifications for two purposes: to notify that a network requires sign in
+ * (NotificationType.SIGN_IN), or to notify that a network does not have Internet access
+ * (NotificationType.NO_INTERNET). We display at most one notification per ID, so on a
+ * particular network we can display the notification type that was most recently requested.
+ * So for example if a captive portal fails to reply within a few seconds of connecting, we
+ * might first display NO_INTERNET, and then when the captive portal check completes, display
+ * SIGN_IN.
*
* @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.
*/
- private void setProvNotificationVisibleIntent(boolean visible, int id, int networkType,
- String extraInfo, PendingIntent intent) {
+ private void setProvNotificationVisibleIntent(boolean visible, int id,
+ NotificationType notifyType, int networkType, String extraInfo, PendingIntent intent) {
if (DBG) {
- log("setProvNotificationVisibleIntent: E visible=" + visible + " networkType=" +
- networkType + " extraInfo=" + extraInfo);
+ log("setProvNotificationVisibleIntent " + notifyType + " visible=" + visible
+ + " networkType=" + getNetworkTypeName(networkType)
+ + " extraInfo=" + extraInfo);
}
Resources r = Resources.getSystem();
@@ -3280,27 +3287,38 @@
CharSequence details;
int icon;
Notification notification = new Notification();
- switch (networkType) {
- case ConnectivityManager.TYPE_WIFI:
- title = r.getString(R.string.wifi_available_sign_in, 0);
- details = r.getString(R.string.network_available_sign_in_detailed,
- extraInfo);
- icon = R.drawable.stat_notify_wifi_in_range;
- break;
- case ConnectivityManager.TYPE_MOBILE:
- case ConnectivityManager.TYPE_MOBILE_HIPRI:
- title = r.getString(R.string.network_available_sign_in, 0);
- // TODO: Change this to pull from NetworkInfo once a printable
- // name has been added to it
- details = mTelephonyManager.getNetworkOperatorName();
- icon = R.drawable.stat_notify_rssi_in_range;
- break;
- default:
- title = r.getString(R.string.network_available_sign_in, 0);
- details = r.getString(R.string.network_available_sign_in_detailed,
- extraInfo);
- icon = R.drawable.stat_notify_rssi_in_range;
- break;
+ if (notifyType == NotificationType.NO_INTERNET &&
+ networkType == ConnectivityManager.TYPE_WIFI) {
+ title = r.getString(R.string.wifi_no_internet, 0);
+ details = r.getString(R.string.wifi_no_internet_detailed);
+ icon = R.drawable.stat_notify_wifi_in_range; // TODO: Need new icon.
+ } else if (notifyType == NotificationType.SIGN_IN) {
+ switch (networkType) {
+ case ConnectivityManager.TYPE_WIFI:
+ title = r.getString(R.string.wifi_available_sign_in, 0);
+ details = r.getString(R.string.network_available_sign_in_detailed,
+ extraInfo);
+ icon = R.drawable.stat_notify_wifi_in_range;
+ break;
+ case ConnectivityManager.TYPE_MOBILE:
+ case ConnectivityManager.TYPE_MOBILE_HIPRI:
+ title = r.getString(R.string.network_available_sign_in, 0);
+ // TODO: Change this to pull from NetworkInfo once a printable
+ // name has been added to it
+ details = mTelephonyManager.getNetworkOperatorName();
+ icon = R.drawable.stat_notify_rssi_in_range;
+ break;
+ default:
+ title = r.getString(R.string.network_available_sign_in, 0);
+ details = r.getString(R.string.network_available_sign_in_detailed,
+ extraInfo);
+ icon = R.drawable.stat_notify_rssi_in_range;
+ break;
+ }
+ } else {
+ Slog.wtf(TAG, "Unknown notification type " + notifyType + "on network type "
+ + getNetworkTypeName(networkType));
+ return;
}
notification.when = 0;
@@ -3315,18 +3333,17 @@
try {
notificationManager.notify(NOTIFICATION_ID, id, notification);
} catch (NullPointerException npe) {
- loge("setNotificaitionVisible: visible notificationManager npe=" + npe);
+ loge("setNotificationVisible: visible notificationManager npe=" + npe);
npe.printStackTrace();
}
} else {
try {
notificationManager.cancel(NOTIFICATION_ID, id);
} catch (NullPointerException npe) {
- loge("setNotificaitionVisible: cancel notificationManager npe=" + npe);
+ loge("setNotificationVisible: cancel notificationManager npe=" + npe);
npe.printStackTrace();
}
}
- mIsNotificationVisible = visible;
}
/** Location to an updatable file listing carrier provisioning urls.