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

Commit f660edb2 authored by Christoph Studer's avatar Christoph Studer Committed by Android (Google) Code Review
Browse files

Merge "SysUI: Display group children when no summary is present" into lmp-dev

parents cad266aa c8db24bc
Loading
Loading
Loading
Loading
+14 −0
Original line number Original line Diff line number Diff line
@@ -1731,6 +1731,20 @@ public class Notification implements Parcelable
        return contentView != null || extras.getBoolean(Builder.EXTRA_REBUILD_CONTENT_VIEW);
        return contentView != null || extras.getBoolean(Builder.EXTRA_REBUILD_CONTENT_VIEW);
    }
    }


    /**
     * @hide
     */
    public boolean isGroupSummary() {
        return mGroupKey != null && (flags & FLAG_GROUP_SUMMARY) != 0;
    }

    /**
     * @hide
     */
    public boolean isGroupChild() {
        return mGroupKey != null && (flags & FLAG_GROUP_SUMMARY) == 0;
    }

    /**
    /**
     * Builder class for {@link Notification} objects.
     * Builder class for {@link Notification} objects.
     *
     *
+27 −38
Original line number Original line Diff line number Diff line
@@ -36,7 +36,6 @@ import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.database.ContentObserver;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.net.Uri;
import android.os.Build;
import android.os.Build;
@@ -96,7 +95,8 @@ import static com.android.keyguard.KeyguardHostView.OnDismissAction;


public abstract class BaseStatusBar extends SystemUI implements
public abstract class BaseStatusBar extends SystemUI implements
        CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
        CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
        RecentsComponent.Callbacks, ExpandableNotificationRow.ExpansionLogger {
        RecentsComponent.Callbacks, ExpandableNotificationRow.ExpansionLogger,
        NotificationData.Environment {
    public static final String TAG = "StatusBar";
    public static final String TAG = "StatusBar";
    public static final boolean DEBUG = false;
    public static final boolean DEBUG = false;
    public static final boolean MULTIUSER_DEBUG = false;
    public static final boolean MULTIUSER_DEBUG = false;
@@ -132,7 +132,7 @@ public abstract class BaseStatusBar extends SystemUI implements
    protected H mHandler = createHandler();
    protected H mHandler = createHandler();


    // all notifications
    // all notifications
    protected NotificationData mNotificationData = new NotificationData();
    protected NotificationData mNotificationData;
    protected NotificationStackScrollLayout mStackScroller;
    protected NotificationStackScrollLayout mStackScroller;


    // for heads up notifications
    // for heads up notifications
@@ -201,6 +201,7 @@ public abstract class BaseStatusBar extends SystemUI implements
    protected NotificationOverflowContainer mKeyguardIconOverflowContainer;
    protected NotificationOverflowContainer mKeyguardIconOverflowContainer;
    protected DismissView mDismissView;
    protected DismissView mDismissView;


    @Override  // NotificationData.Environment
    public boolean isDeviceProvisioned() {
    public boolean isDeviceProvisioned() {
        return mDeviceProvisioned;
        return mDeviceProvisioned;
    }
    }
@@ -304,10 +305,6 @@ public abstract class BaseStatusBar extends SystemUI implements
                @Override
                @Override
                public void run() {
                public void run() {
                    for (StatusBarNotification sbn : notifications) {
                    for (StatusBarNotification sbn : notifications) {
                        if (shouldFilterOut(sbn.getNotification())) {
                            if (DEBUG) Log.d(TAG, "Ignoring notification: " + sbn);
                            continue;
                        }
                        addNotification(sbn, currentRanking);
                        addNotification(sbn, currentRanking);
                    }
                    }
                }
                }
@@ -322,20 +319,8 @@ public abstract class BaseStatusBar extends SystemUI implements
                @Override
                @Override
                public void run() {
                public void run() {
                    Notification n = sbn.getNotification();
                    Notification n = sbn.getNotification();
                    boolean isUpdate = mNotificationData.findByKey(sbn.getKey()) != null
                    boolean isUpdate = mNotificationData.get(sbn.getKey()) != null
                            || isHeadsUp(sbn.getKey());
                            || isHeadsUp(sbn.getKey());
                    if (shouldFilterOut(n)) {
                        if (DEBUG) Log.d(TAG, "Ignoring notification: " + sbn);
                        // If this is an update, i.e. the notification existed
                        // before but wasn't filtered out, remove the old
                        // instance. Otherwise just update the ranking.
                        if (isUpdate) {
                            removeNotification(sbn.getKey(), rankingMap);
                        } else {
                            updateNotificationRanking(rankingMap);
                        }
                        return;
                    }
                    if (isUpdate) {
                    if (isUpdate) {
                        updateNotification(sbn, rankingMap);
                        updateNotification(sbn, rankingMap);
                    } else {
                    } else {
@@ -368,11 +353,6 @@ public abstract class BaseStatusBar extends SystemUI implements
            });
            });
        }
        }


        private boolean shouldFilterOut(Notification n) {
            // Don't accept group children.
            return n.getGroup() != null
                    && (n.flags & Notification.FLAG_GROUP_SUMMARY) == 0;
        }
    };
    };


    private void updateCurrentProfilesCache() {
    private void updateCurrentProfilesCache() {
@@ -391,6 +371,8 @@ public abstract class BaseStatusBar extends SystemUI implements
        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
        mDisplay = mWindowManager.getDefaultDisplay();
        mDisplay = mWindowManager.getDefaultDisplay();


        mNotificationData = new NotificationData(this);

        mDreamManager = IDreamManager.Stub.asInterface(
        mDreamManager = IDreamManager.Stub.asInterface(
                ServiceManager.checkService(DreamService.DREAM_SERVICE));
                ServiceManager.checkService(DreamService.DREAM_SERVICE));
        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -499,7 +481,8 @@ public abstract class BaseStatusBar extends SystemUI implements
      return mHeadsUpNotificationView != null && mHeadsUpNotificationView.isShowing(key);
      return mHeadsUpNotificationView != null && mHeadsUpNotificationView.isShowing(key);
    }
    }


    public boolean notificationIsForCurrentProfiles(StatusBarNotification n) {
    @Override  // NotificationData.Environment
    public boolean isNotificationForCurrentProfiles(StatusBarNotification n) {
        final int thisUserId = mCurrentUserId;
        final int thisUserId = mCurrentUserId;
        final int notificationUserId = n.getUserId();
        final int notificationUserId = n.getUserId();
        if (DEBUG && MULTIUSER_DEBUG) {
        if (DEBUG && MULTIUSER_DEBUG) {
@@ -881,6 +864,16 @@ public abstract class BaseStatusBar extends SystemUI implements
        return mUsersAllowingPrivateNotifications.get(userHandle);
        return mUsersAllowingPrivateNotifications.get(userHandle);
    }
    }


    /**
     * Returns true if we're on a secure lockscreen and the user wants to hide "sensitive"
     * notification data. If so, private notifications should show their (possibly
     * auto-generated) publicVersion, and secret notifications should be totally invisible.
     */
    @Override  // NotificationData.Environment
    public boolean shouldHideSensitiveContents(int userid) {
        return isLockscreenPublicMode() && !userAllowsPrivateNotificationsInPublic(userid);
    }

    public void onNotificationClear(StatusBarNotification notification) {
    public void onNotificationClear(StatusBarNotification notification) {
        try {
        try {
            mBarService.onNotificationClear(
            mBarService.onNotificationClear(
@@ -1381,11 +1374,14 @@ public abstract class BaseStatusBar extends SystemUI implements
    protected void updateRowStates() {
    protected void updateRowStates() {
        int maxKeyguardNotifications = getMaxKeyguardNotifications();
        int maxKeyguardNotifications = getMaxKeyguardNotifications();
        mKeyguardIconOverflowContainer.getIconsView().removeAllViews();
        mKeyguardIconOverflowContainer.getIconsView().removeAllViews();
        final int N = mNotificationData.size();

        ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
        final int N = activeNotifications.size();

        int visibleNotifications = 0;
        int visibleNotifications = 0;
        boolean onKeyguard = mState == StatusBarState.KEYGUARD;
        boolean onKeyguard = mState == StatusBarState.KEYGUARD;
        for (int i = 0; i < N; i++) {
        for (int i = 0; i < N; i++) {
            NotificationData.Entry entry = mNotificationData.get(i);
            NotificationData.Entry entry = activeNotifications.get(i);
            if (onKeyguard) {
            if (onKeyguard) {
                entry.row.setExpansionDisabled(true);
                entry.row.setExpansionDisabled(true);
            } else {
            } else {
@@ -1461,7 +1457,7 @@ public abstract class BaseStatusBar extends SystemUI implements
        if (wasHeadsUp) {
        if (wasHeadsUp) {
            oldEntry = mHeadsUpNotificationView.getEntry();
            oldEntry = mHeadsUpNotificationView.getEntry();
        } else {
        } else {
            oldEntry = mNotificationData.findByKey(key);
            oldEntry = mNotificationData.get(key);
        }
        }
        if (oldEntry == null) {
        if (oldEntry == null) {
            return;
            return;
@@ -1620,6 +1616,7 @@ public abstract class BaseStatusBar extends SystemUI implements
                            notification.getNotification().tickerText);
                            notification.getNotification().tickerText);
                    oldEntry.icon.set(ic);
                    oldEntry.icon.set(ic);
                    inflateViews(oldEntry, mStackScroller, wasHeadsUp);
                    inflateViews(oldEntry, mStackScroller, wasHeadsUp);
                    mNotificationData.updateRanking(ranking);
                    updateNotifications();
                    updateNotifications();
                }
                }
            }
            }
@@ -1630,7 +1627,7 @@ public abstract class BaseStatusBar extends SystemUI implements
        updateNotificationVetoButton(oldEntry.row, notification);
        updateNotificationVetoButton(oldEntry.row, notification);


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


        // Restart the ticker if it's still running
        // Restart the ticker if it's still running
@@ -1725,14 +1722,6 @@ public abstract class BaseStatusBar extends SystemUI implements
        return interrupt;
        return interrupt;
    }
    }


    // Q: What kinds of notifications should show during setup?
    // A: Almost none! Only things coming from the system (package is "android") that also
    // have special "kind" tags marking them as relevant for setup (see below).
    protected boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) {
        return "android".equals(sbn.getPackageName())
                && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP);
    }

    public boolean inKeyguardRestrictedInputMode() {
    public boolean inKeyguardRestrictedInputMode() {
        return KeyguardTouchDelegate.getInstance(mContext).isInputRestricted();
        return KeyguardTouchDelegate.getInstance(mContext).isInputRestricted();
    }
    }
+136 −52
Original line number Original line Diff line number Diff line
@@ -20,18 +20,22 @@ import android.app.Notification;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.view.View;
import android.view.View;


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


/**
/**
 * The list of currently displaying notifications.
 * The list of currently displaying notifications.
 *
 * TODO: Rename to NotificationList.
 */
 */
public class NotificationData {
public class NotificationData {

    private final Environment mEnvironment;

    public static final class Entry {
    public static final class Entry {
        public String key;
        public String key;
        public StatusBarNotification notification;
        public StatusBarNotification notification;
@@ -44,7 +48,6 @@ public class NotificationData {
        public boolean autoRedacted; // whether the redacted notification was generated by us
        public boolean autoRedacted; // whether the redacted notification was generated by us
        public boolean legacy; // whether the notification has a legacy, dark background
        public boolean legacy; // whether the notification has a legacy, dark background


        public Entry() {}
        public Entry(StatusBarNotification n, StatusBarIconView ic) {
        public Entry(StatusBarNotification n, StatusBarIconView ic) {
            this.key = n.getKey();
            this.key = n.getKey();
            this.notification = n;
            this.notification = n;
@@ -58,12 +61,6 @@ public class NotificationData {
            return expandedBig;
            return expandedBig;
        }
        }
        public View getPublicContentView() { return expandedPublic; }
        public View getPublicContentView() { return expandedPublic; }
        /**
         * Set the flag indicating that this is being touched by the user.
         */
        public void setUserLocked(boolean userLocked) {
            row.setUserLocked(userLocked);
        }


        public void setInterruption() {
        public void setInterruption() {
            interruption = true;
            interruption = true;
@@ -90,7 +87,9 @@ public class NotificationData {
        }
        }
    }
    }


    private final ArrayList<Entry> mEntries = new ArrayList<Entry>();
    private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
    private final ArrayList<Entry> mSortedAndFiltered = new ArrayList<>();

    private RankingMap mRankingMap;
    private RankingMap mRankingMap;
    private final Ranking mTmpRanking = new Ranking();
    private final Ranking mTmpRanking = new Ranking();
    private final Comparator<Entry> mRankingComparator = new Comparator<Entry>() {
    private final Comparator<Entry> mRankingComparator = new Comparator<Entry>() {
@@ -118,36 +117,37 @@ public class NotificationData {
        }
        }
    };
    };


    public int size() {
    public NotificationData(Environment environment) {
        return mEntries.size();
        mEnvironment = environment;
    }
    }


    public Entry get(int i) {
    /**
        return mEntries.get(i);
     * Returns the sorted list of active notifications (depending on {@link Environment}
     *
     * <p>
     * This call doesn't update the list of active notifications. Call {@link #filterAndSort()}
     * when the environment changes.
     * <p>
     * Don't hold on to or modify the returned list.
     */
    public ArrayList<Entry> getActiveNotifications() {
        return mSortedAndFiltered;
    }
    }


    public Entry findByKey(String key) {
    public Entry get(String key) {
        for (Entry e : mEntries) {
        return mEntries.get(key);
            if (e.key.equals(key)) {
                return e;
            }
        }
        return null;
    }
    }


    public void add(Entry entry, RankingMap ranking) {
    public void add(Entry entry, RankingMap ranking) {
        mEntries.add(entry);
        mEntries.put(entry.notification.getKey(), entry);
        updateRankingAndSort(ranking);
        updateRankingAndSort(ranking);
    }
    }


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


    public void updateRanking(RankingMap ranking) {
    public void updateRanking(RankingMap ranking) {
@@ -155,45 +155,79 @@ public class NotificationData {
    }
    }


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


    private void updateRankingAndSort(RankingMap ranking) {
    private void updateRankingAndSort(RankingMap ranking) {
        if (ranking != null) {
        if (ranking != null) {
            mRankingMap = ranking;
            mRankingMap = ranking;
        }
        }
        Collections.sort(mEntries, mRankingComparator);
        filterAndSort();
    }
    }


    /**
    // TODO: This should not be public. Instead the Environment should notify this class when
     * Return whether there are any visible items (i.e. items without an error).
    // anything changed, and this class should call back the UI so it updates itself.
     */
    public void filterAndSort() {
    public boolean hasVisibleItems() {
        mSortedAndFiltered.clear();
        for (Entry e : mEntries) {

            if (e.expanded != null) { // the view successfully inflated
        ArraySet<String> groupsWithSummaries = null;
        final int N = mEntries.size();
        for (int i = 0; i < N; i++) {
            Entry entry = mEntries.valueAt(i);
            StatusBarNotification sbn = entry.notification;

            if (shouldFilterOut(sbn)) {
                continue;
            }

            if (sbn.getNotification().isGroupSummary()) {
                if (groupsWithSummaries == null) {
                    groupsWithSummaries = new ArraySet<>();
                }
                groupsWithSummaries.add(sbn.getGroupKey());
            }
            mSortedAndFiltered.add(entry);
        }

        // Second pass: Filter out group children with summary.
        if (groupsWithSummaries != null) {
            final int M = mSortedAndFiltered.size();
            for (int i = M - 1; i >= 0; i--) {
                Entry ent = mSortedAndFiltered.get(i);
                StatusBarNotification sbn = ent.notification;
                if (sbn.getNotification().isGroupChild() &&
                        groupsWithSummaries.contains(sbn.getGroupKey())) {
                    mSortedAndFiltered.remove(i);
                }
            }
        }

        Collections.sort(mSortedAndFiltered, mRankingComparator);
    }

    private boolean shouldFilterOut(StatusBarNotification sbn) {
        if (!(mEnvironment.isDeviceProvisioned() ||
                showNotificationEvenIfUnprovisioned(sbn))) {
            return true;
            return true;
        }
        }

        if (!mEnvironment.isNotificationForCurrentProfiles(sbn)) {
            return true;
        }

        if (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET &&
                mEnvironment.shouldHideSensitiveContents(sbn.getUserId())) {
            return true;
        }
        }
        return false;
        return false;
    }
    }


    /**
    /**
     * Return whether there are any clearable items (that aren't errors).
     * Return whether there are any clearable notifications (that aren't errors).
     */
     */
    public boolean hasClearableItems() {
    public boolean hasActiveClearableNotifications() {
        for (Entry e : mEntries) {
        for (Entry e : mSortedAndFiltered) {
            if (e.expanded != null) { // the view successfully inflated
            if (e.expanded != null) { // the view successfully inflated
                if (e.notification.isClearable()) {
                if (e.notification.isClearable()) {
                    return true;
                    return true;
@@ -202,4 +236,54 @@ public class NotificationData {
        }
        }
        return false;
        return false;
    }
    }

    // Q: What kinds of notifications should show during setup?
    // A: Almost none! Only things coming from the system (package is "android") that also
    // have special "kind" tags marking them as relevant for setup (see below).
    public static boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) {
        return "android".equals(sbn.getPackageName())
                && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP);
    }

    public void dump(PrintWriter pw, String indent) {
        int N = mSortedAndFiltered.size();
        pw.print(indent);
        pw.println("active notifications: " + N);
        for (int i = 0; i < N; i++) {
            NotificationData.Entry e = mSortedAndFiltered.get(i);
            dumpEntry(pw, indent, i, e);
        }

        int M = mEntries.size();
        pw.print(indent);
        pw.println("inactive notifications: " + M);
        for (int i = 0; i < M; i++) {
            Entry entry = mEntries.valueAt(i);
            if (!mSortedAndFiltered.contains(entry)) {
                dumpEntry(pw, indent, i, entry);
            }
        }
    }

    private void dumpEntry(PrintWriter pw, String indent, int i, Entry e) {
        pw.print(indent);
        pw.println("  [" + i + "] key=" + e.key + " icon=" + e.icon);
        StatusBarNotification n = e.notification;
        pw.print(indent);
        pw.println("      pkg=" + n.getPackageName() + " id=" + n.getId() + " score=" + n
                .getScore());
        pw.print(indent);
        pw.println("      notification=" + n.getNotification());
        pw.print(indent);
        pw.println("      tickerText=\"" + n.getNotification().tickerText + "\"");
    }

    /**
     * Provides access to keyguard state and user settings dependent data.
     */
    public interface Environment {
        public boolean shouldHideSensitiveContents(int userId);
        public boolean isDeviceProvisioned();
        public boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
    }
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -1346,7 +1346,7 @@ public class NotificationPanelView extends PanelView implements
        float factor = 1f;
        float factor = 1f;
        if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
        if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
            factor = 0.6f;
            factor = 0.6f;
        } else if (!mStatusBar.hasNotifications()) {
        } else if (!mStatusBar.hasActiveNotifications()) {
            factor = 0.4f;
            factor = 0.4f;
        }
        }
        mEmptyDragAmount = amount * factor;
        mEmptyDragAmount = amount * factor;
+52 −103

File changed.

Preview size limit exceeded, changes collapsed.