diff options
16 files changed, 372 insertions, 187 deletions
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 38293bf2defd..61210d3e0011 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -480,4 +480,7 @@ <!-- Preferred refresh rate at keyguard, if supported by the display --> <integer name="config_keyguardRefreshRate">-1</integer> + <!-- Whether or not to add a "people" notifications section --> + <bool name="config_usePeopleFiltering">false</bool> + </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java index 289277e63760..f782fab7e49f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar; import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED; import static com.android.systemui.DejankUtils.whitelistIpcs; +import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT; import android.app.ActivityManager; import android.app.KeyguardManager; @@ -316,7 +317,7 @@ public class NotificationLockscreenUserManagerImpl implements boolean exceedsPriorityThreshold; if (NotificationUtils.useNewInterruptionModel(mContext) && hideSilentNotificationsOnLockscreen()) { - exceedsPriorityThreshold = entry.isTopBucket(); + exceedsPriorityThreshold = entry.getBucket() != BUCKET_SILENT; } else { exceedsPriorityThreshold = !getEntryManager().getNotificationData().isAmbient(entry.key); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index 4a27a4ed31a1..b6b149dd049a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -124,7 +124,7 @@ public class NotificationEntryManager implements @Inject public NotificationEntryManager(Context context) { - mNotificationData = new NotificationData(); + mNotificationData = new NotificationData(context); } /** Adds a {@link NotificationEntryListener}. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java index 1af47dd0f4c0..dfbbf987dd96 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java @@ -36,6 +36,7 @@ public class NotificationUtils { private static final int[] sLocationOffset = new int[2]; @Nullable private static Boolean sUseNewInterruptionModel = null; + @Nullable private static Boolean sUsePeopleFiltering = null; public static boolean isGrayscale(ImageView v, ContrastColorUtil colorUtil) { Object isGrayscale = v.getTag(R.id.icon_is_grayscale); @@ -87,4 +88,17 @@ public class NotificationUtils { } return sUseNewInterruptionModel; } + + /** + * Caches and returns the value of the people filtering setting. Cannot change except through + * process restarts. + */ + public static boolean usePeopleFiltering(Context context) { + if (sUsePeopleFiltering == null) { + sUsePeopleFiltering = context.getResources().getBoolean( + R.bool.config_usePeopleFiltering); + } + + return sUsePeopleFiltering; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java index 727e245ae38b..aacb2dd0682f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java @@ -16,10 +16,15 @@ package com.android.systemui.statusbar.notification.collection; +import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING; +import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE; +import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT; + import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.Person; +import android.content.Context; import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.SnoozeCriterion; @@ -30,6 +35,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dependency; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.notification.NotificationFilter; +import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.policy.HeadsUpManager; @@ -44,6 +50,7 @@ import java.util.Objects; * The list of currently displaying notifications. */ public class NotificationData { + private static final String TAG = "NotificationData"; private final NotificationFilter mNotificationFilter = Dependency.get(NotificationFilter.class); @@ -64,6 +71,11 @@ public class NotificationData { private RankingMap mRankingMap; private final Ranking mTmpRanking = new Ranking(); + private final boolean mUsePeopleFiltering; + + public NotificationData(Context context) { + mUsePeopleFiltering = NotificationUtils.usePeopleFiltering(context); + } public void setHeadsUpManager(HeadsUpManager headsUpManager) { mHeadsUpManager = headsUpManager; @@ -72,52 +84,25 @@ public class NotificationData { @VisibleForTesting protected final Comparator<NotificationEntry> mRankingComparator = new Comparator<NotificationEntry>() { - private final Ranking mRankingA = new Ranking(); - private final Ranking mRankingB = new Ranking(); - @Override public int compare(NotificationEntry a, NotificationEntry b) { final StatusBarNotification na = a.notification; final StatusBarNotification nb = b.notification; - int aImportance = NotificationManager.IMPORTANCE_DEFAULT; - int bImportance = NotificationManager.IMPORTANCE_DEFAULT; - int aRank = 0; - int bRank = 0; - - if (mRankingMap != null) { - // RankingMap as received from NoMan - getRanking(a.key, mRankingA); - getRanking(b.key, mRankingB); - aImportance = mRankingA.getImportance(); - bImportance = mRankingB.getImportance(); - aRank = mRankingA.getRank(); - bRank = mRankingB.getRank(); - } + int aRank = getRank(a.key); + int bRank = getRank(b.key); - String mediaNotification = getMediaManager().getMediaNotificationKey(); + boolean aMedia = isImportantMedia(a); + boolean bMedia = isImportantMedia(b); - // IMPORTANCE_MIN media streams are allowed to drift to the bottom - final boolean aMedia = a.key.equals(mediaNotification) - && aImportance > NotificationManager.IMPORTANCE_MIN; - final boolean bMedia = b.key.equals(mediaNotification) - && bImportance > NotificationManager.IMPORTANCE_MIN; + boolean aSystemMax = isSystemMax(a); + boolean bSystemMax = isSystemMax(b); - boolean aSystemMax = aImportance >= NotificationManager.IMPORTANCE_HIGH - && isSystemNotification(na); - boolean bSystemMax = bImportance >= NotificationManager.IMPORTANCE_HIGH - && isSystemNotification(nb); + boolean aHeadsUp = a.isRowHeadsUp(); + boolean bHeadsUp = b.isRowHeadsUp(); - - boolean aHeadsUp = a.getRow().isHeadsUp(); - boolean bHeadsUp = b.getRow().isHeadsUp(); - - // HACK: This should really go elsewhere, but it's currently not straightforward to - // extract the comparison code and we're guaranteed to touch every element, so this is - // the best place to set the buckets for the moment. - a.setIsTopBucket(aHeadsUp || aMedia || aSystemMax || a.isHighPriority()); - b.setIsTopBucket(bHeadsUp || bMedia || bSystemMax || b.isHighPriority()); - - if (aHeadsUp != bHeadsUp) { + if (mUsePeopleFiltering && a.hasAssociatedPeople() != b.hasAssociatedPeople()) { + return a.hasAssociatedPeople() ? -1 : 1; + } else if (aHeadsUp != bHeadsUp) { return aHeadsUp ? -1 : 1; } else if (aHeadsUp) { // Provide consistent ranking with headsUpManager @@ -317,14 +302,6 @@ public class NotificationData { return Ranking.VISIBILITY_NO_OVERRIDE; } - public int getImportance(String key) { - if (mRankingMap != null) { - getRanking(key, mTmpRanking); - return mTmpRanking.getImportance(); - } - return NotificationManager.IMPORTANCE_UNSPECIFIED; - } - public List<SnoozeCriterion> getSnoozeCriteria(String key) { if (mRankingMap != null) { getRanking(key, mTmpRanking); @@ -349,6 +326,22 @@ public class NotificationData { return 0; } + private boolean isImportantMedia(NotificationEntry e) { + int importance = e.ranking().getImportance(); + boolean media = e.key.equals(getMediaManager().getMediaNotificationKey()) + && importance > NotificationManager.IMPORTANCE_MIN; + + return media; + } + + private boolean isSystemMax(NotificationEntry e) { + int importance = e.ranking().getImportance(); + boolean sys = importance >= NotificationManager.IMPORTANCE_HIGH + && isSystemNotification(e.notification); + + return sys; + } + public boolean shouldHide(String key) { if (mRankingMap != null) { getRanking(key, mTmpRanking); @@ -414,13 +407,37 @@ public class NotificationData { } } - if (mSortedAndFiltered.size() == 1) { - // HACK: We need the comparator to run on all children in order to set the - // isHighPriority field. If there is only one child, then the comparison won't be run, - // so we have to trigger it manually. Get rid of this code as soon as possible. - mRankingComparator.compare(mSortedAndFiltered.get(0), mSortedAndFiltered.get(0)); + Collections.sort(mSortedAndFiltered, mRankingComparator); + + int bucket = BUCKET_PEOPLE; + for (NotificationEntry e : mSortedAndFiltered) { + assignBucketForEntry(e); + if (e.getBucket() < bucket) { + android.util.Log.wtf(TAG, "Detected non-contiguous bucket!"); + } + bucket = e.getBucket(); + } + } + + private void assignBucketForEntry(NotificationEntry e) { + boolean isHeadsUp = e.isRowHeadsUp(); + boolean isMedia = isImportantMedia(e); + boolean isSystemMax = isSystemMax(e); + + setBucket(e, isHeadsUp, isMedia, isSystemMax); + } + + private void setBucket( + NotificationEntry e, + boolean isHeadsUp, + boolean isMedia, + boolean isSystemMax) { + if (mUsePeopleFiltering && e.hasAssociatedPeople()) { + e.setBucket(BUCKET_PEOPLE); + } else if (isHeadsUp || isMedia || isSystemMax || e.isHighPriority()) { + e.setBucket(BUCKET_ALERTING); } else { - Collections.sort(mSortedAndFiltered, mRankingComparator); + e.setBucket(BUCKET_SILENT); } } @@ -466,6 +483,19 @@ public class NotificationData { } /** + * Get the current set of buckets for notification entries, as defined here + */ + public static int[] getNotificationBuckets(Context context) { + if (NotificationUtils.usePeopleFiltering(context)) { + return new int[]{BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT}; + } else if (NotificationUtils.useNewInterruptionModel(context)) { + return new int[]{BUCKET_ALERTING, BUCKET_SILENT}; + } else { + return new int[]{BUCKET_ALERTING}; + } + } + + /** * Provides access to keyguard state and user settings dependent data. */ public interface KeyguardEnvironment { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index 71cdcf748679..a33d23c0b5d5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -21,6 +21,7 @@ import static android.app.Notification.CATEGORY_CALL; import static android.app.Notification.CATEGORY_EVENT; import static android.app.Notification.CATEGORY_MESSAGE; import static android.app.Notification.CATEGORY_REMINDER; +import static android.app.Notification.EXTRA_MESSAGES; import static android.app.Notification.FLAG_BUBBLE; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE; @@ -29,6 +30,8 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICAT import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; +import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING; + import android.annotation.NonNull; import android.app.Notification; import android.app.Notification.MessagingStyle.Message; @@ -38,6 +41,7 @@ import android.app.Person; import android.content.Context; import android.graphics.drawable.Icon; import android.os.Bundle; +import android.os.Parcelable; import android.os.SystemClock; import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.SnoozeCriterion; @@ -58,6 +62,7 @@ import com.android.systemui.statusbar.notification.InflationException; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag; import com.android.systemui.statusbar.notification.row.NotificationGuts; +import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager; import java.util.ArrayList; import java.util.List; @@ -99,6 +104,7 @@ public final class NotificationEntry { public int targetSdk; private long lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET; public CharSequence remoteInputText; + private final List<Person> mAssociatedPeople = new ArrayList<>(); /** * If {@link android.app.RemoteInput#getEditChoicesBeforeSending} is enabled, and the user is @@ -140,12 +146,11 @@ public final class NotificationEntry { */ private boolean mHighPriority; - private boolean mIsTopBucket; - private boolean mSensitive = true; private Runnable mOnSensitiveChangedListener; private boolean mAutoHeadsUp; private boolean mPulseSupressed; + private int mBucket = BUCKET_ALERTING; public NotificationEntry( @NonNull StatusBarNotification sbn, @@ -173,11 +178,12 @@ public final class NotificationEntry { * TODO: Make this package-private */ public void setNotification(StatusBarNotification sbn) { - if (!sbn.getKey().equals(key)) { + if (sbn.getKey() != null && key != null && !sbn.getKey().equals(key)) { throw new IllegalArgumentException("New key " + sbn.getKey() + " doesn't match existing key " + key); } notification = sbn; + updatePeopleList(); } /** @@ -263,20 +269,39 @@ public final class NotificationEntry { this.mHighPriority = highPriority; } - /** - * @return True if the notif should appear in the "top" or "important" section of notifications - * (as opposed to the "bottom" or "silent" section). This is usually the same as - * {@link #isHighPriority()}, but there are certain exceptions, such as media notifs. - */ - public boolean isTopBucket() { - return mIsTopBucket; + public boolean isBubble() { + return (notification.getNotification().flags & FLAG_BUBBLE) != 0; } - public void setIsTopBucket(boolean isTopBucket) { - mIsTopBucket = isTopBucket; + + private void updatePeopleList() { + mAssociatedPeople.clear(); + + Bundle extras = notification.getNotification().extras; + if (extras == null) { + return; + } + + List<Person> p = extras.getParcelableArrayList(Notification.EXTRA_PEOPLE_LIST); + + if (p != null) { + mAssociatedPeople.addAll(p); + } + + if (Notification.MessagingStyle.class.equals( + notification.getNotification().getNotificationStyle())) { + final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES); + if (!ArrayUtils.isEmpty(messages)) { + for (Notification.MessagingStyle.Message message : + Notification.MessagingStyle.Message + .getMessagesFromBundleArray(messages)) { + mAssociatedPeople.add(message.getSenderPerson()); + } + } + } } - public boolean isBubble() { - return (notification.getNotification().flags & FLAG_BUBBLE) != 0; + boolean hasAssociatedPeople() { + return mAssociatedPeople.size() > 0; } /** @@ -295,6 +320,15 @@ public final class NotificationEntry { } } + @NotificationSectionsManager.PriorityBucket + public int getBucket() { + return mBucket; + } + + public void setBucket(@NotificationSectionsManager.PriorityBucket int bucket) { + mBucket = bucket; + } + public ExpandableNotificationRow getRow() { return row; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java index 422184699952..ec0c6348fd89 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java @@ -16,11 +16,10 @@ package com.android.systemui.statusbar.notification.stack; -import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.NUM_SECTIONS; - - +import android.content.Context; import android.util.MathUtils; +import com.android.systemui.statusbar.notification.collection.NotificationData; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -51,11 +50,14 @@ public class NotificationRoundnessManager implements OnHeadsUpChangedListener { private float mAppearFraction; @Inject - NotificationRoundnessManager(KeyguardBypassController keyguardBypassController) { - mFirstInSectionViews = new ActivatableNotificationView[NUM_SECTIONS]; - mLastInSectionViews = new ActivatableNotificationView[NUM_SECTIONS]; - mTmpFirstInSectionViews = new ActivatableNotificationView[NUM_SECTIONS]; - mTmpLastInSectionViews = new ActivatableNotificationView[NUM_SECTIONS]; + NotificationRoundnessManager( + KeyguardBypassController keyguardBypassController, + Context context) { + int numberOfSections = NotificationData.getNotificationBuckets(context).length; + mFirstInSectionViews = new ActivatableNotificationView[numberOfSections]; + mLastInSectionViews = new ActivatableNotificationView[numberOfSections]; + mTmpFirstInSectionViews = new ActivatableNotificationView[numberOfSections]; + mTmpLastInSectionViews = new ActivatableNotificationView[numberOfSections]; mBypassController = keyguardBypassController; } @@ -157,7 +159,7 @@ public class NotificationRoundnessManager implements OnHeadsUpChangedListener { public void updateRoundedChildren(NotificationSection[] sections) { boolean anyChanged = false; - for (int i = 0; i < NUM_SECTIONS; i++) { + for (int i = 0; i < sections.length; i++) { mTmpFirstInSectionViews[i] = mFirstInSectionViews[i]; mTmpLastInSectionViews[i] = mLastInSectionViews[i]; mFirstInSectionViews[i] = sections[i].getFirstVisibleChild(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java index f39ed2e89432..9d456ef785a8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java @@ -33,6 +33,7 @@ import com.android.systemui.statusbar.notification.row.ActivatableNotificationVi * bounds change. */ class NotificationSection { + private @NotificationSectionsManager.PriorityBucket int mBucket; private View mOwningView; private Rect mBounds = new Rect(); private Rect mCurrentBounds = new Rect(-1, -1, -1, -1); @@ -43,8 +44,9 @@ class NotificationSection { private ActivatableNotificationView mFirstVisibleChild; private ActivatableNotificationView mLastVisibleChild; - NotificationSection(View owningView) { + NotificationSection(View owningView, @NotificationSectionsManager.PriorityBucket int bucket) { mOwningView = owningView; + mBucket = bucket; } public void cancelAnimators() { @@ -72,6 +74,11 @@ class NotificationSection { return mBottomAnimator != null || mTopAnimator != null; } + @NotificationSectionsManager.PriorityBucket + public int getBucket() { + return mBucket; + } + public void startBackgroundAnimation(boolean animateTop, boolean animateBottom) { // Left and right bounds are always applied immediately. mCurrentBounds.left = mBounds.left; @@ -199,12 +206,16 @@ class NotificationSection { return mLastVisibleChild; } - public void setFirstVisibleChild(ActivatableNotificationView child) { + public boolean setFirstVisibleChild(ActivatableNotificationView child) { + boolean changed = mFirstVisibleChild != child; mFirstVisibleChild = child; + return changed; } - public void setLastVisibleChild(ActivatableNotificationView child) { + public boolean setLastVisibleChild(ActivatableNotificationView child) { + boolean changed = mLastVisibleChild != child; mLastVisibleChild = child; + return changed; } public void resetCurrentBounds() { @@ -291,5 +302,4 @@ class NotificationSection { mBounds.bottom = bottom; return bottom; } - } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java index d119fb79e4c6..d0444ae81b89 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java @@ -18,6 +18,10 @@ package com.android.systemui.statusbar.notification.stack; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Intent; import android.provider.Settings; @@ -34,23 +38,31 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; +import java.lang.annotation.Retention; +import java.util.ArrayList; +import java.util.List; + /** * Manages the boundaries of the two notification sections (high priority and low priority). Also * shows/hides the headers for those sections where appropriate. * * TODO: Move remaining sections logic from NSSL into this class. */ -class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvider { +public class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvider { + + private static final String TAG = "NotifSectionsManager"; + private static final boolean DEBUG = false; + private final NotificationStackScrollLayout mParent; private final ActivityStarter mActivityStarter; private final StatusBarStateController mStatusBarStateController; private final ConfigurationController mConfigurationController; - private final boolean mUseMultipleSections; + private final int mNumberOfSections; private boolean mInitialized = false; private SectionHeaderView mGentleHeader; private boolean mGentleHeaderVisible = false; - @Nullable private ExpandableNotificationRow mFirstGentleNotif; + @Nullable private View.OnClickListener mOnClearGentleNotifsClickListener; NotificationSectionsManager( @@ -58,12 +70,21 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide ActivityStarter activityStarter, StatusBarStateController statusBarStateController, ConfigurationController configurationController, - boolean useMultipleSections) { + int numberOfSections) { mParent = parent; mActivityStarter = activityStarter; mStatusBarStateController = statusBarStateController; mConfigurationController = configurationController; - mUseMultipleSections = useMultipleSections; + mNumberOfSections = numberOfSections; + } + + NotificationSection[] createSectionsForBuckets(int[] buckets) { + NotificationSection[] sections = new NotificationSection[buckets.length]; + for (int i = 0; i < buckets.length; i++) { + sections[i] = new NotificationSection(mParent, buckets[i] /* bucket */); + } + + return sections; } /** Must be called before use. */ @@ -111,8 +132,38 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide } @Override - public boolean beginsSection(View view) { - return view == getFirstLowPriorityChild(); + public boolean beginsSection(@NonNull View view, @Nullable View previous) { + boolean begin = false; + if (view instanceof ExpandableNotificationRow) { + if (previous instanceof ExpandableNotificationRow) { + // If we're drawing the first non-person notification, break out a section + ExpandableNotificationRow curr = (ExpandableNotificationRow) view; + ExpandableNotificationRow prev = (ExpandableNotificationRow) previous; + + begin = curr.getEntry().getBucket() != prev.getEntry().getBucket(); + } + } + + if (!begin) { + begin = view == mGentleHeader; + } + + return begin; + } + + private boolean isUsingMultipleSections() { + return mNumberOfSections > 1; + } + + private @PriorityBucket int getBucket(ActivatableNotificationView view) + throws IllegalArgumentException { + if (view instanceof ExpandableNotificationRow) { + return ((ExpandableNotificationRow) view).getEntry().getBucket(); + } else if (view == mGentleHeader) { + return BUCKET_SILENT; + } + + throw new IllegalArgumentException("I don't know how to find a bucket for this view :("); } /** @@ -120,11 +171,10 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide * bookkeeping and adds/moves/removes section headers if appropriate. */ void updateSectionBoundaries() { - if (!mUseMultipleSections) { + if (!isUsingMultipleSections()) { return; } - mFirstGentleNotif = null; int firstGentleNotifIndex = -1; final int n = mParent.getChildCount(); @@ -133,9 +183,8 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide if (child instanceof ExpandableNotificationRow && child.getVisibility() != View.GONE) { ExpandableNotificationRow row = (ExpandableNotificationRow) child; - if (!row.getEntry().isTopBucket()) { + if (row.getEntry().getBucket() == BUCKET_SILENT) { firstGentleNotifIndex = i; - mFirstGentleNotif = row; break; } } @@ -184,78 +233,73 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide } /** - * Updates the boundaries (as tracked by their first and last views) of the high and low - * priority sections. + * Updates the boundaries (as tracked by their first and last views) of the priority sections. * * @return {@code true} If the last view in the top section changed (so we need to animate). */ - boolean updateFirstAndLastViewsInSections( - final NotificationSection highPrioritySection, - final NotificationSection lowPrioritySection, - ActivatableNotificationView firstChild, - ActivatableNotificationView lastChild) { - if (mUseMultipleSections) { - ActivatableNotificationView previousLastHighPriorityChild = - highPrioritySection.getLastVisibleChild(); - ActivatableNotificationView previousFirstLowPriorityChild = - lowPrioritySection.getFirstVisibleChild(); - ActivatableNotificationView lastHighPriorityChild = getLastHighPriorityChild(); - ActivatableNotificationView firstLowPriorityChild = getFirstLowPriorityChild(); - if (lastHighPriorityChild != null && firstLowPriorityChild != null) { - highPrioritySection.setFirstVisibleChild(firstChild); - highPrioritySection.setLastVisibleChild(lastHighPriorityChild); - lowPrioritySection.setFirstVisibleChild(firstLowPriorityChild); - lowPrioritySection.setLastVisibleChild(lastChild); - } else if (lastHighPriorityChild != null) { - highPrioritySection.setFirstVisibleChild(firstChild); - highPrioritySection.setLastVisibleChild(lastChild); - lowPrioritySection.setFirstVisibleChild(null); - lowPrioritySection.setLastVisibleChild(null); - } else { - highPrioritySection.setFirstVisibleChild(null); - highPrioritySection.setLastVisibleChild(null); - lowPrioritySection.setFirstVisibleChild(firstChild); - lowPrioritySection.setLastVisibleChild(lastChild); + boolean updateFirstAndLastViewsForAllSections( + NotificationSection[] sections, + List<ActivatableNotificationView> children) { + + if (sections.length <= 0 || children.size() <= 0) { + for (NotificationSection s : sections) { + s.setFirstVisibleChild(null); + s.setLastVisibleChild(null); } - return lastHighPriorityChild != previousLastHighPriorityChild - || firstLowPriorityChild != previousFirstLowPriorityChild; - } else { - highPrioritySection.setFirstVisibleChild(firstChild); - highPrioritySection.setLastVisibleChild(lastChild); return false; } - } - @VisibleForTesting - SectionHeaderView getGentleHeaderView() { - return mGentleHeader; - } + boolean changed = false; + ArrayList<ActivatableNotificationView> viewsInBucket = new ArrayList<>(); + for (NotificationSection s : sections) { + int filter = s.getBucket(); + viewsInBucket.clear(); - @Nullable - private ActivatableNotificationView getFirstLowPriorityChild() { - if (mGentleHeaderVisible) { - return mGentleHeader; - } else { - return mFirstGentleNotif; - } - } + //TODO: do this in a single pass, and more better + for (ActivatableNotificationView v : children) { + if (getBucket(v) == filter) { + viewsInBucket.add(v); + } - @Nullable - private ActivatableNotificationView getLastHighPriorityChild() { - ActivatableNotificationView lastChildBeforeGap = null; - int childCount = mParent.getChildCount(); - for (int i = 0; i < childCount; i++) { - View child = mParent.getChildAt(i); - if (child.getVisibility() != View.GONE && child instanceof ExpandableNotificationRow) { - ExpandableNotificationRow row = (ExpandableNotificationRow) child; - if (!row.getEntry().isTopBucket()) { - break; + if (viewsInBucket.size() >= 1) { + changed |= s.setFirstVisibleChild(viewsInBucket.get(0)); + changed |= s.setLastVisibleChild(viewsInBucket.get(viewsInBucket.size() - 1)); } else { - lastChildBeforeGap = row; + changed |= s.setFirstVisibleChild(null); + changed |= s.setLastVisibleChild(null); } } } - return lastChildBeforeGap; + + if (DEBUG) { + logSections(sections); + } + + return changed; + } + + private void logSections(NotificationSection[] sections) { + for (int i = 0; i < sections.length; i++) { + NotificationSection s = sections[i]; + ActivatableNotificationView first = s.getFirstVisibleChild(); + String fs = first == null ? "(null)" + : (first instanceof ExpandableNotificationRow) + ? ((ExpandableNotificationRow) first).getEntry().key + : Integer.toHexString(System.identityHashCode(first)); + ActivatableNotificationView last = s.getLastVisibleChild(); + String ls = last == null ? "(null)" + : (last instanceof ExpandableNotificationRow) + ? ((ExpandableNotificationRow) last).getEntry().key + : Integer.toHexString(System.identityHashCode(last)); + android.util.Log.d(TAG, "updateSections: f=" + fs + " s=" + i); + android.util.Log.d(TAG, "updateSections: l=" + ls + " s=" + i); + } + } + + + @VisibleForTesting + SectionHeaderView getGentleHeaderView() { + return mGentleHeader; } private final ConfigurationListener mConfigurationListener = new ConfigurationListener() { @@ -279,4 +323,20 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide mOnClearGentleNotifsClickListener.onClick(v); } } + + /** + * For now, declare the available notification buckets (sections) here so that other + * presentation code can decide what to do based on an entry's buckets + * + */ + @Retention(SOURCE) + @IntDef(prefix = { "BUCKET_" }, value = { + BUCKET_PEOPLE, + BUCKET_ALERTING, + BUCKET_SILENT + }) + public @interface PriorityBucket {} + public static final int BUCKET_PEOPLE = 0; + public static final int BUCKET_ALERTING = 1; + public static final int BUCKET_SILENT = 2; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 1c9b2256af9b..a67018ef9710 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.stack; import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters; +import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT; import static com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.ANCHOR_SCROLLING; import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE; import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY; @@ -112,6 +113,7 @@ import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.ShadeViewRefactor; import com.android.systemui.statusbar.notification.ShadeViewRefactor.RefactorComponent; import com.android.systemui.statusbar.notification.VisualStabilityManager; +import com.android.systemui.statusbar.notification.collection.NotificationData; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; @@ -172,7 +174,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd * Sentinel value for no current active pointer. Used by {@link #mActivePointerId}. */ private static final int INVALID_POINTER = -1; - static final int NUM_SECTIONS = 2; /** * The distance in pixels between sections when the sections are directly adjacent (no visible * gap is drawn between them). In this case we don't want to round their corners. @@ -351,7 +352,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd return true; } }; - private NotificationSection[] mSections = new NotificationSection[NUM_SECTIONS]; + private NotificationSection[] mSections; private boolean mAnimateNextBackgroundTop; private boolean mAnimateNextBackgroundBottom; private boolean mAnimateNextSectionBoundsChange; @@ -522,9 +523,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd mAllowLongPress = allowLongPress; - for (int i = 0; i < NUM_SECTIONS; i++) { - mSections[i] = new NotificationSection(this); - } mRoundnessManager = notificationRoundnessManager; mHeadsUpManager = headsUpManager; @@ -533,19 +531,21 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd mKeyguardBypassController = keyguardBypassController; mFalsingManager = falsingManager; + int[] buckets = NotificationData.getNotificationBuckets(context); mSectionsManager = new NotificationSectionsManager( this, activityStarter, statusBarStateController, configurationController, - NotificationUtils.useNewInterruptionModel(context)); + buckets.length); mSectionsManager.initialize(LayoutInflater.from(context)); mSectionsManager.setOnClearGentleNotifsClickListener(v -> { // Leave the shade open if there will be other notifs left over to clear final boolean closeShade = !hasActiveClearableNotifications(ROWS_HIGH_PRIORITY); clearNotifications(ROWS_GENTLE, closeShade); }); + mSections = mSectionsManager.createSectionsForBuckets(buckets); mAmbientState = new AmbientState(context, mSectionsManager, mHeadsUpManager); mBgColor = context.getColor(R.color.notification_shade_background_color); @@ -773,7 +773,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd protected void onDraw(Canvas canvas) { if (mShouldDrawNotificationBackground && (mSections[0].getCurrentBounds().top - < mSections[NUM_SECTIONS - 1].getCurrentBounds().bottom + < mSections[mSections.length - 1].getCurrentBounds().bottom || mAmbientState.isDozing())) { drawBackground(canvas); } else if (mInHeadsUpPinnedMode || mHeadsUpAnimatingAway) { @@ -819,7 +819,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd int lockScreenLeft = mSidePaddings; int lockScreenRight = getWidth() - mSidePaddings; int lockScreenTop = mSections[0].getCurrentBounds().top; - int lockScreenBottom = mSections[NUM_SECTIONS - 1].getCurrentBounds().bottom; + int lockScreenBottom = mSections[mSections.length - 1].getCurrentBounds().bottom; int hiddenLeft = getWidth() / 2; int hiddenTop = mTopPadding; @@ -2636,6 +2636,21 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd return null; } + //TODO: We shouldn't have to generate this list every time + private List<ActivatableNotificationView> getChildrenWithBackground() { + ArrayList<ActivatableNotificationView> children = new ArrayList<>(); + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child.getVisibility() != View.GONE && child instanceof ActivatableNotificationView + && child != mShelf) { + children.add((ActivatableNotificationView) child); + } + } + + return children; + } + /** * Fling the scroll view * @@ -3198,8 +3213,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd ActivatableNotificationView firstChild = getFirstChildWithBackground(); ActivatableNotificationView lastChild = getLastChildWithBackground(); - boolean sectionViewsChanged = mSectionsManager.updateFirstAndLastViewsInSections( - mSections[0], mSections[1], firstChild, lastChild); + boolean sectionViewsChanged = mSectionsManager.updateFirstAndLastViewsForAllSections( + mSections, getChildrenWithBackground()); if (mAnimationsEnabled && mIsExpanded) { mAnimateNextBackgroundTop = firstChild != previousFirstChild; @@ -5780,7 +5795,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd currentIndex++; boolean beforeSpeedBump; if (mHighPriorityBeforeSpeedBump) { - beforeSpeedBump = row.getEntry().isTopBucket(); + beforeSpeedBump = row.getEntry().getBucket() < BUCKET_SILENT; } else { beforeSpeedBump = !row.getEntry().isAmbient(); } @@ -5838,9 +5853,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd case ROWS_ALL: return true; case ROWS_HIGH_PRIORITY: - return row.getEntry().isTopBucket(); + return row.getEntry().getBucket() < BUCKET_SILENT; case ROWS_GENTLE: - return !row.getEntry().isTopBucket(); + return row.getEntry().getBucket() == BUCKET_SILENT; default: throw new IllegalArgumentException("Unknown selection: " + selection); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index ef8048487022..4b61064f4a54 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.notification.stack; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.content.res.Resources; import android.util.Log; @@ -411,8 +413,10 @@ public class StackScrollAlgorithm { float currentYPosition, boolean reverse) { ExpandableView child = algorithmState.visibleChildren.get(i); + ExpandableView previousChild = i > 0 ? algorithmState.visibleChildren.get(i - 1) : null; final boolean applyGapHeight = - childNeedsGapHeight(ambientState.getSectionProvider(), algorithmState, i, child); + childNeedsGapHeight( + ambientState.getSectionProvider(), algorithmState, i, child, previousChild); ExpandableViewState childViewState = child.getViewState(); childViewState.location = ExpandableViewState.LOCATION_UNKNOWN; @@ -477,8 +481,11 @@ public class StackScrollAlgorithm { SectionProvider sectionProvider, StackScrollAlgorithmState algorithmState, int visibleIndex, - View child) { - boolean needsGapHeight = sectionProvider.beginsSection(child) && visibleIndex > 0; + View child, + View previousChild) { + + boolean needsGapHeight = sectionProvider.beginsSection(child, previousChild) + && visibleIndex > 0; if (ANCHOR_SCROLLING) { needsGapHeight &= visibleIndex != algorithmState.anchorViewIndex; } @@ -749,6 +756,6 @@ public class StackScrollAlgorithm { * True if this view starts a new "section" of notifications, such as the gentle * notifications section. False if sections are not enabled. */ - boolean beginsSection(View view); + boolean beginsSection(@NonNull View view, @Nullable View previous); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java index 57dd8c94c790..a02764320b6c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java @@ -19,11 +19,12 @@ package com.android.systemui.statusbar; import static android.content.Intent.ACTION_USER_SWITCHED; import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL; +import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT; + import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -166,7 +167,10 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1); when(mNotificationData.isHighPriority(any())).thenReturn(false); - assertTrue(mLockscreenUserManager.shouldShowOnKeyguard(mock(NotificationEntry.class))); + NotificationEntry entry = new NotificationEntryBuilder().build(); + entry.setBucket(BUCKET_SILENT); + + assertTrue(mLockscreenUserManager.shouldShowOnKeyguard(entry)); } @Test @@ -179,7 +183,9 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase { Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0); when(mNotificationData.isHighPriority(any())).thenReturn(false); - assertFalse(mLockscreenUserManager.shouldShowOnKeyguard(mock(NotificationEntry.class))); + NotificationEntry entry = new NotificationEntryBuilder().build(); + entry.setBucket(BUCKET_SILENT); + assertFalse(mLockscreenUserManager.shouldShowOnKeyguard(entry)); } private class TestNotificationLockscreenUserManager diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java index a145c1251f57..8d496a72e3b2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java @@ -73,7 +73,7 @@ public class NotificationListControllerTest extends SysuiTestCase { private DeviceProvisionedListener mProvisionedListener; // TODO: Remove this once EntryManager no longer needs to be mocked - private NotificationData mNotificationData = new NotificationData(); + private NotificationData mNotificationData = new NotificationData(mContext); private int mNextNotifId = 0; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java index 9bcbfbc836b3..ab7f960d6a15 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java @@ -32,6 +32,8 @@ import static com.android.systemui.statusbar.notification.collection.Notificatio import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_IMPORTANCE; import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_RANK; import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_VIS_EFFECTS; +import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING; +import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT; import static junit.framework.Assert.assertEquals; @@ -48,6 +50,7 @@ import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Person; +import android.content.Context; import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; @@ -136,7 +139,7 @@ public class NotificationDataTest extends SysuiTestCase { mDependency.injectTestDependency(KeyguardEnvironment.class, mEnvironment); when(mEnvironment.isDeviceProvisioned()).thenReturn(true); when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true); - mNotificationData = new TestableNotificationData(); + mNotificationData = new TestableNotificationData(mContext); mNotificationData.updateRanking(mock(NotificationListenerService.RankingMap.class)); mRow = new NotificationTestHelper(getContext()).createRow(); Dependency.get(InitController.class).executePostInitTasks(); @@ -527,8 +530,7 @@ public class NotificationDataTest extends SysuiTestCase { @Test public void testSort_samePriorityUsesNMSRank() { - // NMS rank says A and then B. But A is not high priority and B is, so B should sort in - // front + // NMS rank says A and then B, and they are the same priority so use that rank Notification aN = new Notification.Builder(mContext, "test") .setStyle(new Notification.MessagingStyle("")) .build(); @@ -571,8 +573,7 @@ public class NotificationDataTest extends SysuiTestCase { } @Test - public void testSort_properlySetsIsTopBucket() { - + public void testSort_properlySetsAlertingBucket() { Notification notification = new Notification.Builder(mContext, "test") .build(); NotificationEntry entry = new NotificationEntryBuilder() @@ -591,11 +592,11 @@ public class NotificationDataTest extends SysuiTestCase { entry.setRow(mRow); mNotificationData.add(entry); - assertTrue(entry.isTopBucket()); + assertEquals(entry.getBucket(), BUCKET_ALERTING); } @Test - public void testSort_properlySetsIsNotTopBucket() { + public void testSort_properlySetsSilentBucket() { Notification notification = new Notification.Builder(mContext, "test") .build(); @@ -613,10 +614,9 @@ public class NotificationDataTest extends SysuiTestCase { mNotificationData.rankingOverrides.put(entry.key(), override); entry.setRow(mRow); - mNotificationData.add(entry); - assertFalse(entry.isTopBucket()); + assertEquals(entry.getBucket(), BUCKET_SILENT); } private void initStatusBarNotification(boolean allowDuringSetup) { @@ -631,8 +631,8 @@ public class NotificationDataTest extends SysuiTestCase { } public static class TestableNotificationData extends NotificationData { - public TestableNotificationData() { - super(); + public TestableNotificationData(Context context) { + super(context); } public static final String OVERRIDE_RANK = "r"; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java index 524ad85c3a98..addceb5def6e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java @@ -64,7 +64,7 @@ public class NotificationRoundnessManagerTest extends SysuiTestCase { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mRoundnessManager = new NotificationRoundnessManager(mBypassController); + mRoundnessManager = new NotificationRoundnessManager(mBypassController, mContext); com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper(); NotificationTestHelper testHelper = new NotificationTestHelper(getContext()); mFirst = testHelper.createRow(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java index 59d0f912d38e..56ed0e3a6af3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java @@ -18,6 +18,9 @@ package com.android.systemui.statusbar.notification.stack; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING; +import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; @@ -74,7 +77,7 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { mActivityStarterDelegate, mStatusBarStateController, mConfigurationController, - true); + 2); // Required in order for the header inflation to work properly when(mNssl.generateLayoutParams(any(AttributeSet.class))) .thenReturn(new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); @@ -263,8 +266,8 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { when(notifRow.getVisibility()).thenReturn(View.VISIBLE); when(notifRow.getEntry().isHighPriority()) .thenReturn(children[i] == ChildType.HIPRI); - when(notifRow.getEntry().isTopBucket()) - .thenReturn(children[i] == ChildType.HIPRI); + when(notifRow.getEntry().getBucket()).thenReturn( + children[i] == ChildType.HIPRI ? BUCKET_ALERTING : BUCKET_SILENT); when(notifRow.getParent()).thenReturn(mNssl); child = notifRow; break; |