Add notification listener plugin hook
Allows plugin control over notifications right at the entrance to sysui and gives them the opportunity to mess with them how they see fit. Test: manual Change-Id: I569bf37138da66d0524acecfa36ceb409f98fbb4
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -5754,11 +5754,12 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
}
|
||||
};
|
||||
|
||||
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.");
|
||||
@@ -5783,7 +5784,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
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() {
|
||||
@@ -5827,14 +5828,9 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5842,13 +5838,10 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user