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

Commit 3a7c4a56 authored by Kenny Guy's avatar Kenny Guy
Browse files

Show notifications from related users.

When filtering notifications for user include those for users that
are related to the current user.
Pipe through user id so we know which user the notification is for.

Change-Id: I4e2657c23bd7b611d450be5a1f9457824bc062cb
parent 0e6ad3b8
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -41,11 +41,11 @@ interface IStatusBarService
            out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications,
            out int[] switches, out List<IBinder> binders);
    void onPanelRevealed();
    void onNotificationClick(String pkg, String tag, int id);
    void onNotificationClick(String pkg, String tag, int id, int userId);
    void onNotificationError(String pkg, String tag, int id,
            int uid, int initialPid, String message);
    void onClearAllNotifications();
    void onNotificationClear(String pkg, String tag, int id);
            int uid, int initialPid, String message, int userId);
    void onClearAllNotifications(int userId);
    void onNotificationClear(String pkg, String tag, int id, int userId);
    void setSystemUiVisibility(int vis, int mask);
    void setHardKeyboardEnabled(boolean enabled);
    void toggleRecentApps();
+46 −14
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.database.ContentObserver;
@@ -46,6 +47,7 @@ import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
@@ -55,6 +57,7 @@ import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.TextAppearanceSpan;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.ContextThemeWrapper;
import android.view.Display;
@@ -140,6 +143,7 @@ public abstract class BaseStatusBar extends SystemUI implements
    protected PopupMenu mNotificationBlamePopup;

    protected int mCurrentUserId = 0;
    final protected SparseArray<UserInfo> mRelatedUsers = new SparseArray<UserInfo>();

    protected int mLayoutDirection = -1; // invalid
    private Locale mLocale;
