summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res/layout/people_strip.xml43
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_footer.xml11
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_section_header.xml19
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml32
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml3
-rw-r--r--packages/SystemUI/res/values/styles.xml10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java382
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt48
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java6
22 files changed, 379 insertions, 378 deletions
diff --git a/packages/SystemUI/res/layout/people_strip.xml b/packages/SystemUI/res/layout/people_strip.xml
index 982aa8ef6d16..c2dbacaa64f7 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"
>
- <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
- android:id="@+id/backgroundNormal"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
- <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
- android:id="@+id/backgroundDimmed"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
<LinearLayout
android:id="@+id/people_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:gravity="center"
+ android:layout_marginEnd="8dp"
+ android:gravity="bottom"
android:orientation="horizontal">
- <TextView
+ <FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginStart="@dimen/notification_section_header_padding_left"
- android:gravity="start"
- android:textAlignment="gravity"
- android:text="@string/notification_section_header_conversations"
- android:textSize="12sp"
- android:textColor="@color/notification_section_header_label_color"
- android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
- />
+ android:gravity="start|center_vertical"
+ android:layout_weight="1">
+
+ <TextView
+ style="@style/TextAppearance.NotificationSectionHeaderButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/notification_section_header_conversations"
+ />
+
+ </FrameLayout>
<ImageView
android:layout_width="48dp"
@@ -84,16 +79,10 @@
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
- android:layout_marginEnd="8dp"
android:padding="8dp"
android:scaleType="fitCenter"
/>
</LinearLayout>
- <com.android.systemui.statusbar.notification.FakeShadowView
- android:id="@+id/fake_shadow"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
</com.android.systemui.statusbar.notification.stack.PeopleHubView>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_footer.xml b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
index 174a3b8e004b..36ba66af5729 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 @@
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
- android:layout_height="wrap_content" >
+ android:layout_height="wrap_content">
<com.android.systemui.statusbar.notification.row.FooterViewButton
- style="@android:style/Widget.Material.Button.Borderless"
+ style="@style/TextAppearance.NotificationSectionHeaderButton"
android:id="@+id/manage_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -35,10 +35,9 @@
android:focusable="true"
android:contentDescription="@string/accessibility_manage_notification"
android:text="@string/manage_notifications_text"
- android:textColor="?attr/wallpaperTextColor"
- android:textAllCaps="false"/>
+ />
<com.android.systemui.statusbar.notification.row.FooterViewButton
- style="@android:style/Widget.Material.Button.Borderless"
+ style="@style/TextAppearance.NotificationSectionHeaderButton"
android:id="@+id/dismiss_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -46,6 +45,6 @@
android:focusable="true"
android:contentDescription="@string/accessibility_clear_all"
android:text="@string/clear_all_notifications_text"
- android:textColor="?attr/wallpaperTextColor"/>
+ />
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
</com.android.systemui.statusbar.notification.row.FooterView>
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 508619a27e81..0043d7a7bdad 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"
>
- <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
- android:id="@+id/backgroundNormal"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
- android:id="@+id/backgroundDimmed"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
<LinearLayout
android:id="@+id/content"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
android:gravity="center_vertical"
android:orientation="horizontal"
>
<include layout="@layout/status_bar_notification_section_header_contents"/>
</LinearLayout>
- <com.android.systemui.statusbar.notification.FakeShadowView
- android:id="@+id/fake_shadow"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
</com.android.systemui.statusbar.notification.stack.SectionHeaderView>
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 feabd1c72a65..df4b0471c78b 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 @@
<!-- Used by both status_bar_notification_header and SectionHeaderView -->
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
- <TextView
- android:id="@+id/header_label"
+ <FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginStart="@dimen/notification_section_header_padding_left"
- android:gravity="start"
- android:textAlignment="gravity"
- android:text="@string/notification_section_header_gentle"
- android:textSize="12sp"
- android:textColor="@color/notification_section_header_label_color"
- android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
- />
+ android:gravity="start|center_vertical"
+ android:layout_weight="1">
+
+ <TextView
+ style="@style/TextAppearance.NotificationSectionHeaderButton"
+ android:id="@+id/header_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/notification_section_header_gentle"
+ />
+
+ </FrameLayout>
<ImageView
android:id="@+id/btn_clear_all"
- android:layout_width="@dimen/notification_section_header_height"
- android:layout_height="@dimen/notification_section_header_height"
- android:layout_marginEnd="4dp"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
android:src="@drawable/status_bar_notification_section_header_clear_btn"
android:contentDescription="@string/accessibility_notification_section_header_gentle_clear_all"
android:scaleType="center"
+ android:tint="?attr/wallpaperTextColor"
+ android:tintMode="src_in"
+ android:visibility="gone"
/>
</merge>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 15575a49bb5e..f9b0666c695f 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -744,7 +744,7 @@
<!-- The top padding of the clear all button -->
<dimen name="clear_all_padding_top">12dp</dimen>
- <dimen name="notification_section_header_height">48dp</dimen>
+ <dimen name="notification_section_header_height">56dp</dimen>
<dimen name="notification_section_header_padding_left">16dp</dimen>
<!-- Largest size an avatar might need to be drawn in the user picker, status bar, or
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5e9feff566e5..89d500281e90 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1204,6 +1204,9 @@
<!-- Section title for notifications that do not vibrate or make noise. [CHAR LIMIT=40] -->
<string name="notification_section_header_gentle">Silent notifications</string>
+ <!-- Section title for notifications that vibrate or make noise. [CHAR LIMIT=40] -->
+ <string name="notification_section_header_alerting">Alerting notifications</string>
+
<!-- Section title for conversational notifications. [CHAR LIMIT=40] -->
<string name="notification_section_header_conversations">Conversations</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 557e2d65202b..36c4526fb521 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -554,6 +554,14 @@
<item name="android:gravity">center</item>
</style>
+ <style
+ name="TextAppearance.NotificationSectionHeaderButton"
+ parent="@android:style/Widget.Material.Button.Borderless">
+ <item name="android:textColor">?attr/wallpaperTextColor</item>
+ <item name="android:textAllCaps">false</item>
+ <item name="android:textSize">16sp</item>
+ </style>
+
<style name="TextAppearance.HeadsUpStatusBarText"
parent="@*android:style/TextAppearance.DeviceDefault.Notification.Info">
</style>
@@ -661,5 +669,5 @@
<item name="android:textSize">12sp</item>
<item name="android:textColor">@color/control_secondary_text</item>
</style>
-
+
</resources>
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 009551168010..48386dce5d3f 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 e612c07ac18a..9c942a52b966 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 efcef7124035..16574abab7aa 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<PeopleHubModel>
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 ec1d6deb1b8f..e28d03fc8b42 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<PeopleHubViewModelFactory> {
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 a0fef0068b05..e79d89f3a45c 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 23433cb1682d..b3561c2deda7 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 boolean mInitialized = false;
-
- private SectionHeaderView mGentleHeader;
- private boolean mGentleHeaderVisible = false;
+ private final int mNumberOfSections;
- 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();
- }
- }
+ 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 View getAssociatedViewForClickAnimation() {
+ return mPeopleHubView;
+ }
- @NonNull
- @Override
- public Sequence<DataListener<PersonViewModel>> getPersonViewAdapters() {
- return mPeopleHubView.getPersonViewAdapters();
- }
- };
+ @NonNull
+ @Override
+ public Sequence<DataListener<PersonViewModel>> getPersonViewAdapters() {
+ return mPeopleHubView.getPersonViewAdapters();
+ }
+ };
+
+ private NotificationStackScrollLayout mParent;
+ private boolean mInitialized = false;
+ private SectionHeaderView mGentleHeader;
+ 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);
}
- /**
- * 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);
+ private <T extends ExpandableView> 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);
}
}
- if (mPeopleHubView != null) {
- if (mPeopleHubView.getTransientContainer() != null) {
- mPeopleHubView.getTransientContainer().removeView(mPeopleHubView);
- } else if (mPeopleHubView.getParent() != null) {
- oldPeopleHubPos = mParent.indexOfChild(mPeopleHubView);
- mParent.removeView(mPeopleHubView);
- }
+
+ view = (T) layoutInflater.inflate(layoutResId, mParent, false);
+
+ if (oldPos != -1) {
+ mParent.addView(view, oldPos);
}
- mGentleHeader = (SectionHeaderView) layoutInflater.inflate(
- R.layout.status_bar_notification_section_header, mParent, false);
- NotificationRowComponent sectionHeaderComponent = mNotificationRowComponentBuilder
- .activatableNotificationView(mGentleHeader)
- .build();
- sectionHeaderComponent.getActivatableNotificationViewController().init();
+ return view;
+ }
+ /**
+ * Reinflates the entire notification header, including all decoration views.
+ */
+ void reinflateViews(LayoutInflater layoutInflater) {
+ 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);
+ mAlertingHeader = reinflateView(
+ mAlertingHeader, layoutInflater, R.layout.status_bar_notification_section_header);
+ mAlertingHeader.setHeaderText(R.string.notification_section_header_alerting);
+ mAlertingHeader.setOnHeaderClickListener(this::onGentleHeaderClick);
- NotificationRowComponent notificationRowComponent = mNotificationRowComponentBuilder
- .activatableNotificationView(mPeopleHubView)
- .build();
- notificationRowComponent.getActivatableNotificationViewController().init();
-
- if (oldPeopleHubPos != -1) {
- mParent.addView(mPeopleHubView, oldPeopleHubPos);
+ 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++;
- ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- if (firstNonHeadsUpIndex == -1 && !row.isHeadsUp()) {
- firstNonHeadsUpIndex = i;
+ 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;
}
- if (row.getEntry().getBucket() == BUCKET_PEOPLE) {
- peopleNotificationsPresent = true;
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ 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_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;
- }
-
- // make room for peopleHub
- int offset = adjustPeopleHubVisibilityAndPosition(
- firstNonHeadsUpIndex, peopleNotificationsPresent);
- if (firstGentleIndex != -1) {
- firstGentleIndex += offset;
- }
-
- adjustGentleHeaderVisibilityAndPosition(firstGentleIndex);
+ // Allow swiping the people header if the section is empty
+ mPeopleHubView.setCanSwipe(mPeopleHubVisible && !peopleNotifsPresent);
- 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 2eeda1f48df3..1bd9bbecc26e 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 e5717aeefdcb..151c6b272a3e 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<PersonDataListenerImpl>
- val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
- get() = personControllers.asSequence()
+ lateinit var personViewAdapters: Sequence<DataListener<PersonViewModel?>>
+ 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 add982dabf02..ad3ff69eb5c8 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 10821d63d4cc..945a9db7c836 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 b3d0d22445b6..6388fe1a69c1 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 45c51d42c250..f11c42bda6cc 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
@@ -148,6 +149,53 @@ class NotificationRankingManagerTest : SysuiTestCase() {
}
@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)
val aN = Notification.Builder(mContext, "test")
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 867a9b97d622..abce8b517dfb 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 51f214d8cda2..abfbcd99167b 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 2e6fbe7d1ddb..408dfc0e1dee 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);