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.content.ComponentName; 18 import android.content.Context; 19 import android.os.RemoteException; 20 import android.service.notification.NotificationListenerService; 21 import android.service.notification.StatusBarNotification; 22 23 import com.android.systemui.Dependency; 24 import com.android.systemui.plugins.NotificationListenerController; 25 import com.android.systemui.plugins.NotificationListenerController.NotificationProvider; 26 import com.android.systemui.plugins.PluginListener; 27 import com.android.systemui.shared.plugins.PluginManager; 28 29 import java.util.ArrayList; 30 31 /** 32 * A version of NotificationListenerService that passes all info to 33 * any plugins connected. Also allows those plugins the chance to cancel 34 * any incoming callbacks or to trigger new ones. 35 */ 36 public class NotificationListenerWithPlugins extends NotificationListenerService implements 37 PluginListener<NotificationListenerController> { 38 39 private ArrayList<NotificationListenerController> mPlugins = new ArrayList<>(); 40 private boolean mConnected; 41 42 @Override registerAsSystemService(Context context, ComponentName componentName, int currentUser)43 public void registerAsSystemService(Context context, ComponentName componentName, 44 int currentUser) throws RemoteException { 45 super.registerAsSystemService(context, componentName, currentUser); 46 Dependency.get(PluginManager.class).addPluginListener(this, 47 NotificationListenerController.class); 48 } 49 50 @Override unregisterAsSystemService()51 public void unregisterAsSystemService() throws RemoteException { 52 super.unregisterAsSystemService(); 53 Dependency.get(PluginManager.class).removePluginListener(this); 54 } 55 56 @Override getActiveNotifications()57 public StatusBarNotification[] getActiveNotifications() { 58 StatusBarNotification[] activeNotifications = super.getActiveNotifications(); 59 for (NotificationListenerController plugin : mPlugins) { 60 activeNotifications = plugin.getActiveNotifications(activeNotifications); 61 } 62 return activeNotifications; 63 } 64 65 @Override getCurrentRanking()66 public RankingMap getCurrentRanking() { 67 RankingMap currentRanking = super.getCurrentRanking(); 68 for (NotificationListenerController plugin : mPlugins) { 69 currentRanking = plugin.getCurrentRanking(currentRanking); 70 } 71 return currentRanking; 72 } 73 onPluginConnected()74 public void onPluginConnected() { 75 mConnected = true; 76 mPlugins.forEach(p -> p.onListenerConnected(getProvider())); 77 } 78 79 /** 80 * Called when listener receives a onNotificationPosted. 81 * Returns true to indicate this callback should be skipped. 82 */ onPluginNotificationPosted(StatusBarNotification sbn, final RankingMap rankingMap)83 public boolean onPluginNotificationPosted(StatusBarNotification sbn, 84 final RankingMap rankingMap) { 85 for (NotificationListenerController plugin : mPlugins) { 86 if (plugin.onNotificationPosted(sbn, rankingMap)) { 87 return true; 88 } 89 } 90 return false; 91 } 92 93 /** 94 * Called when listener receives a onNotificationRemoved. 95 * Returns true to indicate this callback should be skipped. 96 */ onPluginNotificationRemoved(StatusBarNotification sbn, final RankingMap rankingMap)97 public boolean onPluginNotificationRemoved(StatusBarNotification sbn, 98 final RankingMap rankingMap) { 99 for (NotificationListenerController plugin : mPlugins) { 100 if (plugin.onNotificationRemoved(sbn, rankingMap)) { 101 return true; 102 } 103 } 104 return false; 105 } 106 onPluginRankingUpdate(RankingMap rankingMap)107 public RankingMap onPluginRankingUpdate(RankingMap rankingMap) { 108 return getCurrentRanking(); 109 } 110 111 @Override onPluginConnected(NotificationListenerController plugin, Context pluginContext)112 public void onPluginConnected(NotificationListenerController plugin, Context pluginContext) { 113 mPlugins.add(plugin); 114 if (mConnected) { 115 plugin.onListenerConnected(getProvider()); 116 } 117 } 118 119 @Override onPluginDisconnected(NotificationListenerController plugin)120 public void onPluginDisconnected(NotificationListenerController plugin) { 121 mPlugins.remove(plugin); 122 } 123 getProvider()124 private NotificationProvider getProvider() { 125 return new NotificationProvider() { 126 @Override 127 public StatusBarNotification[] getActiveNotifications() { 128 return NotificationListenerWithPlugins.super.getActiveNotifications(); 129 } 130 131 @Override 132 public RankingMap getRankingMap() { 133 return NotificationListenerWithPlugins.super.getCurrentRanking(); 134 } 135 136 @Override 137 public void addNotification(StatusBarNotification sbn) { 138 onNotificationPosted(sbn, getRankingMap()); 139 } 140 141 @Override 142 public void removeNotification(StatusBarNotification sbn) { 143 onNotificationRemoved(sbn, getRankingMap()); 144 } 145 146 @Override 147 public void updateRanking() { 148 onNotificationRankingUpdate(getRankingMap()); 149 } 150 }; 151 } 152 } 153