1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.statusbar.phone; 16 17 import android.app.NotificationChannel; 18 import android.content.ComponentName; 19 import android.content.Context; 20 import android.os.RemoteException; 21 import android.os.UserHandle; 22 import android.service.notification.NotificationListenerService; 23 import android.service.notification.StatusBarNotification; 24 25 import com.android.systemui.Dependency; 26 import com.android.systemui.plugins.NotificationListenerController; 27 import com.android.systemui.plugins.NotificationListenerController.NotificationProvider; 28 import com.android.systemui.plugins.PluginListener; 29 import com.android.systemui.shared.plugins.PluginManager; 30 31 import java.util.ArrayList; 32 33 /** 34 * A version of NotificationListenerService that passes all info to 35 * any plugins connected. Also allows those plugins the chance to cancel 36 * any incoming callbacks or to trigger new ones. 37 */ 38 public class NotificationListenerWithPlugins extends NotificationListenerService implements 39 PluginListener<NotificationListenerController> { 40 41 private ArrayList<NotificationListenerController> mPlugins = new ArrayList<>(); 42 private boolean mConnected; 43 44 @Override registerAsSystemService(Context context, ComponentName componentName, int currentUser)45 public void registerAsSystemService(Context context, ComponentName componentName, 46 int currentUser) throws RemoteException { 47 super.registerAsSystemService(context, componentName, currentUser); 48 Dependency.get(PluginManager.class).addPluginListener(this, 49 NotificationListenerController.class); 50 } 51 52 @Override unregisterAsSystemService()53 public void unregisterAsSystemService() throws RemoteException { 54 super.unregisterAsSystemService(); 55 Dependency.get(PluginManager.class).removePluginListener(this); 56 } 57 58 @Override getActiveNotifications()59 public StatusBarNotification[] getActiveNotifications() { 60 StatusBarNotification[] activeNotifications = super.getActiveNotifications(); 61 for (NotificationListenerController plugin : mPlugins) { 62 activeNotifications = plugin.getActiveNotifications(activeNotifications); 63 } 64 return activeNotifications; 65 } 66 67 @Override getCurrentRanking()68 public RankingMap getCurrentRanking() { 69 RankingMap currentRanking = super.getCurrentRanking(); 70 for (NotificationListenerController plugin : mPlugins) { 71 currentRanking = plugin.getCurrentRanking(currentRanking); 72 } 73 return currentRanking; 74 } 75 onPluginConnected()76 public void onPluginConnected() { 77 mConnected = true; 78 mPlugins.forEach(p -> p.onListenerConnected(getProvider())); 79 } 80 81 /** 82 * Called when listener receives a onNotificationPosted. 83 * Returns true if there's a plugin determining to skip the default callbacks. 84 */ onPluginNotificationPosted(StatusBarNotification sbn, final RankingMap rankingMap)85 public boolean onPluginNotificationPosted(StatusBarNotification sbn, 86 final RankingMap rankingMap) { 87 for (NotificationListenerController plugin : mPlugins) { 88 if (plugin.onNotificationPosted(sbn, rankingMap)) { 89 return true; 90 } 91 } 92 return false; 93 } 94 95 /** 96 * Called when listener receives a onNotificationRemoved. 97 * Returns true if there's a plugin determining to skip the default callbacks. 98 */ onPluginNotificationRemoved(StatusBarNotification sbn, final RankingMap rankingMap)99 public boolean onPluginNotificationRemoved(StatusBarNotification sbn, 100 final RankingMap rankingMap) { 101 for (NotificationListenerController plugin : mPlugins) { 102 if (plugin.onNotificationRemoved(sbn, rankingMap)) { 103 return true; 104 } 105 } 106 return false; 107 } 108 109 /** 110 * Called when listener receives a onNotificationChannelModified. 111 * Returns true if there's a plugin determining to skip the default callbacks. 112 */ onPluginNotificationChannelModified( String pkgName, UserHandle user, NotificationChannel channel, int modificationType)113 public boolean onPluginNotificationChannelModified( 114 String pkgName, UserHandle user, NotificationChannel channel, int modificationType) { 115 for (NotificationListenerController plugin : mPlugins) { 116 if (plugin.onNotificationChannelModified(pkgName, user, channel, modificationType)) { 117 return true; 118 } 119 } 120 return false; 121 } 122 onPluginRankingUpdate(RankingMap rankingMap)123 public RankingMap onPluginRankingUpdate(RankingMap rankingMap) { 124 return getCurrentRanking(); 125 } 126 127 @Override onPluginConnected(NotificationListenerController plugin, Context pluginContext)128 public void onPluginConnected(NotificationListenerController plugin, Context pluginContext) { 129 mPlugins.add(plugin); 130 if (mConnected) { 131 plugin.onListenerConnected(getProvider()); 132 } 133 } 134 135 @Override onPluginDisconnected(NotificationListenerController plugin)136 public void onPluginDisconnected(NotificationListenerController plugin) { 137 mPlugins.remove(plugin); 138 } 139 getProvider()140 private NotificationProvider getProvider() { 141 return new NotificationProvider() { 142 @Override 143 public StatusBarNotification[] getActiveNotifications() { 144 return NotificationListenerWithPlugins.super.getActiveNotifications(); 145 } 146 147 @Override 148 public RankingMap getRankingMap() { 149 return NotificationListenerWithPlugins.super.getCurrentRanking(); 150 } 151 152 @Override 153 public void addNotification(StatusBarNotification sbn) { 154 onNotificationPosted(sbn, getRankingMap()); 155 } 156 157 @Override 158 public void removeNotification(StatusBarNotification sbn) { 159 onNotificationRemoved(sbn, getRankingMap()); 160 } 161 162 @Override 163 public void updateRanking() { 164 onNotificationRankingUpdate(getRankingMap()); 165 } 166 }; 167 } 168 } 169