1010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham/*
2010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham * Copyright (C) 2017 The Android Open Source Project
3010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham *
4010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham * Licensed under the Apache License, Version 2.0 (the "License");
5010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham * you may not use this file except in compliance with the License.
6010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham * You may obtain a copy of the License at
7010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham *
8010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham *      http://www.apache.org/licenses/LICENSE-2.0
9010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham *
10010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham * Unless required by applicable law or agreed to in writing, software
11010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham * distributed under the License is distributed on an "AS IS" BASIS,
12010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham * See the License for the specific language governing permissions and
14010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham * limitations under the License.
15010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham */
16010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
179438ed414fdabadb4cd09da184867b1c44b91095Tony Wickhampackage com.android.launcher3.notification;
18010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
19541e13c2652badee856aebc448e578a75229661eRajeev Kumarimport android.annotation.TargetApi;
20010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport android.app.Notification;
2174884ce164b228afe93f4cae5f0351ec969ed55cTony Wickhamimport android.app.NotificationChannel;
22541e13c2652badee856aebc448e578a75229661eRajeev Kumarimport android.os.Build;
23010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport android.os.Handler;
24010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport android.os.Looper;
25010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport android.os.Message;
26010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport android.service.notification.NotificationListenerService;
27010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport android.service.notification.StatusBarNotification;
28010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport android.support.annotation.Nullable;
2974884ce164b228afe93f4cae5f0351ec969ed55cTony Wickhamimport android.text.TextUtils;
30541e13c2652badee856aebc448e578a75229661eRajeev Kumarimport android.util.ArraySet;
31f423f0a6d440836e968f112e295d85eae8f146caAdam Cohenimport android.util.Log;
32de57cafbb2f30d2255ffc334323b8eb8083dd748Sunny Goyalimport android.util.Pair;
33d48710c2835d891b216914ef1fdd3740e6cfc101Tony
34010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport com.android.launcher3.LauncherModel;
35010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport com.android.launcher3.util.PackageUserKey;
36d48710c2835d891b216914ef1fdd3740e6cfc101Tonyimport com.android.launcher3.util.SettingsObserver;
37d48710c2835d891b216914ef1fdd3740e6cfc101Tony
38010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport java.util.ArrayList;
39010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport java.util.Arrays;
40010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport java.util.Collections;
41010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport java.util.List;
42010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhamimport java.util.Set;
43010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
44d48710c2835d891b216914ef1fdd3740e6cfc101Tonyimport static com.android.launcher3.SettingsActivity.NOTIFICATION_BADGING;
45d48710c2835d891b216914ef1fdd3740e6cfc101Tony
46010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham/**
47010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham * A {@link NotificationListenerService} that sends updates to its
48010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham * {@link NotificationsChangedListener} when notifications are posted or canceled,
49010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham * as well and when this service first connects. An instance of NotificationListener,
50be3c7d0c56fe35e8822c4bb5ee22ad44ed504850Tony * and its methods for getting notifications, can be obtained via {@link #getInstanceIfConnected()}.
51010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham */
52541e13c2652badee856aebc448e578a75229661eRajeev Kumar@TargetApi(Build.VERSION_CODES.O)
53010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickhampublic class NotificationListener extends NotificationListenerService {
54010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
55f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen    public static final String TAG = "NotificationListener";
56f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen
57010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    private static final int MSG_NOTIFICATION_POSTED = 1;
58010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    private static final int MSG_NOTIFICATION_REMOVED = 2;
59010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    private static final int MSG_NOTIFICATION_FULL_REFRESH = 3;
60010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
61010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    private static NotificationListener sNotificationListenerInstance = null;
62010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    private static NotificationsChangedListener sNotificationsChangedListener;
63be3c7d0c56fe35e8822c4bb5ee22ad44ed504850Tony    private static boolean sIsConnected;
64d48710c2835d891b216914ef1fdd3740e6cfc101Tony    private static boolean sIsCreated;
65010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
66010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    private final Handler mWorkerHandler;
67010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    private final Handler mUiHandler;
68541e13c2652badee856aebc448e578a75229661eRajeev Kumar    private final Ranking mTempRanking = new Ranking();
69d670b995d28615113687e432f6c098aa4cf7b303Tony Wickham
70d48710c2835d891b216914ef1fdd3740e6cfc101Tony    private SettingsObserver mNotificationBadgingObserver;
71d48710c2835d891b216914ef1fdd3740e6cfc101Tony
72541e13c2652badee856aebc448e578a75229661eRajeev Kumar    private final Handler.Callback mWorkerCallback = new Handler.Callback() {
73010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        @Override
74010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        public boolean handleMessage(Message message) {
75010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham            switch (message.what) {
76010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                case MSG_NOTIFICATION_POSTED:
77010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    mUiHandler.obtainMessage(message.what, message.obj).sendToTarget();
78010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    break;
79010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                case MSG_NOTIFICATION_REMOVED:
80010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    mUiHandler.obtainMessage(message.what, message.obj).sendToTarget();
81010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    break;
82010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                case MSG_NOTIFICATION_FULL_REFRESH:
83f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen                    List<StatusBarNotification> activeNotifications;
84f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen                    if (sIsConnected) {
85f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen                        try {
86d48710c2835d891b216914ef1fdd3740e6cfc101Tony                            activeNotifications = filterNotifications(getActiveNotifications());
87f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen                        } catch (SecurityException ex) {
88f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen                            Log.e(TAG, "SecurityException: failed to fetch notifications");
89f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen                            activeNotifications = new ArrayList<StatusBarNotification>();
90f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen
91f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen                        }
92f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen                    } else {
93f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen                        activeNotifications = new ArrayList<StatusBarNotification>();
94f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen                    }
95f423f0a6d440836e968f112e295d85eae8f146caAdam Cohen
96010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    mUiHandler.obtainMessage(message.what, activeNotifications).sendToTarget();
97010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    break;
98010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham            }
99010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham            return true;
100010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        }
101010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    };
102010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
103541e13c2652badee856aebc448e578a75229661eRajeev Kumar    private final Handler.Callback mUiCallback = new Handler.Callback() {
104010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        @Override
105010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        public boolean handleMessage(Message message) {
106010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham            switch (message.what) {
107010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                case MSG_NOTIFICATION_POSTED:
108010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    if (sNotificationsChangedListener != null) {
109988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham                        NotificationPostedMsg msg = (NotificationPostedMsg) message.obj;
110988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham                        sNotificationsChangedListener.onNotificationPosted(msg.packageUserKey,
111988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham                                msg.notificationKey, msg.shouldBeFilteredOut);
112010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    }
113010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    break;
114010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                case MSG_NOTIFICATION_REMOVED:
115010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    if (sNotificationsChangedListener != null) {
1162f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham                        Pair<PackageUserKey, NotificationKeyData> pair
1172f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham                                = (Pair<PackageUserKey, NotificationKeyData>) message.obj;
118010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                        sNotificationsChangedListener.onNotificationRemoved(pair.first, pair.second);
119010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    }
120010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    break;
121010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                case MSG_NOTIFICATION_FULL_REFRESH:
122010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    if (sNotificationsChangedListener != null) {
123010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                        sNotificationsChangedListener.onNotificationFullRefresh(
124010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                                (List<StatusBarNotification>) message.obj);
125010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    }
126010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                    break;
127010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham            }
128010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham            return true;
129010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        }
130010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    };
131010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
132010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    public NotificationListener() {
133010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        super();
134010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        mWorkerHandler = new Handler(LauncherModel.getWorkerLooper(), mWorkerCallback);
135010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        mUiHandler = new Handler(Looper.getMainLooper(), mUiCallback);
136be3c7d0c56fe35e8822c4bb5ee22ad44ed504850Tony        sNotificationListenerInstance = this;
137010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
138010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
139d48710c2835d891b216914ef1fdd3740e6cfc101Tony    @Override
140d48710c2835d891b216914ef1fdd3740e6cfc101Tony    public void onCreate() {
141d48710c2835d891b216914ef1fdd3740e6cfc101Tony        super.onCreate();
142d48710c2835d891b216914ef1fdd3740e6cfc101Tony        sIsCreated = true;
143d48710c2835d891b216914ef1fdd3740e6cfc101Tony        mNotificationBadgingObserver = new SettingsObserver.Secure(getContentResolver()) {
144d48710c2835d891b216914ef1fdd3740e6cfc101Tony            @Override
145d48710c2835d891b216914ef1fdd3740e6cfc101Tony            public void onSettingChanged(boolean isNotificationBadgingEnabled) {
146d48710c2835d891b216914ef1fdd3740e6cfc101Tony                if (!isNotificationBadgingEnabled) {
147d48710c2835d891b216914ef1fdd3740e6cfc101Tony                    requestUnbind();
148d48710c2835d891b216914ef1fdd3740e6cfc101Tony                }
149d48710c2835d891b216914ef1fdd3740e6cfc101Tony            }
150d48710c2835d891b216914ef1fdd3740e6cfc101Tony        };
151d48710c2835d891b216914ef1fdd3740e6cfc101Tony        mNotificationBadgingObserver.register(NOTIFICATION_BADGING);
152d48710c2835d891b216914ef1fdd3740e6cfc101Tony    }
153d48710c2835d891b216914ef1fdd3740e6cfc101Tony
154d48710c2835d891b216914ef1fdd3740e6cfc101Tony    @Override
155d48710c2835d891b216914ef1fdd3740e6cfc101Tony    public void onDestroy() {
156d48710c2835d891b216914ef1fdd3740e6cfc101Tony        super.onDestroy();
157d48710c2835d891b216914ef1fdd3740e6cfc101Tony        sIsCreated = false;
158d48710c2835d891b216914ef1fdd3740e6cfc101Tony        mNotificationBadgingObserver.unregister();
159d48710c2835d891b216914ef1fdd3740e6cfc101Tony    }
160d48710c2835d891b216914ef1fdd3740e6cfc101Tony
161be3c7d0c56fe35e8822c4bb5ee22ad44ed504850Tony    public static @Nullable NotificationListener getInstanceIfConnected() {
162be3c7d0c56fe35e8822c4bb5ee22ad44ed504850Tony        return sIsConnected ? sNotificationListenerInstance : null;
163010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
164010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
165010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    public static void setNotificationsChangedListener(NotificationsChangedListener listener) {
166010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        sNotificationsChangedListener = listener;
167010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
168cba189344d82753ccce0cc5479771c5a78e85c56Tony Wickham        NotificationListener notificationListener = getInstanceIfConnected();
169cba189344d82753ccce0cc5479771c5a78e85c56Tony Wickham        if (notificationListener != null) {
170cba189344d82753ccce0cc5479771c5a78e85c56Tony Wickham            notificationListener.onNotificationFullRefresh();
171d48710c2835d891b216914ef1fdd3740e6cfc101Tony        } else if (!sIsCreated && sNotificationsChangedListener != null) {
172d48710c2835d891b216914ef1fdd3740e6cfc101Tony            // User turned off badging globally, so we unbound this service;
173d48710c2835d891b216914ef1fdd3740e6cfc101Tony            // tell the listener that there are no notifications to remove dots.
174d48710c2835d891b216914ef1fdd3740e6cfc101Tony            sNotificationsChangedListener.onNotificationFullRefresh(
175d48710c2835d891b216914ef1fdd3740e6cfc101Tony                    Collections.<StatusBarNotification>emptyList());
176010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        }
177010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
178010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
179010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    public static void removeNotificationsChangedListener() {
180010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        sNotificationsChangedListener = null;
181010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
182010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
183010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    @Override
184010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    public void onListenerConnected() {
185010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        super.onListenerConnected();
186be3c7d0c56fe35e8822c4bb5ee22ad44ed504850Tony        sIsConnected = true;
187010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        onNotificationFullRefresh();
188010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
189010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
190010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    private void onNotificationFullRefresh() {
191010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        mWorkerHandler.obtainMessage(MSG_NOTIFICATION_FULL_REFRESH).sendToTarget();
192010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
193010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
194010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    @Override
195010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    public void onListenerDisconnected() {
196010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        super.onListenerDisconnected();
197be3c7d0c56fe35e8822c4bb5ee22ad44ed504850Tony        sIsConnected = false;
198010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
199010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
200010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    @Override
201010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    public void onNotificationPosted(final StatusBarNotification sbn) {
202010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        super.onNotificationPosted(sbn);
203988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham        mWorkerHandler.obtainMessage(MSG_NOTIFICATION_POSTED, new NotificationPostedMsg(sbn))
204988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham                .sendToTarget();
205988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham    }
206988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham
207988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham    /**
208988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham     * An object containing data to send to MSG_NOTIFICATION_POSTED targets.
209988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham     */
210988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham    private class NotificationPostedMsg {
211541e13c2652badee856aebc448e578a75229661eRajeev Kumar        final PackageUserKey packageUserKey;
212541e13c2652badee856aebc448e578a75229661eRajeev Kumar        final NotificationKeyData notificationKey;
213541e13c2652badee856aebc448e578a75229661eRajeev Kumar        final boolean shouldBeFilteredOut;
214988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham
215988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham        NotificationPostedMsg(StatusBarNotification sbn) {
216988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham            packageUserKey = PackageUserKey.fromNotification(sbn);
2172f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham            notificationKey = NotificationKeyData.fromNotification(sbn);
218d670b995d28615113687e432f6c098aa4cf7b303Tony Wickham            shouldBeFilteredOut = shouldBeFilteredOut(sbn);
219010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        }
220010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
221010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
222010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    @Override
223010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    public void onNotificationRemoved(final StatusBarNotification sbn) {
224010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        super.onNotificationRemoved(sbn);
2252f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham        Pair<PackageUserKey, NotificationKeyData> packageUserKeyAndNotificationKey
2262f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham                = new Pair<>(PackageUserKey.fromNotification(sbn),
2272f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham                        NotificationKeyData.fromNotification(sbn));
228988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham        mWorkerHandler.obtainMessage(MSG_NOTIFICATION_REMOVED, packageUserKeyAndNotificationKey)
229988f34b7f2bb7e57d99ec19fbe9b7024da1fe52fTony Wickham                .sendToTarget();
230010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
231010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
232010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    /** This makes a potentially expensive binder call and should be run on a background thread. */
2332f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham    public List<StatusBarNotification> getNotificationsForKeys(List<NotificationKeyData> keys) {
234010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        StatusBarNotification[] notifications = NotificationListener.this
2352f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham                .getActiveNotifications(NotificationKeyData.extractKeysOnly(keys)
2362f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham                        .toArray(new String[keys.size()]));
237541e13c2652badee856aebc448e578a75229661eRajeev Kumar        return notifications == null
238d48710c2835d891b216914ef1fdd3740e6cfc101Tony                ? Collections.<StatusBarNotification>emptyList() : Arrays.asList(notifications);
239010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
240010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
241010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    /**
242010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham     * Filter out notifications that don't have an intent
243010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham     * or are headers for grouped notifications.
244010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham     *
245d670b995d28615113687e432f6c098aa4cf7b303Tony Wickham     * @see #shouldBeFilteredOut(StatusBarNotification)
246010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham     */
247010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    private List<StatusBarNotification> filterNotifications(
248010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham            StatusBarNotification[] notifications) {
249010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        if (notifications == null) return null;
250541e13c2652badee856aebc448e578a75229661eRajeev Kumar        Set<Integer> removedNotifications = new ArraySet<>();
251010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        for (int i = 0; i < notifications.length; i++) {
252d670b995d28615113687e432f6c098aa4cf7b303Tony Wickham            if (shouldBeFilteredOut(notifications[i])) {
253010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                removedNotifications.add(i);
254010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham            }
255010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        }
256010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        List<StatusBarNotification> filteredNotifications = new ArrayList<>(
257010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                notifications.length - removedNotifications.size());
258010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        for (int i = 0; i < notifications.length; i++) {
259010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham            if (!removedNotifications.contains(i)) {
260010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham                filteredNotifications.add(notifications[i]);
261010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham            }
262010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        }
263010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        return filteredNotifications;
264010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
265010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
266d670b995d28615113687e432f6c098aa4cf7b303Tony Wickham    private boolean shouldBeFilteredOut(StatusBarNotification sbn) {
2675632e183f335470cbe0f0d1018a2b5b99f9d41c6Tony Wickham        getCurrentRanking().getRanking(sbn.getKey(), mTempRanking);
2685632e183f335470cbe0f0d1018a2b5b99f9d41c6Tony Wickham        if (!mTempRanking.canShowBadge()) {
2695632e183f335470cbe0f0d1018a2b5b99f9d41c6Tony Wickham            return true;
270d670b995d28615113687e432f6c098aa4cf7b303Tony Wickham        }
271d670b995d28615113687e432f6c098aa4cf7b303Tony Wickham        Notification notification = sbn.getNotification();
27274884ce164b228afe93f4cae5f0351ec969ed55cTony Wickham        if (mTempRanking.getChannel().getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
27374884ce164b228afe93f4cae5f0351ec969ed55cTony Wickham            // Special filtering for the default, legacy "Miscellaneous" channel.
27474884ce164b228afe93f4cae5f0351ec969ed55cTony Wickham            if ((notification.flags & Notification.FLAG_ONGOING_EVENT) != 0) {
27574884ce164b228afe93f4cae5f0351ec969ed55cTony Wickham                return true;
27674884ce164b228afe93f4cae5f0351ec969ed55cTony Wickham            }
27774884ce164b228afe93f4cae5f0351ec969ed55cTony Wickham        }
278010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        boolean isGroupHeader = (notification.flags & Notification.FLAG_GROUP_SUMMARY) != 0;
27974884ce164b228afe93f4cae5f0351ec969ed55cTony Wickham        CharSequence title = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
28074884ce164b228afe93f4cae5f0351ec969ed55cTony Wickham        CharSequence text = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
28144410552339377f55a98b32dbadb4f7cf3aa8d83Tony Wickham        boolean missingTitleAndText = TextUtils.isEmpty(title) && TextUtils.isEmpty(text);
28244410552339377f55a98b32dbadb4f7cf3aa8d83Tony Wickham        return (isGroupHeader || missingTitleAndText);
283010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
284010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham
285010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    public interface NotificationsChangedListener {
2862f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham        void onNotificationPosted(PackageUserKey postedPackageUserKey,
2872f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham                NotificationKeyData notificationKey, boolean shouldBeFilteredOut);
2882f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham        void onNotificationRemoved(PackageUserKey removedPackageUserKey,
2892f5bb169154d25bc8c164f057117fb056ad2de96Tony Wickham                NotificationKeyData notificationKey);
290010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham        void onNotificationFullRefresh(List<StatusBarNotification> activeNotifications);
291010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham    }
292010d2550184179785e4467ff1ffb4f4f4e850ec2Tony Wickham}
293