Merge "Alerting notifications section header + new header style"
This commit is contained in:
committed by
Android (Google) Code Review
commit
e10efd8c81
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 ->
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user