1 /* 2 * Copyright (C) 2022 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.systemui.dreams; 18 19 import android.annotation.NonNull; 20 import android.service.notification.NotificationListenerService; 21 import android.service.notification.StatusBarNotification; 22 23 import com.android.systemui.dagger.qualifiers.Background; 24 import com.android.systemui.statusbar.NotificationListener; 25 import com.android.systemui.statusbar.NotificationListener.NotificationHandler; 26 import com.android.systemui.statusbar.policy.CallbackController; 27 28 import java.util.ArrayList; 29 import java.util.Arrays; 30 import java.util.HashSet; 31 import java.util.List; 32 import java.util.Set; 33 import java.util.concurrent.Executor; 34 35 /*** 36 * {@link DreamOverlayNotificationCountProvider} provides the current notification count to 37 * registered callbacks. Ongoing notifications are not included in the count. 38 */ 39 public class DreamOverlayNotificationCountProvider 40 implements CallbackController<DreamOverlayNotificationCountProvider.Callback> { 41 private final Set<String> mNotificationKeys = new HashSet<>(); 42 private final List<Callback> mCallbacks = new ArrayList<>(); 43 44 private final NotificationHandler mNotificationHandler = new NotificationHandler() { 45 @Override 46 public void onNotificationPosted( 47 StatusBarNotification sbn, NotificationListenerService.RankingMap rankingMap) { 48 if (sbn.isOngoing()) { 49 // Don't count ongoing notifications. 50 return; 51 } 52 mNotificationKeys.add(sbn.getKey()); 53 reportNotificationCountChanged(); 54 } 55 56 @Override 57 public void onNotificationRemoved( 58 StatusBarNotification sbn, NotificationListenerService.RankingMap rankingMap) { 59 mNotificationKeys.remove(sbn.getKey()); 60 reportNotificationCountChanged(); 61 } 62 63 @Override 64 public void onNotificationRemoved( 65 StatusBarNotification sbn, 66 NotificationListenerService.RankingMap rankingMap, 67 int reason) { 68 mNotificationKeys.remove(sbn.getKey()); 69 reportNotificationCountChanged(); 70 } 71 72 @Override 73 public void onNotificationRankingUpdate(NotificationListenerService.RankingMap rankingMap) { 74 } 75 76 @Override 77 public void onNotificationsInitialized() { 78 } 79 }; 80 DreamOverlayNotificationCountProvider( NotificationListener notificationListener, @Background Executor bgExecutor)81 public DreamOverlayNotificationCountProvider( 82 NotificationListener notificationListener, 83 @Background Executor bgExecutor) { 84 notificationListener.addNotificationHandler(mNotificationHandler); 85 86 bgExecutor.execute(() -> { 87 Arrays.stream(notificationListener.getActiveNotifications()) 88 .forEach(sbn -> mNotificationKeys.add(sbn.getKey())); 89 reportNotificationCountChanged(); 90 } 91 ); 92 } 93 94 @Override addCallback(@onNull Callback callback)95 public void addCallback(@NonNull Callback callback) { 96 if (!mCallbacks.contains(callback)) { 97 mCallbacks.add(callback); 98 callback.onNotificationCountChanged(mNotificationKeys.size()); 99 } 100 } 101 102 @Override removeCallback(@onNull Callback callback)103 public void removeCallback(@NonNull Callback callback) { 104 mCallbacks.remove(callback); 105 } 106 reportNotificationCountChanged()107 private void reportNotificationCountChanged() { 108 final int notificationCount = mNotificationKeys.size(); 109 mCallbacks.forEach(callback -> callback.onNotificationCountChanged(notificationCount)); 110 } 111 112 /** 113 * A callback to be registered with {@link DreamOverlayNotificationCountProvider} to receive 114 * changes to the current notification count. 115 */ 116 public interface Callback { 117 /** 118 * Called when the notification count has changed. 119 * @param count The current notification count. 120 */ onNotificationCountChanged(int count)121 void onNotificationCountChanged(int count); 122 } 123 } 124