Move notification code out of ConnectivityService.
Bug: 31025214 Change-Id: I4190be6b57f92298b79bea8868f1876ecbfd2d75
This commit is contained in:
@@ -38,8 +38,6 @@ import static android.net.NetworkPolicyManager.uidRulesToString;
|
|||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.BroadcastOptions;
|
import android.app.BroadcastOptions;
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
@@ -135,6 +133,8 @@ import com.android.server.connectivity.Nat464Xlat;
|
|||||||
import com.android.server.connectivity.NetworkAgentInfo;
|
import com.android.server.connectivity.NetworkAgentInfo;
|
||||||
import com.android.server.connectivity.NetworkDiagnostics;
|
import com.android.server.connectivity.NetworkDiagnostics;
|
||||||
import com.android.server.connectivity.NetworkMonitor;
|
import com.android.server.connectivity.NetworkMonitor;
|
||||||
|
import com.android.server.connectivity.NetworkNotificationManager;
|
||||||
|
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
|
||||||
import com.android.server.connectivity.PacManager;
|
import com.android.server.connectivity.PacManager;
|
||||||
import com.android.server.connectivity.PermissionMonitor;
|
import com.android.server.connectivity.PermissionMonitor;
|
||||||
import com.android.server.connectivity.Tethering;
|
import com.android.server.connectivity.Tethering;
|
||||||
@@ -436,6 +436,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
TelephonyManager mTelephonyManager;
|
TelephonyManager mTelephonyManager;
|
||||||
|
|
||||||
private KeepaliveTracker mKeepaliveTracker;
|
private KeepaliveTracker mKeepaliveTracker;
|
||||||
|
private NetworkNotificationManager mNotifier;
|
||||||
|
|
||||||
// sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
|
// sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
|
||||||
private final static int MIN_NET_ID = 100; // some reserved marks
|
private final static int MIN_NET_ID = 100; // some reserved marks
|
||||||
@@ -832,6 +833,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||||
|
|
||||||
mKeepaliveTracker = new KeepaliveTracker(mHandler);
|
mKeepaliveTracker = new KeepaliveTracker(mHandler);
|
||||||
|
mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NetworkRequest createInternetRequestForTransport(int transportType) {
|
private NetworkRequest createInternetRequestForTransport(int transportType) {
|
||||||
@@ -2230,14 +2232,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
updateCapabilities(nai, nai.networkCapabilities);
|
updateCapabilities(nai, nai.networkCapabilities);
|
||||||
}
|
}
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
setProvNotificationVisibleIntent(false, netId, null, 0, null, null, false);
|
mNotifier.setProvNotificationVisibleIntent(false, netId, null, 0, null,
|
||||||
|
null, false);
|
||||||
} else {
|
} else {
|
||||||
if (nai == null) {
|
if (nai == null) {
|
||||||
loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
|
loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!nai.networkMisc.provisioningNotificationDisabled) {
|
if (!nai.networkMisc.provisioningNotificationDisabled) {
|
||||||
setProvNotificationVisibleIntent(true, netId, NotificationType.SIGN_IN,
|
mNotifier.setProvNotificationVisibleIntent(true, netId,
|
||||||
|
NotificationType.SIGN_IN,
|
||||||
nai.networkInfo.getType(), nai.networkInfo.getExtraInfo(),
|
nai.networkInfo.getType(), nai.networkInfo.getExtraInfo(),
|
||||||
(PendingIntent)msg.obj, nai.networkMisc.explicitlySelected);
|
(PendingIntent)msg.obj, nai.networkMisc.explicitlySelected);
|
||||||
}
|
}
|
||||||
@@ -2710,8 +2714,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
|
PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
|
||||||
mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
|
mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
|
||||||
|
|
||||||
setProvNotificationVisibleIntent(true, nai.network.netId, NotificationType.NO_INTERNET,
|
mNotifier.setProvNotificationVisibleIntent(true, nai.network.netId,
|
||||||
nai.networkInfo.getType(), nai.networkInfo.getExtraInfo(), pendingIntent, true);
|
NotificationType.NO_INTERNET, nai.networkInfo.getType(),
|
||||||
|
nai.networkInfo.getExtraInfo(), pendingIntent, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InternalHandler extends Handler {
|
private class InternalHandler extends Handler {
|
||||||
@@ -3617,118 +3622,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String NOTIFICATION_ID = "CaptivePortal.Notification";
|
|
||||||
private static enum NotificationType { SIGN_IN, NO_INTERNET; };
|
|
||||||
|
|
||||||
private void setProvNotificationVisible(boolean visible, int networkType, String action) {
|
|
||||||
Intent intent = new Intent(action);
|
|
||||||
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, NotificationType.SIGN_IN,
|
|
||||||
networkType, null, pendingIntent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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,
|
|
||||||
NotificationType notifyType, int networkType, String extraInfo, PendingIntent intent,
|
|
||||||
boolean highPriority) {
|
|
||||||
if (VDBG || (DBG && visible)) {
|
|
||||||
log("setProvNotificationVisibleIntent " + notifyType + " visible=" + visible
|
|
||||||
+ " networkType=" + getNetworkTypeName(networkType)
|
|
||||||
+ " extraInfo=" + extraInfo + " highPriority=" + highPriority);
|
|
||||||
}
|
|
||||||
|
|
||||||
Resources r = Resources.getSystem();
|
|
||||||
NotificationManager notificationManager = (NotificationManager) mContext
|
|
||||||
.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
|
|
||||||
if (visible) {
|
|
||||||
CharSequence title;
|
|
||||||
CharSequence details;
|
|
||||||
int icon;
|
|
||||||
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 notification = new Notification.Builder(mContext)
|
|
||||||
.setWhen(0)
|
|
||||||
.setSmallIcon(icon)
|
|
||||||
.setAutoCancel(true)
|
|
||||||
.setTicker(title)
|
|
||||||
.setColor(mContext.getColor(
|
|
||||||
com.android.internal.R.color.system_notification_accent_color))
|
|
||||||
.setContentTitle(title)
|
|
||||||
.setContentText(details)
|
|
||||||
.setContentIntent(intent)
|
|
||||||
.setLocalOnly(true)
|
|
||||||
.setPriority(highPriority ?
|
|
||||||
Notification.PRIORITY_HIGH :
|
|
||||||
Notification.PRIORITY_DEFAULT)
|
|
||||||
.setDefaults(highPriority ? Notification.DEFAULT_ALL : 0)
|
|
||||||
.setOnlyAlertOnce(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
try {
|
|
||||||
notificationManager.notifyAsUser(NOTIFICATION_ID, id, notification, UserHandle.ALL);
|
|
||||||
} catch (NullPointerException npe) {
|
|
||||||
loge("setNotificationVisible: visible notificationManager npe=" + npe);
|
|
||||||
npe.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
notificationManager.cancelAsUser(NOTIFICATION_ID, id, UserHandle.ALL);
|
|
||||||
} catch (NullPointerException npe) {
|
|
||||||
loge("setNotificationVisible: cancel notificationManager npe=" + npe);
|
|
||||||
npe.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Location to an updatable file listing carrier provisioning urls.
|
/** Location to an updatable file listing carrier provisioning urls.
|
||||||
* An example:
|
* An example:
|
||||||
*
|
*
|
||||||
@@ -3832,7 +3725,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
enforceConnectivityInternalPermission();
|
enforceConnectivityInternalPermission();
|
||||||
final long ident = Binder.clearCallingIdentity();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
setProvNotificationVisible(visible, networkType, action);
|
mNotifier.setProvNotificationVisible(visible, networkType, action);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.server.connectivity;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import com.android.internal.R;
|
||||||
|
|
||||||
|
import static android.net.ConnectivityManager.getNetworkTypeName;
|
||||||
|
|
||||||
|
|
||||||
|
public class NetworkNotificationManager {
|
||||||
|
|
||||||
|
public static enum NotificationType { SIGN_IN, NO_INTERNET; };
|
||||||
|
|
||||||
|
private static final String NOTIFICATION_ID = "CaptivePortal.Notification";
|
||||||
|
|
||||||
|
private static final String TAG = NetworkNotificationManager.class.getSimpleName();
|
||||||
|
private static final boolean DBG = true;
|
||||||
|
private static final boolean VDBG = false;
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private final TelephonyManager mTelephonyManager;
|
||||||
|
|
||||||
|
public NetworkNotificationManager(Context context, TelephonyManager telephonyManager) {
|
||||||
|
mContext = context;
|
||||||
|
mTelephonyManager = telephonyManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
public void setProvNotificationVisibleIntent(boolean visible, int id,
|
||||||
|
NotificationType notifyType, int networkType, String extraInfo, PendingIntent intent,
|
||||||
|
boolean highPriority) {
|
||||||
|
if (VDBG || (DBG && visible)) {
|
||||||
|
Slog.d(TAG, "setProvNotificationVisibleIntent " + notifyType + " visible=" + visible
|
||||||
|
+ " networkType=" + getNetworkTypeName(networkType)
|
||||||
|
+ " extraInfo=" + extraInfo + " highPriority=" + highPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
Resources r = Resources.getSystem();
|
||||||
|
NotificationManager notificationManager = (NotificationManager) mContext
|
||||||
|
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
|
if (visible) {
|
||||||
|
CharSequence title;
|
||||||
|
CharSequence details;
|
||||||
|
int icon;
|
||||||
|
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 notification = new Notification.Builder(mContext)
|
||||||
|
.setWhen(0)
|
||||||
|
.setSmallIcon(icon)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.setTicker(title)
|
||||||
|
.setColor(mContext.getColor(
|
||||||
|
com.android.internal.R.color.system_notification_accent_color))
|
||||||
|
.setContentTitle(title)
|
||||||
|
.setContentText(details)
|
||||||
|
.setContentIntent(intent)
|
||||||
|
.setLocalOnly(true)
|
||||||
|
.setPriority(highPriority ?
|
||||||
|
Notification.PRIORITY_HIGH :
|
||||||
|
Notification.PRIORITY_DEFAULT)
|
||||||
|
.setDefaults(highPriority ? Notification.DEFAULT_ALL : 0)
|
||||||
|
.setOnlyAlertOnce(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
try {
|
||||||
|
notificationManager.notifyAsUser(NOTIFICATION_ID, id, notification, UserHandle.ALL);
|
||||||
|
} catch (NullPointerException npe) {
|
||||||
|
Slog.d(TAG, "setNotificationVisible: visible notificationManager npe=" + npe);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
notificationManager.cancelAsUser(NOTIFICATION_ID, id, UserHandle.ALL);
|
||||||
|
} catch (NullPointerException npe) {
|
||||||
|
Slog.d(TAG, "setNotificationVisible: cancel notificationManager npe=" + npe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Legacy provisioning notifications coming directly from DcTracker.
|
||||||
|
*/
|
||||||
|
public void setProvNotificationVisible(boolean visible, int networkType, String action) {
|
||||||
|
Intent intent = new Intent(action);
|
||||||
|
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);
|
||||||
|
mNotifier.setProvNotificationVisibleIntent(visible, id, NotificationType.SIGN_IN,
|
||||||
|
networkType, null, pendingIntent, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user