1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.dialer.notification; 18 19 import android.app.Notification; 20 import android.app.NotificationManager; 21 import android.content.Context; 22 import android.service.notification.StatusBarNotification; 23 import android.support.annotation.NonNull; 24 import android.support.annotation.Nullable; 25 import android.support.v4.os.BuildCompat; 26 import android.text.TextUtils; 27 import android.util.Pair; 28 import com.android.dialer.common.Assert; 29 import com.android.dialer.common.LogUtil; 30 import java.util.HashSet; 31 import java.util.Set; 32 33 /** 34 * Wrapper around the notification manager APIs. The wrapper ensures that channels are set and that 35 * notifications are limited to 10 per group. 36 */ 37 public final class DialerNotificationManager { 38 39 private static final Set<StatusBarNotification> throttledNotificationSet = new HashSet<>(); 40 notify(@onNull Context context, int id, @NonNull Notification notification)41 public static void notify(@NonNull Context context, int id, @NonNull Notification notification) { 42 Assert.isNotNull(context); 43 Assert.isNotNull(notification); 44 throw Assert.createUnsupportedOperationFailException("all notifications must have tags"); 45 } 46 notify( @onNull Context context, @NonNull String tag, int id, @NonNull Notification notification)47 public static void notify( 48 @NonNull Context context, @NonNull String tag, int id, @NonNull Notification notification) { 49 Assert.isNotNull(context); 50 Assert.isNotNull(notification); 51 Assert.checkArgument(!TextUtils.isEmpty(tag)); 52 53 if (BuildCompat.isAtLeastO()) { 54 Assert.checkArgument(!TextUtils.isEmpty(notification.getChannelId())); 55 } 56 57 getNotificationManager(context).notify(tag, id, notification); 58 throttledNotificationSet.addAll(NotificationThrottler.throttle(context, notification)); 59 } 60 cancel(@onNull Context context, int id)61 public static void cancel(@NonNull Context context, int id) { 62 Assert.isNotNull(context); 63 throw Assert.createUnsupportedOperationFailException( 64 "notification IDs are not unique across the app, a tag must be specified"); 65 } 66 cancel(@onNull Context context, @NonNull String tag, int id)67 public static void cancel(@NonNull Context context, @NonNull String tag, int id) { 68 Assert.isNotNull(context); 69 Assert.checkArgument(!TextUtils.isEmpty(tag)); 70 71 NotificationManager notificationManager = getNotificationManager(context); 72 StatusBarNotification[] notifications = notificationManager.getActiveNotifications(); 73 74 String groupKey = findGroupKey(notifications, tag, id); 75 if (!TextUtils.isEmpty(groupKey)) { 76 Pair<StatusBarNotification, Integer> groupSummaryAndCount = 77 getGroupSummaryAndCount(notifications, groupKey); 78 if (groupSummaryAndCount.first != null && groupSummaryAndCount.second <= 1) { 79 LogUtil.i( 80 "DialerNotificationManager.cancel", 81 "last notification in group (%s) removed, also removing group summary", 82 groupKey); 83 notificationManager.cancel( 84 groupSummaryAndCount.first.getTag(), groupSummaryAndCount.first.getId()); 85 } 86 } 87 88 notificationManager.cancel(tag, id); 89 } 90 cancelAll(Context context, String prefix)91 public static void cancelAll(Context context, String prefix) { 92 NotificationManager notificationManager = getNotificationManager(context); 93 StatusBarNotification[] notifications = notificationManager.getActiveNotifications(); 94 for (StatusBarNotification notification : notifications) { 95 if (notification.getTag() != null && notification.getTag().startsWith(prefix)) { 96 notificationManager.cancel(notification.getTag(), notification.getId()); 97 } 98 } 99 } 100 getActiveNotifications(@onNull Context context)101 public static StatusBarNotification[] getActiveNotifications(@NonNull Context context) { 102 Assert.isNotNull(context); 103 return getNotificationManager(context).getActiveNotifications(); 104 } 105 106 @Nullable findGroupKey( @onNull StatusBarNotification[] notifications, @NonNull String tag, int id)107 private static String findGroupKey( 108 @NonNull StatusBarNotification[] notifications, @NonNull String tag, int id) { 109 for (StatusBarNotification notification : notifications) { 110 if (TextUtils.equals(tag, notification.getTag()) && id == notification.getId()) { 111 return notification.getNotification().getGroup(); 112 } 113 } 114 return null; 115 } 116 117 @NonNull getGroupSummaryAndCount( @onNull StatusBarNotification[] notifications, @NonNull String groupKey)118 private static Pair<StatusBarNotification, Integer> getGroupSummaryAndCount( 119 @NonNull StatusBarNotification[] notifications, @NonNull String groupKey) { 120 StatusBarNotification groupSummaryNotification = null; 121 int groupCount = 0; 122 for (StatusBarNotification notification : notifications) { 123 if (TextUtils.equals(groupKey, notification.getNotification().getGroup())) { 124 if ((notification.getNotification().flags & Notification.FLAG_GROUP_SUMMARY) != 0) { 125 groupSummaryNotification = notification; 126 } else { 127 groupCount++; 128 } 129 } 130 } 131 return new Pair<>(groupSummaryNotification, groupCount); 132 } 133 134 @NonNull getNotificationManager(@onNull Context context)135 private static NotificationManager getNotificationManager(@NonNull Context context) { 136 return context.getSystemService(NotificationManager.class); 137 } 138 getThrottledNotificationSet()139 public static Set<StatusBarNotification> getThrottledNotificationSet() { 140 return throttledNotificationSet; 141 } 142 DialerNotificationManager()143 private DialerNotificationManager() {} 144 } 145