Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a263e4e4 authored by Kenny Guy's avatar Kenny Guy
Browse files

Pipe notifications from related users to listeners.

For Listeners built against L or greater
Send notifications from related users to listeners.
Return notifications from related users getAllActiveNotifications
Cancel notifications from related users in cancelAllNotifications
Deprecate StatusBarNotification.getUserId() and expose getUser()
as APIs should use UserHandles.
Deprecate cancelNotification that takes package, id and tag
in favour of one that takes key.

Fix bug that notifications from related users didn't
trigger sounds.

Change-Id: I1b1c20c9f305b8f3c4047bc5720d8e99cdedfe70
parent 2eadb856
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -24348,7 +24348,8 @@ package android.service.notification {
  public abstract class NotificationListenerService extends android.app.Service {
  public abstract class NotificationListenerService extends android.app.Service {
    ctor public NotificationListenerService();
    ctor public NotificationListenerService();
    method public final void cancelAllNotifications();
    method public final void cancelAllNotifications();
    method public final void cancelNotification(java.lang.String, java.lang.String, int);
    method public final deprecated void cancelNotification(java.lang.String, java.lang.String, int);
    method public final void cancelNotification(java.lang.String);
    method public final void cancelNotifications(java.lang.String[]);
    method public final void cancelNotifications(java.lang.String[]);
    method public java.lang.String[] getActiveNotificationKeys();
    method public java.lang.String[] getActiveNotificationKeys();
    method public android.service.notification.StatusBarNotification[] getActiveNotifications();
    method public android.service.notification.StatusBarNotification[] getActiveNotifications();
@@ -24371,7 +24372,8 @@ package android.service.notification {
    method public java.lang.String getPackageName();
    method public java.lang.String getPackageName();
    method public long getPostTime();
    method public long getPostTime();
    method public java.lang.String getTag();
    method public java.lang.String getTag();
    method public int getUserId();
    method public android.os.UserHandle getUser();
    method public deprecated int getUserId();
    method public boolean isClearable();
    method public boolean isClearable();
    method public boolean isOngoing();
    method public boolean isOngoing();
    method public void writeToParcel(android.os.Parcel, int);
    method public void writeToParcel(android.os.Parcel, int);
+34 −1
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.os.IBinder;
import android.os.IBinder;
import android.os.ServiceManager;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Log;
import android.util.Log;


/**
/**
@@ -121,11 +122,43 @@ public abstract class NotificationListenerService extends Service {
     *     {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
     *     {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
     * @param id  ID of the notification as specified by the notifying app in
     * @param id  ID of the notification as specified by the notifying app in
     *     {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
     *     {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
     * <p>
     * @deprecated Use {@link #cancelNotification(String key)}
     * instead. Beginning with {@link android.os.Build.VERSION_CODES#L} this method will no longer
     * cancel the notification. It will continue to cancel the notification for applications
     * whose {@code targetSdkVersion} is earlier than {@link android.os.Build.VERSION_CODES#L}.
     */
     */
    public final void cancelNotification(String pkg, String tag, int id) {
    public final void cancelNotification(String pkg, String tag, int id) {
        if (!isBound()) return;
        if (!isBound()) return;
        try {
        try {
            getNotificationInterface().cancelNotificationFromListener(mWrapper, pkg, tag, id);
            getNotificationInterface().cancelNotificationFromListener(
                    mWrapper, pkg, tag, id);
        } catch (android.os.RemoteException ex) {
            Log.v(TAG, "Unable to contact notification manager", ex);
        }
    }

    /**
     * Inform the notification manager about dismissal of a single notification.
     * <p>
     * Use this if your listener has a user interface that allows the user to dismiss individual
     * notifications, similar to the behavior of Android's status bar and notification panel.
     * It should be called after the user dismisses a single notification using your UI;
     * upon being informed, the notification manager will actually remove the notification
     * and you will get an {@link #onNotificationRemoved(StatusBarNotification)} callback.
     * <P>
     * <b>Note:</b> If your listener allows the user to fire a notification's
     * {@link android.app.Notification#contentIntent} by tapping/clicking/etc., you should call
     * this method at that time <i>if</i> the Notification in question has the
     * {@link android.app.Notification#FLAG_AUTO_CANCEL} flag set.
     * <p>
     * @param key Notification to dismiss from {@link StatusBarNotification#getKey()}.
     */
    public final void cancelNotification(String key) {
        if (!isBound()) return;
        try {
            getNotificationInterface().cancelNotificationsFromListener(mWrapper,
                    new String[] {key});
        } catch (android.os.RemoteException ex) {
        } catch (android.os.RemoteException ex) {
            Log.v(TAG, "Unable to contact notification manager", ex);
            Log.v(TAG, "Unable to contact notification manager", ex);
        }
        }
+5 −2
Original line number Original line Diff line number Diff line
@@ -175,7 +175,11 @@ public class StatusBarNotification implements Parcelable {
                && ((notification.flags & Notification.FLAG_NO_CLEAR) == 0);
                && ((notification.flags & Notification.FLAG_NO_CLEAR) == 0);
    }
    }


    /** Returns a userHandle for the instance of the app that posted this notification. */
    /**
     * Returns a userHandle for the instance of the app that posted this notification.
     *
     * @deprecated Use {@link #getUser()} instead.
     */
    public int getUserId() {
    public int getUserId() {
        return this.user.getIdentifier();
        return this.user.getIdentifier();
    }
    }
@@ -219,7 +223,6 @@ public class StatusBarNotification implements Parcelable {


    /**
    /**
     * The {@link android.os.UserHandle} for whom this notification is intended.
     * The {@link android.os.UserHandle} for whom this notification is intended.
     * @hide
     */
     */
    public UserHandle getUser() {
    public UserHandle getUser() {
        return user;
        return user;
+144 −62
Original line number Original line Diff line number Diff line
@@ -51,6 +51,7 @@ import android.media.AudioManager;
import android.media.IRingtonePlayer;
import android.media.IRingtonePlayer;
import android.net.Uri;
import android.net.Uri;
import android.os.Binder;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder;
import android.os.Message;
import android.os.Message;
@@ -185,10 +186,10 @@ public class NotificationManagerService extends SystemService {
    // things that will be put into mListeners as soon as they're ready
    // things that will be put into mListeners as soon as they're ready
    private ArrayList<String> mServicesBinding = new ArrayList<String>();
    private ArrayList<String> mServicesBinding = new ArrayList<String>();
    // lists the component names of all enabled (and therefore connected) listener
    // lists the component names of all enabled (and therefore connected) listener
    // app services for the current user only
    // app services for current profiles.
    private HashSet<ComponentName> mEnabledListenersForCurrentUser
    private HashSet<ComponentName> mEnabledListenersForCurrentProfiles
            = new HashSet<ComponentName>();
            = new HashSet<ComponentName>();
    // Just the packages from mEnabledListenersForCurrentUser
    // Just the packages from mEnabledListenersForCurrentProfiles
    private HashSet<String> mEnabledListenerPackageNames = new HashSet<String>();
    private HashSet<String> mEnabledListenerPackageNames = new HashSet<String>();


    // Notification control database. For now just contains disabled packages.
    // Notification control database. For now just contains disabled packages.
@@ -242,32 +243,40 @@ public class NotificationManagerService extends SystemService {
        int userid;
        int userid;
        boolean isSystem;
        boolean isSystem;
        ServiceConnection connection;
        ServiceConnection connection;
        int targetSdkVersion;


        public NotificationListenerInfo(INotificationListener listener, ComponentName component,
        public NotificationListenerInfo(INotificationListener listener, ComponentName component,
                int userid, boolean isSystem) {
                int userid, boolean isSystem, int targetSdkVersion) {
            this.listener = listener;
            this.listener = listener;
            this.component = component;
            this.component = component;
            this.userid = userid;
            this.userid = userid;
            this.isSystem = isSystem;
            this.isSystem = isSystem;
            this.connection = null;
            this.connection = null;
            this.targetSdkVersion = targetSdkVersion;
        }
        }


        public NotificationListenerInfo(INotificationListener listener, ComponentName component,
        public NotificationListenerInfo(INotificationListener listener, ComponentName component,
                int userid, ServiceConnection connection) {
                int userid, ServiceConnection connection, int targetSdkVersion) {
            this.listener = listener;
            this.listener = listener;
            this.component = component;
            this.component = component;
            this.userid = userid;
            this.userid = userid;
            this.isSystem = false;
            this.isSystem = false;
            this.connection = connection;
            this.connection = connection;
            this.targetSdkVersion = targetSdkVersion;
        }
        }


        boolean enabledAndUserMatches(StatusBarNotification sbn) {
        boolean enabledAndUserMatches(StatusBarNotification sbn) {
            final int nid = sbn.getUserId();
            final int nid = sbn.getUserId();
            if (!isEnabledForCurrentUser()) {
            if (!isEnabledForCurrentProfiles()) {
                return false;
                return false;
            }
            }
            if (this.userid == UserHandle.USER_ALL) return true;
            if (this.userid == UserHandle.USER_ALL) return true;
            return (nid == UserHandle.USER_ALL || nid == this.userid);
            if (nid == UserHandle.USER_ALL || nid == this.userid) return true;
            return supportsProfiles() && isCurrentProfile(nid);
        }

        boolean supportsProfiles() {
            return targetSdkVersion >= Build.VERSION_CODES.L;
        }
        }


        public void notifyPostedIfUserMatch(StatusBarNotification sbn) {
        public void notifyPostedIfUserMatch(StatusBarNotification sbn) {
@@ -299,11 +308,11 @@ public class NotificationManagerService extends SystemService {
            removeListenerImpl(this.listener, this.userid);
            removeListenerImpl(this.listener, this.userid);
        }
        }


        /** convenience method for looking in mEnabledListenersForCurrentUser */
        /** convenience method for looking in mEnabledListenersForCurrentProfiles */
        public boolean isEnabledForCurrentUser() {
        public boolean isEnabledForCurrentProfiles() {
            if (this.isSystem) return true;
            if (this.isSystem) return true;
            if (this.connection == null) return false;
            if (this.connection == null) return false;
            return mEnabledListenersForCurrentUser.contains(this.component);
            return mEnabledListenersForCurrentProfiles.contains(this.component);
        }
        }
    }
    }


@@ -506,18 +515,25 @@ public class NotificationManagerService extends SystemService {
     * Remove notification access for any services that no longer exist.
     * Remove notification access for any services that no longer exist.
     */
     */
    void disableNonexistentListeners() {
    void disableNonexistentListeners() {
        int currentUser = ActivityManager.getCurrentUser();
        int[] userIds = getCurrentProfileIds();
        final int N = userIds.length;
        for (int i = 0 ; i < N; ++i) {
            disableNonexistentListeners(userIds[i]);
        }
    }

    void disableNonexistentListeners(int userId) {
        String flatIn = Settings.Secure.getStringForUser(
        String flatIn = Settings.Secure.getStringForUser(
                getContext().getContentResolver(),
                getContext().getContentResolver(),
                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
                currentUser);
                userId);
        if (!TextUtils.isEmpty(flatIn)) {
        if (!TextUtils.isEmpty(flatIn)) {
            if (DBG) Slog.v(TAG, "flat before: " + flatIn);
            if (DBG) Slog.v(TAG, "flat before: " + flatIn);
            PackageManager pm = getContext().getPackageManager();
            PackageManager pm = getContext().getPackageManager();
            List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
            List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
                    new Intent(NotificationListenerService.SERVICE_INTERFACE),
                    new Intent(NotificationListenerService.SERVICE_INTERFACE),
                    PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
                    PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
                    currentUser);
                    userId);


            Set<ComponentName> installed = new HashSet<ComponentName>();
            Set<ComponentName> installed = new HashSet<ComponentName>();
            for (int i = 0, count = installedServices.size(); i < count; i++) {
            for (int i = 0, count = installedServices.size(); i < count; i++) {
@@ -551,7 +567,7 @@ public class NotificationManagerService extends SystemService {
            if (!flatIn.equals(flatOut)) {
            if (!flatIn.equals(flatOut)) {
                Settings.Secure.putStringForUser(getContext().getContentResolver(),
                Settings.Secure.putStringForUser(getContext().getContentResolver(),
                        Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
                        Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
                        flatOut, currentUser);
                        flatOut, userId);
            }
            }
        }
        }
    }
    }
@@ -561,54 +577,70 @@ public class NotificationManagerService extends SystemService {
     * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
     * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
     */
     */
    void rebindListenerServices() {
    void rebindListenerServices() {
        final int currentUser = ActivityManager.getCurrentUser();
        final int[] userIds = getCurrentProfileIds();
        String flat = Settings.Secure.getStringForUser(
        final int nUserIds = userIds.length;

        final SparseArray<String> flat = new SparseArray<String>();

        for (int i = 0; i < nUserIds; ++i) {
            flat.put(userIds[i], Settings.Secure.getStringForUser(
                    getContext().getContentResolver(),
                    getContext().getContentResolver(),
                    Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
                    Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
                currentUser);
                    userIds[i]));
        }


        NotificationListenerInfo[] toRemove = new NotificationListenerInfo[mListeners.size()];
        NotificationListenerInfo[] toRemove = new NotificationListenerInfo[mListeners.size()];
        final ArrayList<ComponentName> toAdd;
        final SparseArray<ArrayList<ComponentName>> toAdd
                = new SparseArray<ArrayList<ComponentName>>();


        synchronized (mNotificationList) {
        synchronized (mNotificationList) {
            // unbind and remove all existing listeners
            // unbind and remove all existing listeners
            toRemove = mListeners.toArray(toRemove);
            toRemove = mListeners.toArray(toRemove);


            toAdd = new ArrayList<ComponentName>();
            final HashSet<ComponentName> newEnabled = new HashSet<ComponentName>();
            final HashSet<ComponentName> newEnabled = new HashSet<ComponentName>();
            final HashSet<String> newPackages = new HashSet<String>();
            final HashSet<String> newPackages = new HashSet<String>();


            for (int i = 0; i < nUserIds; ++i) {
                final ArrayList<ComponentName> add = new ArrayList<ComponentName>();
                toAdd.put(userIds[i], add);

                // decode the list of components
                // decode the list of components
            if (flat != null) {
                String toDecode = flat.get(userIds[i]);
                String[] components = flat.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR);
                if (toDecode != null) {
                for (int i=0; i<components.length; i++) {
                    String[] components = toDecode.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR);
                    for (int j = 0; j < components.length; j++) {
                        final ComponentName component
                        final ComponentName component
                            = ComponentName.unflattenFromString(components[i]);
                                = ComponentName.unflattenFromString(components[j]);
                        if (component != null) {
                        if (component != null) {
                            newEnabled.add(component);
                            newEnabled.add(component);
                        toAdd.add(component);
                            add.add(component);
                            newPackages.add(component.getPackageName());
                            newPackages.add(component.getPackageName());
                        }
                        }
                    }
                    }


                mEnabledListenersForCurrentUser = newEnabled;
                mEnabledListenerPackageNames = newPackages;
                }
                }
            }
            }
            mEnabledListenersForCurrentProfiles = newEnabled;
            mEnabledListenerPackageNames = newPackages;
        }


        for (NotificationListenerInfo info : toRemove) {
        for (NotificationListenerInfo info : toRemove) {
            final ComponentName component = info.component;
            final ComponentName component = info.component;
            final int oldUser = info.userid;
            final int oldUser = info.userid;
            Slog.v(TAG, "disabling notification listener for user " + oldUser + ": " + component);
            Slog.v(TAG, "disabling notification listener for user "
                    + oldUser + ": " + component);
            unregisterListenerService(component, info.userid);
            unregisterListenerService(component, info.userid);
        }
        }


        final int N = toAdd.size();
        for (int i = 0; i < nUserIds; ++i) {
        for (int i=0; i<N; i++) {
            final ArrayList<ComponentName> add = toAdd.get(userIds[i]);
            final ComponentName component = toAdd.get(i);
            final int N = add.size();
            Slog.v(TAG, "enabling notification listener for user " + currentUser + ": "
            for (int j = 0; j < N; j++) {
                final ComponentName component = add.get(j);
                Slog.v(TAG, "enabling notification listener for user " + userIds[i] + ": "
                        + component);
                        + component);
            registerListenerService(component, currentUser);
                registerListenerService(component, userIds[i]);
            }
        }
        }
    }
    }


@@ -656,6 +688,16 @@ public class NotificationManagerService extends SystemService {
                    getContext(), 0, new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS), 0);
                    getContext(), 0, new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS), 0);
            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);


            ApplicationInfo appInfo = null;
            try {
                appInfo = getContext().getPackageManager().getApplicationInfo(
                        name.getPackageName(), 0);
            } catch (NameNotFoundException e) {
                // Ignore if the package doesn't exist we won't be able to bind to the service.
            }
            final int targetSdkVersion =
                    appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE;

            try {
            try {
                if (DBG) Slog.v(TAG, "binding: " + intent);
                if (DBG) Slog.v(TAG, "binding: " + intent);
                if (!getContext().bindServiceAsUser(intent,
                if (!getContext().bindServiceAsUser(intent,
@@ -671,7 +713,8 @@ public class NotificationManagerService extends SystemService {
                                        mListener = INotificationListener.Stub.asInterface(service);
                                        mListener = INotificationListener.Stub.asInterface(service);
                                        NotificationListenerInfo info
                                        NotificationListenerInfo info
                                                = new NotificationListenerInfo(
                                                = new NotificationListenerInfo(
                                                mListener, name, userid, this);
                                                        mListener, name, userid, this,
                                                        targetSdkVersion);
                                        service.linkToDeath(info, 0);
                                        service.linkToDeath(info, 0);
                                        added = mListeners.add(info);
                                        added = mListeners.add(info);
                                    } catch (RemoteException e) {
                                    } catch (RemoteException e) {
@@ -945,7 +988,8 @@ public class NotificationManagerService extends SystemService {
        @Override
        @Override
        public void onClearAll(int callingUid, int callingPid, int userId) {
        public void onClearAll(int callingUid, int callingPid, int userId) {
            synchronized (mNotificationList) {
            synchronized (mNotificationList) {
                cancelAllLocked(callingUid, callingPid, userId, REASON_DELEGATE_CANCEL_ALL, null);
                cancelAllLocked(callingUid, callingPid, userId, REASON_DELEGATE_CANCEL_ALL, null,
                        /*includeCurrentProfiles*/ true);
            }
            }
        }
        }


@@ -1239,6 +1283,8 @@ public class NotificationManagerService extends SystemService {
        }
        }
        updateZenMode();
        updateZenMode();


        updateCurrentProfilesCache(getContext());

        // register for various Intents
        // register for various Intents
        IntentFilter filter = new IntentFilter();
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_ON);
@@ -1582,14 +1628,21 @@ public class NotificationManagerService extends SystemService {
                        final int N = keys.length;
                        final int N = keys.length;
                        for (int i = 0; i < N; i++) {
                        for (int i = 0; i < N; i++) {
                            NotificationRecord r = mNotificationsByKey.get(keys[i]);
                            NotificationRecord r = mNotificationsByKey.get(keys[i]);
                            final int userId = r.sbn.getUserId();
                            if (userId != info.userid && userId != UserHandle.USER_ALL &&
                                    !isCurrentProfile(userId)) {
                                throw new SecurityException("Disallowed call from listener: "
                                        + info.listener);
                            }
                            if (r != null) {
                            if (r != null) {
                                cancelNotificationFromListenerLocked(info, callingUid, callingPid,
                                cancelNotificationFromListenerLocked(info, callingUid, callingPid,
                                        r.sbn.getPackageName(), r.sbn.getTag(), r.sbn.getId());
                                        r.sbn.getPackageName(), r.sbn.getTag(), r.sbn.getId(),
                                        userId);
                            }
                            }
                        }
                        }
                    } else {
                    } else {
                        cancelAllLocked(callingUid, callingPid, info.userid,
                        cancelAllLocked(callingUid, callingPid, info.userid,
                                REASON_LISTENER_CANCEL_ALL, info);
                                REASON_LISTENER_CANCEL_ALL, info, info.supportsProfiles());
                    }
                    }
                }
                }
            } finally {
            } finally {
@@ -1598,11 +1651,11 @@ public class NotificationManagerService extends SystemService {
        }
        }


        private void cancelNotificationFromListenerLocked(NotificationListenerInfo info,
        private void cancelNotificationFromListenerLocked(NotificationListenerInfo info,
                int callingUid, int callingPid, String pkg, String tag, int id) {
                int callingUid, int callingPid, String pkg, String tag, int id, int userId) {
            cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
            cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
                    Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
                    Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
                    true,
                    true,
                    info.userid, REASON_LISTENER_CANCEL, info);
                    userId, REASON_LISTENER_CANCEL, info);
        }
        }


        /**
        /**
@@ -1621,8 +1674,14 @@ public class NotificationManagerService extends SystemService {
            try {
            try {
                synchronized (mNotificationList) {
                synchronized (mNotificationList) {
                    final NotificationListenerInfo info = checkListenerTokenLocked(token);
                    final NotificationListenerInfo info = checkListenerTokenLocked(token);
                    if (info.supportsProfiles()) {
                        Log.e(TAG, "Ignoring deprecated cancelNotification(pkg, tag, id) "
                                + "from " + info.component
                                + " use cancelNotification(key) instead.");
                    } else {
                        cancelNotificationFromListenerLocked(info, callingUid, callingPid,
                        cancelNotificationFromListenerLocked(info, callingUid, callingPid,
                            pkg, tag, id);
                                pkg, tag, id, info.userid);
                    }
                }
                }
            } finally {
            } finally {
                Binder.restoreCallingIdentity(identity);
                Binder.restoreCallingIdentity(identity);
@@ -1701,9 +1760,9 @@ public class NotificationManagerService extends SystemService {
    void dumpImpl(PrintWriter pw) {
    void dumpImpl(PrintWriter pw) {
        pw.println("Current Notification Manager state:");
        pw.println("Current Notification Manager state:");


        pw.println("  Listeners (" + mEnabledListenersForCurrentUser.size()
        pw.println("  Listeners (" + mEnabledListenersForCurrentProfiles.size()
                + ") enabled for current user:");
                + ") enabled for current profiles:");
        for (ComponentName cmpt : mEnabledListenersForCurrentUser) {
        for (ComponentName cmpt : mEnabledListenersForCurrentProfiles) {
            pw.println("    " + cmpt);
            pw.println("    " + cmpt);
        }
        }


@@ -1995,7 +2054,8 @@ public class NotificationManagerService extends SystemService {
                            && (!(old != null
                            && (!(old != null
                                && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
                                && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
                            && (r.getUserId() == UserHandle.USER_ALL ||
                            && (r.getUserId() == UserHandle.USER_ALL ||
                                (r.getUserId() == userId && r.getUserId() == currentUser))
                                (r.getUserId() == userId && r.getUserId() == currentUser) ||
                                isCurrentProfile(r.getUserId()))
                            && canInterrupt
                            && canInterrupt
                            && mSystemReady
                            && mSystemReady
                            && mAudioManager != null) {
                            && mAudioManager != null) {
@@ -2131,7 +2191,8 @@ public class NotificationManagerService extends SystemService {
        synchronized (mNotificationList) {
        synchronized (mNotificationList) {
            try {
            try {
                NotificationListenerInfo info
                NotificationListenerInfo info
                        = new NotificationListenerInfo(listener, component, userid, true);
                        = new NotificationListenerInfo(listener, component, userid,
                        /*isSystem*/ true, Build.VERSION_CODES.L);
                listener.asBinder().linkToDeath(info, 0);
                listener.asBinder().linkToDeath(info, 0);
                mListeners.add(info);
                mListeners.add(info);
            } catch (RemoteException e) {
            } catch (RemoteException e) {
@@ -2461,10 +2522,8 @@ public class NotificationManagerService extends SystemService {
     * because it matches one of the users profiles.
     * because it matches one of the users profiles.
     */
     */
    private boolean notificationMatchesCurrentProfiles(NotificationRecord r, int userId) {
    private boolean notificationMatchesCurrentProfiles(NotificationRecord r, int userId) {
        synchronized (mCurrentProfiles) {
        return notificationMatchesUserId(r, userId)
        return notificationMatchesUserId(r, userId)
                    || mCurrentProfiles.get(r.getUserId()) != null;
                || isCurrentProfile(r.getUserId());
        }
    }
    }


    /**
    /**
@@ -2553,7 +2612,7 @@ public class NotificationManagerService extends SystemService {
    }
    }


    void cancelAllLocked(int callingUid, int callingPid, int userId, int reason,
    void cancelAllLocked(int callingUid, int callingPid, int userId, int reason,
            NotificationListenerInfo listener) {
            NotificationListenerInfo listener, boolean includeCurrentProfiles) {
        EventLogTags.writeNotificationCancelAll(callingUid, callingPid,
        EventLogTags.writeNotificationCancelAll(callingUid, callingPid,
                null, userId, 0, 0, reason,
                null, userId, 0, 0, reason,
                listener == null ? null : listener.component.toShortString());
                listener == null ? null : listener.component.toShortString());
@@ -2561,9 +2620,15 @@ public class NotificationManagerService extends SystemService {
        final int N = mNotificationList.size();
        final int N = mNotificationList.size();
        for (int i=N-1; i>=0; i--) {
        for (int i=N-1; i>=0; i--) {
            NotificationRecord r = mNotificationList.get(i);
            NotificationRecord r = mNotificationList.get(i);
            if (includeCurrentProfiles) {
                if (!notificationMatchesCurrentProfiles(r, userId)) {
                if (!notificationMatchesCurrentProfiles(r, userId)) {
                    continue;
                    continue;
                }
                }
            } else {
                if (!notificationMatchesUserId(r, userId)) {
                    continue;
                }
            }


            if ((r.getFlags() & (Notification.FLAG_ONGOING_EVENT
            if ((r.getFlags() & (Notification.FLAG_ONGOING_EVENT
                            | Notification.FLAG_NO_CLEAR)) == 0) {
                            | Notification.FLAG_NO_CLEAR)) == 0) {
@@ -2678,8 +2743,8 @@ public class NotificationManagerService extends SystemService {


    private void updateCurrentProfilesCache(Context context) {
    private void updateCurrentProfilesCache(Context context) {
        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
        int currentUserId = ActivityManager.getCurrentUser();
        if (userManager != null) {
        if (userManager != null) {
            int currentUserId = ActivityManager.getCurrentUser();
            List<UserInfo> profiles = userManager.getProfiles(currentUserId);
            List<UserInfo> profiles = userManager.getProfiles(currentUserId);
            synchronized (mCurrentProfiles) {
            synchronized (mCurrentProfiles) {
                mCurrentProfiles.clear();
                mCurrentProfiles.clear();
@@ -2690,6 +2755,23 @@ public class NotificationManagerService extends SystemService {
        }
        }
    }
    }


    private int[] getCurrentProfileIds() {
        synchronized (mCurrentProfiles) {
            int[] users = new int[mCurrentProfiles.size()];
            final int N = mCurrentProfiles.size();
            for (int i = 0; i < N; ++i) {
                users[i] = mCurrentProfiles.keyAt(i);
            }
            return users;
        }
    }

    private boolean isCurrentProfile(int userId) {
        synchronized (mCurrentProfiles) {
            return mCurrentProfiles.get(userId) != null;
        }
    }

    private boolean isCall(String pkg, Notification n) {
    private boolean isCall(String pkg, Notification n) {
        return CALL_PACKAGES.contains(pkg);
        return CALL_PACKAGES.contains(pkg);
    }
    }