diff --git a/packages/SystemUI/res/layout/people_strip.xml b/packages/SystemUI/res/layout/people_strip.xml index 982aa8ef6d16d..c2dbacaa64f79 100644 --- a/packages/SystemUI/res/layout/people_strip.xml +++ b/packages/SystemUI/res/layout/people_strip.xml @@ -19,39 +19,34 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="@dimen/notification_section_header_height" + android:paddingStart="4dp" + android:paddingEnd="4dp" android:focusable="true" android:clickable="true" > - - - - - + android:gravity="start|center_vertical" + android:layout_weight="1"> + + + + - - diff --git a/packages/SystemUI/res/layout/status_bar_notification_footer.xml b/packages/SystemUI/res/layout/status_bar_notification_footer.xml index 174a3b8e004b6..36ba66af5729d 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_footer.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_footer.xml @@ -25,9 +25,9 @@ + android:layout_height="wrap_content"> + /> + /> diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml index 508619a27e813..0043d7a7bdada 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml @@ -19,32 +19,21 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="@dimen/notification_section_header_height" + android:paddingStart="4dp" + android:paddingEnd="4dp" android:focusable="true" android:clickable="true" > - - - - - diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml index feabd1c72a653..df4b0471c78b6 100644 --- a/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml +++ b/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml @@ -16,26 +16,30 @@ - + android:gravity="start|center_vertical" + android:layout_weight="1"> + + + + diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 15575a49bb5e7..f9b0666c695f5 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -744,7 +744,7 @@ 12dp - 48dp + 56dp 16dp Silent notifications + + Alerting notifications + Conversations diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 557e2d65202bb..36c4526fb521d 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -554,6 +554,14 @@ center + + @@ -661,5 +669,5 @@ 12sp @color/control_secondary_text - + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt index 009551168010a..48386dce5d3fc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt @@ -22,6 +22,7 @@ import android.provider.DeviceConfig import com.android.internal.annotations.VisibleForTesting import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NOTIFICATIONS_USE_PEOPLE_FILTERING import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING +import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_HEADS_UP import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT import com.android.systemui.util.DeviceConfigProxy @@ -45,7 +46,7 @@ class NotificationSectionsFeatureManager @Inject constructor( fun getNotificationBuckets(): IntArray { return when { isFilteringEnabled() -> - intArrayOf(BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT) + intArrayOf(BUCKET_HEADS_UP, BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT) NotificationUtils.useNewInterruptionModel(context) -> intArrayOf(BUCKET_ALERTING, BUCKET_SILENT) else -> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt index e612c07ac18a7..9c942a52b9666 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt @@ -28,6 +28,7 @@ import com.android.systemui.statusbar.notification.NotificationSectionsFeatureMa import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING +import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_HEADS_UP import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT import com.android.systemui.statusbar.phone.NotificationGroupManager @@ -90,12 +91,12 @@ open class NotificationRankingManager @Inject constructor( val bIsHighPriority = b.isHighPriority() when { - usePeopleFiltering && aIsPeople != bIsPeople -> if (aIsPeople) -1 else 1 - usePeopleFiltering && aIsImportantPeople != bIsImportantPeople -> - if (aIsImportantPeople) -1 else 1 aHeadsUp != bHeadsUp -> if (aHeadsUp) -1 else 1 // Provide consistent ranking with headsUpManager aHeadsUp -> headsUpManager.compare(a, b) + usePeopleFiltering && aIsPeople != bIsPeople -> if (aIsPeople) -1 else 1 + usePeopleFiltering && aIsImportantPeople != bIsImportantPeople -> + if (aIsImportantPeople) -1 else 1 // Upsort current media notification. aMedia != bMedia -> if (aMedia) -1 else 1 // Upsort PRIORITY_MAX system notifications @@ -162,7 +163,9 @@ open class NotificationRankingManager @Inject constructor( isMedia: Boolean, isSystemMax: Boolean ) { - if (usePeopleFiltering && entry.isPeopleNotification()) { + if (usePeopleFiltering && isHeadsUp) { + entry.bucket = BUCKET_HEADS_UP + } else if (usePeopleFiltering && entry.isPeopleNotification()) { entry.bucket = BUCKET_PEOPLE } else if (isHeadsUp || isMedia || isSystemMax || entry.isHighPriority()) { entry.bucket = BUCKET_ALERTING diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt index efcef7124035a..16574abab7aad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt @@ -24,8 +24,8 @@ abstract class PeopleHubModule { @Binds abstract fun peopleHubSectionFooterViewAdapter( - impl: PeopleHubSectionFooterViewAdapterImpl - ): PeopleHubSectionFooterViewAdapter + impl: PeopleHubViewAdapterImpl + ): PeopleHubViewAdapter @Binds abstract fun peopleHubDataSource(impl: PeopleHubDataSourceImpl): DataSource diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt index ec1d6deb1b8fc..e28d03fc8b421 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt @@ -25,17 +25,16 @@ import android.provider.Settings import android.view.View import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter -import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager import javax.inject.Inject import javax.inject.Singleton /** Boundary between the View and PeopleHub, as seen by the View. */ -interface PeopleHubSectionFooterViewAdapter { - fun bindView(viewBoundary: PeopleHubSectionFooterViewBoundary) +interface PeopleHubViewAdapter { + fun bindView(viewBoundary: PeopleHubViewBoundary): Subscription } -/** Abstract `View` representation of PeopleHub footer in [NotificationSectionsManager]. */ -interface PeopleHubSectionFooterViewBoundary { +/** Abstract `View` representation of PeopleHub. */ +interface PeopleHubViewBoundary { /** View used for animating the activity launch caused by clicking a person in the hub. */ val associatedViewForClickAnimation: View @@ -57,23 +56,22 @@ interface PeopleHubViewModelFactory { } /** - * Wraps a [PeopleHubSectionFooterViewBoundary] in a [DataListener], and connects it to the data + * Wraps a [PeopleHubViewBoundary] in a [DataListener], and connects it to the data * pipeline. * * @param dataSource PeopleHub data pipeline. */ @Singleton -class PeopleHubSectionFooterViewAdapterImpl @Inject constructor( +class PeopleHubViewAdapterImpl @Inject constructor( private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubViewModelFactory> -) : PeopleHubSectionFooterViewAdapter { +) : PeopleHubViewAdapter { - override fun bindView(viewBoundary: PeopleHubSectionFooterViewBoundary) { - dataSource.registerListener(PeopleHubDataListenerImpl(viewBoundary)) - } + override fun bindView(viewBoundary: PeopleHubViewBoundary): Subscription = + dataSource.registerListener(PeopleHubDataListenerImpl(viewBoundary)) } private class PeopleHubDataListenerImpl( - private val viewBoundary: PeopleHubSectionFooterViewBoundary + private val viewBoundary: PeopleHubViewBoundary ) : DataListener { override fun onDataChanged(data: PeopleHubViewModelFactory) { @@ -92,7 +90,7 @@ private class PeopleHubDataListenerImpl( * Converts [PeopleHubModel]s into [PeopleHubViewModelFactory]s. * * This class serves as the glue between the View layer (which depends on - * [PeopleHubSectionFooterViewBoundary]) and the Data layer (which produces [PeopleHubModel]s). + * [PeopleHubViewBoundary]) and the Data layer (which produces [PeopleHubModel]s). */ @Singleton class PeopleHubViewModelFactoryDataSourceImpl @Inject constructor( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java index a0fef0068b051..e79d89f3a45c0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java @@ -67,29 +67,34 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final int givenSize = MeasureSpec.getSize(heightMeasureSpec); + final int givenHeight = MeasureSpec.getSize(heightMeasureSpec); final int viewHorizontalPadding = getPaddingStart() + getPaddingEnd(); + + // Max height is as large as possible, unless otherwise requested int ownMaxHeight = Integer.MAX_VALUE; int heightMode = MeasureSpec.getMode(heightMeasureSpec); - if (heightMode != MeasureSpec.UNSPECIFIED && givenSize != 0) { - ownMaxHeight = Math.min(givenSize, ownMaxHeight); + if (heightMode != MeasureSpec.UNSPECIFIED && givenHeight != 0) { + // Set our max height to what was requested from the parent + ownMaxHeight = Math.min(givenHeight, ownMaxHeight); } - int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST); + + // height of the largest child int maxChildHeight = 0; + int atMostOwnMaxHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST); int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); if (child.getVisibility() == GONE) { continue; } - int childHeightSpec = newHeightSpec; + int childHeightSpec = atMostOwnMaxHeightSpec; ViewGroup.LayoutParams layoutParams = child.getLayoutParams(); if (layoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT) { if (layoutParams.height >= 0) { - // An actual height is set - childHeightSpec = layoutParams.height > ownMaxHeight - ? MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.EXACTLY) - : MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY); + // If an actual height is set, cap it to the max height + childHeightSpec = MeasureSpec.makeMeasureSpec( + Math.min(layoutParams.height, ownMaxHeight), + MeasureSpec.EXACTLY); } child.measure(getChildMeasureSpec( widthMeasureSpec, viewHorizontalPadding, layoutParams.width), @@ -100,15 +105,22 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable { mMatchParentViews.add(child); } } + + // Set our own height to the given height, or the height of the largest child int ownHeight = heightMode == MeasureSpec.EXACTLY - ? givenSize : Math.min(ownMaxHeight, maxChildHeight); - newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY); + ? givenHeight + : Math.min(ownMaxHeight, maxChildHeight); + int exactlyOwnHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY); + + // Now that we know our own height, measure the children that are MATCH_PARENT for (View child : mMatchParentViews) { child.measure(getChildMeasureSpec( widthMeasureSpec, viewHorizontalPadding, child.getLayoutParams().width), - newHeightSpec); + exactlyOwnHeightSpec); } mMatchParentViews.clear(); + + // Finish up int width = MeasureSpec.getSize(widthMeasureSpec); setMeasuredDimension(width, ownHeight); } 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 23433cb1682df..b3561c2deda73 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 @@ -16,11 +16,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.LayoutRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Intent; @@ -35,18 +34,21 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager; import com.android.systemui.statusbar.notification.people.DataListener; -import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter; -import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewBoundary; +import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter; +import com.android.systemui.statusbar.notification.people.PeopleHubViewBoundary; import com.android.systemui.statusbar.notification.people.PersonViewModel; +import com.android.systemui.statusbar.notification.people.Subscription; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; -import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent; +import com.android.systemui.statusbar.notification.row.ExpandableView; +import com.android.systemui.statusbar.notification.row.StackScrollerDecorView; 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; +import java.util.Objects; import javax.inject.Inject; @@ -63,63 +65,65 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section private static final String TAG = "NotifSectionsManager"; private static final boolean DEBUG = false; - private NotificationStackScrollLayout mParent; private final ActivityStarter mActivityStarter; private final StatusBarStateController mStatusBarStateController; private final ConfigurationController mConfigurationController; - private final int mNumberOfSections; + private final PeopleHubViewAdapter mPeopleHubViewAdapter; private final NotificationSectionsFeatureManager mSectionsFeatureManager; - private final NotificationRowComponent.Builder mNotificationRowComponentBuilder; + private final int mNumberOfSections; + + private final PeopleHubViewBoundary mPeopleHubViewBoundary = new PeopleHubViewBoundary() { + @Override + public void setVisible(boolean isVisible) { + if (mPeopleHubVisible != isVisible) { + mPeopleHubVisible = isVisible; + if (mInitialized) { + updateSectionBoundaries(); + } + } + } + + @NonNull + @Override + public View getAssociatedViewForClickAnimation() { + return mPeopleHubView; + } + + @NonNull + @Override + public Sequence> getPersonViewAdapters() { + return mPeopleHubView.getPersonViewAdapters(); + } + }; + + private NotificationStackScrollLayout mParent; private boolean mInitialized = false; private SectionHeaderView mGentleHeader; - private boolean mGentleHeaderVisible = false; - - private boolean mPeopleHubVisible = false; - private PeopleHubView mPeopleHubView; - private final PeopleHubSectionFooterViewAdapter mPeopleHubViewAdapter; - private final PeopleHubSectionFooterViewBoundary mPeopleHubViewBoundary = - new PeopleHubSectionFooterViewBoundary() { - @Override - public void setVisible(boolean isVisible) { - if (mPeopleHubVisible != isVisible) { - mPeopleHubVisible = isVisible; - if (mInitialized) { - updateSectionBoundaries(); - } - } - } - - @NonNull - @Override - public View getAssociatedViewForClickAnimation() { - return mPeopleHubView; - } - - @NonNull - @Override - public Sequence> getPersonViewAdapters() { - return mPeopleHubView.getPersonViewAdapters(); - } - }; - + private boolean mGentleHeaderVisible; @Nullable private View.OnClickListener mOnClearGentleNotifsClickListener; + private SectionHeaderView mAlertingHeader; + private boolean mAlertingHeaderVisible; + + private PeopleHubView mPeopleHubView; + private boolean mPeopleHeaderVisible; + private boolean mPeopleHubVisible = false; + @Nullable private Subscription mPeopleHubSubscription; + @Inject NotificationSectionsManager( ActivityStarter activityStarter, StatusBarStateController statusBarStateController, ConfigurationController configurationController, - PeopleHubSectionFooterViewAdapter peopleHubViewAdapter, - NotificationSectionsFeatureManager sectionsFeatureManager, - NotificationRowComponent.Builder notificationRowComponentBuilder) { + PeopleHubViewAdapter peopleHubViewAdapter, + NotificationSectionsFeatureManager sectionsFeatureManager) { mActivityStarter = activityStarter; mStatusBarStateController = statusBarStateController; mConfigurationController = configurationController; mPeopleHubViewAdapter = peopleHubViewAdapter; mSectionsFeatureManager = sectionsFeatureManager; mNumberOfSections = mSectionsFeatureManager.getNumberOfBuckets(); - mNotificationRowComponentBuilder = notificationRowComponentBuilder; } NotificationSection[] createSectionsForBuckets() { @@ -141,105 +145,81 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section mInitialized = true; mParent = parent; reinflateViews(layoutInflater); - mPeopleHubViewAdapter.bindView(mPeopleHubViewBoundary); mConfigurationController.addCallback(mConfigurationListener); } + private T reinflateView( + T view, LayoutInflater layoutInflater, @LayoutRes int layoutResId) { + int oldPos = -1; + if (view != null) { + if (view.getTransientContainer() != null) { + view.getTransientContainer().removeView(mGentleHeader); + } else if (view.getParent() != null) { + oldPos = mParent.indexOfChild(view); + mParent.removeView(view); + } + } + + view = (T) layoutInflater.inflate(layoutResId, mParent, false); + + if (oldPos != -1) { + mParent.addView(view, oldPos); + } + + return view; + } + /** * Reinflates the entire notification header, including all decoration views. */ void reinflateViews(LayoutInflater layoutInflater) { - int oldGentleHeaderPos = -1; - int oldPeopleHubPos = -1; - if (mGentleHeader != null) { - if (mGentleHeader.getTransientContainer() != null) { - mGentleHeader.getTransientContainer().removeView(mGentleHeader); - } else if (mGentleHeader.getParent() != null) { - oldGentleHeaderPos = mParent.indexOfChild(mGentleHeader); - mParent.removeView(mGentleHeader); - } - } - if (mPeopleHubView != null) { - if (mPeopleHubView.getTransientContainer() != null) { - mPeopleHubView.getTransientContainer().removeView(mPeopleHubView); - } else if (mPeopleHubView.getParent() != null) { - oldPeopleHubPos = mParent.indexOfChild(mPeopleHubView); - mParent.removeView(mPeopleHubView); - } - } - - mGentleHeader = (SectionHeaderView) layoutInflater.inflate( - R.layout.status_bar_notification_section_header, mParent, false); - NotificationRowComponent sectionHeaderComponent = mNotificationRowComponentBuilder - .activatableNotificationView(mGentleHeader) - .build(); - sectionHeaderComponent.getActivatableNotificationViewController().init(); - + mGentleHeader = reinflateView( + mGentleHeader, layoutInflater, R.layout.status_bar_notification_section_header); + mGentleHeader.setHeaderText(R.string.notification_section_header_gentle); mGentleHeader.setOnHeaderClickListener(this::onGentleHeaderClick); mGentleHeader.setOnClearAllClickListener(this::onClearGentleNotifsClick); - if (oldGentleHeaderPos != -1) { - mParent.addView(mGentleHeader, oldGentleHeaderPos); - } - - mPeopleHubView = (PeopleHubView) layoutInflater.inflate( - R.layout.people_strip, mParent, false); - - NotificationRowComponent notificationRowComponent = mNotificationRowComponentBuilder - .activatableNotificationView(mPeopleHubView) - .build(); - notificationRowComponent.getActivatableNotificationViewController().init(); - - if (oldPeopleHubPos != -1) { - mParent.addView(mPeopleHubView, oldPeopleHubPos); + mAlertingHeader = reinflateView( + mAlertingHeader, layoutInflater, R.layout.status_bar_notification_section_header); + mAlertingHeader.setHeaderText(R.string.notification_section_header_alerting); + mAlertingHeader.setOnHeaderClickListener(this::onGentleHeaderClick); + + if (mPeopleHubSubscription != null) { + mPeopleHubSubscription.unsubscribe(); } + mPeopleHubView = reinflateView(mPeopleHubView, layoutInflater, R.layout.people_strip); + mPeopleHubSubscription = mPeopleHubViewAdapter.bindView(mPeopleHubViewBoundary); } - /** Listener for when the "clear all" buttton is clciked on the gentle notification header. */ + /** Listener for when the "clear all" button is clicked on the gentle notification header. */ void setOnClearGentleNotifsClickListener(View.OnClickListener listener) { mOnClearGentleNotifsClickListener = listener; } - /** Must be called whenever the UI mode changes (i.e. when we enter night mode). */ - void onUiModeChanged() { - mGentleHeader.onUiModeChanged(); - } - @Override public boolean beginsSection(@NonNull View view, @Nullable View previous) { - boolean begin = false; - if (view instanceof ActivatableNotificationView) { - if (previous instanceof ActivatableNotificationView) { - // If we're drawing the first non-person notification, break out a section - ActivatableNotificationView curr = (ActivatableNotificationView) view; - ActivatableNotificationView prev = (ActivatableNotificationView) previous; - - begin = getBucket(curr) != getBucket(prev); - } - } - - if (!begin) { - begin = view == mGentleHeader || view == mPeopleHubView; - } - - return begin; + return view == mGentleHeader + || view == mPeopleHubView + || view == mAlertingHeader + || !Objects.equals(getBucket(view), getBucket(previous)); } 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) { + @Nullable + private Integer getBucket(View view) { + if (view == mGentleHeader) { return BUCKET_SILENT; } else if (view == mPeopleHubView) { return BUCKET_PEOPLE; + } else if (view == mAlertingHeader) { + return BUCKET_ALERTING; + } else if (view instanceof ExpandableNotificationRow) { + return ((ExpandableNotificationRow) view).getEntry().getBucket(); } - - throw new IllegalArgumentException("I don't know how to find a bucket for this view :("); + return null; } /** @@ -251,118 +231,104 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section return; } - boolean peopleNotificationsPresent = false; - int firstNonHeadsUpIndex = -1; - int firstGentleIndex = -1; - int notifCount = 0; + final boolean showHeaders = mStatusBarStateController.getState() != StatusBarState.KEYGUARD; + final boolean usingPeopleFiltering = mSectionsFeatureManager.isFilteringEnabled(); - final int n = mParent.getChildCount(); - for (int i = 0; i < n; i++) { - View child = mParent.getChildAt(i); - if (child instanceof ExpandableNotificationRow && child.getVisibility() != View.GONE) { - notifCount++; + boolean peopleNotifsPresent = false; + int peopleHeaderTarget = -1; + int alertingHeaderTarget = -1; + int gentleHeaderTarget = -1; + + int viewCount = 0; + + if (showHeaders) { + final int childCount = mParent.getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = mParent.getChildAt(i); + if (child.getVisibility() == View.GONE + || !(child instanceof ExpandableNotificationRow)) { + continue; + } ExpandableNotificationRow row = (ExpandableNotificationRow) child; - if (firstNonHeadsUpIndex == -1 && !row.isHeadsUp()) { - firstNonHeadsUpIndex = i; + switch (row.getEntry().getBucket()) { + case BUCKET_PEOPLE: + if (peopleHeaderTarget == -1) { + peopleNotifsPresent = true; + peopleHeaderTarget = viewCount; + viewCount++; + } + break; + case BUCKET_ALERTING: + if (usingPeopleFiltering && alertingHeaderTarget == -1) { + alertingHeaderTarget = viewCount; + viewCount++; + } + break; + case BUCKET_SILENT: + if (gentleHeaderTarget == -1) { + gentleHeaderTarget = viewCount; + viewCount++; + } + break; } - if (row.getEntry().getBucket() == BUCKET_PEOPLE) { - peopleNotificationsPresent = true; - } - if (row.getEntry().getBucket() == BUCKET_SILENT) { - firstGentleIndex = i; - break; + viewCount++; + } + if (usingPeopleFiltering && mPeopleHubVisible && peopleHeaderTarget == -1) { + // Insert the people header even if there are no people visible, in order to show + // the hub. Put it directly above the next header. + if (alertingHeaderTarget != -1) { + peopleHeaderTarget = alertingHeaderTarget; + alertingHeaderTarget++; + gentleHeaderTarget++; + } else if (gentleHeaderTarget != -1) { + peopleHeaderTarget = gentleHeaderTarget; + gentleHeaderTarget++; + } else { + // Put it at the end of the list. + peopleHeaderTarget = viewCount; } } } - if (firstNonHeadsUpIndex == -1) { - firstNonHeadsUpIndex = firstGentleIndex != -1 ? firstGentleIndex : notifCount; - } + // Allow swiping the people header if the section is empty + mPeopleHubView.setCanSwipe(mPeopleHubVisible && !peopleNotifsPresent); - // make room for peopleHub - int offset = adjustPeopleHubVisibilityAndPosition( - firstNonHeadsUpIndex, peopleNotificationsPresent); - if (firstGentleIndex != -1) { - firstGentleIndex += offset; - } - - adjustGentleHeaderVisibilityAndPosition(firstGentleIndex); - - mGentleHeader.setAreThereDismissableGentleNotifs( - mParent.hasActiveClearableNotifications(ROWS_GENTLE)); + mPeopleHeaderVisible = adjustHeaderVisibilityAndPosition( + peopleHeaderTarget, mPeopleHubView, mPeopleHeaderVisible); + mAlertingHeaderVisible = adjustHeaderVisibilityAndPosition( + alertingHeaderTarget, mAlertingHeader, mAlertingHeaderVisible); + mGentleHeaderVisible = adjustHeaderVisibilityAndPosition( + gentleHeaderTarget, mGentleHeader, mGentleHeaderVisible); } - private void adjustGentleHeaderVisibilityAndPosition(int firstGentleNotifIndex) { - final boolean showGentleHeader = - firstGentleNotifIndex != -1 - && mStatusBarStateController.getState() != StatusBarState.KEYGUARD; - final int currentHeaderIndex = mParent.indexOfChild(mGentleHeader); - - if (!showGentleHeader) { - if (mGentleHeaderVisible) { - mGentleHeaderVisible = false; - mParent.removeView(mGentleHeader); + private boolean adjustHeaderVisibilityAndPosition( + int targetIndex, StackScrollerDecorView header, boolean isCurrentlyVisible) { + if (targetIndex == -1) { + if (isCurrentlyVisible) { + mParent.removeView(header); } + return false; } else { - if (!mGentleHeaderVisible) { - mGentleHeaderVisible = true; + if (header instanceof SwipeableView) { + ((SwipeableView) header).resetTranslation(); + } + if (!isCurrentlyVisible) { // If the header is animating away, it will still have a parent, so detach it first // TODO: We should really cancel the active animations here. This will happen // automatically when the view's intro animation starts, but it's a fragile link. - if (mGentleHeader.getTransientContainer() != null) { - mGentleHeader.getTransientContainer().removeTransientView(mGentleHeader); - mGentleHeader.setTransientContainer(null); + if (header.getTransientContainer() != null) { + header.getTransientContainer().removeTransientView(header); + header.setTransientContainer(null); } - mParent.addView(mGentleHeader, firstGentleNotifIndex); - } else if (currentHeaderIndex != firstGentleNotifIndex - 1) { - // Relocate the header to be immediately before the first child in the section - int targetIndex = firstGentleNotifIndex; - if (currentHeaderIndex < firstGentleNotifIndex) { - // Adjust the target index to account for the header itself being temporarily - // removed during the position change. - targetIndex--; - } - - mParent.changeViewPosition(mGentleHeader, targetIndex); + header.setContentVisible(true); + mParent.addView(header, targetIndex); + } else if (mParent.indexOfChild(header) != targetIndex) { + mParent.changeViewPosition(header, targetIndex); } + return true; } } - private int adjustPeopleHubVisibilityAndPosition( - int targetIndex, boolean peopleNotificationsPresent) { - final boolean showPeopleHeader = mNumberOfSections > 2 - && mStatusBarStateController.getState() != StatusBarState.KEYGUARD - && (peopleNotificationsPresent || mPeopleHubVisible); - final int currentHubIndex = mParent.indexOfChild(mPeopleHubView); - final boolean currentlyVisible = currentHubIndex >= 0; - - mPeopleHubView.setCanSwipe(showPeopleHeader && !peopleNotificationsPresent); - - if (!showPeopleHeader) { - if (currentlyVisible) { - mParent.removeView(mPeopleHubView); - return -1; - } - } else { - mPeopleHubView.unDismiss(); - mPeopleHubView.resetTranslation(); - if (!currentlyVisible) { - if (mPeopleHubView.getTransientContainer() != null) { - mPeopleHubView.getTransientContainer().removeTransientView(mPeopleHubView); - mPeopleHubView.setTransientContainer(null); - } - mParent.addView(mPeopleHubView, targetIndex); - return 1; - } else if (currentHubIndex != targetIndex) { - if (currentHubIndex < targetIndex) { - targetIndex--; - } - mParent.changeViewPosition(mPeopleHubView, targetIndex); - } - } - return 0; - } - /** * Updates the boundaries (as tracked by their first and last views) of the priority sections. * @@ -388,7 +354,12 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section //TODO: do this in a single pass, and more better for (ActivatableNotificationView v : children) { - if (getBucket(v) == filter) { + Integer bucket = getBucket(v); + if (bucket == null) { + throw new IllegalArgumentException("Cannot find section bucket for view"); + } + + if (bucket == filter) { viewsInBucket.add(v); } @@ -463,16 +434,17 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section /** * 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_HEADS_UP, 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; + public static final int BUCKET_HEADS_UP = 0; + public static final int BUCKET_PEOPLE = 1; + public static final int BUCKET_ALERTING = 2; + public static final int BUCKET_SILENT = 3; } 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 2eeda1f48df38..1bd9bbecc26e1 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 @@ -815,7 +815,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd mBgColor = mContext.getColor(R.color.notification_shade_background_color); updateBackgroundDimming(); mShelf.onUiModeChanged(); - mSectionsManager.onUiModeChanged(); } @ShadeViewRefactor(RefactorComponent.DECORATOR) @@ -1632,8 +1631,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd @ShadeViewRefactor(RefactorComponent.COORDINATOR) private ExpandableView getChildAtPosition(float touchX, float touchY) { - return getChildAtPosition(touchX, touchY, true /* requireMinHeight */); - + return getChildAtPosition( + touchX, touchY, true /* requireMinHeight */, true /* ignoreDecors */); } /** @@ -1642,17 +1641,18 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd * @param touchX the x coordinate * @param touchY the y coordinate * @param requireMinHeight Whether a minimum height is required for a child to be returned. + * @param ignoreDecors Whether decors can be returned * @return the child at the given location. */ @ShadeViewRefactor(RefactorComponent.COORDINATOR) private ExpandableView getChildAtPosition(float touchX, float touchY, - boolean requireMinHeight) { + boolean requireMinHeight, boolean ignoreDecors) { // find the view under the pointer, accounting for GONE views final int count = getChildCount(); for (int childIdx = 0; childIdx < count; childIdx++) { ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx); if (slidingChild.getVisibility() != VISIBLE - || slidingChild instanceof StackScrollerDecorView) { + || (ignoreDecors && slidingChild instanceof StackScrollerDecorView)) { continue; } float childTop = slidingChild.getTranslationY(); @@ -4166,7 +4166,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd case MotionEvent.ACTION_DOWN: { final int y = (int) ev.getY(); mScrolledToTopOnFirstDown = isScrolledToTop(); - if (getChildAtPosition(ev.getX(), y, false /* requireMinHeight */) == null) { + final ExpandableView childAtTouchPos = getChildAtPosition( + ev.getX(), y, false /* requireMinHeight */, false /* ignoreDecors */); + if (childAtTouchPos == null) { setIsBeingDragged(false); recycleVelocityTracker(); break; @@ -6299,8 +6301,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } if (view instanceof PeopleHubView) { - PeopleHubView row = (PeopleHubView) view; - row.dismiss(false); mSectionsManager.hidePeopleRow(); } @@ -6325,8 +6325,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd @Override public View getChildAtPosition(MotionEvent ev) { - View child = NotificationStackScrollLayout.this.getChildAtPosition(ev.getX(), - ev.getY()); + View child = NotificationStackScrollLayout.this.getChildAtPosition( + ev.getX(), + ev.getY(), + true /* requireMinHeight */, + false /* ignoreDecors */); if (child instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) child; ExpandableNotificationRow parent = row.getNotificationParent(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt index e5717aeefdcbd..151c6b272a3e9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt @@ -25,30 +25,32 @@ import com.android.systemui.R import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin import com.android.systemui.statusbar.notification.people.DataListener import com.android.systemui.statusbar.notification.people.PersonViewModel -import com.android.systemui.statusbar.notification.row.ActivatableNotificationView +import com.android.systemui.statusbar.notification.row.StackScrollerDecorView class PeopleHubView(context: Context, attrs: AttributeSet) : - ActivatableNotificationView(context, attrs), SwipeableView { + StackScrollerDecorView(context, attrs), SwipeableView { private lateinit var contents: ViewGroup - private lateinit var personControllers: List - val personViewAdapters: Sequence> - get() = personControllers.asSequence() + lateinit var personViewAdapters: Sequence> + private set override fun onFinishInflate() { - super.onFinishInflate() contents = requireViewById(R.id.people_list) - personControllers = (0 until contents.childCount) + personViewAdapters = (0 until contents.childCount) .reversed() .asSequence() .mapNotNull { idx -> (contents.getChildAt(idx) as? ImageView)?.let(::PersonDataListenerImpl) } .toList() + .asSequence() + super.onFinishInflate() + setVisible(true /* nowVisible */, false /* animate */) } - override fun getContentView(): View = contents + override fun findContentView(): View = contents + override fun findSecondaryView(): View? = null override fun hasFinishedInitialization(): Boolean = true diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java index add982dabf029..ad3ff69eb5c80 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java @@ -17,8 +17,8 @@ package com.android.systemui.statusbar.notification.stack; import android.annotation.Nullable; +import android.annotation.StringRes; import android.content.Context; -import android.graphics.RectF; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -28,7 +28,7 @@ import android.widget.ImageView; import android.widget.TextView; import com.android.systemui.R; -import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; +import com.android.systemui.statusbar.notification.row.StackScrollerDecorView; import java.util.Objects; @@ -36,23 +36,22 @@ import java.util.Objects; * Similar in size and appearance to the NotificationShelf, appears at the beginning of some * notification sections. Currently only used for gentle notifications. */ -public class SectionHeaderView extends ActivatableNotificationView { +public class SectionHeaderView extends StackScrollerDecorView { private ViewGroup mContents; private TextView mLabelView; private ImageView mClearAllButton; @Nullable private View.OnClickListener mOnClearClickListener = null; - private final RectF mTmpRect = new RectF(); - public SectionHeaderView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onFinishInflate() { - super.onFinishInflate(); mContents = Objects.requireNonNull(findViewById(R.id.content)); bindContents(); + super.onFinishInflate(); + setVisible(true /* nowVisible */, false /* animate */); } private void bindContents() { @@ -64,15 +63,20 @@ public class SectionHeaderView extends ActivatableNotificationView { } @Override - protected View getContentView() { + protected View findContentView() { return mContents; } + @Override + protected View findSecondaryView() { + return null; + } + /** * Destroys and reinflates the visible contents of the section header. For use on configuration * changes or any other time that layout values might need to be re-evaluated. * - * Does not reinflate the base content view itself ({@link #getContentView()} or any of the + * Does not reinflate the base content view itself ({@link #findContentView()} or any of the * decorator views, such as the background view or shadow view. */ void reinflateContents() { @@ -88,35 +92,20 @@ public class SectionHeaderView extends ActivatableNotificationView { return true; } - /** Must be called whenever the UI mode changes (i.e. when we enter night mode). */ - void onUiModeChanged() { - updateBackgroundColors(); - mLabelView.setTextColor( - getContext().getColor(R.color.notification_section_header_label_color)); - mClearAllButton.setImageResource( - R.drawable.status_bar_notification_section_header_clear_btn); - } - void setAreThereDismissableGentleNotifs(boolean areThereDismissableGentleNotifs) { mClearAllButton.setVisibility(areThereDismissableGentleNotifs ? View.VISIBLE : View.GONE); } @Override - protected boolean disallowSingleClick(MotionEvent event) { - // Disallow single click on lockscreen if user is tapping on clear all button - mTmpRect.set( - mClearAllButton.getLeft(), - mClearAllButton.getTop(), - mClearAllButton.getLeft() + mClearAllButton.getWidth(), - mClearAllButton.getTop() + mClearAllButton.getHeight()); - return mTmpRect.contains(event.getX(), event.getY()); + public boolean onInterceptTouchEvent(MotionEvent ev) { + return super.onInterceptTouchEvent(ev); } /** * Fired whenever the user clicks on the body of the header (e.g. no sub-buttons or anything). */ void setOnHeaderClickListener(View.OnClickListener listener) { - mContents.setOnClickListener(listener); + mLabelView.setOnClickListener(listener); } /** Fired when the user clicks on the "X" button on the far right of the header. */ @@ -124,4 +113,8 @@ public class SectionHeaderView extends ActivatableNotificationView { mOnClearClickListener = listener; mClearAllButton.setOnClickListener(listener); } + + void setHeaderText(@StringRes int resId) { + mLabelView.setText(resId); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 10821d63d4cc2..945a9db7c836b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -21,7 +21,6 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.IntDef; import android.app.AlarmManager; -import android.content.res.Resources; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Handler; @@ -45,7 +44,6 @@ import com.android.systemui.DejankUtils; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.colorextraction.SysuiColorExtractor; -import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dock.DockManager; import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.notification.stack.ViewState; @@ -116,7 +114,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo * A scrim varies its opacity based on a busyness factor, for example * how many notifications are currently visible. */ - public static final float BUSY_SCRIM_ALPHA = 0.54f; + public static final float BUSY_SCRIM_ALPHA = 0.75f; /** * The most common scrim, the one under the keyguard. @@ -146,8 +144,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private GradientColors mColors; private boolean mNeedsDrawableColorUpdate; - private float mScrimBehindAlpha; - private float mScrimBehindAlphaResValue; private float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD; // Assuming the shade is expanded during initialization @@ -192,7 +188,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo @Inject public ScrimController(LightBarController lightBarController, DozeParameters dozeParameters, AlarmManager alarmManager, KeyguardStateController keyguardStateController, - @Main Resources resources, DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler, KeyguardUpdateMonitor keyguardUpdateMonitor, SysuiColorExtractor sysuiColorExtractor, DockManager dockManager) { @@ -203,14 +198,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo mDarkenWhileDragging = !mKeyguardStateController.canDismissLockScreen(); mKeyguardUpdateMonitor = keyguardUpdateMonitor; mKeyguardVisibilityCallback = new KeyguardVisibilityCallback(); - mScrimBehindAlphaResValue = resources.getFloat(R.dimen.scrim_behind_alpha); mHandler = handler; mTimeTicker = new AlarmTimeout(alarmManager, this::onHideWallpaperTimeout, "hide_aod_wallpaper", mHandler); mWakeLock = delayedWakeLockBuilder.setHandler(mHandler).setTag("Scrims").build(); // Scrim alpha is initially set to the value on the resource but might be changed // to make sure that text on top of it is legible. - mScrimBehindAlpha = mScrimBehindAlphaResValue; mDozeParameters = dozeParameters; mDockManager = dockManager; keyguardStateController.addCallback(new KeyguardStateController.Callback() { @@ -587,7 +580,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo int mainColor = mColors.getMainColor(); float minOpacity = ColorUtils.calculateMinimumBackgroundAlpha(textColor, mainColor, 4.5f /* minimumContrast */) / 255f; - mScrimBehindAlpha = Math.max(mScrimBehindAlphaResValue, minOpacity); dispatchScrimState(mScrimBehind.getViewAlpha()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt index b3d0d22445b6a..6388fe1a69c1c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt @@ -63,7 +63,7 @@ class NotificationSectionsFeatureManagerTest : SysuiTestCase() { DeviceConfig.NAMESPACE_SYSTEMUI, NOTIFICATIONS_USE_PEOPLE_FILTERING, "true", false) assertTrue("People filtering should be enabled", manager!!.isFilteringEnabled()) - assertTrue("Expecting 3 buckets when people filtering is enabled", - manager!!.getNumberOfBuckets() == 3) + assertTrue("Expecting 4 buckets when people filtering is enabled", + manager!!.getNumberOfBuckets() == 4) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt index 45c51d42c2504..f11c42bda6ccb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt @@ -32,6 +32,7 @@ import com.android.systemui.statusbar.notification.NotificationFilter import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier +import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT import com.android.systemui.statusbar.phone.NotificationGroupManager @@ -147,6 +148,53 @@ class NotificationRankingManagerTest : SysuiTestCase() { rankingManager.updateRanking(null, listOf(a, b), "test")) } + @Test + fun testSort_headsUp_trumpsPeople() { + whenever(sectionsManager.isFilteringEnabled()).thenReturn(true) + val aN = Notification.Builder(mContext, "test") + .setStyle(Notification.MessagingStyle("")) + .build() + val a = NotificationEntryBuilder() + .setImportance(IMPORTANCE_HIGH) + .setPkg("pkg") + .setOpPkg("pkg") + .setTag("tag") + .setNotification(aN) + .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT)) + .setUser(mContext.getUser()) + .setOverrideGroupKey("") + .build() + + whenever(personNotificationIdentifier.isImportantPeopleNotification(a.sbn, a.ranking)) + .thenReturn(true) + whenever(personNotificationIdentifier.isPeopleNotification(a.sbn, a.ranking)) + .thenReturn(true) + + val bN = Notification.Builder(mContext, "test") + .setStyle(Notification.MessagingStyle("")) + .build() + val b = NotificationEntryBuilder() + .setImportance(IMPORTANCE_HIGH) + .setPkg("pkg2") + .setOpPkg("pkg2") + .setTag("tag") + .setNotification(bN) + .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT)) + .setUser(mContext.getUser()) + .setOverrideGroupKey("") + .build() + b.row = mock(ExpandableNotificationRow::class.java).also { + whenever(it.isHeadsUp).thenReturn(true) + } + + whenever(personNotificationIdentifier.isImportantPeopleNotification(a.sbn, a.ranking)) + .thenReturn(false) + whenever(personNotificationIdentifier.isPeopleNotification(a.sbn, a.ranking)) + .thenReturn(false) + + assertEquals(listOf(b, a), rankingManager.updateRanking(null, listOf(a, b), "test")) + } + @Test fun testSort_importantPeople() { whenever(sectionsManager.isFilteringEnabled()).thenReturn(true) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt index 867a9b97d6229..abce8b517dfbc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt @@ -43,7 +43,7 @@ class PeopleHubViewControllerTest : SysuiTestCase() { @JvmField @Rule val mockito: MockitoRule = MockitoJUnit.rule() - @Mock private lateinit var mockViewBoundary: PeopleHubSectionFooterViewBoundary + @Mock private lateinit var mockViewBoundary: PeopleHubViewBoundary @Mock private lateinit var mockActivityStarter: ActivityStarter @Test @@ -67,7 +67,7 @@ class PeopleHubViewControllerTest : SysuiTestCase() { return mockSubscription } } - val adapter = PeopleHubSectionFooterViewAdapterImpl(fakeFactoryDataSource) + val adapter = PeopleHubViewAdapterImpl(fakeFactoryDataSource) adapter.bindView(mockViewBoundary) 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 51f214d8cda23..abfbcd99167b5 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 @@ -45,8 +45,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager; -import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter; -import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; +import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter; import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent; @@ -71,7 +70,7 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { @Mock private ActivityStarterDelegate mActivityStarterDelegate; @Mock private StatusBarStateController mStatusBarStateController; @Mock private ConfigurationController mConfigurationController; - @Mock private PeopleHubSectionFooterViewAdapter mPeopleHubAdapter; + @Mock private PeopleHubViewAdapter mPeopleHubAdapter; @Mock private NotificationSectionsFeatureManager mSectionsFeatureManager; @Mock private NotificationRowComponent mNotificationRowComponent; @Mock private ActivatableNotificationViewController mActivatableNotificationViewController; @@ -90,18 +89,8 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { mStatusBarStateController, mConfigurationController, mPeopleHubAdapter, - mSectionsFeatureManager, - new NotificationRowComponent.Builder() { - @Override - public NotificationRowComponent.Builder activatableNotificationView( - ActivatableNotificationView view) { - return this; - } - - @Override - public NotificationRowComponent build() { - return mNotificationRowComponent; - }}); + mSectionsFeatureManager + ); // Required in order for the header inflation to work properly when(mNssl.generateLayoutParams(any(AttributeSet.class))) .thenReturn(new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index 2e6fbe7d1ddb1..408dfc0e1deec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -36,7 +36,6 @@ import static org.mockito.Mockito.when; import android.animation.Animator; import android.app.AlarmManager; -import android.content.res.Resources; import android.graphics.Color; import android.os.Handler; import android.testing.AndroidTestingRunner; @@ -91,8 +90,6 @@ public class ScrimControllerTest extends SysuiTestCase { @Mock LightBarController mLightBarController; @Mock - Resources mResources; - @Mock DelayedWakeLock.Builder mDelayedWakeLockBuilder; @Mock private DelayedWakeLock mWakeLock; @@ -216,8 +213,7 @@ public class ScrimControllerTest extends SysuiTestCase { when(mDockManager.isDocked()).thenReturn(false); mScrimController = new ScrimController(mLightBarController, - mDozeParamenters, mAlarmManager, mKeyguardStateController, - mResources, mDelayedWakeLockBuilder, + mDozeParamenters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder, new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor, mSysuiColorExtractor, mDockManager); mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);