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

Commit 8a766c6a authored by Christoph Studer's avatar Christoph Studer Committed by Android Git Automerger
Browse files

am 47b43918: Merge "SysUI: Reflect notification ranking" into lmp-preview-dev

* commit '47b439181075416ec46667239215102becde7afd':
  SysUI: Reflect notification ranking
parents 9d4e6911 67e83d57
Loading
Loading
Loading
Loading
+63 −71
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import android.provider.Settings;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
@@ -77,11 +78,12 @@ import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SearchPanelView;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.phone.KeyguardTouchDelegate;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;

import static com.android.keyguard.KeyguardHostView.OnDismissAction;
@@ -195,7 +197,7 @@ public abstract class BaseStatusBar extends SystemUI implements
                    mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0);
            if (provisioned != mDeviceProvisioned) {
                mDeviceProvisioned = provisioned;
                updateNotificationIcons();
                updateNotifications();
            }
            final int mode = Settings.Global.getInt(mContext.getContentResolver(),
                    Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
@@ -213,7 +215,7 @@ public abstract class BaseStatusBar extends SystemUI implements
            // so we just dump our cache ...
            mUsersAllowingPrivateNotifications.clear();
            // ... and refresh all the notifications
            updateNotificationIcons();
            updateNotifications();
        }
    };

@@ -284,11 +286,12 @@ public abstract class BaseStatusBar extends SystemUI implements
        public void onListenerConnected() {
            if (DEBUG) Log.d(TAG, "onListenerConnected");
            final StatusBarNotification[] notifications = getActiveNotifications();
            final Ranking currentRanking = getCurrentRanking();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    for (StatusBarNotification sbn : notifications) {
                        addNotificationInternal(sbn);
                        addNotificationInternal(sbn, currentRanking);
                    }
                }
            });
@@ -297,13 +300,14 @@ public abstract class BaseStatusBar extends SystemUI implements
        @Override
        public void onNotificationPosted(final StatusBarNotification sbn) {
            if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
            final Ranking currentRanking = getCurrentRanking();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (mNotificationData.findByKey(sbn.getKey()) != null) {
                        updateNotificationInternal(sbn);
                        updateNotificationInternal(sbn, currentRanking);
                    } else {
                        addNotificationInternal(sbn);
                        addNotificationInternal(sbn, currentRanking);
                    }
                }
            });
@@ -312,10 +316,24 @@ public abstract class BaseStatusBar extends SystemUI implements
        @Override
        public void onNotificationRemoved(final StatusBarNotification sbn) {
            if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);
            final Ranking currentRanking = getCurrentRanking();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    removeNotificationInternal(sbn.getKey());
                    removeNotificationInternal(sbn.getKey(), currentRanking);
                }
            });
        }

        @Override
        public void onNotificationRankingUpdate() {
            if (DEBUG) Log.d(TAG, "onRankingUpdate");
            final Ranking currentRanking = getCurrentRanking();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mNotificationData.updateRanking(currentRanking);
                    updateNotifications();
                }
            });
        }
