blob: c375574f023da768a25cdf830a39c599eea1e8be [file] [log] [blame]
Eliot Courtney21bc05f2017-10-19 17:03:34 +09001/*
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
17package com.android.systemui.statusbar;
18
19import static com.android.systemui.statusbar.RemoteInputController.processForRemoteInput;
Mady Mellor1a4e86f2019-05-03 16:07:23 -070020import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
Eliot Courtney21bc05f2017-10-19 17:03:34 +090021import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
22import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_CHILD_NOTIFICATIONS;
23
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050024import android.annotation.SuppressLint;
25import android.app.NotificationManager;
Eliot Courtney21bc05f2017-10-19 17:03:34 +090026import android.content.ComponentName;
27import android.content.Context;
28import android.os.RemoteException;
29import android.os.UserHandle;
30import android.service.notification.StatusBarNotification;
31import android.util.Log;
32
Eliot Courtney6c313d32017-12-14 19:57:51 +090033import com.android.systemui.Dependency;
Rohan Shah20790b82018-07-02 17:21:04 -070034import com.android.systemui.statusbar.notification.NotificationEntryManager;
Jason Monk297c04e2018-08-23 17:16:59 -040035import com.android.systemui.statusbar.phone.NotificationGroupManager;
Eliot Courtney21bc05f2017-10-19 17:03:34 +090036import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins;
37
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050038import java.util.ArrayList;
39
Eliot Courtney21bc05f2017-10-19 17:03:34 +090040/**
41 * This class handles listening to notification updates and passing them along to
42 * NotificationPresenter to be displayed to the user.
43 */
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050044@SuppressLint("OverrideAbstract")
Eliot Courtney21bc05f2017-10-19 17:03:34 +090045public class NotificationListener extends NotificationListenerWithPlugins {
46 private static final String TAG = "NotificationListener";
47
Eliot Courtney6c313d32017-12-14 19:57:51 +090048 // Dependencies:
49 private final NotificationRemoteInputManager mRemoteInputManager =
50 Dependency.get(NotificationRemoteInputManager.class);
Jason Monk297c04e2018-08-23 17:16:59 -040051 private final NotificationEntryManager mEntryManager =
52 Dependency.get(NotificationEntryManager.class);
53 private final NotificationGroupManager mGroupManager =
54 Dependency.get(NotificationGroupManager.class);
Eliot Courtney6c313d32017-12-14 19:57:51 +090055
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050056 private final ArrayList<NotificationSettingsListener> mSettingsListeners = new ArrayList<>();
Eliot Courtney21bc05f2017-10-19 17:03:34 +090057 private final Context mContext;
58
Eliot Courtney6c313d32017-12-14 19:57:51 +090059 public NotificationListener(Context context) {
Eliot Courtney21bc05f2017-10-19 17:03:34 +090060 mContext = context;
61 }
62
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050063 public void addNotificationSettingsListener(NotificationSettingsListener listener) {
64 mSettingsListeners.add(listener);
65 }
66
Eliot Courtney21bc05f2017-10-19 17:03:34 +090067 @Override
68 public void onListenerConnected() {
69 if (DEBUG) Log.d(TAG, "onListenerConnected");
70 onPluginConnected();
71 final StatusBarNotification[] notifications = getActiveNotifications();
72 if (notifications == null) {
73 Log.w(TAG, "onListenerConnected unable to get active notifications.");
74 return;
75 }
76 final RankingMap currentRanking = getCurrentRanking();
Jason Monk297c04e2018-08-23 17:16:59 -040077 Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
Eliot Courtney21bc05f2017-10-19 17:03:34 +090078 for (StatusBarNotification sbn : notifications) {
Eliot Courtney4a96b362017-12-14 19:38:52 +090079 mEntryManager.addNotification(sbn, currentRanking);
Eliot Courtney21bc05f2017-10-19 17:03:34 +090080 }
81 });
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050082 NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
Julia Reynolds6d2b7e62019-03-22 15:15:38 -040083 onSilentStatusBarIconsVisibilityChanged(noMan.shouldHideSilentStatusBarIcons());
Eliot Courtney21bc05f2017-10-19 17:03:34 +090084 }
85
86 @Override
87 public void onNotificationPosted(final StatusBarNotification sbn,
88 final RankingMap rankingMap) {
89 if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
90 if (sbn != null && !onPluginNotificationPosted(sbn, rankingMap)) {
Jason Monk297c04e2018-08-23 17:16:59 -040091 Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
Eliot Courtney21bc05f2017-10-19 17:03:34 +090092 processForRemoteInput(sbn.getNotification(), mContext);
93 String key = sbn.getKey();
Eliot Courtneya6d8cf22017-10-20 13:26:58 +090094 boolean isUpdate =
Eliot Courtney4a96b362017-12-14 19:38:52 +090095 mEntryManager.getNotificationData().get(key) != null;
Eliot Courtney21bc05f2017-10-19 17:03:34 +090096 // In case we don't allow child notifications, we ignore children of
97 // notifications that have a summary, since` we're not going to show them
98 // anyway. This is true also when the summary is canceled,
99 // because children are automatically canceled by NoMan in that case.
100 if (!ENABLE_CHILD_NOTIFICATIONS
Jason Monk297c04e2018-08-23 17:16:59 -0400101 && mGroupManager.isChildInGroupWithSummary(sbn)) {
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900102 if (DEBUG) {
103 Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);
104 }
105
106 // Remove existing notification to avoid stale data.
107 if (isUpdate) {
Mady Mellor1a4e86f2019-05-03 16:07:23 -0700108 mEntryManager.removeNotification(key, rankingMap, UNDEFINED_DISMISS_REASON);
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900109 } else {
Eliot Courtney4a96b362017-12-14 19:38:52 +0900110 mEntryManager.getNotificationData()
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900111 .updateRanking(rankingMap);
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900112 }
113 return;
114 }
115 if (isUpdate) {
Eliot Courtney4a96b362017-12-14 19:38:52 +0900116 mEntryManager.updateNotification(sbn, rankingMap);
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900117 } else {
Eliot Courtney4a96b362017-12-14 19:38:52 +0900118 mEntryManager.addNotification(sbn, rankingMap);
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900119 }
120 });
121 }
122 }
123
124 @Override
Mady Mellorc2ff0112019-03-28 14:18:06 -0700125 public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
126 int reason) {
127 if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn + " reason: " + reason);
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900128 if (sbn != null && !onPluginNotificationRemoved(sbn, rankingMap)) {
129 final String key = sbn.getKey();
Jason Monk297c04e2018-08-23 17:16:59 -0400130 Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
Mady Mellorc2ff0112019-03-28 14:18:06 -0700131 mEntryManager.removeNotification(key, rankingMap, reason);
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900132 });
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900133 }
134 }
135
136 @Override
Mady Mellorc2ff0112019-03-28 14:18:06 -0700137 public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
Mady Mellor1a4e86f2019-05-03 16:07:23 -0700138 onNotificationRemoved(sbn, rankingMap, UNDEFINED_DISMISS_REASON);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700139 }
140
141 @Override
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900142 public void onNotificationRankingUpdate(final RankingMap rankingMap) {
143 if (DEBUG) Log.d(TAG, "onRankingUpdate");
144 if (rankingMap != null) {
145 RankingMap r = onPluginRankingUpdate(rankingMap);
Jason Monk297c04e2018-08-23 17:16:59 -0400146 Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
Eliot Courtney4a96b362017-12-14 19:38:52 +0900147 mEntryManager.updateNotificationRanking(r);
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900148 });
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900149 }
150 }
151
Julia Reynolds12ad7ca2019-01-28 09:29:16 -0500152 @Override
Julia Reynolds6d2b7e62019-03-22 15:15:38 -0400153 public void onSilentStatusBarIconsVisibilityChanged(boolean hideSilentStatusIcons) {
Julia Reynolds12ad7ca2019-01-28 09:29:16 -0500154 for (NotificationSettingsListener listener : mSettingsListeners) {
155 listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons);
156 }
157 }
158
Julia Reynolds7c2367f2019-01-30 14:50:14 -0500159 public void registerAsSystemService() {
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900160 try {
161 registerAsSystemService(mContext,
162 new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
163 UserHandle.USER_ALL);
164 } catch (RemoteException e) {
165 Log.e(TAG, "Unable to register notification listener", e);
166 }
167 }
Julia Reynolds12ad7ca2019-01-28 09:29:16 -0500168
169 public interface NotificationSettingsListener {
170
171 default void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) { }
Julia Reynolds12ad7ca2019-01-28 09:29:16 -0500172 }
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900173}