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.plugins.NotificationListenerController; 26 import com.android.systemui.plugins.NotificationListenerController.NotificationProvider; 27 import com.android.systemui.plugins.PluginListener; 28 import com.android.systemui.plugins.PluginManager; 29 30 import java.util.ArrayList; 31 32 import javax.inject.Inject; 33 34 /** 35 * A version of NotificationListenerService that passes all info to 36 * any plugins connected. Also allows those plugins the chance to cancel 37 * any incoming callbacks or to trigger new ones. 38 */ 39 public class NotificationListenerWithPlugins extends NotificationListenerService implements 40 PluginListener<NotificationListenerController> { 41 42 private ArrayList<NotificationListenerController> mPlugins = new ArrayList<>(); 43 private boolean mConnected; 44 private PluginManager mPluginManager; 45 46 @Inject NotificationListenerWithPlugins(PluginManager pluginManager)47 public NotificationListenerWithPlugins(PluginManager pluginManager) { 48 super(); 49 mPluginManager = pluginManager; 50 } 51 52 @Override registerAsSystemService(Context context, ComponentName componentName, int currentUser)53 public void registerAsSystemService(Context context, ComponentName componentName, 54 int currentUser) throws RemoteException { 55 super.registerAsSystemService(context, componentName, currentUser); 56 mPluginManager.addPluginListener(this, NotificationListenerController.class); 57 } 58 59 @Override unregisterAsSystemService()60 public void unregisterAsSystemService() throws RemoteException { 61 super.unregisterAsSystemService(); 62 mPluginManager.removePluginListener(this); 63 } 64 65 @Override getActiveNotifications()66 public StatusBarNotification[] getActiveNotifications() { 67 StatusBarNotification[] activeNotifications = super.getActiveNotifications(); 68 for (NotificationListenerController plugin : mPlugins) { 69 activeNotifications = plugin.getActiveNotifications(activeNotifications); 70 } 71 return activeNotifications; 72 } 73 74 @Override getCurrentRanking()75 public RankingMap getCurrentRanking() { 76 return onPluginRankingUpdate(super.getCurrentRanking()); 77 } 78 onPluginConnected()79 public void onPluginConnected() { 80 mConnected = true; 81 mPlugins.forEach(p -> p.onListenerConnected(getProvider())); 82 } 83 84 /** 85 * Called when listener receives a onNotificationPosted. 86 * Returns true if there's a plugin determining to skip the default callbacks. 87 */ onPluginNotificationPosted(StatusBarNotification sbn, final RankingMap rankingMap)88 public boolean onPluginNotificationPosted(StatusBarNotification sbn, 89 final RankingMap rankingMap) { 90 for (NotificationListenerController plugin : mPlugins) { 91 if (plugin.onNotificationPosted(sbn, rankingMap)) { 92 return true; 93 } 94 } 95 return false; 96 } 97 98 /** 99 * Called when listener receives a onNotificationRemoved. 100 * Returns true if there's a plugin determining to skip the default callbacks. 101 */ onPluginNotificationRemoved(StatusBarNotification sbn, final RankingMap rankingMap)102 public boolean onPluginNotificationRemoved(StatusBarNotification sbn, 103 final RankingMap rankingMap) { 104 for (NotificationListenerController plugin : mPlugins) { 105 if (plugin.onNotificationRemoved(sbn, rankingMap)) { 106 return true; 107 } 108 } 109 return false; 110 } 111 112 /** 113 * Called when listener receives a onNotificationChannelModified. 114 * Returns true if there's a plugin determining to skip the default callbacks. 115 */ onPluginNotificationChannelModified( String pkgName, UserHandle user, NotificationChannel channel, int modificationType)116 public boolean onPluginNotificationChannelModified( 117 String pkgName, UserHandle user, NotificationChannel channel, int modificationType) { 118 for (NotificationListenerController plugin : mPlugins) { 119 if (plugin.onNotificationChannelModified(pkgName, user, channel, modificationType)) { 120 return true; 121 } 122 } 123 return false; 124 } 125 onPluginRankingUpdate(RankingMap rankingMap)126 protected RankingMap onPluginRankingUpdate(RankingMap rankingMap) { 127 for (NotificationListenerController plugin : mPlugins) { 128 rankingMap = plugin.getCurrentRanking(rankingMap); 129 } 130 return rankingMap; 131 } 132 133 @Override onPluginConnected(NotificationListenerController plugin, Context pluginContext)134 public void onPluginConnected(NotificationListenerController plugin, Context pluginContext) { 135 mPlugins.add(plugin); 136 if (mConnected) { 137 plugin.onListenerConnected(getProvider()); 138 } 139 } 140 141 @Override onPluginDisconnected(NotificationListenerController plugin)142 public void onPluginDisconnected(NotificationListenerController plugin) { 143 mPlugins.remove(plugin); 144 } 145 getProvider()146 private NotificationProvider getProvider() { 147 return new NotificationProvider() { 148 @Override 149 public StatusBarNotification[] getActiveNotifications() { 150 return NotificationListenerWithPlugins.super.getActiveNotifications(); 151 } 152 153 @Override 154 public RankingMap getRankingMap() { 155 return NotificationListenerWithPlugins.super.getCurrentRanking(); 156 } 157 158 @Override 159 public void addNotification(StatusBarNotification sbn) { 160 onNotificationPosted(sbn, getRankingMap()); 161 } 162 163 @Override 164 public void removeNotification(StatusBarNotification sbn) { 165 onNotificationRemoved(sbn, getRankingMap()); 166 } 167 168 @Override 169 public void updateRanking() { 170 onNotificationRankingUpdate(getRankingMap()); 171 } 172 }; 173 } 174 } 175