Merge "Show correct last notification time for grouped notifications" into udc-dev am: f32a80bfb3
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21609427 Change-Id: Ia340d0568cba730e51eeca0513dea2e79faf5f00 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.systemui.statusbar.notification.collection.coordinator
|
||||
|
||||
import android.util.ArrayMap
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.statusbar.notification.collection.GroupEntry
|
||||
import com.android.systemui.statusbar.notification.collection.ListEntry
|
||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline
|
||||
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
|
||||
import com.android.systemui.statusbar.notification.collection.render.NotifGroupController
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||
import com.android.systemui.util.time.SystemClock
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/** A small coordinator which finds, stores, and applies the closest notification time. */
|
||||
@CoordinatorScope
|
||||
class GroupWhenCoordinator
|
||||
@Inject
|
||||
constructor(
|
||||
@Main private val delayableExecutor: DelayableExecutor,
|
||||
private val systemClock: SystemClock
|
||||
) : Coordinator {
|
||||
|
||||
private val invalidator = object : Invalidator("GroupWhenCoordinator") {}
|
||||
private val notificationGroupTimes = ArrayMap<GroupEntry, Long>()
|
||||
private var cancelInvalidateListRunnable: Runnable? = null
|
||||
|
||||
private val invalidateListRunnable: Runnable = Runnable {
|
||||
invalidator.invalidateList("future notification invalidation")
|
||||
}
|
||||
|
||||
override fun attach(pipeline: NotifPipeline) {
|
||||
pipeline.addOnBeforeFinalizeFilterListener(::onBeforeFinalizeFilterListener)
|
||||
pipeline.addOnAfterRenderGroupListener(::onAfterRenderGroupListener)
|
||||
pipeline.addPreRenderInvalidator(invalidator)
|
||||
}
|
||||
|
||||
private fun onBeforeFinalizeFilterListener(entries: List<ListEntry>) {
|
||||
cancelListInvalidation()
|
||||
notificationGroupTimes.clear()
|
||||
|
||||
val now = systemClock.currentTimeMillis()
|
||||
var closestFutureTime = Long.MAX_VALUE
|
||||
entries.asSequence().filterIsInstance<GroupEntry>().forEach { groupEntry ->
|
||||
val whenMillis = calculateGroupNotificationTime(groupEntry, now)
|
||||
notificationGroupTimes[groupEntry] = whenMillis
|
||||
if (whenMillis > now) {
|
||||
closestFutureTime = min(closestFutureTime, whenMillis)
|
||||
}
|
||||
}
|
||||
|
||||
if (closestFutureTime != Long.MAX_VALUE) {
|
||||
cancelInvalidateListRunnable =
|
||||
delayableExecutor.executeDelayed(invalidateListRunnable, closestFutureTime - now)
|
||||
}
|
||||
}
|
||||
|
||||
private fun cancelListInvalidation() {
|
||||
cancelInvalidateListRunnable?.run()
|
||||
cancelInvalidateListRunnable = null
|
||||
}
|
||||
|
||||
private fun onAfterRenderGroupListener(group: GroupEntry, controller: NotifGroupController) {
|
||||
notificationGroupTimes[group]?.let(controller::setNotificationGroupWhen)
|
||||
}
|
||||
|
||||
private fun calculateGroupNotificationTime(
|
||||
groupEntry: GroupEntry,
|
||||
currentTimeMillis: Long
|
||||
): Long {
|
||||
var pastTime = Long.MIN_VALUE
|
||||
var futureTime = Long.MAX_VALUE
|
||||
groupEntry.children
|
||||
.asSequence()
|
||||
.mapNotNull { child -> child.sbn.notification.`when`.takeIf { it > 0 } }
|
||||
.forEach { time ->
|
||||
val isInThePast = currentTimeMillis - time > 0
|
||||
if (isInThePast) {
|
||||
pastTime = max(pastTime, time)
|
||||
} else {
|
||||
futureTime = min(futureTime, time)
|
||||
}
|
||||
}
|
||||
|
||||
if (pastTime == Long.MIN_VALUE && futureTime == Long.MAX_VALUE) {
|
||||
return checkNotNull(groupEntry.summary).creationTime
|
||||
}
|
||||
|
||||
return if (futureTime != Long.MAX_VALUE) futureTime else pastTime
|
||||
}
|
||||
}
|
||||
@@ -31,31 +31,32 @@ interface NotifCoordinators : Coordinator, PipelineDumpable
|
||||
|
||||
@CoordinatorScope
|
||||
class NotifCoordinatorsImpl @Inject constructor(
|
||||
notifPipelineFlags: NotifPipelineFlags,
|
||||
dataStoreCoordinator: DataStoreCoordinator,
|
||||
hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator,
|
||||
hideNotifsForOtherUsersCoordinator: HideNotifsForOtherUsersCoordinator,
|
||||
keyguardCoordinator: KeyguardCoordinator,
|
||||
rankingCoordinator: RankingCoordinator,
|
||||
appOpsCoordinator: AppOpsCoordinator,
|
||||
deviceProvisionedCoordinator: DeviceProvisionedCoordinator,
|
||||
bubbleCoordinator: BubbleCoordinator,
|
||||
headsUpCoordinator: HeadsUpCoordinator,
|
||||
gutsCoordinator: GutsCoordinator,
|
||||
conversationCoordinator: ConversationCoordinator,
|
||||
debugModeCoordinator: DebugModeCoordinator,
|
||||
groupCountCoordinator: GroupCountCoordinator,
|
||||
mediaCoordinator: MediaCoordinator,
|
||||
preparationCoordinator: PreparationCoordinator,
|
||||
remoteInputCoordinator: RemoteInputCoordinator,
|
||||
rowAppearanceCoordinator: RowAppearanceCoordinator,
|
||||
stackCoordinator: StackCoordinator,
|
||||
shadeEventCoordinator: ShadeEventCoordinator,
|
||||
smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
|
||||
viewConfigCoordinator: ViewConfigCoordinator,
|
||||
visualStabilityCoordinator: VisualStabilityCoordinator,
|
||||
sensitiveContentCoordinator: SensitiveContentCoordinator,
|
||||
dismissibilityCoordinator: DismissibilityCoordinator
|
||||
notifPipelineFlags: NotifPipelineFlags,
|
||||
dataStoreCoordinator: DataStoreCoordinator,
|
||||
hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator,
|
||||
hideNotifsForOtherUsersCoordinator: HideNotifsForOtherUsersCoordinator,
|
||||
keyguardCoordinator: KeyguardCoordinator,
|
||||
rankingCoordinator: RankingCoordinator,
|
||||
appOpsCoordinator: AppOpsCoordinator,
|
||||
deviceProvisionedCoordinator: DeviceProvisionedCoordinator,
|
||||
bubbleCoordinator: BubbleCoordinator,
|
||||
headsUpCoordinator: HeadsUpCoordinator,
|
||||
gutsCoordinator: GutsCoordinator,
|
||||
conversationCoordinator: ConversationCoordinator,
|
||||
debugModeCoordinator: DebugModeCoordinator,
|
||||
groupCountCoordinator: GroupCountCoordinator,
|
||||
groupWhenCoordinator: GroupWhenCoordinator,
|
||||
mediaCoordinator: MediaCoordinator,
|
||||
preparationCoordinator: PreparationCoordinator,
|
||||
remoteInputCoordinator: RemoteInputCoordinator,
|
||||
rowAppearanceCoordinator: RowAppearanceCoordinator,
|
||||
stackCoordinator: StackCoordinator,
|
||||
shadeEventCoordinator: ShadeEventCoordinator,
|
||||
smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
|
||||
viewConfigCoordinator: ViewConfigCoordinator,
|
||||
visualStabilityCoordinator: VisualStabilityCoordinator,
|
||||
sensitiveContentCoordinator: SensitiveContentCoordinator,
|
||||
dismissibilityCoordinator: DismissibilityCoordinator
|
||||
) : NotifCoordinators {
|
||||
|
||||
private val mCoordinators: MutableList<Coordinator> = ArrayList()
|
||||
@@ -82,6 +83,7 @@ class NotifCoordinatorsImpl @Inject constructor(
|
||||
mCoordinators.add(debugModeCoordinator)
|
||||
mCoordinators.add(conversationCoordinator)
|
||||
mCoordinators.add(groupCountCoordinator)
|
||||
mCoordinators.add(groupWhenCoordinator)
|
||||
mCoordinators.add(mediaCoordinator)
|
||||
mCoordinators.add(rowAppearanceCoordinator)
|
||||
mCoordinators.add(stackCoordinator)
|
||||
|
||||
@@ -20,4 +20,7 @@ package com.android.systemui.statusbar.notification.collection.render
|
||||
interface NotifGroupController {
|
||||
/** Set the number of children that this group would have if not for the 8-child max */
|
||||
fun setUntruncatedChildCount(untruncatedChildCount: Int)
|
||||
|
||||
/** Set the when value of notification group that reflects most important closest notification time */
|
||||
fun setNotificationGroupWhen(whenMillis: Long)
|
||||
}
|
||||
@@ -851,6 +851,19 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
mChildrenContainer.setUntruncatedChildCount(childCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see NotificationChildrenContainer#setNotificationGroupWhen(long)
|
||||
*/
|
||||
public void setNotificationGroupWhen(long whenMillis) {
|
||||
if (mIsSummaryWithChildren) {
|
||||
mChildrenContainer.setNotificationGroupWhen(whenMillis);
|
||||
} else {
|
||||
Log.w(TAG, "setNotificationGroupWhen( whenMillis: " + whenMillis + ")"
|
||||
+ " mIsSummaryWithChildren: false"
|
||||
+ " mChildrenContainer has not been inflated yet.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after children have been attached to set the expansion states
|
||||
*/
|
||||
|
||||
@@ -348,6 +348,15 @@ public class ExpandableNotificationRowController implements NotifViewController
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotificationGroupWhen(long whenMillis) {
|
||||
if (mView.isSummaryWithChildren()) {
|
||||
mView.setNotificationGroupWhen(whenMillis);
|
||||
} else {
|
||||
Log.w(TAG, "Called setNotificationTime(" + whenMillis + ") on a leaf row");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSystemExpanded(boolean systemExpanded) {
|
||||
mView.setSystemExpanded(systemExpanded);
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
import android.widget.DateTimeView;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
@@ -344,6 +345,21 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple
|
||||
mTransformationHelper.setVisible(visible);
|
||||
}
|
||||
|
||||
/***
|
||||
* Set Notification when value
|
||||
* @param whenMillis
|
||||
*/
|
||||
public void setNotificationWhen(long whenMillis) {
|
||||
if (mNotificationHeader == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final View timeView = mNotificationHeader.findViewById(com.android.internal.R.id.time);
|
||||
|
||||
if (timeView instanceof DateTimeView) {
|
||||
((DateTimeView) timeView).setTime(whenMillis);
|
||||
}
|
||||
}
|
||||
protected void addTransformedViews(View... views) {
|
||||
for (View view : views) {
|
||||
if (view != null) {
|
||||
|
||||
@@ -295,6 +295,19 @@ public class NotificationChildrenContainer extends ViewGroup
|
||||
updateGroupOverflow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the notification time in the group so that the view can show the latest event in the UI
|
||||
* appropriately.
|
||||
*/
|
||||
public void setNotificationGroupWhen(long whenMillis) {
|
||||
if (mNotificationHeaderWrapper != null) {
|
||||
mNotificationHeaderWrapper.setNotificationWhen(whenMillis);
|
||||
}
|
||||
if (mNotificationHeaderWrapperLowPriority != null) {
|
||||
mNotificationHeaderWrapperLowPriority.setNotificationWhen(whenMillis);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child notification to this view.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.systemui.statusbar.notification.collection.coordinator
|
||||
|
||||
import android.app.Notification
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.statusbar.SbnBuilder
|
||||
import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
|
||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderGroupListener
|
||||
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener
|
||||
import com.android.systemui.statusbar.notification.collection.render.NotifGroupController
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.eq
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.android.systemui.util.mockito.withArgCaptor
|
||||
import com.android.systemui.util.time.SystemClock
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.InjectMocks
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations.initMocks
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@TestableLooper.RunWithLooper
|
||||
class GroupWhenCoordinatorTest : SysuiTestCase() {
|
||||
|
||||
private lateinit var beforeFinalizeFilterListener: OnBeforeFinalizeFilterListener
|
||||
private lateinit var afterRenderGroupListener: OnAfterRenderGroupListener
|
||||
|
||||
@Mock private lateinit var pipeline: NotifPipeline
|
||||
|
||||
@Mock private lateinit var delayableExecutor: DelayableExecutor
|
||||
|
||||
@Mock private lateinit var groupController: NotifGroupController
|
||||
|
||||
@Mock private lateinit var systemClock: SystemClock
|
||||
|
||||
@InjectMocks private lateinit var coordinator: GroupWhenCoordinator
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
initMocks(this)
|
||||
whenever(systemClock.currentTimeMillis()).thenReturn(NOW)
|
||||
coordinator.attach(pipeline)
|
||||
|
||||
beforeFinalizeFilterListener = withArgCaptor {
|
||||
verify(pipeline).addOnBeforeFinalizeFilterListener(capture())
|
||||
}
|
||||
afterRenderGroupListener = withArgCaptor {
|
||||
verify(pipeline).addOnAfterRenderGroupListener(capture())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setNotificationGroupWhen_setClosestTimeByNow_whenAllNotificationsAreBeforeNow() {
|
||||
// GIVEN
|
||||
val summaryEntry = buildNotificationEntry(0, NOW)
|
||||
val childEntry1 = buildNotificationEntry(1, NOW - 10L)
|
||||
val childEntry2 = buildNotificationEntry(2, NOW - 100L)
|
||||
val groupEntry =
|
||||
GroupEntryBuilder()
|
||||
.setSummary(summaryEntry)
|
||||
.setChildren(listOf(childEntry1, childEntry2))
|
||||
.build()
|
||||
// WHEN
|
||||
beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
|
||||
afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
|
||||
|
||||
// THEN
|
||||
verify(groupController).setNotificationGroupWhen(eq(NOW - 10L))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setNotificationGroupWhen_setClosestTimeByNow_whenAllNotificationsAreAfterNow() {
|
||||
// GIVEN
|
||||
val summaryEntry = buildNotificationEntry(0, NOW)
|
||||
val childEntry1 = buildNotificationEntry(1, NOW + 10L)
|
||||
val childEntry2 = buildNotificationEntry(2, NOW + 100L)
|
||||
|
||||
val groupEntry =
|
||||
GroupEntryBuilder()
|
||||
.setSummary(summaryEntry)
|
||||
.setChildren(listOf(childEntry1, childEntry2))
|
||||
.build()
|
||||
|
||||
// WHEN
|
||||
beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
|
||||
afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
|
||||
|
||||
// THEN
|
||||
verify(groupController).setNotificationGroupWhen(eq(NOW + 10L))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setNotificationGroupWhen_setClosestFutureTimeByNow_whenThereAreBothBeforeAndAfterNow() {
|
||||
// GIVEN
|
||||
val summaryEntry = buildNotificationEntry(0, NOW)
|
||||
val childEntry1 = buildNotificationEntry(1, NOW + 100L)
|
||||
val childEntry2 = buildNotificationEntry(2, NOW + 10L)
|
||||
val childEntry3 = buildNotificationEntry(3, NOW - 100L)
|
||||
val childEntry4 = buildNotificationEntry(4, NOW - 9L)
|
||||
|
||||
val groupEntry =
|
||||
GroupEntryBuilder()
|
||||
.setSummary(summaryEntry)
|
||||
.setChildren(listOf(childEntry1, childEntry2, childEntry3, childEntry4))
|
||||
.build()
|
||||
|
||||
// WHEN
|
||||
beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
|
||||
afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
|
||||
|
||||
// THEN
|
||||
verify(groupController).setNotificationGroupWhen(eq(NOW + 10L))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setNotificationGroupWhen_filterInvalidNotificationTimes() {
|
||||
// GIVEN
|
||||
val summaryEntry = buildNotificationEntry(0, NOW)
|
||||
val childEntry1 = buildNotificationEntry(1, NOW + 100L)
|
||||
val childEntry2 = buildNotificationEntry(2, -20000L)
|
||||
val childEntry3 = buildNotificationEntry(4, 0)
|
||||
|
||||
val groupEntry =
|
||||
GroupEntryBuilder()
|
||||
.setSummary(summaryEntry)
|
||||
.setChildren(listOf(childEntry1, childEntry2, childEntry3))
|
||||
.build()
|
||||
|
||||
// WHEN
|
||||
beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
|
||||
afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
|
||||
|
||||
// THEN
|
||||
verify(groupController).setNotificationGroupWhen(eq(NOW + 100))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setNotificationGroupWhen_setSummaryTimeWhenAllNotificationTimesAreInvalid() {
|
||||
// GIVEN
|
||||
val summaryEntry = buildNotificationEntry(0, NOW)
|
||||
val childEntry1 = buildNotificationEntry(1, 0)
|
||||
val childEntry2 = buildNotificationEntry(2, -1)
|
||||
|
||||
val groupEntry =
|
||||
GroupEntryBuilder()
|
||||
.setSummary(summaryEntry)
|
||||
.setChildren(listOf(childEntry1, childEntry2))
|
||||
.build()
|
||||
|
||||
// WHEN
|
||||
beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
|
||||
afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
|
||||
|
||||
// THEN
|
||||
verify(groupController, never()).setNotificationGroupWhen(NOW)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setNotificationGroupWhen_schedulePipelineInvalidationWhenAnyNotificationIsInTheFuture() {
|
||||
// GIVEN
|
||||
val summaryEntry = buildNotificationEntry(0, NOW)
|
||||
val childEntry1 = buildNotificationEntry(1, NOW + 1000L)
|
||||
val childEntry2 = buildNotificationEntry(2, NOW + 2000L)
|
||||
val childEntry3 = buildNotificationEntry(3, NOW - 100L)
|
||||
|
||||
val groupEntry =
|
||||
GroupEntryBuilder()
|
||||
.setSummary(summaryEntry)
|
||||
.setChildren(listOf(childEntry1, childEntry2, childEntry3))
|
||||
.build()
|
||||
|
||||
// WHEN
|
||||
beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
|
||||
afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
|
||||
|
||||
// THEN
|
||||
verify(delayableExecutor).executeDelayed(any(), eq(1000))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setNotificationGroupWhen_cancelPrevPipelineInvalidation() {
|
||||
// GIVEN
|
||||
val summaryEntry = buildNotificationEntry(0, NOW)
|
||||
val childEntry1 = buildNotificationEntry(1, NOW + 1L)
|
||||
val prevInvalidation = mock<Runnable>()
|
||||
whenever(delayableExecutor.executeDelayed(any(), any())).thenReturn(prevInvalidation)
|
||||
|
||||
val groupEntry =
|
||||
GroupEntryBuilder().setSummary(summaryEntry).setChildren(listOf(childEntry1)).build()
|
||||
|
||||
// WHEN
|
||||
beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
|
||||
afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
|
||||
|
||||
beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
|
||||
|
||||
// THEN
|
||||
verify(prevInvalidation).run()
|
||||
}
|
||||
|
||||
private fun buildNotificationEntry(id: Int, timeMillis: Long): NotificationEntry {
|
||||
val notification = Notification.Builder(mContext).setWhen(timeMillis).build()
|
||||
val sbn = SbnBuilder().setNotification(notification).build()
|
||||
return NotificationEntryBuilder().setId(id).setSbn(sbn).build()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val NOW = 1000L
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user