blob: 14009214bdc5c1bdc967742c1166e84cac50eb02 [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
Govinda Wasserman3e7ce552019-08-13 11:35:44 -040040import javax.inject.Inject;
41import javax.inject.Singleton;
42
Eliot Courtney21bc05f2017-10-19 17:03:34 +090043/**
44 * This class handles listening to notification updates and passing them along to
45 * NotificationPresenter to be displayed to the user.
46 */
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050047@SuppressLint("OverrideAbstract")
Govinda Wasserman3e7ce552019-08-13 11:35:44 -040048@Singleton
Eliot Courtney21bc05f2017-10-19 17:03:34 +090049public class NotificationListener extends NotificationListenerWithPlugins {
50 private static final String TAG = "NotificationListener";
51
Eliot Courtney6c313d32017-12-14 19:57:51 +090052 // Dependencies:
53 private final NotificationRemoteInputManager mRemoteInputManager =
54 Dependency.get(NotificationRemoteInputManager.class);
Jason Monk297c04e2018-08-23 17:16:59 -040055 private final NotificationEntryManager mEntryManager =
56 Dependency.get(NotificationEntryManager.class);
57 private final NotificationGroupManager mGroupManager =
58 Dependency.get(NotificationGroupManager.class);
Eliot Courtney6c313d32017-12-14 19:57:51 +090059
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050060 private final ArrayList<NotificationSettingsListener> mSettingsListeners = new ArrayList<>();
Eliot Courtney21bc05f2017-10-19 17:03:34 +090061 private final Context mContext;
62
Govinda Wasserman3e7ce552019-08-13 11:35:44 -040063 @Inject
Eliot Courtney6c313d32017-12-14 19:57:51 +090064 public NotificationListener(Context context) {
Eliot Courtney21bc05f2017-10-19 17:03:34 +090065 mContext = context;
66 }
67
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050068 public void addNotificationSettingsListener(NotificationSettingsListener listener) {
69 mSettingsListeners.add(listener);
70 }
71
Eliot Courtney21bc05f2017-10-19 17:03:34 +090072 @Override
73 public void onListenerConnected() {
74 if (DEBUG) Log.d(TAG, "onListenerConnected");
75 onPluginConnected();
76 final StatusBarNotification[] notifications = getActiveNotifications();
77 if (notifications == null) {
78 Log.w(TAG, "onListenerConnected unable to get active notifications.");
79 return;
80 }
81 final RankingMap currentRanking = getCurrentRanking();
Jason Monk297c04e2018-08-23 17:16:59 -040082 Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
Eliot Courtney21bc05f2017-10-19 17:03:34 +090083 for (StatusBarNotification sbn : notifications) {
Eliot Courtney4a96b362017-12-14 19:38:52 +090084 mEntryManager.addNotification(sbn, currentRanking);
Eliot Courtney21bc05f2017-10-19 17:03:34 +090085 }
86 });
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050087 NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
Julia Reynolds6d2b7e62019-03-22 15:15:38 -040088 onSilentStatusBarIconsVisibilityChanged(noMan.shouldHideSilentStatusBarIcons());
Eliot Courtney21bc05f2017-10-19 17:03:34 +090089 }
90
91 @Override
92 public void onNotificationPosted(final StatusBarNotification sbn,
93 final RankingMap rankingMap) {
94 if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
95 if (sbn != null && !onPluginNotificationPosted(sbn, rankingMap)) {
Jason Monk297c04e2018-08-23 17:16:59 -040096 Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
Eliot Courtney21bc05f2017-10-19 17:03:34 +090097 processForRemoteInput(sbn.getNotification(), mContext);
98 String key = sbn.getKey();
Eliot Courtneya6d8cf22017-10-20 13:26:58 +090099 boolean isUpdate =
Eliot Courtney4a96b362017-12-14 19:38:52 +0900100 mEntryManager.getNotificationData().get(key) != null;
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900101 // In case we don't allow child notifications, we ignore children of
102 // notifications that have a summary, since` we're not going to show them
103 // anyway. This is true also when the summary is canceled,
104 // because children are automatically canceled by NoMan in that case.
105 if (!ENABLE_CHILD_NOTIFICATIONS
Jason Monk297c04e2018-08-23 17:16:59 -0400106 && mGroupManager.isChildInGroupWithSummary(sbn)) {
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900107 if (DEBUG) {
108 Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);
109 }
110
111 // Remove existing notification to avoid stale data.
112 if (isUpdate) {
Mady Mellor1a4e86f2019-05-03 16:07:23 -0700113 mEntryManager.removeNotification(key, rankingMap, UNDEFINED_DISMISS_REASON);
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900114 } else {
Eliot Courtney4a96b362017-12-14 19:38:52 +0900115 mEntryManager.getNotificationData()
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900116 .updateRanking(rankingMap);
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900117 }
118 return;
119 }
120 if (isUpdate) {
Eliot Courtney4a96b362017-12-14 19:38:52 +0900121 mEntryManager.updateNotification(sbn, rankingMap);
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900122 } else {
Eliot Courtney4a96b362017-12-14 19:38:52 +0900123 mEntryManager.addNotification(sbn, rankingMap);
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900124 }
125 });
126 }
127 }
128
129 @Override
Mady Mellorc2ff0112019-03-28 14:18:06 -0700130 public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
131 int reason) {
132 if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn + " reason: " + reason);
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900133 if (sbn != null && !onPluginNotificationRemoved(sbn, rankingMap)) {
134 final String key = sbn.getKey();
Jason Monk297c04e2018-08-23 17:16:59 -0400135 Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
Mady Mellorc2ff0112019-03-28 14:18:06 -0700136 mEntryManager.removeNotification(key, rankingMap, reason);
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900137 });
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900138 }
139 }
140
141 @Override
Mady Mellorc2ff0112019-03-28 14:18:06 -0700142 public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
Mady Mellor1a4e86f2019-05-03 16:07:23 -0700143 onNotificationRemoved(sbn, rankingMap, UNDEFINED_DISMISS_REASON);
Mady Mellorc2ff0112019-03-28 14:18:06 -0700144 }
145
146 @Override
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900147 public void onNotificationRankingUpdate(final RankingMap rankingMap) {
148 if (DEBUG) Log.d(TAG, "onRankingUpdate");
149 if (rankingMap != null) {
150 RankingMap r = onPluginRankingUpdate(rankingMap);
Jason Monk297c04e2018-08-23 17:16:59 -0400151 Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
Eliot Courtney4a96b362017-12-14 19:38:52 +0900152 mEntryManager.updateNotificationRanking(r);
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900153 });
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900154 }
155 }
156
Julia Reynolds12ad7ca2019-01-28 09:29:16 -0500157 @Override
Julia Reynolds6d2b7e62019-03-22 15:15:38 -0400158 public void onSilentStatusBarIconsVisibilityChanged(boolean hideSilentStatusIcons) {
Julia Reynolds12ad7ca2019-01-28 09:29:16 -0500159 for (NotificationSettingsListener listener : mSettingsListeners) {
160 listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons);
161 }
162 }
163
Julia Reynolds7c2367f2019-01-30 14:50:14 -0500164 public void registerAsSystemService() {
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900165 try {
166 registerAsSystemService(mContext,
167 new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
168 UserHandle.USER_ALL);
169 } catch (RemoteException e) {
170 Log.e(TAG, "Unable to register notification listener", e);
171 }
172 }
Julia Reynolds12ad7ca2019-01-28 09:29:16 -0500173
174 public interface NotificationSettingsListener {
175
176 default void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) { }
Julia Reynolds12ad7ca2019-01-28 09:29:16 -0500177 }
Eliot Courtney21bc05f2017-10-19 17:03:34 +0900178}