@@ -156,6 +160,8 @@ public abstract class BaseStatusBar extends SystemUI implements
    private Context mLightThemeContext;
    private ImageUtils mImageUtils = new ImageUtils();

    private UserManager mUserManager;

    // UI-specific methods

    /**
@@ -248,12 +254,26 @@ public abstract class BaseStatusBar extends SystemUI implements
            String action = intent.getAction();
            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
                updateRelatedUserCache();
                if (true) Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
                userSwitched(mCurrentUserId);
            } else if (Intent.ACTION_USER_ADDED.equals(action)) {
                updateRelatedUserCache();
            }
        }
    };

    private void updateRelatedUserCache() {
        synchronized (mRelatedUsers) {
            mRelatedUsers.clear();
            if (mUserManager != null) {
                for (UserInfo related : mUserManager.getRelatedUsers(mCurrentUserId)) {
                    mRelatedUsers.put(related.id, related);
                }
            }
        }
    }

    public void start() {
        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
@@ -287,6 +307,8 @@ public abstract class BaseStatusBar extends SystemUI implements
        mLocale = mContext.getResources().getConfiguration().locale;
        mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);

        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);

        // Connect in to the status bar manager service
        StatusBarIconList iconList = new StatusBarIconList();
        ArrayList<IBinder> notificationKeys = new ArrayList<IBinder>();
@@ -348,22 +370,28 @@ public abstract class BaseStatusBar extends SystemUI implements

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_USER_SWITCHED);
        filter.addAction(Intent.ACTION_USER_ADDED);
        mContext.registerReceiver(mBroadcastReceiver, filter);

        updateRelatedUserCache();
    }

    public void userSwitched(int newUserId) {
        // should be overridden
    }

    public boolean notificationIsForCurrentUser(StatusBarNotification n) {
    public boolean notificationIsForCurrentOrRelatedUser(StatusBarNotification n) {
        final int thisUserId = mCurrentUserId;
        final int notificationUserId = n.getUserId();
        if (DEBUG && MULTIUSER_DEBUG) {
            Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d",
                    n, thisUserId, notificationUserId));
        }
        synchronized (mRelatedUsers) {
            return notificationUserId == UserHandle.USER_ALL
                || thisUserId == notificationUserId;
                    || thisUserId == notificationUserId
                    || mRelatedUsers.get(notificationUserId) != null;
        }
    }

    @Override
@@ -389,13 +417,14 @@ public abstract class BaseStatusBar extends SystemUI implements
            final String _pkg = n.getPackageName();
            final String _tag = n.getTag();
            final int _id = n.getId();
            final int _userId = n.getUserId();
            vetoButton.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View v) {
                        // Accessibility feedback
                        v.announceForAccessibility(
                                mContext.getString(R.string.accessibility_notification_dismissed));
                        try {
                            mBarService.onNotificationClear(_pkg, _tag, _id);
                            mBarService.onNotificationClear(_pkg, _tag, _id, _userId);

                        } catch (RemoteException ex) {
                            // system process is dead if we're here.
@@ -907,7 +936,7 @@ public abstract class BaseStatusBar extends SystemUI implements
        PendingIntent contentIntent = sbn.getNotification().contentIntent;
        if (contentIntent != null) {
            final View.OnClickListener listener = makeClicker(contentIntent,
                    sbn.getPackageName(), sbn.getTag(), sbn.getId(), isHeadsUp);
                    sbn.getPackageName(), sbn.getTag(), sbn.getId(), isHeadsUp, sbn.getUserId());
            content.setOnClickListener(listener);
        } else {
            content.setOnClickListener(null);
@@ -1017,7 +1046,7 @@ public abstract class BaseStatusBar extends SystemUI implements
            TextView debug = (TextView) row.findViewById(R.id.debug_info);
            if (debug != null) {
                debug.setVisibility(View.VISIBLE);
                debug.setText("U " + entry.notification.getUserId());
                debug.setText("CU " + mCurrentUserId +" NU " + entry.notification.getUserId());
            }
        }
        entry.row = row;
@@ -1030,9 +1059,9 @@ public abstract class BaseStatusBar extends SystemUI implements
        return true;
    }

    public NotificationClicker makeClicker(PendingIntent intent, String pkg, String tag, int id,
            boolean forHun) {
        return new NotificationClicker(intent, pkg, tag, id, forHun);
    public NotificationClicker makeClicker(PendingIntent intent, String pkg, String tag,
            int id, boolean forHun, int userId) {
        return new NotificationClicker(intent, pkg, tag, id, forHun, userId);
    }

    protected class NotificationClicker implements View.OnClickListener {
@@ -1041,14 +1070,16 @@ public abstract class BaseStatusBar extends SystemUI implements
        private String mTag;
        private int mId;
        private boolean mIsHeadsUp;
        private int mUserId;

        public NotificationClicker(PendingIntent intent, String pkg, String tag, int id,
                boolean forHun) {
                boolean forHun, int userId) {
            mIntent = intent;
            mPkg = pkg;
            mTag = tag;
            mId = id;
            mIsHeadsUp = forHun;
            mUserId = userId;
        }

        public void onClick(View v) {
@@ -1084,7 +1115,7 @@ public abstract class BaseStatusBar extends SystemUI implements
                if (mIsHeadsUp) {
                    mHandler.sendEmptyMessage(MSG_HIDE_HEADS_UP);
                }
                mBarService.onNotificationClick(mPkg, mTag, mId);
                mBarService.onNotificationClick(mPkg, mTag, mId, mUserId);
            } catch (RemoteException ex) {
                // system process is dead if we're here.
            }
@@ -1122,7 +1153,8 @@ public abstract class BaseStatusBar extends SystemUI implements
    void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
        removeNotification(key);
        try {
            mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(), n.getInitialPid(), message);
            mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(),
                    n.getInitialPid(), message, n.getUserId());
        } catch (RemoteException ex) {
            // The end is nigh.
        }
@@ -1391,7 +1423,7 @@ public abstract class BaseStatusBar extends SystemUI implements
        updateNotificationVetoButton(oldEntry.row, notification);

        // Is this for you?
        boolean isForCurrentUser = notificationIsForCurrentUser(notification);
        boolean isForCurrentUser = notificationIsForCurrentOrRelatedUser(notification);
        if (DEBUG) Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");

        // Restart the ticker if it's still running
@@ -1443,7 +1475,7 @@ public abstract class BaseStatusBar extends SystemUI implements
        if (contentIntent != null) {
            final View.OnClickListener listener = makeClicker(contentIntent,
                    notification.getPackageName(), notification.getTag(), notification.getId(),
                    isHeadsUp);
                    isHeadsUp, notification.getUserId());
            entry.content.setOnClickListener(listener);
        } else {
            entry.content.setOnClickListener(null);
+9 −5
Original line number Diff line number Diff line
@@ -1056,7 +1056,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
        for (int i=0; i<N; i++) {
            Entry ent = mNotificationData.get(N-i-1);
            if (!(provisioned || showNotificationEvenIfUnprovisioned(ent.notification))) continue;
            if (!notificationIsForCurrentUser(ent.notification)) continue;

            // TODO How do we want to badge notifcations from related users.
            if (!notificationIsForCurrentOrRelatedUser(ent.notification)) continue;

            final int vis = ent.notification.getNotification().visibility;
            if (vis != Notification.VISIBILITY_SECRET) {
                // when isLockscreenPublicMode() we show the public form of VISIBILITY_PRIVATE notifications
@@ -1114,7 +1117,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
            Entry ent = mNotificationData.get(N-i-1);
            if (!((provisioned && ent.notification.getScore() >= HIDE_ICONS_BELOW_SCORE)
                    || showNotificationEvenIfUnprovisioned(ent.notification))) continue;
            if (!notificationIsForCurrentUser(ent.notification)) continue;
            if (!notificationIsForCurrentOrRelatedUser(ent.notification)) continue;
            if (isLockscreenPublicMode()
                    && ent.notification.getNotification().visibility
                            == Notification.VISIBILITY_SECRET
@@ -2121,7 +2124,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
        if (!isDeviceProvisioned()) return;

        // not for you
        if (!notificationIsForCurrentUser(n)) return;
        if (!notificationIsForCurrentOrRelatedUser(n)) return;

        // Show the ticker if one is requested. Also don't do this
        // until status bar window is attached to the window manager,
@@ -2429,7 +2432,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
                                }
                                try {
                                    mPile.setViewRemoval(true);
                                    mBarService.onClearAllNotifications();
                                    mBarService.onClearAllNotifications(mCurrentUserId);
                                } catch (Exception ex) { }
                            }
                        };
@@ -2607,7 +2610,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
                mBarService.onNotificationClear(
                        mInterruptingNotificationEntry.notification.getPackageName(),
                        mInterruptingNotificationEntry.notification.getTag(),
                        mInterruptingNotificationEntry.notification.getId());
                        mInterruptingNotificationEntry.notification.getId(),
                        mInterruptingNotificationEntry.notification.getUserId());
            } catch (android.os.RemoteException ex) {
                // oh well
            }
+4 −4
Original line number Diff line number Diff line
@@ -20,11 +20,11 @@ import android.os.IBinder;

public interface NotificationDelegate {
    void onSetDisabled(int status);
    void onClearAll();
    void onNotificationClick(String pkg, String tag, int id);
    void onNotificationClear(String pkg, String tag, int id);
    void onClearAll(int userId);
    void onNotificationClick(String pkg, String tag, int id, int userId);
    void onNotificationClear(String pkg, String tag, int id, int userId);
    void onNotificationError(String pkg, String tag, int id,
            int uid, int initialPid, String message);
            int uid, int initialPid, String message, int userId);
    void onPanelRevealed();
    boolean allowDisable(int what, IBinder token, String pkg);
}
+46 −19
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Bitmap;
@@ -56,6 +57,7 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
import android.provider.Settings;
import android.service.notification.INotificationListener;
@@ -67,6 +69,7 @@ import android.util.AtomicFile;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -217,6 +220,9 @@ public class NotificationManagerService extends SystemService {
            ));
    private static final String EXTRA_INTERCEPT = "android.intercept";

    // Users related to the current user.
    final protected SparseArray<UserInfo> mRelatedUsers = new SparseArray<UserInfo>();

    private class NotificationListenerInfo implements IBinder.DeathRecipient {
        INotificationListener listener;
        ComponentName component;
@@ -910,28 +916,21 @@ public class NotificationManagerService extends SystemService {
        }

        @Override
        public void onClearAll() {
            // XXX to be totally correct, the caller should tell us which user
            // this is for.
            cancelAll(ActivityManager.getCurrentUser());
        public void onClearAll(int userId) {
            cancelAll(userId);
        }

        @Override
        public void onNotificationClick(String pkg, String tag, int id) {
            // XXX to be totally correct, the caller should tell us which user
            // this is for.
        public void onNotificationClick(String pkg, String tag, int id, int userId) {
            cancelNotification(pkg, tag, id, Notification.FLAG_AUTO_CANCEL,
                    Notification.FLAG_FOREGROUND_SERVICE, false,
                    ActivityManager.getCurrentUser());
                    Notification.FLAG_FOREGROUND_SERVICE, false, userId);
        }

        @Override
        public void onNotificationClear(String pkg, String tag, int id) {
            // XXX to be totally correct, the caller should tell us which user
            // this is for.
        public void onNotificationClear(String pkg, String tag, int id, int userId) {
            cancelNotification(pkg, tag, id, 0,
                    Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
                true, ActivityManager.getCurrentUser());
                    true, userId);
        }

        @Override
@@ -969,12 +968,10 @@ public class NotificationManagerService extends SystemService {

        @Override
        public void onNotificationError(String pkg, String tag, int id,
                int uid, int initialPid, String message) {
                int uid, int initialPid, String message, int userId) {
            Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id
                    + "; will crashApplication(uid=" + uid + ", pid=" + initialPid + ")");
            // XXX to be totally correct, the caller should tell us which user
            // this is for.
            cancelNotification(pkg, tag, id, 0, 0, false, UserHandle.getUserId(uid));
            cancelNotification(pkg, tag, id, 0, 0, false, userId);
            long ident = Binder.clearCallingIdentity();
            try {
                ActivityManagerNative.getDefault().crashApplication(uid, initialPid, pkg,
@@ -1090,6 +1087,9 @@ public class NotificationManagerService extends SystemService {
            } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
                // reload per-user settings
                mSettingsObserver.update(null);
                updateRelatedUserCache(context);
            } else if (action.equals(Intent.ACTION_USER_ADDED)) {
                updateRelatedUserCache(context);
            }
        }
    };
@@ -1223,6 +1223,7 @@ public class NotificationManagerService extends SystemService {
        filter.addAction(Intent.ACTION_USER_PRESENT);
        filter.addAction(Intent.ACTION_USER_STOPPED);
        filter.addAction(Intent.ACTION_USER_SWITCHED);
        filter.addAction(Intent.ACTION_USER_ADDED);
        getContext().registerReceiver(mIntentReceiver, filter);
        IntentFilter pkgFilter = new IntentFilter();
        pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
@@ -2336,6 +2337,18 @@ public class NotificationManagerService extends SystemService {
                || r.getUserId() == userId;
    }

    /**
     * Determine whether the userId applies to the notification in question, either because
     * they match exactly, or one of them is USER_ALL (which is treated as a wildcard) or
     * because it matches a related user.
     */
    private boolean notificationMatchesUserIdOrRelated(NotificationRecord r, int userId) {
        synchronized (mRelatedUsers) {
            return notificationMatchesUserId(r, userId)
                    || mRelatedUsers.get(r.getUserId()) != null;
        }
    }

    /**
     * Cancels all notifications from a given package that have all of the
     * {@code mustHaveFlags}.
@@ -2424,7 +2437,7 @@ public class NotificationManagerService extends SystemService {
            for (int i=N-1; i>=0; i--) {
                NotificationRecord r = mNotificationList.get(i);

                if (!notificationMatchesUserId(r, userId)) {
                if (!notificationMatchesUserIdOrRelated(r, userId)) {
                    continue;
                }

@@ -2582,6 +2595,20 @@ public class NotificationManagerService extends SystemService {
        }
    }

    private void updateRelatedUserCache(Context context) {
        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
        int currentUserId = ActivityManager.getCurrentUser();
        if (userManager != null) {
            List<UserInfo> relatedUsers = userManager.getRelatedUsers(currentUserId);
            synchronized (mRelatedUsers) {
                mRelatedUsers.clear();
                for (UserInfo related : relatedUsers) {
                    mRelatedUsers.put(related.id, related);
                }
            }
        }
    }

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