Merge changes Iadf7f15d,I74702938,Ib8a725cd into nyc-mr2-dev
* changes: DO NOT MERGE Network notifications: revamp keying scheme DO NOT MERGE Define Network notification proto constants. DO NOT MERGE Unit tests for NetworkNotificationManager
This commit is contained in:
@@ -19,7 +19,6 @@ package com.android.server.connectivity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.widget.Toast;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
@@ -27,17 +26,40 @@ import android.net.NetworkCapabilities;
|
||||
import android.os.UserHandle;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Slog;
|
||||
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.widget.Toast;
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
||||
|
||||
import static android.net.NetworkCapabilities.*;
|
||||
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||
|
||||
public class NetworkNotificationManager {
|
||||
|
||||
public static enum NotificationType { SIGN_IN, NO_INTERNET, LOST_INTERNET, NETWORK_SWITCH };
|
||||
public static enum NotificationType {
|
||||
LOST_INTERNET(MetricsEvent.NOTIFICATION_NETWORK_LOST_INTERNET),
|
||||
NETWORK_SWITCH(MetricsEvent.NOTIFICATION_NETWORK_SWITCH),
|
||||
NO_INTERNET(MetricsEvent.NOTIFICATION_NETWORK_NO_INTERNET),
|
||||
SIGN_IN(MetricsEvent.NOTIFICATION_NETWORK_SIGN_IN);
|
||||
|
||||
private static final String NOTIFICATION_ID = "Connectivity.Notification";
|
||||
public final int eventId;
|
||||
|
||||
NotificationType(int eventId) {
|
||||
this.eventId = eventId;
|
||||
Holder.sIdToTypeMap.put(eventId, this);
|
||||
}
|
||||
|
||||
private static class Holder {
|
||||
private static SparseArray<NotificationType> sIdToTypeMap = new SparseArray<>();
|
||||
}
|
||||
|
||||
public static NotificationType getFromId(int id) {
|
||||
return Holder.sIdToTypeMap.get(id);
|
||||
}
|
||||
};
|
||||
|
||||
private static final String TAG = NetworkNotificationManager.class.getSimpleName();
|
||||
private static final boolean DBG = true;
|
||||
@@ -46,11 +68,14 @@ public class NetworkNotificationManager {
|
||||
private final Context mContext;
|
||||
private final TelephonyManager mTelephonyManager;
|
||||
private final NotificationManager mNotificationManager;
|
||||
// Tracks the types of notifications managed by this instance, from creation to cancellation.
|
||||
private final SparseIntArray mNotificationTypeMap;
|
||||
|
||||
public NetworkNotificationManager(Context c, TelephonyManager t, NotificationManager n) {
|
||||
mContext = c;
|
||||
mTelephonyManager = t;
|
||||
mNotificationManager = n;
|
||||
mNotificationTypeMap = new SparseIntArray();
|
||||
}
|
||||
|
||||
// TODO: deal more gracefully with multi-transport networks.
|
||||
@@ -100,8 +125,10 @@ public class NetworkNotificationManager {
|
||||
*/
|
||||
public void showNotification(int id, NotificationType notifyType, NetworkAgentInfo nai,
|
||||
NetworkAgentInfo switchToNai, PendingIntent intent, boolean highPriority) {
|
||||
int transportType;
|
||||
String extraInfo;
|
||||
final String tag = tagFor(id);
|
||||
final int eventId = notifyType.eventId;
|
||||
final int transportType;
|
||||
final String extraInfo;
|
||||
if (nai != null) {
|
||||
transportType = getFirstTransportType(nai);
|
||||
extraInfo = nai.networkInfo.getExtraInfo();
|
||||
@@ -114,9 +141,9 @@ public class NetworkNotificationManager {
|
||||
}
|
||||
|
||||
if (DBG) {
|
||||
Slog.d(TAG, "showNotification id=" + id + " " + notifyType
|
||||
+ " transportType=" + getTransportName(transportType)
|
||||
+ " extraInfo=" + extraInfo + " highPriority=" + highPriority);
|
||||
Slog.d(TAG, String.format(
|
||||
"showNotification tag=%s event=%s transport=%s extraInfo=%d highPrioriy=%s",
|
||||
tag, nameOf(eventId), getTransportName(transportType), extraInfo, highPriority));
|
||||
}
|
||||
|
||||
Resources r = Resources.getSystem();
|
||||
@@ -184,22 +211,31 @@ public class NetworkNotificationManager {
|
||||
|
||||
Notification notification = builder.build();
|
||||
|
||||
mNotificationTypeMap.put(id, eventId);
|
||||
try {
|
||||
mNotificationManager.notifyAsUser(NOTIFICATION_ID, id, notification, UserHandle.ALL);
|
||||
mNotificationManager.notifyAsUser(tag, eventId, notification, UserHandle.ALL);
|
||||
} catch (NullPointerException npe) {
|
||||
Slog.d(TAG, "setNotificationVisible: visible notificationManager error", npe);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearNotification(int id) {
|
||||
final String tag = tagFor(id);
|
||||
if (mNotificationTypeMap.indexOfKey(id) < 0) {
|
||||
Slog.e(TAG, "cannot clear unknown notification with tag=" + tag);
|
||||
return;
|
||||
}
|
||||
final int eventId = mNotificationTypeMap.get(id);
|
||||
if (DBG) {
|
||||
Slog.d(TAG, "clearNotification id=" + id);
|
||||
Slog.d(TAG, String.format("clearing notification tag=%s event=", tag, nameOf(eventId)));
|
||||
}
|
||||
try {
|
||||
mNotificationManager.cancelAsUser(NOTIFICATION_ID, id, UserHandle.ALL);
|
||||
mNotificationManager.cancelAsUser(tag, eventId, UserHandle.ALL);
|
||||
} catch (NullPointerException npe) {
|
||||
Slog.d(TAG, "setNotificationVisible: cancel notificationManager error", npe);
|
||||
Slog.d(TAG, String.format(
|
||||
"failed to clear notification tag=%s event=", tag, nameOf(eventId)), npe);
|
||||
}
|
||||
mNotificationTypeMap.delete(id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,4 +258,15 @@ public class NetworkNotificationManager {
|
||||
R.string.network_switch_metered_toast, fromTransport, toTransport);
|
||||
Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static String tagFor(int id) {
|
||||
return String.format("ConnectivityNotification:%d", id);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static String nameOf(int eventId) {
|
||||
NotificationType t = NotificationType.getFromId(eventId);
|
||||
return (t != null) ? t.name() : "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import junit.framework.TestCase;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.*;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.anyInt;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class NetworkNotificationManagerTest extends TestCase {
|
||||
|
||||
static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities();
|
||||
static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities();
|
||||
static {
|
||||
CELL_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
|
||||
CELL_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
|
||||
|
||||
WIFI_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
|
||||
WIFI_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
|
||||
}
|
||||
|
||||
@Mock Context mCtx;
|
||||
@Mock Resources mResources;
|
||||
@Mock PackageManager mPm;
|
||||
@Mock TelephonyManager mTelephonyManager;
|
||||
@Mock NotificationManager mNotificationManager;
|
||||
@Mock NetworkAgentInfo mWifiNai;
|
||||
@Mock NetworkAgentInfo mCellNai;
|
||||
@Mock NetworkInfo mNetworkInfo;
|
||||
ArgumentCaptor<Notification> mCaptor;
|
||||
|
||||
NetworkNotificationManager mManager;
|
||||
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mCaptor = ArgumentCaptor.forClass(Notification.class);
|
||||
mWifiNai.networkCapabilities = WIFI_CAPABILITIES;
|
||||
mWifiNai.networkInfo = mNetworkInfo;
|
||||
mCellNai.networkCapabilities = CELL_CAPABILITIES;
|
||||
mCellNai.networkInfo = mNetworkInfo;
|
||||
when(mCtx.getResources()).thenReturn(mResources);
|
||||
when(mCtx.getPackageManager()).thenReturn(mPm);
|
||||
when(mCtx.getApplicationInfo()).thenReturn(new ApplicationInfo());
|
||||
when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B);
|
||||
|
||||
mManager = new NetworkNotificationManager(mCtx, mTelephonyManager, mNotificationManager);
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testNotificationsShownAndCleared() {
|
||||
final int NETWORK_ID_BASE = 100;
|
||||
List<NotificationType> types = Arrays.asList(NotificationType.values());
|
||||
List<Integer> ids = new ArrayList<>(types.size());
|
||||
for (int i = 0; i < ids.size(); i++) {
|
||||
ids.add(NETWORK_ID_BASE + i);
|
||||
}
|
||||
Collections.shuffle(ids);
|
||||
Collections.shuffle(types);
|
||||
|
||||
for (int i = 0; i < ids.size(); i++) {
|
||||
mManager.showNotification(ids.get(i), types.get(i), mWifiNai, mCellNai, null, false);
|
||||
}
|
||||
|
||||
Collections.shuffle(ids);
|
||||
for (int i = 0; i < ids.size(); i++) {
|
||||
mManager.clearNotification(ids.get(i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < ids.size(); i++) {
|
||||
final int id = ids.get(i);
|
||||
final int eventId = types.get(i).eventId;
|
||||
final String tag = NetworkNotificationManager.tagFor(id);
|
||||
verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any());
|
||||
verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(eventId), any());
|
||||
}
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testNoInternetNotificationsNotShownForCellular() {
|
||||
mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false);
|
||||
mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false);
|
||||
|
||||
verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
|
||||
|
||||
mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
|
||||
|
||||
final int eventId = NO_INTERNET.eventId;
|
||||
final String tag = NetworkNotificationManager.tagFor(102);
|
||||
verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any());
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testNotificationsNotShownIfNoInternetCapability() {
|
||||
mWifiNai.networkCapabilities = new NetworkCapabilities();
|
||||
mWifiNai.networkCapabilities .addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
|
||||
mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
|
||||
mManager.showNotification(103, LOST_INTERNET, mWifiNai, mCellNai, null, false);
|
||||
mManager.showNotification(104, NETWORK_SWITCH, mWifiNai, mCellNai, null, false);
|
||||
|
||||
verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user