summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java9
-rw-r--r--java/com/android/dialer/app/calllog/MissedCallNotifier.java77
-rw-r--r--java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java60
-rw-r--r--java/com/android/dialer/blocking/FilteredNumbersUtil.java7
-rw-r--r--java/com/android/dialer/notification/DialerNotificationManager.java125
-rw-r--r--java/com/android/dialer/notification/NotificationManagerUtils.java41
-rw-r--r--java/com/android/dialer/notification/NotificationThrottler.java102
-rw-r--r--java/com/android/incallui/ExternalCallNotifier.java92
-rw-r--r--java/com/android/incallui/StatusBarNotifier.java22
-rw-r--r--java/com/android/incallui/call/ExternalCallList.java6
-rw-r--r--java/com/android/incallui/spam/SpamCallListListener.java35
-rw-r--r--java/com/android/incallui/spam/SpamNotificationActivity.java11
-rw-r--r--java/com/android/incallui/spam/SpamNotificationService.java10
13 files changed, 411 insertions, 186 deletions
diff --git a/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java b/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java
index c64e03e4e..584f07fe3 100644
--- a/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java
+++ b/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java
@@ -18,7 +18,6 @@ package com.android.dialer.app.calllog;
import android.annotation.TargetApi;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.os.Build.VERSION_CODES;
@@ -35,6 +34,7 @@ import com.android.dialer.app.R;
import com.android.dialer.calllogutils.PhoneAccountUtils;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.notification.NotificationChannelManager;
/** Shows a notification in the status bar for legacy vociemail. */
@@ -77,9 +77,7 @@ public final class LegacyVoicemailNotifier {
callVoicemailIntent,
voicemailSettingsIntent,
isRefresh);
- context
- .getSystemService(NotificationManager.class)
- .notify(NOTIFICATION_TAG, NOTIFICATION_ID, notification);
+ DialerNotificationManager.notify(context, NOTIFICATION_TAG, NOTIFICATION_ID, notification);
}
@NonNull
@@ -151,8 +149,7 @@ public final class LegacyVoicemailNotifier {
public static void cancelNotification(@NonNull Context context) {
LogUtil.enterBlock("LegacyVoicemailNotifier.cancelNotification");
Assert.checkArgument(BuildCompat.isAtLeastO());
- NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
- notificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
+ DialerNotificationManager.cancel(context, NOTIFICATION_TAG, NOTIFICATION_ID);
}
private LegacyVoicemailNotifier() {}
diff --git a/java/com/android/dialer/app/calllog/MissedCallNotifier.java b/java/com/android/dialer/app/calllog/MissedCallNotifier.java
index e0e3fdf3f..b363b5ab6 100644
--- a/java/com/android/dialer/app/calllog/MissedCallNotifier.java
+++ b/java/com/android/dialer/app/calllog/MissedCallNotifier.java
@@ -17,7 +17,6 @@ package com.android.dialer.app.calllog;
import android.app.Notification;
import android.app.Notification.Builder;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -48,7 +47,9 @@ import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.notification.NotificationChannelId;
+import com.android.dialer.notification.NotificationManagerUtils;
import com.android.dialer.phonenumbercache.ContactInfo;
import com.android.dialer.phonenumberutil.PhoneNumberHelper;
import com.android.dialer.util.DialerUtils;
@@ -59,9 +60,17 @@ import java.util.Set;
/** Creates a notification for calls that the user missed (neither answered nor rejected). */
public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
- static final String NOTIFICATION_TAG_PREFIX = "MissedCall_";
- static final String NOTIFICATION_GROUP = "MissedCall";
+ /** Prefix used to generate a unique tag for each missed call notification. */
+ private static final String NOTIFICATION_TAG_PREFIX = "MissedCall_";
+ /** Common ID for all missed call notifications. */
private static final int NOTIFICATION_ID = 1;
+ /** Tag for the group summary notification. */
+ private static final String GROUP_SUMMARY_NOTIFICATION_TAG = "GroupSummary_MissedCall";
+ /**
+ * Key used to associate all missed call notifications and the summary as belonging to a single
+ * group.
+ */
+ private static final String GROUP_KEY = "MissedCallGroup";
private final Context context;
private final CallLogNotificationsQueryHelper callLogNotificationsQueryHelper;
@@ -202,33 +211,29 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
configureLedOnNotification(notification);
LogUtil.i("MissedCallNotifier.updateMissedCallNotification", "adding missed call notification");
- getNotificationMgr().notify(getNotificationTagForGroupSummary(), NOTIFICATION_ID, notification);
+ DialerNotificationManager.notify(
+ context, GROUP_SUMMARY_NOTIFICATION_TAG, NOTIFICATION_ID, notification);
if (useCallList) {
// Do not repost active notifications to prevent erasing post call notes.
- NotificationManager manager = getNotificationMgr();
Set<String> activeTags = new ArraySet<>();
- for (StatusBarNotification activeNotification : manager.getActiveNotifications()) {
+ for (StatusBarNotification activeNotification :
+ DialerNotificationManager.getActiveNotifications(context)) {
activeTags.add(activeNotification.getTag());
}
for (NewCall call : newCalls) {
String callTag = getNotificationTagForCall(call);
if (!activeTags.contains(callTag)) {
- manager.notify(callTag, NOTIFICATION_ID, getNotificationForCall(call, null));
+ DialerNotificationManager.notify(
+ context, callTag, NOTIFICATION_ID, getNotificationForCall(call, null));
}
}
}
}
public static void cancelAllMissedCallNotifications(@NonNull Context context) {
- NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
- for (StatusBarNotification notification : notificationManager.getActiveNotifications()) {
- String tag = notification.getTag();
- if (tag != null && tag.startsWith(NOTIFICATION_TAG_PREFIX)) {
- notificationManager.cancel(tag, notification.getId());
- }
- }
+ NotificationManagerUtils.cancelAllInGroup(context, GROUP_KEY);
}
public static void cancelSingleMissedCallNotification(
@@ -239,31 +244,9 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
"unable to cancel notification, uri is null");
return;
}
- NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
- String callTag = getNotificationTagForCallUri(callUri);
- String summaryTag = getNotificationTagForGroupSummary();
- int notificationCount = 0;
-
- for (StatusBarNotification notification : notificationManager.getActiveNotifications()) {
- String currentTag = notification.getTag();
- if (currentTag == null) {
- continue;
- }
- if (currentTag.equals(callTag)) {
- notificationManager.cancel(notification.getTag(), notification.getId());
- } else if (currentTag.startsWith(NOTIFICATION_TAG_PREFIX) && !currentTag.equals(summaryTag)) {
- notificationCount++;
- }
- }
-
- if (notificationCount == 0) {
- // There are no more missed call notifications. Remove the summary notification too.
- notificationManager.cancel(summaryTag, NOTIFICATION_ID);
- }
- }
-
- private static String getNotificationTagForGroupSummary() {
- return NOTIFICATION_TAG_PREFIX + "GroupSummary";
+ // This will also dismiss the group summary if there are no more missed call notifications.
+ DialerNotificationManager.cancel(
+ context, getNotificationTagForCallUri(callUri), NOTIFICATION_ID);
}
private static String getNotificationTagForCall(@NonNull NewCall call) {
@@ -280,11 +263,11 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
for (NewCall call : newCalls) {
if (call.number.equals(number.replace("tel:", ""))) {
// Update the first notification that matches our post call note sender.
- getNotificationMgr()
- .notify(
- getNotificationTagForCall(call),
- NOTIFICATION_ID,
- getNotificationForCall(call, note));
+ DialerNotificationManager.notify(
+ context,
+ getNotificationTagForCall(call),
+ NOTIFICATION_ID,
+ getNotificationForCall(call, note));
break;
}
}
@@ -366,7 +349,7 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
private Notification.Builder createNotificationBuilder() {
return new Notification.Builder(context)
- .setGroup(NOTIFICATION_GROUP)
+ .setGroup(GROUP_KEY)
.setSmallIcon(android.R.drawable.stat_notify_missed_call)
.setColor(context.getResources().getColor(R.color.dialer_theme_color, null))
.setAutoCancel(true)
@@ -466,8 +449,4 @@ public class MissedCallNotifier implements Worker<Pair<Integer, String>, Void> {
private void closeSystemDialogs(Context context) {
context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
}
-
- private NotificationManager getNotificationMgr() {
- return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
- }
}
diff --git a/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java b/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java
index 99fe466d8..cbadfd317 100644
--- a/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java
+++ b/java/com/android/dialer/app/calllog/VisualVoicemailNotifier.java
@@ -17,7 +17,6 @@
package com.android.dialer.app.calllog;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
@@ -26,7 +25,6 @@ import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
-import android.service.notification.StatusBarNotification;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.os.BuildCompat;
@@ -43,7 +41,9 @@ import com.android.dialer.app.list.DialtactsPagerAdapter;
import com.android.dialer.common.LogUtil;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
+import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.notification.NotificationChannelManager;
+import com.android.dialer.notification.NotificationManagerUtils;
import com.android.dialer.phonenumbercache.ContactInfo;
import com.android.dialer.telecom.TelecomUtil;
import java.util.List;
@@ -51,9 +51,17 @@ import java.util.Map;
/** Shows a notification in the status bar for visual voicemail. */
final class VisualVoicemailNotifier {
+ /** Prefix used to generate a unique tag for each voicemail notification. */
private static final String NOTIFICATION_TAG_PREFIX = "VisualVoicemail_";
- private static final String NOTIFICATION_GROUP = "VisualVoicemail";
+ /** Common ID for all voicemail notifications. */
private static final int NOTIFICATION_ID = 1;
+ /** Tag for the group summary notification. */
+ private static final String GROUP_SUMMARY_NOTIFICATION_TAG = "GroupSummary_VisualVoicemail";
+ /**
+ * Key used to associate all voicemail notifications and the summary as belonging to a single
+ * group.
+ */
+ private static final String GROUP_KEY = "VisualVoicemailGroup";
public static void showNotifications(
@NonNull Context context,
@@ -82,12 +90,12 @@ final class VisualVoicemailNotifier {
groupSummary.setChannelId(NotificationChannelManager.getVoicemailChannelId(context, handle));
}
- NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
- notificationManager.notify(
- getNotificationTagForGroupSummary(), NOTIFICATION_ID, groupSummary.build());
+ DialerNotificationManager.notify(
+ context, GROUP_SUMMARY_NOTIFICATION_TAG, NOTIFICATION_ID, groupSummary.build());
for (NewCall voicemail : newCalls) {
- notificationManager.notify(
+ DialerNotificationManager.notify(
+ context,
getNotificationTagForVoicemail(voicemail),
NOTIFICATION_ID,
createNotificationForVoicemail(context, voicemail, contactInfos));
@@ -96,13 +104,7 @@ final class VisualVoicemailNotifier {
public static void cancelAllVoicemailNotifications(@NonNull Context context) {
LogUtil.enterBlock("VisualVoicemailNotifier.cancelAllVoicemailNotifications");
- NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
- for (StatusBarNotification notification : notificationManager.getActiveNotifications()) {
- String tag = notification.getTag();
- if (tag != null && tag.startsWith(NOTIFICATION_TAG_PREFIX)) {
- notificationManager.cancel(tag, notification.getId());
- }
- }
+ NotificationManagerUtils.cancelAllInGroup(context, GROUP_KEY);
}
public static void cancelSingleVoicemailNotification(
@@ -112,27 +114,9 @@ final class VisualVoicemailNotifier {
LogUtil.e("VisualVoicemailNotifier.cancelSingleVoicemailNotification", "uri is null");
return;
}
- NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
- String voicemailTag = getNotificationTagForUri(voicemailUri);
- String summaryTag = getNotificationTagForGroupSummary();
- int notificationCount = 0;
-
- for (StatusBarNotification notification : notificationManager.getActiveNotifications()) {
- String currentTag = notification.getTag();
- if (currentTag == null) {
- continue;
- }
- if (currentTag.equals(voicemailTag)) {
- notificationManager.cancel(notification.getTag(), notification.getId());
- } else if (currentTag.startsWith(NOTIFICATION_TAG_PREFIX) && !currentTag.equals(summaryTag)) {
- notificationCount++;
- }
- }
-
- if (notificationCount == 0) {
- // There are no more visual voicemail notifications. Remove the summary notification too.
- notificationManager.cancel(summaryTag, NOTIFICATION_ID);
- }
+ // This will also dismiss the group summary if there are no more voicemail notifications.
+ DialerNotificationManager.cancel(
+ context, getNotificationTagForUri(voicemailUri), NOTIFICATION_ID);
}
private static String getNotificationTagForVoicemail(@NonNull NewCall voicemail) {
@@ -143,15 +127,11 @@ final class VisualVoicemailNotifier {
return NOTIFICATION_TAG_PREFIX + voicemailUri;
}
- private static String getNotificationTagForGroupSummary() {
- return NOTIFICATION_TAG_PREFIX + "GroupSummary";
- }
-
private static Notification.Builder createNotificationBuilder(@NonNull Context context) {
return new Notification.Builder(context)
.setSmallIcon(android.R.drawable.stat_notify_voicemail)
.setColor(context.getColor(R.color.dialer_theme_color))
- .setGroup(NOTIFICATION_GROUP)
+ .setGroup(GROUP_KEY)
.setOnlyAlertOnce(true)
.setAutoCancel(true);
}
diff --git a/java/com/android/dialer/blocking/FilteredNumbersUtil.java b/java/com/android/dialer/blocking/FilteredNumbersUtil.java
index 9e0c23c80..fba3b86db 100644
--- a/java/com/android/dialer/blocking/FilteredNumbersUtil.java
+++ b/java/com/android/dialer/blocking/FilteredNumbersUtil.java
@@ -16,7 +16,6 @@
package com.android.dialer.blocking;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentValues;
import android.content.Context;
@@ -36,6 +35,7 @@ import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler.OnHasBlockedN
import com.android.dialer.common.LogUtil;
import com.android.dialer.logging.InteractionEvent;
import com.android.dialer.logging.Logger;
+import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.notification.NotificationChannelId;
import com.android.dialer.util.DialerUtils;
import com.android.dialer.util.PermissionsUtil;
@@ -242,8 +242,6 @@ public class FilteredNumbersUtil {
return;
}
- NotificationManager notificationManager =
- (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder builder =
new Notification.Builder(context)
.setSmallIcon(R.drawable.quantum_ic_block_white_24)
@@ -263,7 +261,8 @@ public class FilteredNumbersUtil {
FilteredNumberCompat.createManageBlockedNumbersIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT));
- notificationManager.notify(
+ DialerNotificationManager.notify(
+ context,
CALL_BLOCKING_NOTIFICATION_TAG,
CALL_BLOCKING_DISABLED_BY_EMERGENCY_CALL_NOTIFICATION_ID,
builder.build());
diff --git a/java/com/android/dialer/notification/DialerNotificationManager.java b/java/com/android/dialer/notification/DialerNotificationManager.java
new file mode 100644
index 000000000..0e3420169
--- /dev/null
+++ b/java/com/android/dialer/notification/DialerNotificationManager.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2017 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.dialer.notification;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.StatusBarNotification;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.os.BuildCompat;
+import android.text.TextUtils;
+import android.util.Pair;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+
+/**
+ * Wrapper around the notification manager APIs. The wrapper ensures that channels are set and that
+ * notifications are limited to 10 per group.
+ */
+public final class DialerNotificationManager {
+ public static void notify(@NonNull Context context, int id, @NonNull Notification notification) {
+ Assert.isNotNull(context);
+ Assert.isNotNull(notification);
+ throw Assert.createUnsupportedOperationFailException("all notifications must have tags");
+ }
+
+ public static void notify(
+ @NonNull Context context, @NonNull String tag, int id, @NonNull Notification notification) {
+ Assert.isNotNull(context);
+ Assert.isNotNull(notification);
+ Assert.checkArgument(!TextUtils.isEmpty(tag));
+
+ if (BuildCompat.isAtLeastO()) {
+ Assert.checkArgument(!TextUtils.isEmpty(notification.getChannelId()));
+ }
+
+ getNotificationManager(context).notify(tag, id, notification);
+ NotificationThrottler.throttle(context, notification);
+ }
+
+ public static void cancel(@NonNull Context context, int id) {
+ Assert.isNotNull(context);
+ throw Assert.createUnsupportedOperationFailException(
+ "notification IDs are not unique across the app, a tag must be specified");
+ }
+
+ public static void cancel(@NonNull Context context, @NonNull String tag, int id) {
+ Assert.isNotNull(context);
+ Assert.checkArgument(!TextUtils.isEmpty(tag));
+
+ NotificationManager notificationManager = getNotificationManager(context);
+ StatusBarNotification[] notifications = notificationManager.getActiveNotifications();
+
+ String groupKey = findGroupKey(notifications, tag, id);
+ if (!TextUtils.isEmpty(groupKey)) {
+ Pair<StatusBarNotification, Integer> groupSummaryAndCount =
+ getGroupSummaryAndCount(notifications, groupKey);
+ if (groupSummaryAndCount.first != null && groupSummaryAndCount.second <= 1) {
+ LogUtil.i(
+ "DialerNotificationManager.cancel",
+ "last notification in group (%s) removed, also removing group summary",
+ groupKey);
+ notificationManager.cancel(
+ groupSummaryAndCount.first.getTag(), groupSummaryAndCount.first.getId());
+ }
+ }
+
+ notificationManager.cancel(tag, id);
+ }
+
+ public static StatusBarNotification[] getActiveNotifications(@NonNull Context context) {
+ Assert.isNotNull(context);
+ return getNotificationManager(context).getActiveNotifications();
+ }
+
+ @Nullable
+ private static String findGroupKey(
+ @NonNull StatusBarNotification[] notifications, @NonNull String tag, int id) {
+ for (StatusBarNotification notification : notifications) {
+ if (TextUtils.equals(tag, notification.getTag()) && id == notification.getId()) {
+ return notification.getNotification().getGroup();
+ }
+ }
+ return null;
+ }
+
+ @NonNull
+ private static Pair<StatusBarNotification, Integer> getGroupSummaryAndCount(
+ @NonNull StatusBarNotification[] notifications, @NonNull String groupKey) {
+ StatusBarNotification groupSummaryNotification = null;
+ int groupCount = 0;
+ for (StatusBarNotification notification : notifications) {
+ if (TextUtils.equals(groupKey, notification.getNotification().getGroup())) {
+ if ((notification.getNotification().flags & Notification.FLAG_GROUP_SUMMARY) != 0) {
+ groupSummaryNotification = notification;
+ } else {
+ groupCount++;
+ }
+ }
+ }
+ return new Pair<>(groupSummaryNotification, groupCount);
+ }
+
+ @NonNull
+ private static NotificationManager getNotificationManager(@NonNull Context context) {
+ return context.getSystemService(NotificationManager.class);
+ }
+
+ private DialerNotificationManager() {}
+}
diff --git a/java/com/android/dialer/notification/NotificationManagerUtils.java b/java/com/android/dialer/notification/NotificationManagerUtils.java
new file mode 100644
index 000000000..d99a9036d
--- /dev/null
+++ b/java/com/android/dialer/notification/NotificationManagerUtils.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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.dialer.notification;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.StatusBarNotification;
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
+import com.android.dialer.common.Assert;
+
+/** Utilities to manage notifications. */
+public final class NotificationManagerUtils {
+ public static void cancelAllInGroup(@NonNull Context context, @NonNull String groupKey) {
+ Assert.isNotNull(context);
+ Assert.checkArgument(!TextUtils.isEmpty(groupKey));
+
+ NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
+ for (StatusBarNotification notification : notificationManager.getActiveNotifications()) {
+ if (TextUtils.equals(groupKey, notification.getNotification().getGroup())) {
+ notificationManager.cancel(notification.getTag(), notification.getId());
+ }
+ }
+ }
+
+ private NotificationManagerUtils() {}
+}
diff --git a/java/com/android/dialer/notification/NotificationThrottler.java b/java/com/android/dialer/notification/NotificationThrottler.java
new file mode 100644
index 000000000..7c2428737
--- /dev/null
+++ b/java/com/android/dialer/notification/NotificationThrottler.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 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.dialer.notification;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.StatusBarNotification;
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Utility to ensure that only a certain number of notifications are shown for a particular
+ * notification type. Once the limit is reached, older notifications are cancelled.
+ */
+/* package */ class NotificationThrottler {
+ private static final int MAX_NOTIFICATIONS_PER_TAG = 10;
+
+ /* package */ static void throttle(@NonNull Context context, @NonNull Notification notification) {
+ Assert.isNotNull(context);
+ Assert.isNotNull(notification);
+
+ // No limiting for non-grouped notifications.
+ String groupKey = notification.getGroup();
+ if (TextUtils.isEmpty(groupKey)) {
+ return;
+ }
+
+ int count = 0;
+ NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
+ for (StatusBarNotification currentNotification : notificationManager.getActiveNotifications()) {
+ if (isNotificationInGroup(currentNotification, groupKey)) {
+ count++;
+ }
+ }
+
+ if (count > MAX_NOTIFICATIONS_PER_TAG) {
+ LogUtil.i(
+ "NotificationThrottler.throttle",
+ "groupKey: %s is over limit, count: %d, limit: %d",
+ groupKey,
+ count,
+ MAX_NOTIFICATIONS_PER_TAG);
+ List<StatusBarNotification> notifications = getSortedMatchingNotifications(context, groupKey);
+ for (int i = 0; i < (count - MAX_NOTIFICATIONS_PER_TAG); i++) {
+ notificationManager.cancel(notifications.get(i).getTag(), notifications.get(i).getId());
+ }
+ }
+ }
+
+ private static List<StatusBarNotification> getSortedMatchingNotifications(
+ @NonNull Context context, @NonNull String groupKey) {
+ List<StatusBarNotification> notifications = new ArrayList<>();
+ NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
+ for (StatusBarNotification notification : notificationManager.getActiveNotifications()) {
+ if (isNotificationInGroup(notification, groupKey)) {
+ notifications.add(notification);
+ }
+ }
+ Collections.sort(
+ notifications,
+ new Comparator<StatusBarNotification>() {
+ @Override
+ public int compare(StatusBarNotification left, StatusBarNotification right) {
+ return Long.compare(left.getPostTime(), right.getPostTime());
+ }
+ });
+ return notifications;
+ }
+
+ private static boolean isNotificationInGroup(
+ @NonNull StatusBarNotification notification, @NonNull String groupKey) {
+ // Don't include group summaries.
+ if ((notification.getNotification().flags & Notification.FLAG_GROUP_SUMMARY) != 0) {
+ return false;
+ }
+
+ return TextUtils.equals(groupKey, notification.getNotification().getGroup());
+ }
+
+ private NotificationThrottler() {}
+}
diff --git a/java/com/android/incallui/ExternalCallNotifier.java b/java/com/android/incallui/ExternalCallNotifier.java
index ed3c91897..9e7805236 100644
--- a/java/com/android/incallui/ExternalCallNotifier.java
+++ b/java/com/android/incallui/ExternalCallNotifier.java
@@ -18,7 +18,6 @@ package com.android.incallui;
import android.annotation.TargetApi;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -41,7 +40,9 @@ import com.android.contacts.common.ContactsUtils;
import com.android.contacts.common.compat.CallCompat;
import com.android.contacts.common.preference.ContactsPreferences;
import com.android.contacts.common.util.ContactDisplayUtils;
+import com.android.dialer.common.Assert;
import com.android.dialer.contactphoto.BitmapUtil;
+import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.notification.NotificationChannelId;
import com.android.incallui.call.DialerCall;
import com.android.incallui.call.DialerCallDelegate;
@@ -58,17 +59,25 @@ import java.util.Map;
*/
public class ExternalCallNotifier implements ExternalCallList.ExternalCallListener {
- /** Tag used with the notification manager to uniquely identify external call notifications. */
+ /**
+ * Common tag for all external call notifications. Unlike other grouped notifications in Dialer,
+ * external call notifications are uniquely identified by ID.
+ */
private static final String NOTIFICATION_TAG = "EXTERNAL_CALL";
- private static final int NOTIFICATION_SUMMARY_ID = -1;
+ private static final int GROUP_SUMMARY_NOTIFICATION_ID = -1;
+ private static final String GROUP_SUMMARY_NOTIFICATION_TAG = "GroupSummary_ExternalCall";
+ /**
+ * Key used to associate all external call notifications and the summary as belonging to a single
+ * group.
+ */
+ private static final String GROUP_KEY = "ExternalCallGroup";
private final Context mContext;
private final ContactInfoCache mContactInfoCache;
private Map<Call, NotificationInfo> mNotifications = new ArrayMap<>();
private int mNextUniqueNotificationId;
private ContactsPreferences mContactsPreferences;
- private boolean mShowingSummary;
/** Initializes a new instance of the external call notifier. */
public ExternalCallNotifier(
@@ -85,9 +94,7 @@ public class ExternalCallNotifier implements ExternalCallList.ExternalCallListen
@Override
public void onExternalCallAdded(android.telecom.Call call) {
Log.i(this, "onExternalCallAdded " + call);
- if (mNotifications.containsKey(call)) {
- throw new IllegalArgumentException();
- }
+ Assert.checkArgument(!mNotifications.containsKey(call));
NotificationInfo info = new NotificationInfo(call, mNextUniqueNotificationId++);
mNotifications.put(call, info);
@@ -108,9 +115,7 @@ public class ExternalCallNotifier implements ExternalCallList.ExternalCallListen
/** Handles updates to an external call. */
@Override
public void onExternalCallUpdated(Call call) {
- if (!mNotifications.containsKey(call)) {
- throw new IllegalArgumentException();
- }
+ Assert.checkArgument(mNotifications.containsKey(call));
postNotification(mNotifications.get(call));
}
@@ -183,28 +188,13 @@ public class ExternalCallNotifier implements ExternalCallList.ExternalCallListen
/** Dismisses a notification for an external call. */
private void dismissNotification(Call call) {
- if (!mNotifications.containsKey(call)) {
- throw new IllegalArgumentException();
- }
+ Assert.checkArgument(mNotifications.containsKey(call));
- NotificationManager notificationManager =
- (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.cancel(NOTIFICATION_TAG, mNotifications.get(call).getNotificationId());
+ // This will also dismiss the group summary if there are no more external call notifications.
+ DialerNotificationManager.cancel(
+ mContext, NOTIFICATION_TAG, mNotifications.get(call).getNotificationId());
mNotifications.remove(call);
-
- if (mShowingSummary && mNotifications.size() <= 1) {
- // Where a summary notification is showing and there is now not enough notifications to
- // necessitate a summary, cancel the summary.
- notificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_SUMMARY_ID);
- mShowingSummary = false;
-
- // If there is still a single call requiring a notification, re-post the notification as a
- // standalone notification without a summary notification.
- if (mNotifications.size() == 1) {
- postNotification(mNotifications.values().iterator().next());
- }
- }
}
/**
@@ -237,7 +227,7 @@ public class ExternalCallNotifier implements ExternalCallList.ExternalCallListen
builder.setOngoing(true);
// Make the notification prioritized over the other normal notifications.
builder.setPriority(Notification.PRIORITY_HIGH);
- builder.setGroup(NOTIFICATION_TAG);
+ builder.setGroup(GROUP_KEY);
boolean isVideoCall = VideoProfile.isVideo(info.getCall().getDetails().getVideoState());
// Set the content ("Ongoing call on another device")
@@ -293,28 +283,10 @@ public class ExternalCallNotifier implements ExternalCallList.ExternalCallListen
builder.setPublicVersion(publicBuilder.build());
Notification notification = builder.build();
- NotificationManager notificationManager =
- (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.notify(NOTIFICATION_TAG, info.getNotificationId(), notification);
-
- if (!mShowingSummary && mNotifications.size() > 1) {
- // If the number of notifications shown is > 1, and we're not already showing a group summary,
- // build one now. This will ensure the like notifications are grouped together.
-
- Notification.Builder summary = new Notification.Builder(mContext);
- // Set notification as ongoing since calls are long-running versus a point-in-time notice.
- summary.setOngoing(true);
- // Make the notification prioritized over the other normal notifications.
- summary.setPriority(Notification.PRIORITY_HIGH);
- summary.setGroup(NOTIFICATION_TAG);
- summary.setGroupSummary(true);
- summary.setSmallIcon(R.drawable.quantum_ic_call_white_24);
- if (BuildCompat.isAtLeastO()) {
- summary.setChannelId(NotificationChannelId.DEFAULT);
- }
- notificationManager.notify(NOTIFICATION_TAG, NOTIFICATION_SUMMARY_ID, summary.build());
- mShowingSummary = true;
- }
+ DialerNotificationManager.notify(
+ mContext, NOTIFICATION_TAG, info.getNotificationId(), notification);
+
+ showGroupSummaryNotification(mContext);
}
/**
@@ -475,4 +447,20 @@ public class ExternalCallNotifier implements ExternalCallList.ExternalCallListen
mPersonReference = personReference;
}
}
+
+ private static void showGroupSummaryNotification(@NonNull Context context) {
+ Notification.Builder summary = new Notification.Builder(context);
+ // Set notification as ongoing since calls are long-running versus a point-in-time notice.
+ summary.setOngoing(true);
+ // Make the notification prioritized over the other normal notifications.
+ summary.setPriority(Notification.PRIORITY_HIGH);
+ summary.setGroup(GROUP_KEY);
+ summary.setGroupSummary(true);
+ summary.setSmallIcon(R.drawable.quantum_ic_call_white_24);
+ if (BuildCompat.isAtLeastO()) {
+ summary.setChannelId(NotificationChannelId.DEFAULT);
+ }
+ DialerNotificationManager.notify(
+ context, GROUP_SUMMARY_NOTIFICATION_TAG, GROUP_SUMMARY_NOTIFICATION_ID, summary.build());
+ }
}
diff --git a/java/com/android/incallui/StatusBarNotifier.java b/java/com/android/incallui/StatusBarNotifier.java
index 07f179edc..d20c62f4b 100644
--- a/java/com/android/incallui/StatusBarNotifier.java
+++ b/java/com/android/incallui/StatusBarNotifier.java
@@ -28,7 +28,6 @@ import static com.android.incallui.NotificationBroadcastReceiver.ACTION_HANG_UP_
import android.Manifest;
import android.app.ActivityManager;
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -62,6 +61,7 @@ import com.android.contacts.common.ContactsUtils;
import com.android.contacts.common.ContactsUtils.UserType;
import com.android.contacts.common.preference.ContactsPreferences;
import com.android.contacts.common.util.ContactDisplayUtils;
+import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.configprovider.ConfigProviderBindings;
import com.android.dialer.contactphoto.BitmapUtil;
@@ -70,6 +70,7 @@ import com.android.dialer.enrichedcall.Session;
import com.android.dialer.lettertile.LetterTileDrawable;
import com.android.dialer.lettertile.LetterTileDrawable.ContactType;
import com.android.dialer.multimedia.MultimediaData;
+import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.notification.NotificationChannelId;
import com.android.dialer.oem.MotorolaUtils;
import com.android.dialer.util.DrawableConverter;
@@ -113,7 +114,6 @@ public class StatusBarNotifier
private final Context mContext;
private final ContactInfoCache mContactInfoCache;
- private final NotificationManager mNotificationManager;
private final DialerRingtoneManager mDialerRingtoneManager;
@Nullable private ContactsPreferences mContactsPreferences;
private int mCurrentNotification = NOTIFICATION_NONE;
@@ -126,11 +126,9 @@ public class StatusBarNotifier
private StatusBarCallListener mStatusBarCallListener;
public StatusBarNotifier(@NonNull Context context, @NonNull ContactInfoCache contactInfoCache) {
- Objects.requireNonNull(context);
- mContext = context;
+ mContext = Assert.isNotNull(context);
mContactsPreferences = ContactsPreferencesFactory.newContactsPreferences(mContext);
mContactInfoCache = contactInfoCache;
- mNotificationManager = context.getSystemService(NotificationManager.class);
mDialerRingtoneManager =
new DialerRingtoneManager(
new InCallTonePlayer(new ToneGeneratorFactory(), new PausableExecutorImpl()),
@@ -142,14 +140,12 @@ public class StatusBarNotifier
* Should only be called from a irrecoverable state where it is necessary to dismiss all
* notifications.
*/
- static void clearAllCallNotifications(Context backupContext) {
- LogUtil.i(
+ static void clearAllCallNotifications(Context context) {
+ LogUtil.e(
"StatusBarNotifier.clearAllCallNotifications",
"something terrible happened, clear all InCall notifications");
- NotificationManager notificationManager =
- backupContext.getSystemService(NotificationManager.class);
- notificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
+ DialerNotificationManager.cancel(context, NOTIFICATION_TAG, NOTIFICATION_ID);
}
private static int getWorkStringFromPersonalString(int resId) {
@@ -218,7 +214,7 @@ public class StatusBarNotifier
}
if (mCurrentNotification != NOTIFICATION_NONE) {
LogUtil.i("StatusBarNotifier.cancelNotification", "cancel");
- mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
+ DialerNotificationManager.cancel(mContext, NOTIFICATION_TAG, NOTIFICATION_ID);
}
mCurrentNotification = NOTIFICATION_NONE;
}
@@ -379,7 +375,7 @@ public class StatusBarNotifier
"Canceling old notification so this one can be noisy");
// Moving from a non-interuptive notification (or none) to a noisy one. Cancel the old
// notification (if there is one) so the fullScreenIntent or HUN will show
- mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
+ DialerNotificationManager.cancel(mContext, NOTIFICATION_TAG, NOTIFICATION_ID);
}
break;
case NOTIFICATION_INCOMING_CALL_QUIET:
@@ -438,7 +434,7 @@ public class StatusBarNotifier
"displaying notification for " + notificationType);
try {
- mNotificationManager.notify(NOTIFICATION_TAG, NOTIFICATION_ID, notification);
+ DialerNotificationManager.notify(mContext, NOTIFICATION_TAG, NOTIFICATION_ID, notification);
} catch (RuntimeException e) {
// TODO(b/34744003): Move the memory stats into silent feedback PSD.
ActivityManager activityManager = mContext.getSystemService(ActivityManager.class);
diff --git a/java/com/android/incallui/call/ExternalCallList.java b/java/com/android/incallui/call/ExternalCallList.java
index 52a7a304b..f104dfe9f 100644
--- a/java/com/android/incallui/call/ExternalCallList.java
+++ b/java/com/android/incallui/call/ExternalCallList.java
@@ -22,6 +22,7 @@ import android.support.annotation.NonNull;
import android.telecom.Call;
import android.util.ArraySet;
import com.android.contacts.common.compat.CallCompat;
+import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import java.util.Collections;
import java.util.Set;
@@ -48,9 +49,8 @@ public class ExternalCallList {
/** Begins tracking an external call and notifies listeners of the new call. */
public void onCallAdded(Call telecomCall) {
- if (!telecomCall.getDetails().hasProperty(CallCompat.Details.PROPERTY_IS_EXTERNAL_CALL)) {
- throw new IllegalArgumentException();
- }
+ Assert.checkArgument(
+ telecomCall.getDetails().hasProperty(CallCompat.Details.PROPERTY_IS_EXTERNAL_CALL));
mExternalCalls.add(telecomCall);
telecomCall.registerCallback(mTelecomCallCallback, new Handler(Looper.getMainLooper()));
notifyExternalCallAdded(telecomCall);
diff --git a/java/com/android/incallui/spam/SpamCallListListener.java b/java/com/android/incallui/spam/SpamCallListListener.java
index 7ca3fbba6..997d4d6bc 100644
--- a/java/com/android/incallui/spam/SpamCallListListener.java
+++ b/java/com/android/incallui/spam/SpamCallListListener.java
@@ -19,7 +19,6 @@ package com.android.incallui.spam;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.Notification.Builder;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -46,6 +45,7 @@ import com.android.dialer.location.GeoUtil;
import com.android.dialer.logging.ContactLookupResult;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
+import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.notification.NotificationChannelId;
import com.android.dialer.spam.Spam;
import com.android.dialer.telecom.TelecomUtil;
@@ -62,7 +62,16 @@ import java.util.Random;
* etc).
*/
public class SpamCallListListener implements CallList.Listener {
+ /** Common ID for all spam notifications. */
static final int NOTIFICATION_ID = 1;
+ /** Prefix used to generate a unique tag for each spam notification. */
+ static final String NOTIFICATION_TAG_PREFIX = "SpamCall_";
+ /**
+ * Key used to associate all spam notifications into a single group. Note, unlike other group
+ * notifications in Dialer, spam notifications don't have a top level group summary notification.
+ * The group is still useful for things like rate limiting on a per group basis.
+ */
+ private static final String GROUP_KEY = "SpamCallGroup";
private final Context context;
private final Random random;
@@ -76,8 +85,7 @@ public class SpamCallListListener implements CallList.Listener {
Context context, Random rand, @NonNull DialerExecutorFactory factory) {
this.context = context;
this.random = rand;
- Assert.isNotNull(factory);
- this.dialerExecutorFactory = factory;
+ this.dialerExecutorFactory = Assert.isNotNull(factory);
}
/** Checks if the number is in the call history. */
@@ -254,7 +262,8 @@ public class SpamCallListListener implements CallList.Listener {
.setCategory(Notification.CATEGORY_STATUS)
.setPriority(Notification.PRIORITY_DEFAULT)
.setColor(context.getColor(R.color.dialer_theme_color))
- .setSmallIcon(R.drawable.ic_call_end_white_24dp);
+ .setSmallIcon(R.drawable.ic_call_end_white_24dp)
+ .setGroup(GROUP_KEY);
if (BuildCompat.isAtLeastO()) {
builder.setChannelId(NotificationChannelId.DEFAULT);
}
@@ -294,8 +303,8 @@ public class SpamCallListListener implements CallList.Listener {
.build())
.setContentTitle(
context.getString(R.string.non_spam_notification_title, getDisplayNumber(call)));
- ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE))
- .notify(call.getNumber(), NOTIFICATION_ID, notificationBuilder.build());
+ DialerNotificationManager.notify(
+ context, getNotificationTagForCall(call), NOTIFICATION_ID, notificationBuilder.build());
}
private boolean shouldThrottleSpamNotification() {
@@ -405,8 +414,8 @@ public class SpamCallListListener implements CallList.Listener {
.build())
.setContentTitle(
context.getString(R.string.spam_notification_title, getDisplayNumber(call)));
- ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE))
- .notify(call.getNumber(), NOTIFICATION_ID, notificationBuilder.build());
+ DialerNotificationManager.notify(
+ context, getNotificationTagForCall(call), NOTIFICATION_ID, notificationBuilder.build());
}
/**
@@ -434,7 +443,8 @@ public class SpamCallListListener implements CallList.Listener {
/** Creates a pending intent for {@link SpamNotificationService}. */
private PendingIntent createServicePendingIntent(DialerCall call, String action) {
Intent intent =
- SpamNotificationService.createServiceIntent(context, call, action, NOTIFICATION_ID);
+ SpamNotificationService.createServiceIntent(
+ context, call, action, getNotificationTagForCall(call), NOTIFICATION_ID);
return PendingIntent.getService(
context, (int) System.currentTimeMillis(), intent, PendingIntent.FLAG_ONE_SHOT);
}
@@ -442,8 +452,13 @@ public class SpamCallListListener implements CallList.Listener {
/** Creates a pending intent for {@link SpamNotificationActivity}. */
private PendingIntent createActivityPendingIntent(DialerCall call, String action) {
Intent intent =
- SpamNotificationActivity.createActivityIntent(context, call, action, NOTIFICATION_ID);
+ SpamNotificationActivity.createActivityIntent(
+ context, call, action, getNotificationTagForCall(call), NOTIFICATION_ID);
return PendingIntent.getActivity(
context, (int) System.currentTimeMillis(), intent, PendingIntent.FLAG_ONE_SHOT);
}
+
+ static String getNotificationTagForCall(@NonNull DialerCall call) {
+ return NOTIFICATION_TAG_PREFIX + call.getNumber();
+ }
}
diff --git a/java/com/android/incallui/spam/SpamNotificationActivity.java b/java/com/android/incallui/spam/SpamNotificationActivity.java
index ece0e4931..160db2622 100644
--- a/java/com/android/incallui/spam/SpamNotificationActivity.java
+++ b/java/com/android/incallui/spam/SpamNotificationActivity.java
@@ -18,7 +18,6 @@ package com.android.incallui.spam;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -38,6 +37,7 @@ import com.android.dialer.logging.ContactLookupResult;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.dialer.logging.ReportingLocation;
+import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.spam.Spam;
import com.android.incallui.R;
import com.android.incallui.call.DialerCall;
@@ -57,6 +57,7 @@ public class SpamNotificationActivity extends FragmentActivity {
"com.android.incallui.spam.ACTION_MARK_NUMBER_AS_NOT_SPAM";
private static final String TAG = "SpamNotifications";
+ private static final String EXTRA_NOTIFICATION_TAG = "notification_tag";
private static final String EXTRA_NOTIFICATION_ID = "notification_id";
private static final String EXTRA_CALL_INFO = "call_info";
@@ -82,12 +83,13 @@ public class SpamNotificationActivity extends FragmentActivity {
* @return Intent intent that starts this activity.
*/
public static Intent createActivityIntent(
- Context context, DialerCall call, String action, int notificationId) {
+ Context context, DialerCall call, String action, String notificationTag, int notificationId) {
Intent intent = new Intent(context, SpamNotificationActivity.class);
intent.setAction(action);
// This ensures only one activity of this kind exists at a time.
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(EXTRA_NOTIFICATION_TAG, notificationTag);
intent.putExtra(EXTRA_NOTIFICATION_ID, notificationId);
intent.putExtra(EXTRA_CALL_INFO, newCallInfoBundle(call));
return intent;
@@ -294,10 +296,9 @@ public class SpamNotificationActivity extends FragmentActivity {
/** Cancels the notification associated with the number. */
private void cancelNotification() {
+ String notificationTag = getIntent().getStringExtra(EXTRA_NOTIFICATION_TAG);
int notificationId = getIntent().getIntExtra(EXTRA_NOTIFICATION_ID, 1);
- String number = getCallInfo().getString(CALL_INFO_KEY_PHONE_NUMBER);
- ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE))
- .cancel(number, notificationId);
+ DialerNotificationManager.cancel(this, notificationTag, notificationId);
}
private String getCountryIso() {
diff --git a/java/com/android/incallui/spam/SpamNotificationService.java b/java/com/android/incallui/spam/SpamNotificationService.java
index 7888fc84e..c92d61609 100644
--- a/java/com/android/incallui/spam/SpamNotificationService.java
+++ b/java/com/android/incallui/spam/SpamNotificationService.java
@@ -16,7 +16,6 @@
package com.android.incallui.spam;
-import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
@@ -30,6 +29,7 @@ import com.android.dialer.logging.ContactLookupResult;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.dialer.logging.ReportingLocation;
+import com.android.dialer.notification.DialerNotificationManager;
import com.android.dialer.spam.Spam;
import com.android.incallui.call.DialerCall;
@@ -47,17 +47,19 @@ public class SpamNotificationService extends Service {
private static final String EXTRA_PHONE_NUMBER = "service_phone_number";
private static final String EXTRA_CALL_ID = "service_call_id";
private static final String EXTRA_CALL_START_TIME_MILLIS = "service_call_start_time_millis";
+ private static final String EXTRA_NOTIFICATION_TAG = "service_notification_tag";
private static final String EXTRA_NOTIFICATION_ID = "service_notification_id";
private static final String EXTRA_CONTACT_LOOKUP_RESULT_TYPE =
"service_contact_lookup_result_type";
/** Creates an intent to start this service. */
public static Intent createServiceIntent(
- Context context, DialerCall call, String action, int notificationId) {
+ Context context, DialerCall call, String action, String notificationTag, int notificationId) {
Intent intent = new Intent(context, SpamNotificationService.class);
intent.setAction(action);
intent.putExtra(EXTRA_PHONE_NUMBER, call.getNumber());
intent.putExtra(EXTRA_CALL_ID, call.getUniqueCallId());
intent.putExtra(EXTRA_CALL_START_TIME_MILLIS, call.getTimeAddedMs());
+ intent.putExtra(EXTRA_NOTIFICATION_TAG, notificationTag);
intent.putExtra(EXTRA_NOTIFICATION_ID, notificationId);
intent.putExtra(EXTRA_CONTACT_LOOKUP_RESULT_TYPE, call.getLogState().contactLookupResult);
return intent;
@@ -80,13 +82,13 @@ public class SpamNotificationService extends Service {
return START_NOT_STICKY;
}
String number = intent.getStringExtra(EXTRA_PHONE_NUMBER);
+ String notificationTag = intent.getStringExtra(EXTRA_NOTIFICATION_TAG);
int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, 1);
String countryIso = GeoUtil.getCurrentCountryIso(this);
ContactLookupResult.Type contactLookupResultType =
ContactLookupResult.Type.forNumber(intent.getIntExtra(EXTRA_CONTACT_LOOKUP_RESULT_TYPE, 0));
- ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE))
- .cancel(number, notificationId);
+ DialerNotificationManager.cancel(this, notificationTag, notificationId);
switch (intent.getAction()) {
case SpamNotificationActivity.ACTION_MARK_NUMBER_AS_SPAM: