diff options
16 files changed, 162 insertions, 71 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt index cca847effe94..c8eff1d6c683 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt @@ -2837,9 +2837,7 @@ class SceneContainerStartableTest : SysuiTestCase() { ) private fun fakeHeadsUpRowRepository(key: String, isPinned: Boolean) = - FakeHeadsUpRowRepository(key = key, elementKey = Any()).apply { - this.isPinned.value = isPinned - } + FakeHeadsUpRowRepository(key = key, elementKey = Any(), isPinned = isPinned) private fun setFingerprintSensorType(fingerprintSensorType: FingerprintSensorType) { kosmos.fingerprintPropertyRepository.setProperties( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinatorTest.kt index d772e3effbeb..14148cdc0f03 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinatorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinatorTest.kt @@ -21,7 +21,6 @@ import android.app.Notification import android.app.NotificationManager.IMPORTANCE_DEFAULT import android.app.NotificationManager.IMPORTANCE_LOW import android.platform.test.annotations.EnableFlags -import android.provider.Settings import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase @@ -43,6 +42,7 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.No import com.android.systemui.statusbar.notification.data.repository.FakeHeadsUpRowRepository import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository import com.android.systemui.statusbar.notification.domain.interactor.lockScreenNotificationMinimalismSetting +import com.android.systemui.statusbar.notification.headsup.PinnedStatus import com.android.systemui.statusbar.notification.shared.NotificationMinimalism import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository import com.android.systemui.testKosmos @@ -394,7 +394,7 @@ class LockScreenMinimalismCoordinatorTest : SysuiTestCase() { assertThatTopUnseenKey().isEqualTo(solo1.key) // TEST: even being pinned doesn't take effect immediately - hunRepo1.isPinned.value = true + hunRepo1.pinnedStatus.value = PinnedStatus.PinnedBySystem testScheduler.advanceTimeBy(0.5.seconds) onBeforeTransformGroupsListener.onBeforeTransformGroups(listEntryList) assertThatTopUnseenKey().isEqualTo(solo1.key) @@ -406,8 +406,8 @@ class LockScreenMinimalismCoordinatorTest : SysuiTestCase() { // TEST: repeat; being heads up and pinned for 1 second triggers seen kosmos.headsUpNotificationRepository.orderedHeadsUpRows.value = listOf(hunRepo2) - hunRepo1.isPinned.value = false - hunRepo2.isPinned.value = true + hunRepo1.pinnedStatus.value = PinnedStatus.NotPinned + hunRepo2.pinnedStatus.value = PinnedStatus.PinnedBySystem testScheduler.advanceTimeBy(1.seconds) onBeforeTransformGroupsListener.onBeforeTransformGroups(listEntryList) assertThatTopUnseenKey().isEqualTo(null) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt index d717fe4c1e04..dc0231f40609 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt @@ -31,6 +31,7 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.shade.shadeTestUtil import com.android.systemui.statusbar.notification.data.repository.FakeHeadsUpRowRepository import com.android.systemui.statusbar.notification.data.repository.notificationsKeyguardViewStateRepository +import com.android.systemui.statusbar.notification.headsup.PinnedStatus import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor import com.android.systemui.testKosmos @@ -102,7 +103,7 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test - fun hasPinnedRows_rowGetsPinned_true() = + fun hasPinnedRows_rowGetsPinnedNormally_true() = testScope.runTest { val hasPinnedRows by collectLastValue(underTest.hasPinnedRows) // GIVEN no rows are pinned @@ -115,8 +116,30 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { headsUpRepository.setNotifications(rows) runCurrent() - // WHEN a row gets pinned - rows[0].isPinned.value = true + // WHEN a row gets pinned normally + rows[0].pinnedStatus.value = PinnedStatus.PinnedBySystem + runCurrent() + + // THEN hasPinnedRows updates to true + assertThat(hasPinnedRows).isTrue() + } + + @Test + fun hasPinnedRows_rowGetsPinnedByUser_true() = + testScope.runTest { + val hasPinnedRows by collectLastValue(underTest.hasPinnedRows) + // GIVEN no rows are pinned + val rows = + arrayListOf( + fakeHeadsUpRowRepository("key 0"), + fakeHeadsUpRowRepository("key 1"), + fakeHeadsUpRowRepository("key 2"), + ) + headsUpRepository.setNotifications(rows) + runCurrent() + + // WHEN a row gets pinned due to a chip tap + rows[0].pinnedStatus.value = PinnedStatus.PinnedByUser runCurrent() // THEN hasPinnedRows updates to true @@ -138,7 +161,7 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { runCurrent() // THEN that row gets unpinned - rows[0].isPinned.value = false + rows[0].pinnedStatus.value = PinnedStatus.NotPinned runCurrent() // THEN hasPinnedRows updates to false @@ -246,7 +269,7 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { runCurrent() // WHEN all rows gets pinned - rows[2].isPinned.value = true + rows[2].pinnedStatus.value = PinnedStatus.PinnedBySystem runCurrent() // THEN no rows are filtered @@ -271,7 +294,7 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) // WHEN all rows gets pinned - rows[2].isPinned.value = true + rows[2].pinnedStatus.value = PinnedStatus.PinnedBySystem runCurrent() // THEN no change @@ -329,7 +352,7 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { runCurrent() // WHEN a row gets unpinned - rows[0].isPinned.value = false + rows[0].pinnedStatus.value = PinnedStatus.NotPinned runCurrent() // THEN the unpinned row is filtered @@ -351,7 +374,7 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { runCurrent() // WHEN a row gets unpinned - rows[0].isPinned.value = false + rows[0].pinnedStatus.value = PinnedStatus.NotPinned runCurrent() // THEN all rows are still present @@ -372,15 +395,15 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { headsUpRepository.setNotifications(rows) runCurrent() - rows[0].isPinned.value = true + rows[0].pinnedStatus.value = PinnedStatus.PinnedBySystem runCurrent() assertThat(pinnedHeadsUpRows).containsExactly(rows[0]) - rows[0].isPinned.value = false + rows[0].pinnedStatus.value = PinnedStatus.NotPinned runCurrent() assertThat(pinnedHeadsUpRows).isEmpty() - rows[0].isPinned.value = true + rows[0].pinnedStatus.value = PinnedStatus.PinnedBySystem runCurrent() assertThat(pinnedHeadsUpRows).containsExactly(rows[0]) } @@ -485,7 +508,5 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } private fun fakeHeadsUpRowRepository(key: String, isPinned: Boolean = false) = - FakeHeadsUpRowRepository(key = key, elementKey = Any()).apply { - this.isPinned.value = isPinned - } + FakeHeadsUpRowRepository(key = key, isPinned = isPinned) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImplTest.java index 6e9fd67f32de..01f78cb289fd 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImplTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImplTest.java @@ -72,6 +72,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import kotlinx.coroutines.flow.StateFlowKt; import platform.test.runner.parameterized.ParameterizedAndroidJunit4; import platform.test.runner.parameterized.Parameters; @@ -318,6 +319,8 @@ public class HeadsUpManagerImplTest extends SysuiTestCase { mContext); final HeadsUpManagerImpl.HeadsUpEntry headsUpEntry = mock( HeadsUpManagerImpl.HeadsUpEntry.class); + when(headsUpEntry.getPinnedStatus()) + .thenReturn(StateFlowKt.MutableStateFlow(PinnedStatus.NotPinned)); headsUpEntry.mEntry = notifEntry; hum.onEntryRemoved(headsUpEntry, "test"); diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java index f9dec144652a..979a1d0801f0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java @@ -40,6 +40,7 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.shade.ShadeController; +import com.android.systemui.statusbar.notification.headsup.PinnedStatus; import com.android.systemui.statusbar.notification.logging.NotificationPanelLogger; import com.android.systemui.statusbar.notification.headsup.HeadsUpManager; @@ -91,7 +92,7 @@ public class ExpandableNotificationRowDragControllerTest extends SysuiTestCase { ExpandableNotificationRowDragController controller = createSpyController(); mRow.setDragController(controller); mRow.setHeadsUp(true); - mRow.setPinned(true); + mRow.setPinnedStatus(PinnedStatus.PinnedBySystem); mRow.doLongClickCallback(0, 0); mRow.doDragCallback(0, 0); diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt index bf144729dea3..e592e4b319e3 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt @@ -42,6 +42,7 @@ import com.android.systemui.statusbar.notification.data.repository.activeNotific import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs import com.android.systemui.statusbar.notification.emptyshade.shared.ModesEmptyShadeFix import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor +import com.android.systemui.statusbar.notification.headsup.PinnedStatus import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository import com.android.systemui.statusbar.policy.data.repository.fakeUserSetupRepository import com.android.systemui.statusbar.policy.fakeConfigurationController @@ -522,21 +523,21 @@ class NotificationListViewModelTest(flags: FlagsParameterization) : SysuiTestCas assertThat(pinnedHeadsUpRows).isEmpty() // WHEN a row gets pinned - rows[0].isPinned.value = true + rows[0].pinnedStatus.value = PinnedStatus.PinnedBySystem runCurrent() // THEN it's added to the list assertThat(pinnedHeadsUpRows).containsExactly(rows[0]) // WHEN more rows are pinned - rows[1].isPinned.value = true + rows[1].pinnedStatus.value = PinnedStatus.PinnedBySystem runCurrent() // THEN they are all in the list assertThat(pinnedHeadsUpRows).containsExactly(rows[0], rows[1]) // WHEN a row gets unpinned - rows[0].isPinned.value = false + rows[0].pinnedStatus.value = PinnedStatus.NotPinned runCurrent() // THEN it's removed from the list diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java index 8f0f171ac67e..f9f2cd328094 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java @@ -45,6 +45,7 @@ import com.android.systemui.statusbar.HeadsUpStatusBarView; import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationIconInteractor; +import com.android.systemui.statusbar.notification.headsup.PinnedStatus; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation; @@ -131,13 +132,13 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { @Test public void testShowinEntryUpdated() { - mRow.setPinned(true); + mRow.setPinnedStatus(PinnedStatus.PinnedBySystem); when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(true); when(mHeadsUpManager.getTopEntry()).thenReturn(mEntry); mHeadsUpAppearanceController.onHeadsUpPinned(mEntry); assertEquals(mRow.getEntry(), mHeadsUpStatusBarView.getShowingEntry()); - mRow.setPinned(false); + mRow.setPinnedStatus(PinnedStatus.NotPinned); when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(false); mHeadsUpAppearanceController.onHeadsUpUnPinned(mEntry); assertEquals(null, mHeadsUpStatusBarView.getShowingEntry()); @@ -145,13 +146,13 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { @Test public void testShownUpdated() { - mRow.setPinned(true); + mRow.setPinnedStatus(PinnedStatus.PinnedBySystem); when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(true); when(mHeadsUpManager.getTopEntry()).thenReturn(mEntry); mHeadsUpAppearanceController.onHeadsUpPinned(mEntry); assertTrue(mHeadsUpAppearanceController.isShown()); - mRow.setPinned(false); + mRow.setPinnedStatus(PinnedStatus.NotPinned); when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(false); mHeadsUpAppearanceController.onHeadsUpUnPinned(mEntry); Assert.assertFalse(mHeadsUpAppearanceController.isShown()); @@ -160,13 +161,13 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { @Test @DisableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME) public void testHeaderUpdated() { - mRow.setPinned(true); + mRow.setPinnedStatus(PinnedStatus.PinnedBySystem); when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(true); when(mHeadsUpManager.getTopEntry()).thenReturn(mEntry); mHeadsUpAppearanceController.onHeadsUpPinned(mEntry); assertEquals(mRow.getHeaderVisibleAmount(), 0.0f, 0.0f); - mRow.setPinned(false); + mRow.setPinnedStatus(PinnedStatus.NotPinned); when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(false); mHeadsUpAppearanceController.onHeadsUpUnPinned(mEntry); assertEquals(mRow.getHeaderVisibleAmount(), 1.0f, 0.0f); @@ -176,13 +177,13 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { public void testOperatorNameViewUpdated() { mHeadsUpAppearanceController.setAnimationsEnabled(false); - mRow.setPinned(true); + mRow.setPinnedStatus(PinnedStatus.PinnedBySystem); when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(true); when(mHeadsUpManager.getTopEntry()).thenReturn(mEntry); mHeadsUpAppearanceController.onHeadsUpPinned(mEntry); assertEquals(View.INVISIBLE, mOperatorNameView.getVisibility()); - mRow.setPinned(false); + mRow.setPinnedStatus(PinnedStatus.NotPinned); when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(false); mHeadsUpAppearanceController.onHeadsUpUnPinned(mEntry); assertEquals(View.VISIBLE, mOperatorNameView.getVisibility()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index c487ff5d35bd..6d4d40c43e85 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -65,6 +65,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender; import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; +import com.android.systemui.statusbar.notification.headsup.PinnedStatus; import com.android.systemui.statusbar.notification.icon.IconPack; import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -675,8 +676,8 @@ public final class NotificationEntry extends ListEntry { return row != null && row.isPinnedAndExpanded(); } - public void setRowPinned(boolean pinned) { - if (row != null) row.setPinned(pinned); + public void setRowPinnedStatus(PinnedStatus pinnedStatus) { + if (row != null) row.setPinnedStatus(pinnedStatus); } public boolean isRowHeadsUp() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpRowRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpRowRepository.kt index 7b40812d55c3..266310479a1a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpRowRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/HeadsUpRowRepository.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.data.repository +import com.android.systemui.statusbar.notification.headsup.PinnedStatus import com.android.systemui.statusbar.notification.shared.HeadsUpRowKey import kotlinx.coroutines.flow.StateFlow @@ -31,6 +32,6 @@ interface HeadsUpRowRepository : HeadsUpRowKey { /** A key to identify this row in the view hierarchy. */ val elementKey: Any - /** Whether this notification is "pinned", meaning that it should stay on top of the screen. */ - val isPinned: StateFlow<Boolean> + /** This notification's pinning status. */ + val pinnedStatus: StateFlow<PinnedStatus> } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt index e25127e3e0d6..81335658679b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt @@ -52,7 +52,9 @@ constructor( val topHeadsUpRowIfPinned: Flow<HeadsUpRowKey?> = headsUpRepository.topHeadsUpRow .flatMapLatest { repository -> - repository?.isPinned?.map { pinned -> repository.takeIf { pinned } } ?: flowOf(null) + repository?.pinnedStatus?.map { pinnedStatus -> + repository.takeIf { pinnedStatus.isPinned } + } ?: flowOf(null) } .distinctUntilChanged() @@ -64,7 +66,7 @@ constructor( if (repositories.isNotEmpty()) { val toCombine: List<Flow<Pair<HeadsUpRowRepository, Boolean>>> = repositories.map { repo -> - repo.isPinned.map { isPinned -> repo to isPinned } + repo.pinnedStatus.map { pinnedStatus -> repo to pinnedStatus.isPinned } } combine(toCombine) { pairs -> pairs.toSet() } } else { @@ -102,7 +104,9 @@ constructor( } else { headsUpRepository.activeHeadsUpRows.flatMapLatest { rows -> if (rows.isNotEmpty()) { - combine(rows.map { it.isPinned }) { pins -> pins.any { it } } + combine(rows.map { it.pinnedStatus }) { pinnedStatus -> + pinnedStatus.any { it.isPinned } + } } else { // if the set is empty, there are no flows to combine flowOf(false) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java index 59242d0b8632..99df9f45840a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java @@ -405,9 +405,11 @@ public class HeadsUpManagerImpl } if (shouldHeadsUpAgain) { headsUpEntry.updateEntry(true /* updatePostTime */, "updateNotification"); + PinnedStatus pinnedStatus = shouldHeadsUpBecomePinned(headsUpEntry.mEntry) + ? PinnedStatus.PinnedBySystem + : PinnedStatus.NotPinned; if (headsUpEntry != null) { - setEntryPinned(headsUpEntry, shouldHeadsUpBecomePinned(headsUpEntry.mEntry), - "updateNotificationInternal"); + setEntryPinned(headsUpEntry, pinnedStatus, "updateNotificationInternal"); } } } @@ -562,15 +564,16 @@ public class HeadsUpManagerImpl } protected void setEntryPinned( - @NonNull HeadsUpManagerImpl.HeadsUpEntry headsUpEntry, boolean isPinned, + @NonNull HeadsUpManagerImpl.HeadsUpEntry headsUpEntry, PinnedStatus pinnedStatus, String reason) { - mLogger.logSetEntryPinned(headsUpEntry.mEntry, isPinned, reason); + mLogger.logSetEntryPinned(headsUpEntry.mEntry, pinnedStatus, reason); NotificationEntry entry = headsUpEntry.mEntry; + boolean isPinned = pinnedStatus.isPinned(); if (!isPinned) { headsUpEntry.mWasUnpinned = true; } - if (headsUpEntry.isRowPinned() != isPinned) { - headsUpEntry.setRowPinned(isPinned); + if (headsUpEntry.getPinnedStatus().getValue() != pinnedStatus) { + headsUpEntry.setRowPinnedStatus(pinnedStatus); updatePinnedMode(); if (isPinned && entry.getSbn() != null) { mUiEventLogger.logWithInstanceId( @@ -596,8 +599,10 @@ public class HeadsUpManagerImpl NotificationEntry entry = headsUpEntry.mEntry; entry.setHeadsUp(true); - final boolean shouldPin = shouldHeadsUpBecomePinned(entry); - setEntryPinned(headsUpEntry, shouldPin, "onEntryAdded"); + final PinnedStatus pinnedStatus = shouldHeadsUpBecomePinned(entry) + ? PinnedStatus.PinnedBySystem + : PinnedStatus.NotPinned; + setEntryPinned(headsUpEntry, pinnedStatus, "onEntryAdded"); EventLogTags.writeSysuiHeadsUpStatus(entry.getKey(), 1 /* visible */); for (OnHeadsUpChangedListener listener : mListeners) { listener.onHeadsUpStateChanged(entry, true); @@ -655,7 +660,7 @@ public class HeadsUpManagerImpl protected void onEntryRemoved(HeadsUpEntry headsUpEntry, String reason) { NotificationEntry entry = headsUpEntry.mEntry; entry.setHeadsUp(false); - setEntryPinned(headsUpEntry, false /* isPinned */, "onEntryRemoved"); + setEntryPinned(headsUpEntry, PinnedStatus.NotPinned, "onEntryRemoved"); EventLogTags.writeSysuiHeadsUpStatus(entry.getKey(), 0 /* visible */); mLogger.logNotificationActuallyRemoved(entry); for (OnHeadsUpChangedListener listener : mListeners) { @@ -964,7 +969,7 @@ public class HeadsUpManagerImpl Runnable runnable = () -> { mLogger.logUnpinEntry(key); - setEntryPinned(headsUpEntry, false /* isPinned */, "unpinAll"); + setEntryPinned(headsUpEntry, PinnedStatus.NotPinned, "unpinAll"); // maybe it got un sticky headsUpEntry.updateEntry(false /* updatePostTime */, "unpinAll"); @@ -1235,7 +1240,8 @@ public class HeadsUpManagerImpl @Nullable private Runnable mCancelRemoveRunnable; private boolean mGutsShownPinned; - private final MutableStateFlow<Boolean> mIsPinned = StateFlowKt.MutableStateFlow(false); + private final MutableStateFlow<PinnedStatus> mPinnedStatus = + StateFlowKt.MutableStateFlow(PinnedStatus.NotPinned); /** * If the time this entry has been on was extended @@ -1271,8 +1277,8 @@ public class HeadsUpManagerImpl @Override @NonNull - public StateFlow<Boolean> isPinned() { - return mIsPinned; + public StateFlow<PinnedStatus> getPinnedStatus() { + return mPinnedStatus; } /** Attach a NotificationEntry. */ @@ -1302,9 +1308,9 @@ public class HeadsUpManagerImpl return mEntry != null && mEntry.isRowPinned(); } - protected void setRowPinned(boolean pinned) { - if (mEntry != null) mEntry.setRowPinned(pinned); - mIsPinned.setValue(pinned); + protected void setRowPinnedStatus(PinnedStatus pinnedStatus) { + if (mEntry != null) mEntry.setRowPinnedStatus(pinnedStatus); + mPinnedStatus.setValue(pinnedStatus); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerLogger.kt index 4128116c872f..80225c47e9ea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerLogger.kt @@ -272,16 +272,16 @@ constructor(@NotificationHeadsUpLog private val buffer: LogBuffer) { ) } - fun logSetEntryPinned(entry: NotificationEntry, isPinned: Boolean, reason: String) { + fun logSetEntryPinned(entry: NotificationEntry, pinnedStatus: PinnedStatus, reason: String) { buffer.log( TAG, VERBOSE, { str1 = entry.logKey - bool1 = isPinned str2 = reason + str3 = pinnedStatus.name }, - { "$str2 => set entry pinned $str1 pinned: $bool1" }, + { "$str2 => set entry pinned $str1 pinned: $str3" }, ) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/PinnedStatus.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/PinnedStatus.kt new file mode 100644 index 000000000000..af1805476f05 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/PinnedStatus.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 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.headsup + +/** + * A status representing whether and how a notification is pinned. + * + * @property isPinned true if a notification should be "pinned", meaning that a notification should + * stay on top of the screen. + */ +enum class PinnedStatus(val isPinned: Boolean) { + /** This notification is not pinned. */ + NotPinned(isPinned = false), + /** + * This notification is pinned by the system - likely because when the notification was added or + * updated, it required pinning. + */ + PinnedBySystem(isPinned = true), + /** + * This notification is pinned because the user did an explicit action to pin it (like tapping + * the notification chip in the status bar). + */ + // TODO(b/364653005): Use this status when a user taps the notification chip. + PinnedByUser(isPinned = true), +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 0c142e34bea4..f6d8a8bc11c8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -101,6 +101,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider; import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; +import com.android.systemui.statusbar.notification.headsup.PinnedStatus; import com.android.systemui.statusbar.notification.logging.NotificationCounters; import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag; @@ -277,7 +278,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private NotificationMenuRowPlugin mMenuRow; private ViewStub mGutsStub; private boolean mIsSystemChildExpanded; - private boolean mIsPinned; + private PinnedStatus mPinnedStatus = PinnedStatus.NotPinned; private boolean mExpandAnimationRunning; private AboveShelfChangedListener mAboveShelfChangedListener; private HeadsUpManager mHeadsUpManager; @@ -1154,17 +1155,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView /** * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this * the notification will be rendered on top of the screen. - * - * @param pinned whether it is pinned */ - public void setPinned(boolean pinned) { + public void setPinnedStatus(PinnedStatus pinnedStatus) { int intrinsicHeight = getIntrinsicHeight(); boolean wasAboveShelf = isAboveShelf(); - mIsPinned = pinned; + mPinnedStatus = pinnedStatus; if (intrinsicHeight != getIntrinsicHeight()) { notifyHeightChanged(/* needsAnimation= */ false); } - if (pinned) { + if (pinnedStatus.isPinned()) { setAnimationRunning(true); mExpandedWhenPinned = false; } else if (mExpandedWhenPinned) { @@ -1178,7 +1177,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView @Override public boolean isPinned() { - return mIsPinned; + return mPinnedStatus.isPinned(); } @Override @@ -3749,7 +3748,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView @Override public boolean isAboveShelf() { return (canShowHeadsUp() - && (mIsPinned || mHeadsupDisappearRunning || (mIsHeadsUp && mAboveShelf) + && (mPinnedStatus.isPinned() + || mHeadsupDisappearRunning || (mIsHeadsUp && mAboveShelf) || mExpandAnimationRunning || mChildIsExpanding)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index d8a23d6bd32e..5aee92939ed5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -68,6 +68,7 @@ import com.android.systemui.statusbar.notification.AboveShelfChangedListener; import com.android.systemui.statusbar.notification.FeedbackIcon; import com.android.systemui.statusbar.notification.SourceType; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.headsup.PinnedStatus; import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener; import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization; @@ -394,7 +395,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { ExpandableNotificationRow row = mNotificationTestHelper.createRow(); AboveShelfChangedListener listener = mock(AboveShelfChangedListener.class); row.setAboveShelfChangedListener(listener); - row.setPinned(true); + row.setPinnedStatus(PinnedStatus.PinnedBySystem); verify(listener).onAboveShelfStateChanged(true); } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/data/repository/FakeHeadsUpRowRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/data/repository/FakeHeadsUpRowRepository.kt index 980d65fde6de..7de22d8c8b43 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/data/repository/FakeHeadsUpRowRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/data/repository/FakeHeadsUpRowRepository.kt @@ -16,13 +16,27 @@ package com.android.systemui.statusbar.notification.data.repository +import com.android.systemui.statusbar.notification.headsup.PinnedStatus import kotlinx.coroutines.flow.MutableStateFlow class FakeHeadsUpRowRepository(override val key: String, override val elementKey: Any = Any()) : HeadsUpRowRepository { - constructor(key: String, isPinned: Boolean) : this(key = key) { - this.isPinned.value = isPinned + constructor( + key: String, + elementKey: Any = Any(), + isPinned: Boolean, + ) : this(key = key, elementKey = elementKey) { + this.pinnedStatus.value = if (isPinned) PinnedStatus.PinnedBySystem else PinnedStatus.NotPinned } - override val isPinned: MutableStateFlow<Boolean> = MutableStateFlow(false) + constructor( + key: String, + elementKey: Any = Any(), + pinnedStatus: PinnedStatus, + ) : this(key = key, elementKey = elementKey) { + this.pinnedStatus.value = pinnedStatus + } + + override val pinnedStatus: MutableStateFlow<PinnedStatus> = + MutableStateFlow(PinnedStatus.NotPinned) } |