Merge "Alerting notifications section header + new header style"

This commit is contained in:
TreeHugger Robot
2020-02-21 02:23:25 +00:00
committed by Android (Google) Code Review
22 changed files with 383 additions and 382 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -1222,6 +1222,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>

View File

@@ -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>

View File

@@ -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 ->

View File

@@ -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

View File

@@ -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>

View File

@@ -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(

View File

@@ -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);
}

View File

@@ -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<DataListener<PersonViewModel>> 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<DataListener<PersonViewModel>> 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 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);
}
}
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;
}

View File

@@ -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();

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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());
}

View File

@@ -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)
}
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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));

View File

@@ -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);