Merge "Add notification listener plugin hook" into oc-dr1-dev
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationListenerController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationListenerController.java
new file mode 100644
index 0000000..fac9e98
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationListenerController.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.plugins;
+
+import android.service.notification.NotificationListenerService.RankingMap;
+import android.service.notification.StatusBarNotification;
+
+import com.android.systemui.plugins.NotificationListenerController.NotificationProvider;
+import com.android.systemui.plugins.annotations.DependsOn;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+@ProvidesInterface(action = NotificationListenerController.ACTION,
+ version = NotificationListenerController.VERSION)
+@DependsOn(target = NotificationProvider.class)
+public interface NotificationListenerController extends Plugin {
+ String ACTION = "com.android.systemui.action.PLUGIN_NOTIFICATION_ASSISTANT";
+ int VERSION = 1;
+
+ void onListenerConnected(NotificationProvider provider);
+
+ default boolean onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
+ return false;
+ }
+ default boolean onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
+ return false;
+ }
+
+ default StatusBarNotification[] getActiveNotifications(
+ StatusBarNotification[] activeNotifications) {
+ return activeNotifications;
+ }
+
+ default RankingMap getCurrentRanking(RankingMap currentRanking) {
+ return currentRanking;
+ }
+
+ @ProvidesInterface(version = NotificationProvider.VERSION)
+ interface NotificationProvider {
+ int VERSION = 1;
+
+ // Methods to get info about current notifications
+ StatusBarNotification[] getActiveNotifications();
+ RankingMap getRankingMap();
+
+ // Methods to notify sysui of changes to notification list.
+ void addNotification(StatusBarNotification sbn);
+ void removeNotification(StatusBarNotification sbn);
+ void updateRanking();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationListenerWithPlugins.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationListenerWithPlugins.java
new file mode 100644
index 0000000..9ff907b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationListenerWithPlugins.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.RemoteException;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.NotificationListenerController;
+import com.android.systemui.plugins.NotificationListenerController.NotificationProvider;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+
+import java.util.ArrayList;
+
+/**
+ * A version of NotificationListenerService that passes all info to
+ * any plugins connected. Also allows those plugins the chance to cancel
+ * any incoming callbacks or to trigger new ones.
+ */
+public class NotificationListenerWithPlugins extends NotificationListenerService implements
+ PluginListener<NotificationListenerController> {
+
+ private ArrayList<NotificationListenerController> mPlugins = new ArrayList<>();
+ private boolean mConnected;
+
+ @Override
+ public void registerAsSystemService(Context context, ComponentName componentName,
+ int currentUser) throws RemoteException {
+ super.registerAsSystemService(context, componentName, currentUser);
+ Dependency.get(PluginManager.class).addPluginListener(this,
+ NotificationListenerController.class);
+ }
+
+ @Override
+ public void unregisterAsSystemService() throws RemoteException {
+ super.unregisterAsSystemService();
+ Dependency.get(PluginManager.class).removePluginListener(this);
+ }
+
+ @Override
+ public StatusBarNotification[] getActiveNotifications() {
+ StatusBarNotification[] activeNotifications = super.getActiveNotifications();
+ for (NotificationListenerController plugin : mPlugins) {
+ activeNotifications = plugin.getActiveNotifications(activeNotifications);
+ }
+ return activeNotifications;
+ }
+
+ @Override
+ public RankingMap getCurrentRanking() {
+ RankingMap currentRanking = super.getCurrentRanking();
+ for (NotificationListenerController plugin : mPlugins) {
+ currentRanking = plugin.getCurrentRanking(currentRanking);
+ }
+ return currentRanking;
+ }
+
+ public void onPluginConnected() {
+ mConnected = true;
+ mPlugins.forEach(p -> p.onListenerConnected(getProvider()));
+ }
+
+ /**
+ * Called when listener receives a onNotificationPosted.
+ * Returns true to indicate this callback should be skipped.
+ */
+ public boolean onPluginNotificationPosted(StatusBarNotification sbn,
+ final RankingMap rankingMap) {
+ for (NotificationListenerController plugin : mPlugins) {
+ if (plugin.onNotificationPosted(sbn, rankingMap)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Called when listener receives a onNotificationRemoved.
+ * Returns true to indicate this callback should be skipped.
+ */
+ public boolean onPluginNotificationRemoved(StatusBarNotification sbn,
+ final RankingMap rankingMap) {
+ for (NotificationListenerController plugin : mPlugins) {
+ if (plugin.onNotificationRemoved(sbn, rankingMap)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public RankingMap onPluginRankingUpdate(RankingMap rankingMap) {
+ return getCurrentRanking();
+ }
+
+ @Override
+ public void onPluginConnected(NotificationListenerController plugin, Context pluginContext) {
+ mPlugins.add(plugin);
+ if (mConnected) {
+ plugin.onListenerConnected(getProvider());
+ }
+ }
+
+ @Override
+ public void onPluginDisconnected(NotificationListenerController plugin) {
+ mPlugins.remove(plugin);
+ }
+
+ private NotificationProvider getProvider() {
+ return new NotificationProvider() {
+ @Override
+ public StatusBarNotification[] getActiveNotifications() {
+ return NotificationListenerWithPlugins.super.getActiveNotifications();
+ }
+
+ @Override
+ public RankingMap getRankingMap() {
+ return NotificationListenerWithPlugins.super.getCurrentRanking();
+ }
+
+ @Override
+ public void addNotification(StatusBarNotification sbn) {
+ onNotificationPosted(sbn, getRankingMap());
+ }
+
+ @Override
+ public void removeNotification(StatusBarNotification sbn) {
+ onNotificationRemoved(sbn, getRankingMap());
+ }
+
+ @Override
+ public void updateRanking() {
+ onNotificationRankingUpdate(getRankingMap());
+ }
+ };
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 10cb567..e8b6e07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -5769,11 +5769,12 @@
}
};
- private final NotificationListenerService mNotificationListener =
- new NotificationListenerService() {
+ private final NotificationListenerWithPlugins mNotificationListener =
+ new NotificationListenerWithPlugins() {
@Override
public void onListenerConnected() {
if (DEBUG) Log.d(TAG, "onListenerConnected");
+ onPluginConnected();
final StatusBarNotification[] notifications = getActiveNotifications();
if (notifications == null) {
Log.w(TAG, "onListenerConnected unable to get active notifications.");
@@ -5798,7 +5799,7 @@
public void onNotificationPosted(final StatusBarNotification sbn,
final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
- if (sbn != null) {
+ if (sbn != null && !onPluginNotificationPosted(sbn, rankingMap)) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -5842,14 +5843,9 @@
public void onNotificationRemoved(StatusBarNotification sbn,
final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);
- if (sbn != null) {
+ if (sbn != null && !onPluginNotificationRemoved(sbn, rankingMap)) {
final String key = sbn.getKey();
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- removeNotification(key, rankingMap);
- }
- });
+ mHandler.post(() -> removeNotification(key, rankingMap));
}
}
@@ -5857,13 +5853,10 @@
public void onNotificationRankingUpdate(final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onRankingUpdate");
if (rankingMap != null) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- updateNotificationRanking(rankingMap);
- }
- });
- } }
+ RankingMap r = onPluginRankingUpdate(rankingMap);
+ mHandler.post(() -> updateNotificationRanking(r));
+ }
+ }
};