Merge "allow listeners to disable themselves"

This commit is contained in:
Chris Wren
2016-01-08 15:50:13 +00:00
committed by Android (Google) Code Review
8 changed files with 138 additions and 3 deletions

View File

@@ -33591,6 +33591,8 @@ package android.service.notification {
method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
method public final void requestInterruptionFilter(int);
method public final void requestListenerHints(int);
method public static final void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
method public final void requestUnbind() throws android.os.RemoteException;
method public final void setNotificationsShown(java.lang.String[]);
field public static final java.lang.String CATEGORY_VR_NOTIFICATIONS = "android.intent.category.vr.notifications";
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1

View File

@@ -35730,6 +35730,8 @@ package android.service.notification {
method public void registerAsSystemService(android.content.Context, android.content.ComponentName, int) throws android.os.RemoteException;
method public final void requestInterruptionFilter(int);
method public final void requestListenerHints(int);
method public static final void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
method public final void requestUnbind() throws android.os.RemoteException;
method public final void setNotificationsShown(java.lang.String[]);
method public final void setOnNotificationPostedTrim(int);
method public void unregisterAsSystemService() throws android.os.RemoteException;

View File

@@ -33605,6 +33605,8 @@ package android.service.notification {
method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
method public final void requestInterruptionFilter(int);
method public final void requestListenerHints(int);
method public static final void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
method public final void requestUnbind() throws android.os.RemoteException;
method public final void setNotificationsShown(java.lang.String[]);
field public static final java.lang.String CATEGORY_VR_NOTIFICATIONS = "android.intent.category.vr.notifications";
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1

View File

@@ -68,6 +68,9 @@ interface INotificationManager
void cancelNotificationFromListener(in INotificationListener token, String pkg, String tag, int id);
void cancelNotificationsFromListener(in INotificationListener token, in String[] keys);
void requestBindListener(in ComponentName component);
void requestUnbindListener(in INotificationListener token);
void setNotificationsShownFromListener(in INotificationListener token, in String[] keys);
ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token, in String[] keys, int trim);

View File

@@ -17,13 +17,18 @@
package android.service.notification;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.app.INotificationManager;
import android.app.Notification;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
/**

View File

@@ -692,6 +692,36 @@ public abstract class NotificationListenerService extends Service {
}
}
/**
* Request that the listener be rebound, after a previous call to (@link requestUnbind).
*
* <P>This method will fail for assistants that have
* not been granted the permission by the user.
*
* <P>The service should wait for the {@link #onListenerConnected()} event
* before performing any operations.
*/
public static final void requestRebind(ComponentName componentName)
throws RemoteException {
INotificationManager noMan = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
noMan.requestBindListener(componentName);
}
/**
* Request that the service be unbound.
*
* <P>This will no longer receive updates until
* {@link #requestRebind(ComponentName)} is called.
* The service will likely be kiled by the system after this call.
*/
public final void requestUnbind() throws RemoteException {
if (mWrapper != null) {
INotificationManager noMan = getNotificationInterface();
noMan.requestUnbindListener(mWrapper);
}
}
/** Convert new-style Icons to legacy representations for pre-M clients. */
private void createLegacyIconExtras(Notification n) {
Icon smallIcon = n.getSmallIcon();

View File

@@ -86,7 +86,7 @@ abstract public class ManagedServices {
protected final ArrayList<ManagedServiceInfo> mServices = new ArrayList<ManagedServiceInfo>();
// things that will be put into mServices as soon as they're ready
private final ArrayList<String> mServicesBinding = new ArrayList<String>();
// lists the component names of all enabled (and therefore connected)
// lists the component names of all enabled (and therefore potentially connected)
// app services for current profiles.
private ArraySet<ComponentName> mEnabledServicesForCurrentProfiles
= new ArraySet<ComponentName>();
@@ -97,6 +97,8 @@ abstract public class ManagedServices {
private ArraySet<String> mRestoredPackages = new ArraySet<>();
// State of current service categories
private ArrayMap<String, Boolean> mCategoryEnabled = new ArrayMap<>();
// List of enabled packages that have nevertheless asked not to be run
private ArraySet<ComponentName> mSnoozingForCurrentProfiles = new ArraySet<>();
// Kept to de-dupe user change events (experienced after boot, when we receive a settings and a
@@ -174,6 +176,12 @@ abstract public class ManagedServices {
+ (info.isSystem?" SYSTEM":"")
+ (info.isGuest(this)?" GUEST":""));
}
pw.println(" Snoozed " + getCaption() + "s (" +
mSnoozingForCurrentProfiles.size() + "):");
for (ComponentName name : mSnoozingForCurrentProfiles) {
pw.println(" " + name.flattenToShortString());
}
}
// By convention, restored settings are replicated to another settings
@@ -242,14 +250,25 @@ abstract public class ManagedServices {
rebindServices();
}
public ManagedServiceInfo checkServiceTokenLocked(IInterface service) {
checkNotNull(service);
public ManagedServiceInfo getServiceFromTokenLocked(IInterface service) {
if (service == null) {
return null;
}
final IBinder token = service.asBinder();
final int N = mServices.size();
for (int i = 0; i < N; i++) {
final ManagedServiceInfo info = mServices.get(i);
if (info.service.asBinder() == token) return info;
}
return null;
}
public ManagedServiceInfo checkServiceTokenLocked(IInterface service) {
checkNotNull(service);
ManagedServiceInfo info = getServiceFromTokenLocked(service);
if (info != null) {
return info;
}
throw new SecurityException("Disallowed call from unknown " + getCaption() + ": "
+ service);
}
@@ -278,6 +297,35 @@ abstract public class ManagedServices {
checkType(guest.service);
if (registerServiceImpl(guest) != null) {
onServiceAdded(guest);
onServiceAdded(guest);
}
}
public void setComponentState(ComponentName component, boolean enabled) {
boolean previous = !mSnoozingForCurrentProfiles.contains(component);
if (previous == enabled) {
return;
}
if (enabled) {
mSnoozingForCurrentProfiles.remove(component);
} else {
mSnoozingForCurrentProfiles.add(component);
}
// State changed
if (DEBUG) {
Slog.d(TAG, ((enabled) ? "Enabling " : "Disabling ") + "component " +
component.flattenToShortString());
}
final int[] userIds = mUserProfiles.getCurrentProfileIds();
for (int userId : userIds) {
if (enabled) {
registerServiceLocked(component, userId);
} else {
unregisterServiceLocked(component, userId);
}
}
}
@@ -324,6 +372,7 @@ abstract public class ManagedServices {
private void rebuildRestoredPackages() {
mRestoredPackages.clear();
mSnoozingForCurrentProfiles.clear();
String settingName = restoredSettingName(mConfig);
int[] userIds = mUserProfiles.getCurrentProfileIds();
final int N = userIds.length;
@@ -525,6 +574,7 @@ abstract public class ManagedServices {
add.removeAll(c);
}
}
add.removeAll(mSnoozingForCurrentProfiles);
toAdd.put(userIds[i], add);
@@ -803,6 +853,10 @@ abstract public class ManagedServices {
return ManagedServices.this != host;
}
public ManagedServices getOwner() {
return ManagedServices.this;
}
@Override
public String toString() {
return new StringBuilder("ManagedServiceInfo[")
@@ -846,6 +900,11 @@ abstract public class ManagedServices {
}
}
/** convenience method for looking in mEnabledServicesForCurrentProfiles */
public boolean isComponentEnabledForCurrentProfiles(ComponentName component) {
return mEnabledServicesForCurrentProfiles.contains(component);
}
public static class UserProfiles {
// Profiles of the current user.
private final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();

View File

@@ -1446,6 +1446,37 @@ public class NotificationManagerService extends SystemService {
}
}
/**
* Handle request from an approved listener to re-enable itself.
*
* @param component The componenet to be re-enabled, caller must match package.
*/
@Override
public void requestBindListener(ComponentName component) {
checkCallerIsSystemOrSameApp(component.getPackageName());
long identity = Binder.clearCallingIdentity();
try {
ManagedServices manager = mAssistant.isComponentEnabledForCurrentProfiles(component)
? mAssistant
: mListeners;
manager.setComponentState(component, true);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void requestUnbindListener(INotificationListener token) {
long identity = Binder.clearCallingIdentity();
try {
// allow bound services to disable themselves
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
info.getOwner().setComponentState(info.component, false);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void setNotificationsShownFromListener(INotificationListener token, String[] keys) {
long identity = Binder.clearCallingIdentity();
@@ -3426,6 +3457,7 @@ public class NotificationManagerService extends SystemService {
}
}
@Override
protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
if (mListenersDisablingEffects.remove(removed)) {