@@ -1120,19 +1138,13 @@ public abstract class BaseStatusBar extends SystemUI implements
        }
    }

    protected StatusBarNotification removeNotificationViews(String key) {
        NotificationData.Entry entry = mNotificationData.remove(key);
    protected StatusBarNotification removeNotificationViews(String key, Ranking ranking) {
        NotificationData.Entry entry = mNotificationData.remove(key, ranking);
        if (entry == null) {
            Log.w(TAG, "removeNotification for unknown key: " + key);
            return null;
        }
        // Remove the expanded view.
        ViewGroup rowParent = (ViewGroup)entry.row.getParent();
        if (rowParent != null) rowParent.removeView(entry.row);
        updateRowStates();
        updateNotificationIcons();
        updateSpeedBump();

        updateNotifications();
        return entry.notification;
    }

@@ -1166,35 +1178,17 @@ public abstract class BaseStatusBar extends SystemUI implements
        return entry;
    }

    protected void addNotificationViews(NotificationData.Entry entry) {
    protected void addNotificationViews(Entry entry, Ranking ranking) {
        if (entry == null) {
            return;
        }
        // Add the expanded view and icon.
        int pos = mNotificationData.add(entry);
        if (DEBUG) {
            Log.d(TAG, "addNotificationViews: added at " + pos);
        }
        updateRowStates();
        updateNotificationIcons();
        updateSpeedBump();
        mNotificationData.add(entry, ranking);
        updateNotifications();
    }

    protected void updateSpeedBump() {
        int n = mNotificationData.size();
        int speedBumpIndex = -1;
        for (int i = n-1; i >= 0; i--) {
            NotificationData.Entry entry = mNotificationData.get(i);
            if (entry.row.getVisibility() != View.GONE && speedBumpIndex == -1
                    && entry.row.isBelowSpeedBump() ) {
                speedBumpIndex = n - 1 - i;
            }
        }
        mStackScroller.updateSpeedBumpIndex(speedBumpIndex);
    }

    private void addNotificationViews(StatusBarNotification notification) {
        addNotificationViews(createNotificationViews(notification));
    private void addNotificationViews(StatusBarNotification notification, Ranking ranking) {
        addNotificationViews(createNotificationViews(notification), ranking);
    }

    /**
@@ -1208,17 +1202,17 @@ public abstract class BaseStatusBar extends SystemUI implements
    protected void updateRowStates() {
        int maxKeyguardNotifications = getMaxKeyguardNotifications();
        mKeyguardIconOverflowContainer.getIconsView().removeAllViews();
        int n = mNotificationData.size();
        final int N = mNotificationData.size();
        int visibleNotifications = 0;
        boolean onKeyguard = mState == StatusBarState.KEYGUARD;
        for (int i = n-1; i >= 0; i--) {
        for (int i = 0; i < N; i++) {
            NotificationData.Entry entry = mNotificationData.get(i);
            if (onKeyguard) {
                entry.row.setExpansionDisabled(true);
            } else {
                entry.row.setExpansionDisabled(false);
                if (!entry.row.isUserLocked()) {
                    boolean top = (i == n-1);
                    boolean top = (i == 0);
                    entry.row.setSystemExpanded(top);
                }
            }
@@ -1245,6 +1239,9 @@ public abstract class BaseStatusBar extends SystemUI implements
        } else {
            mKeyguardIconOverflowContainer.setVisibility(View.GONE);
        }
        // Move overflow container to last position.
        mStackScroller.changeViewPosition(mKeyguardIconOverflowContainer,
                mStackScroller.getChildCount() - 1);
    }

    private boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
@@ -1254,7 +1251,7 @@ public abstract class BaseStatusBar extends SystemUI implements
    protected void setZenMode(int mode) {
        if (!isDeviceProvisioned()) return;
        mZenMode = mode;
        updateNotificationIcons();
        updateNotifications();
    }

    protected void setShowLockscreenNotifications(boolean show) {
@@ -1263,41 +1260,37 @@ public abstract class BaseStatusBar extends SystemUI implements

    protected abstract void haltTicker();
    protected abstract void setAreThereNotifications();
    protected abstract void updateNotificationIcons();
    protected abstract void updateNotifications();
    protected abstract void tick(StatusBarNotification n, boolean firstTime);
    protected abstract void updateExpandedViewPos(int expandedPosition);
    protected abstract boolean shouldDisableNavbarGestures();

    protected boolean isTopNotification(ViewGroup parent, NotificationData.Entry entry) {
        return parent != null && parent.indexOfChild(entry.row) == 0;
    }


    @Override
    public void addNotification(StatusBarNotification notification) {
        if (!USE_NOTIFICATION_LISTENER) {
            addNotificationInternal(notification);
            addNotificationInternal(notification, null);
        }
    }

    public abstract void addNotificationInternal(StatusBarNotification notification);
    public abstract void addNotificationInternal(StatusBarNotification notification,
            Ranking ranking);

    @Override
    public void removeNotification(String key) {
        if (!USE_NOTIFICATION_LISTENER) {
            removeNotificationInternal(key);
            removeNotificationInternal(key, null);
        }
    }

    protected abstract void removeNotificationInternal(String key);
    protected abstract void removeNotificationInternal(String key, Ranking ranking);

    public void updateNotification(StatusBarNotification notification) {
        if (!USE_NOTIFICATION_LISTENER) {
            updateNotificationInternal(notification);
            updateNotificationInternal(notification, null);
        }
    }

    public void updateNotificationInternal(StatusBarNotification notification) {
    public void updateNotificationInternal(StatusBarNotification notification, Ranking ranking) {
        if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");

        final NotificationData.Entry oldEntry = mNotificationData.findByKey(notification.getKey());
@@ -1369,18 +1362,12 @@ public abstract class BaseStatusBar extends SystemUI implements
                        && oldPublicContentView.getPackage().equals(publicContentView.getPackage())
                        && oldPublicContentView.getLayoutId() == publicContentView.getLayoutId());

        ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
        boolean orderUnchanged =
                   notification.getNotification().when == oldNotification.getNotification().when
                && notification.getScore() == oldNotification.getScore();
        // score now encompasses/supersedes isOngoing()

        boolean updateTicker = notification.getNotification().tickerText != null
                && !TextUtils.equals(notification.getNotification().tickerText,
                oldEntry.notification.getNotification().tickerText);
        boolean isTopAnyway = isTopNotification(rowParent, oldEntry);
        if (contentsUnchanged && bigContentsUnchanged && headsUpContentsUnchanged && publicUnchanged
                && (orderUnchanged || isTopAnyway)) {
        if (contentsUnchanged && bigContentsUnchanged && headsUpContentsUnchanged
                && publicUnchanged) {
            if (DEBUG) Log.d(TAG, "reusing notification for key: " + notification.getKey());
            oldEntry.notification = notification;
            try {
@@ -1408,22 +1395,20 @@ public abstract class BaseStatusBar extends SystemUI implements
                    handleNotificationError(notification, "Couldn't update icon: " + ic);
                    return;
                }
                updateRowStates();
                updateSpeedBump();
                mNotificationData.updateRanking(ranking);
                updateNotifications();
            }
            catch (RuntimeException e) {
                // It failed to add cleanly.  Log, and remove the view from the panel.
                Log.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
                removeNotificationViews(notification.getKey());
                addNotificationViews(notification);
                removeNotificationViews(notification.getKey(), ranking);
                addNotificationViews(notification, ranking);
            }
        } else {
            if (DEBUG) Log.d(TAG, "not reusing notification for key: " + notification.getKey());
            if (DEBUG) Log.d(TAG, "contents was " + (contentsUnchanged ? "unchanged" : "changed"));
            if (DEBUG) Log.d(TAG, "order was " + (orderUnchanged ? "unchanged" : "changed"));
            if (DEBUG) Log.d(TAG, "notification is " + (isTopAnyway ? "top" : "not top"));
            removeNotificationViews(notification.getKey());
            addNotificationViews(notification);  // will also replace the heads up
            removeNotificationViews(notification.getKey(), ranking);
            addNotificationViews(notification, ranking);  // will also replace the heads up
            final NotificationData.Entry newEntry = mNotificationData.findByKey(
                    notification.getKey());
            final boolean userChangedExpansion = oldEntry.row.hasUserChangedExpansion();
@@ -1570,5 +1555,12 @@ public abstract class BaseStatusBar extends SystemUI implements
            mWindowManager.removeViewImmediate(mSearchPanelView);
        }
        mContext.unregisterReceiver(mBroadcastReceiver);
        if (USE_NOTIFICATION_LISTENER) {
            try {
                mNotificationListener.unregisterAsSystemService();
            } catch (RemoteException e) {
                // Ignore.
            }
        }
    }
}
+4 −4
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ public class InterceptedNotifications {
        for (int i = 0; i < n; i++) {
            final StatusBarNotification sbn = mIntercepted.valueAt(i);
            sbn.getNotification().extras.putBoolean(EXTRA_INTERCEPT, false);
            mBar.addNotificationInternal(sbn);
            mBar.addNotificationInternal(sbn, null);
        }
        mIntercepted.clear();
        updateSyntheticNotification();
@@ -88,7 +88,7 @@ public class InterceptedNotifications {
    private void updateSyntheticNotification() {
        if (mIntercepted.isEmpty()) {
            if (mSynKey != null) {
                mBar.removeNotificationInternal(mSynKey);
                mBar.removeNotificationInternal(mSynKey, null);
                mSynKey = null;
            }
            return;
@@ -107,9 +107,9 @@ public class InterceptedNotifications {
                mBar.getCurrentUserHandle());
        if (mSynKey == null) {
            mSynKey = sbn.getKey();
            mBar.addNotificationInternal(sbn);
            mBar.addNotificationInternal(sbn, null);
        } else {
           mBar.updateNotificationInternal(sbn);
           mBar.updateNotificationInternal(sbn, null);
        }
        final NotificationData.Entry entry = mBar.mNotificationData.findByKey(mSynKey);
        entry.row.setOnClickListener(mSynClickListener);
+49 −20
Original line number Diff line number Diff line
@@ -16,15 +16,19 @@

package com.android.systemui.statusbar;

import android.app.Notification;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.StatusBarNotification;
import android.view.View;
import android.widget.ImageView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

/**
 * The list of currently displaying notifications.
 *
 * TODO: Rename to NotificationList.
 */
public class NotificationData {
    public static final class Entry {
@@ -34,7 +38,6 @@ public class NotificationData {
        public ExpandableNotificationRow row; // the outer expanded view
        public View expanded; // the inflated RemoteViews
        public View expandedPublic; // for insecure lockscreens
        public ImageView largeIcon;
        public View expandedBig;
        private boolean interruption;
        public Entry() {}
@@ -64,18 +67,23 @@ public class NotificationData {
    }

    private final ArrayList<Entry> mEntries = new ArrayList<Entry>();
    private final Comparator<Entry> mEntryCmp = new Comparator<Entry>() {
        // sort first by score, then by when
    private Ranking mRanking;
    private final Comparator<Entry> mRankingComparator = new Comparator<Entry>() {
        @Override
        public int compare(Entry a, Entry b) {
            if (mRanking != null) {
                return mRanking.getRank(a.key) - mRanking.getRank(b.key);
            }

            final StatusBarNotification na = a.notification;
            final StatusBarNotification nb = b.notification;
            int d = na.getScore() - nb.getScore();
            int d = nb.getScore() - na.getScore();
            if (a.interruption != b.interruption) {
                return a.interruption ? 1 : -1;
                return a.interruption ? -1 : 1;
            } else if (d != 0) {
                return d;
            } else {
                return (int) (na.getNotification().when - nb.getNotification().when);
                return (int) (nb.getNotification().when - na.getNotification().when);
            }
        }
    };
@@ -97,26 +105,47 @@ public class NotificationData {
        return null;
    }

    public int add(Entry entry) {
        int i;
        int N = mEntries.size();
        for (i = 0; i < N; i++) {
            if (mEntryCmp.compare(mEntries.get(i), entry) > 0) {
                break;
            }
        }
        mEntries.add(i, entry);
        return i;
    public void add(Entry entry, Ranking ranking) {
        mEntries.add(entry);
        updateRankingAndSort(ranking);
    }

    public Entry remove(String key) {
    public Entry remove(String key, Ranking ranking) {
        Entry e = findByKey(key);
        if (e != null) {
            mEntries.remove(e);
        if (e == null) {
            return null;
        }
        mEntries.remove(e);
        updateRankingAndSort(ranking);
        return e;
    }

    public void updateRanking(Ranking ranking) {
        updateRankingAndSort(ranking);
    }

    public boolean isAmbient(String key) {
        // TODO: Remove when switching to NotificationListener.
        if (mRanking == null) {
            for (Entry entry : mEntries) {
                if (key.equals(entry.key)) {
                    return entry.notification.getNotification().priority ==
                            Notification.PRIORITY_MIN;
                }
            }
        } else {
            return mRanking.isAmbient(key);
        }
        return false;
    }

    private void updateRankingAndSort(Ranking ranking) {
        if (ranking != null) {
            mRanking = ranking;
        }
        Collections.sort(mEntries, mRankingComparator);
    }

    /**
     * Return whether there are any visible items (i.e. items without an error).
     */
+65 −15
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
import android.util.DisplayMetrics;
@@ -1043,13 +1044,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
    }

    @Override
    public void addNotificationInternal(StatusBarNotification notification) {
    public void addNotificationInternal(StatusBarNotification notification, Ranking ranking) {
        if (DEBUG) Log.d(TAG, "addNotification score=" + notification.getScore());
        Entry shadeEntry = createNotificationViews(notification);
        if (shadeEntry == null) {
            return;
        }
        if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(notification)) {
            // Forward the ranking so we can sort the new notification.
            mNotificationData.updateRanking(ranking);
            return;
        }
        if (mUseHeadsUp && shouldInterrupt(notification)) {
@@ -1089,7 +1092,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
                tick(notification, true);
            }
        }
        addNotificationViews(shadeEntry);
        addNotificationViews(shadeEntry, ranking);
        // Recalculate the position of the sliding windows and the titles.
        setAreThereNotifications();
        updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
@@ -1111,8 +1114,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
    }

    @Override
    public void removeNotificationInternal(String key) {
        StatusBarNotification old = removeNotificationViews(key);
    public void removeNotificationInternal(String key, Ranking ranking) {
        StatusBarNotification old = removeNotificationViews(key, ranking);
        if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);

        if (old != null) {
@@ -1149,7 +1152,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
            R.integer.config_show_search_delay);
    }

    private void loadNotificationShade() {
    private void updateNotificationShade() {
        if (mStackScroller == null) return;

        int N = mNotificationData.size();
@@ -1159,7 +1162,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        final boolean provisioned = isDeviceProvisioned();
        // If the device hasn't been through Setup, we only show system notifications
        for (int i=0; i<N; i++) {
            Entry ent = mNotificationData.get(N-i-1);
            Entry ent = mNotificationData.get(i);
            if (!(provisioned || showNotificationEvenIfUnprovisioned(ent.notification))) continue;

            // TODO How do we want to badge notifcations from profiles.
@@ -1190,26 +1193,75 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        for (int i=0; i<toShow.size(); i++) {
            View v = toShow.get(i);
            if (v.getParent() == null) {
                mStackScroller.addView(v, i);
                mStackScroller.addView(v);
            }
        }

        // So after all this work notifications still aren't sorted correctly.
        // Let's do that now by advancing through toShow and mStackScroller in
        // lock-step, making sure mStackScroller matches what we see in toShow.
        int j = 0;
        for (int i = 0; i < mStackScroller.getChildCount(); i++) {
            View child = mStackScroller.getChildAt(i);
            if (!(child instanceof ExpandableNotificationRow)) {
                // We don't care about non-notification views.
                continue;
            }

            if (child == toShow.get(j)) {
                // Everything is well, advance both lists.
                j++;
                continue;
            }

            // Oops, wrong notification at this position. Put the right one
            // here and advance both lists.
            mStackScroller.changeViewPosition(toShow.get(j), i);
            j++;
        }
        updateRowStates();
        updateSpeedbump();
        mNotificationPanel.setQsExpansionEnabled(provisioned && mUserSetup);
    }

    private void updateSpeedbump() {
        int speedbumpIndex = -1;
        int currentIndex = 0;
        for (int i = 0; i < mNotificationData.size(); i++) {
            Entry entry = mNotificationData.get(i);
            if (entry.row.getParent() == null) {
                // This view isn't even added, so the stack scroller doesn't
                // know about it. Ignore completely.
                continue;
            }
            if (entry.row.getVisibility() != View.GONE &&
                    mNotificationData.isAmbient(entry.key)) {
                speedbumpIndex = currentIndex;
                break;
            }
            currentIndex++;
        }
        mStackScroller.updateSpeedBumpIndex(speedbumpIndex);
    }

    @Override
    protected void updateNotificationIcons() {
    protected void updateNotifications() {
        // TODO: Move this into updateNotificationIcons()?
        if (mNotificationIcons == null) return;

        loadNotificationShade();
        updateNotificationShade();
        updateNotificationIcons();
    }

    private void updateNotificationIcons() {
        final LinearLayout.LayoutParams params
            = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight);

        int N = mNotificationData.size();

        if (DEBUG) {
            Log.d(TAG, "refreshing icons: " + N + " notifications, mNotificationIcons=" + mNotificationIcons);
            Log.d(TAG, "refreshing icons: " + N + " notifications, mNotificationIcons=" +
                    mNotificationIcons);
        }

        ArrayList<View> toShow = new ArrayList<View>();
@@ -1217,7 +1269,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        final boolean provisioned = isDeviceProvisioned();
        // If the device hasn't been through Setup, we only show system notifications
        for (int i=0; i<N; i++) {
            Entry ent = mNotificationData.get(N-i-1);
            Entry ent = mNotificationData.get(i);
            if (!((provisioned && ent.notification.getScore() >= HIDE_ICONS_BELOW_SCORE)
                    || showNotificationEvenIfUnprovisioned(ent.notification))) continue;
            if (!notificationIsForCurrentProfiles(ent.notification)) continue;
@@ -2394,7 +2446,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
    public void userSwitched(int newUserId) {
        if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
        animateCollapsePanels();
        updateNotificationIcons();
        updateNotifications();
        resetUserSetupObserver();
    }

@@ -2799,10 +2851,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,

        updateStackScrollerState();
        updatePublicMode();
        updateRowStates();
        updateSpeedBump();
        updateNotifications();
        checkBarModes();
        updateNotificationIcons();
        updateCarrierLabelVisibility(false);
    }

+4 −4

File changed.

Preview size limit exceeded, changes collapsed.