Merge "allow listeners to disable themselves"
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
Reference in New Issue
Block a user