Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/AvalancheControllerTest.kt +71 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.log.logcatLogBuffer import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun import com.android.systemui.statusbar.policy.HeadsUpManagerTestUtil.createFullScreenIntentEntry import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.settings.FakeGlobalSettings import com.android.systemui.util.time.FakeSystemClock Loading Loading @@ -97,6 +98,12 @@ class AvalancheControllerTest : SysuiTestCase() { return entry } private fun createFsiHeadsUpEntry(id: Int): BaseHeadsUpManager.HeadsUpEntry { val entry = testableHeadsUpManager!!.createHeadsUpEntry() entry.setEntry(createFullScreenIntentEntry(id, mContext)) return entry } @Test fun testUpdate_isShowing_runsRunnable() { // Entry is showing Loading Loading @@ -238,4 +245,68 @@ class AvalancheControllerTest : SysuiTestCase() { // Next entry is shown Truth.assertThat(mAvalancheController.headsUpEntryShowing).isEqualTo(nextEntry) } @Test fun testGetDurationMs_lastEntry_useAutoDismissTime() { // Entry is showing val showingEntry = createHeadsUpEntry(id = 0) mAvalancheController.headsUpEntryShowing = showingEntry // Nothing is next mAvalancheController.clearNext() val durationMs = mAvalancheController.getDurationMs(showingEntry, autoDismissMs = 5000) Truth.assertThat(durationMs).isEqualTo(5000) } @Test fun testGetDurationMs_nextEntryLowerPriority_500() { // Entry is showing val showingEntry = createFsiHeadsUpEntry(id = 1) mAvalancheController.headsUpEntryShowing = showingEntry // There's another entry waiting to show next val nextEntry = createHeadsUpEntry(id = 0) mAvalancheController.addToNext(nextEntry, runnableMock!!) // Next entry has lower priority Truth.assertThat(nextEntry.compareNonTimeFields(showingEntry)).isEqualTo(1) val durationMs = mAvalancheController.getDurationMs(showingEntry, autoDismissMs = 5000) Truth.assertThat(durationMs).isEqualTo(5000) } @Test fun testGetDurationMs_nextEntrySamePriority_1000() { // Entry is showing val showingEntry = createHeadsUpEntry(id = 0) mAvalancheController.headsUpEntryShowing = showingEntry // There's another entry waiting to show next val nextEntry = createHeadsUpEntry(id = 1) mAvalancheController.addToNext(nextEntry, runnableMock!!) // Same priority Truth.assertThat(nextEntry.compareNonTimeFields(showingEntry)).isEqualTo(0) val durationMs = mAvalancheController.getDurationMs(showingEntry, autoDismissMs = 5000) Truth.assertThat(durationMs).isEqualTo(1000) } @Test fun testGetDurationMs_nextEntryHigherPriority_500() { // Entry is showing val showingEntry = createHeadsUpEntry(id = 0) mAvalancheController.headsUpEntryShowing = showingEntry // There's another entry waiting to show next val nextEntry = createFsiHeadsUpEntry(id = 1) mAvalancheController.addToNext(nextEntry, runnableMock!!) // Next entry has higher priority Truth.assertThat(nextEntry.compareNonTimeFields(showingEntry)).isEqualTo(-1) val durationMs = mAvalancheController.getDurationMs(showingEntry, autoDismissMs = 5000) Truth.assertThat(durationMs).isEqualTo(500) } } packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java +8 −19 Original line number Diff line number Diff line Loading @@ -117,21 +117,6 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { return HeadsUpManagerTestUtil.createEntry(id, notif); } private PendingIntent createFullScreenIntent() { return PendingIntent.getActivity( getContext(), 0, new Intent(getContext(), this.getClass()), PendingIntent.FLAG_MUTABLE_UNAUDITED); } private NotificationEntry createFullScreenIntentEntry(int id) { final Notification notif = new Notification.Builder(mContext, "") .setSmallIcon(R.drawable.ic_person) .setFullScreenIntent(createFullScreenIntent(), /* highPriority */ true) .build(); return HeadsUpManagerTestUtil.createEntry(id, notif); } private void useAccessibilityTimeout(boolean use) { if (use) { doReturn(TEST_A11Y_AUTO_DISMISS_TIME).when(mAccessibilityMgr) Loading Loading @@ -239,7 +224,8 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { @Test public void testShouldHeadsUpBecomePinned_hasFSI_notUnpinned_true() { final BaseHeadsUpManager hum = createHeadsUpManager(); final NotificationEntry notifEntry = createFullScreenIntentEntry(/* id = */ 0); final NotificationEntry notifEntry = HeadsUpManagerTestUtil.createFullScreenIntentEntry(/* id = */ 0, mContext); // Add notifEntry to ANM mAlertEntries map and make it NOT unpinned hum.showNotification(notifEntry); Loading @@ -254,7 +240,8 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { @Test public void testShouldHeadsUpBecomePinned_wasUnpinned_false() { final BaseHeadsUpManager hum = createHeadsUpManager(); final NotificationEntry notifEntry = createFullScreenIntentEntry(/* id = */ 0); final NotificationEntry notifEntry = HeadsUpManagerTestUtil.createFullScreenIntentEntry(/* id = */ 0, mContext); // Add notifEntry to ANM mAlertEntries map and make it unpinned hum.showNotification(notifEntry); Loading Loading @@ -443,7 +430,8 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { @Test public void testIsSticky_hasFullScreenIntent_true() { final BaseHeadsUpManager hum = createHeadsUpManager(); final NotificationEntry notifEntry = createFullScreenIntentEntry(/* id = */ 0); final NotificationEntry notifEntry = HeadsUpManagerTestUtil.createFullScreenIntentEntry(/* id = */ 0, mContext); hum.showNotification(notifEntry); Loading Loading @@ -554,7 +542,8 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { // Needs full screen intent in order to be pinned final BaseHeadsUpManager.HeadsUpEntry entryToPin = hum.new HeadsUpEntry(); entryToPin.setEntry(createFullScreenIntentEntry(/* id = */ 0)); entryToPin.setEntry( HeadsUpManagerTestUtil.createFullScreenIntentEntry(/* id = */ 0, mContext)); // Note: the standard way to show a notification would be calling showNotification rather // than onAlertEntryAdded. However, in practice showNotification in effect adds Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTestUtil.java +14 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.policy; import android.app.ActivityManager; import android.app.PendingIntent; import android.content.Intent; import android.os.UserHandle; import android.content.Context; Loading Loading @@ -67,4 +69,16 @@ public class HeadsUpManagerTestUtil { return new NotificationEntryBuilder().setSbn( HeadsUpManagerTestUtil.createSbn(id, context)).build(); } protected static NotificationEntry createFullScreenIntentEntry(int id, Context context) { final PendingIntent intent = PendingIntent.getActivity( context, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE); final Notification notif = new Notification.Builder(context, "") .setSmallIcon(com.android.systemui.res.R.drawable.ic_person) .setFullScreenIntent(intent, /* highPriority */ true) .build(); return HeadsUpManagerTestUtil.createEntry(id, notif); } } packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt +25 −9 Original line number Diff line number Diff line Loading @@ -131,21 +131,37 @@ class AvalancheController @Inject constructor() { } /** * Returns true if given HeadsUpEntry is the last one tracked by AvalancheController. Used by * BaseHeadsUpManager.HeadsUpEntry.calculateFinishTime to shorten display duration during active * avalanche. * Returns duration based on * 1) Whether HeadsUpEntry is the last one tracked byAvalancheController * 2) The priority of the top HUN in the next batch Used by * BaseHeadsUpManager.HeadsUpEntry.calculateFinishTime to shorten display duration. */ fun shortenDuration(entry: HeadsUpEntry): Boolean { fun getDurationMs(entry: HeadsUpEntry, autoDismissMs: Int): Int { if (!NotificationThrottleHun.isEnabled) { // Use default display duration, like we always did before AvalancheController existed return false // Use default duration, like we did before AvalancheController existed return autoDismissMs } val showingList: MutableList<HeadsUpEntry> = mutableListOf() headsUpEntryShowing?.let { showingList.add(it) } val allEntryList = showingList + nextList // Shorten duration if not last entry return allEntryList.indexOf(entry) != allEntryList.size - 1 val entryList = showingList + nextList if (entryList.indexOf(entry) == entryList.size - 1) { // Use default duration if last entry return autoDismissMs } nextList.sort() val nextEntry = nextList[0] if (nextEntry.compareNonTimeFields(entry) == -1) { // Next entry is higher priority return 500 } else if (nextEntry.compareNonTimeFields(entry) == 0) { // Next entry is same priority return 1000 } else { return autoDismissMs } } /** Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java +9 −4 Original line number Diff line number Diff line Loading @@ -776,7 +776,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { return mEarliestRemovalTime < mSystemClock.elapsedRealtime(); } public int compareTo(@NonNull HeadsUpEntry headsUpEntry) { public int compareNonTimeFields(HeadsUpEntry headsUpEntry) { boolean isPinned = mEntry.isRowPinned(); boolean otherPinned = headsUpEntry.mEntry.isRowPinned(); if (isPinned && !otherPinned) { Loading Loading @@ -806,7 +806,14 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { } else if (!mRemoteInputActive && headsUpEntry.mRemoteInputActive) { return 1; } return 0; } public int compareTo(@NonNull HeadsUpEntry headsUpEntry) { int nonTimeCompareResult = compareNonTimeFields(headsUpEntry); if (nonTimeCompareResult != 0) { return nonTimeCompareResult; } if (mPostTime > headsUpEntry.mPostTime) { return -1; } else if (mPostTime == headsUpEntry.mPostTime) { Loading Loading @@ -929,10 +936,8 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { int requestedTimeOutMs; if (isStickyForSomeTime()) { requestedTimeOutMs = mStickyForSomeTimeAutoDismissTime; } else if (mAvalancheController.shortenDuration(this)) { requestedTimeOutMs = 1000; } else { requestedTimeOutMs = mAutoDismissTime; requestedTimeOutMs = mAvalancheController.getDurationMs(this, mAutoDismissTime); } final long duration = getRecommendedHeadsUpTimeoutMs(requestedTimeOutMs); return mPostTime + duration; Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/AvalancheControllerTest.kt +71 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.log.logcatLogBuffer import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun import com.android.systemui.statusbar.policy.HeadsUpManagerTestUtil.createFullScreenIntentEntry import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.settings.FakeGlobalSettings import com.android.systemui.util.time.FakeSystemClock Loading Loading @@ -97,6 +98,12 @@ class AvalancheControllerTest : SysuiTestCase() { return entry } private fun createFsiHeadsUpEntry(id: Int): BaseHeadsUpManager.HeadsUpEntry { val entry = testableHeadsUpManager!!.createHeadsUpEntry() entry.setEntry(createFullScreenIntentEntry(id, mContext)) return entry } @Test fun testUpdate_isShowing_runsRunnable() { // Entry is showing Loading Loading @@ -238,4 +245,68 @@ class AvalancheControllerTest : SysuiTestCase() { // Next entry is shown Truth.assertThat(mAvalancheController.headsUpEntryShowing).isEqualTo(nextEntry) } @Test fun testGetDurationMs_lastEntry_useAutoDismissTime() { // Entry is showing val showingEntry = createHeadsUpEntry(id = 0) mAvalancheController.headsUpEntryShowing = showingEntry // Nothing is next mAvalancheController.clearNext() val durationMs = mAvalancheController.getDurationMs(showingEntry, autoDismissMs = 5000) Truth.assertThat(durationMs).isEqualTo(5000) } @Test fun testGetDurationMs_nextEntryLowerPriority_500() { // Entry is showing val showingEntry = createFsiHeadsUpEntry(id = 1) mAvalancheController.headsUpEntryShowing = showingEntry // There's another entry waiting to show next val nextEntry = createHeadsUpEntry(id = 0) mAvalancheController.addToNext(nextEntry, runnableMock!!) // Next entry has lower priority Truth.assertThat(nextEntry.compareNonTimeFields(showingEntry)).isEqualTo(1) val durationMs = mAvalancheController.getDurationMs(showingEntry, autoDismissMs = 5000) Truth.assertThat(durationMs).isEqualTo(5000) } @Test fun testGetDurationMs_nextEntrySamePriority_1000() { // Entry is showing val showingEntry = createHeadsUpEntry(id = 0) mAvalancheController.headsUpEntryShowing = showingEntry // There's another entry waiting to show next val nextEntry = createHeadsUpEntry(id = 1) mAvalancheController.addToNext(nextEntry, runnableMock!!) // Same priority Truth.assertThat(nextEntry.compareNonTimeFields(showingEntry)).isEqualTo(0) val durationMs = mAvalancheController.getDurationMs(showingEntry, autoDismissMs = 5000) Truth.assertThat(durationMs).isEqualTo(1000) } @Test fun testGetDurationMs_nextEntryHigherPriority_500() { // Entry is showing val showingEntry = createHeadsUpEntry(id = 0) mAvalancheController.headsUpEntryShowing = showingEntry // There's another entry waiting to show next val nextEntry = createFsiHeadsUpEntry(id = 1) mAvalancheController.addToNext(nextEntry, runnableMock!!) // Next entry has higher priority Truth.assertThat(nextEntry.compareNonTimeFields(showingEntry)).isEqualTo(-1) val durationMs = mAvalancheController.getDurationMs(showingEntry, autoDismissMs = 5000) Truth.assertThat(durationMs).isEqualTo(500) } }
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java +8 −19 Original line number Diff line number Diff line Loading @@ -117,21 +117,6 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { return HeadsUpManagerTestUtil.createEntry(id, notif); } private PendingIntent createFullScreenIntent() { return PendingIntent.getActivity( getContext(), 0, new Intent(getContext(), this.getClass()), PendingIntent.FLAG_MUTABLE_UNAUDITED); } private NotificationEntry createFullScreenIntentEntry(int id) { final Notification notif = new Notification.Builder(mContext, "") .setSmallIcon(R.drawable.ic_person) .setFullScreenIntent(createFullScreenIntent(), /* highPriority */ true) .build(); return HeadsUpManagerTestUtil.createEntry(id, notif); } private void useAccessibilityTimeout(boolean use) { if (use) { doReturn(TEST_A11Y_AUTO_DISMISS_TIME).when(mAccessibilityMgr) Loading Loading @@ -239,7 +224,8 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { @Test public void testShouldHeadsUpBecomePinned_hasFSI_notUnpinned_true() { final BaseHeadsUpManager hum = createHeadsUpManager(); final NotificationEntry notifEntry = createFullScreenIntentEntry(/* id = */ 0); final NotificationEntry notifEntry = HeadsUpManagerTestUtil.createFullScreenIntentEntry(/* id = */ 0, mContext); // Add notifEntry to ANM mAlertEntries map and make it NOT unpinned hum.showNotification(notifEntry); Loading @@ -254,7 +240,8 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { @Test public void testShouldHeadsUpBecomePinned_wasUnpinned_false() { final BaseHeadsUpManager hum = createHeadsUpManager(); final NotificationEntry notifEntry = createFullScreenIntentEntry(/* id = */ 0); final NotificationEntry notifEntry = HeadsUpManagerTestUtil.createFullScreenIntentEntry(/* id = */ 0, mContext); // Add notifEntry to ANM mAlertEntries map and make it unpinned hum.showNotification(notifEntry); Loading Loading @@ -443,7 +430,8 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { @Test public void testIsSticky_hasFullScreenIntent_true() { final BaseHeadsUpManager hum = createHeadsUpManager(); final NotificationEntry notifEntry = createFullScreenIntentEntry(/* id = */ 0); final NotificationEntry notifEntry = HeadsUpManagerTestUtil.createFullScreenIntentEntry(/* id = */ 0, mContext); hum.showNotification(notifEntry); Loading Loading @@ -554,7 +542,8 @@ public class BaseHeadsUpManagerTest extends SysuiTestCase { // Needs full screen intent in order to be pinned final BaseHeadsUpManager.HeadsUpEntry entryToPin = hum.new HeadsUpEntry(); entryToPin.setEntry(createFullScreenIntentEntry(/* id = */ 0)); entryToPin.setEntry( HeadsUpManagerTestUtil.createFullScreenIntentEntry(/* id = */ 0, mContext)); // Note: the standard way to show a notification would be calling showNotification rather // than onAlertEntryAdded. However, in practice showNotification in effect adds Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTestUtil.java +14 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.policy; import android.app.ActivityManager; import android.app.PendingIntent; import android.content.Intent; import android.os.UserHandle; import android.content.Context; Loading Loading @@ -67,4 +69,16 @@ public class HeadsUpManagerTestUtil { return new NotificationEntryBuilder().setSbn( HeadsUpManagerTestUtil.createSbn(id, context)).build(); } protected static NotificationEntry createFullScreenIntentEntry(int id, Context context) { final PendingIntent intent = PendingIntent.getActivity( context, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE); final Notification notif = new Notification.Builder(context, "") .setSmallIcon(com.android.systemui.res.R.drawable.ic_person) .setFullScreenIntent(intent, /* highPriority */ true) .build(); return HeadsUpManagerTestUtil.createEntry(id, notif); } }
packages/SystemUI/src/com/android/systemui/statusbar/policy/AvalancheController.kt +25 −9 Original line number Diff line number Diff line Loading @@ -131,21 +131,37 @@ class AvalancheController @Inject constructor() { } /** * Returns true if given HeadsUpEntry is the last one tracked by AvalancheController. Used by * BaseHeadsUpManager.HeadsUpEntry.calculateFinishTime to shorten display duration during active * avalanche. * Returns duration based on * 1) Whether HeadsUpEntry is the last one tracked byAvalancheController * 2) The priority of the top HUN in the next batch Used by * BaseHeadsUpManager.HeadsUpEntry.calculateFinishTime to shorten display duration. */ fun shortenDuration(entry: HeadsUpEntry): Boolean { fun getDurationMs(entry: HeadsUpEntry, autoDismissMs: Int): Int { if (!NotificationThrottleHun.isEnabled) { // Use default display duration, like we always did before AvalancheController existed return false // Use default duration, like we did before AvalancheController existed return autoDismissMs } val showingList: MutableList<HeadsUpEntry> = mutableListOf() headsUpEntryShowing?.let { showingList.add(it) } val allEntryList = showingList + nextList // Shorten duration if not last entry return allEntryList.indexOf(entry) != allEntryList.size - 1 val entryList = showingList + nextList if (entryList.indexOf(entry) == entryList.size - 1) { // Use default duration if last entry return autoDismissMs } nextList.sort() val nextEntry = nextList[0] if (nextEntry.compareNonTimeFields(entry) == -1) { // Next entry is higher priority return 500 } else if (nextEntry.compareNonTimeFields(entry) == 0) { // Next entry is same priority return 1000 } else { return autoDismissMs } } /** Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java +9 −4 Original line number Diff line number Diff line Loading @@ -776,7 +776,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { return mEarliestRemovalTime < mSystemClock.elapsedRealtime(); } public int compareTo(@NonNull HeadsUpEntry headsUpEntry) { public int compareNonTimeFields(HeadsUpEntry headsUpEntry) { boolean isPinned = mEntry.isRowPinned(); boolean otherPinned = headsUpEntry.mEntry.isRowPinned(); if (isPinned && !otherPinned) { Loading Loading @@ -806,7 +806,14 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { } else if (!mRemoteInputActive && headsUpEntry.mRemoteInputActive) { return 1; } return 0; } public int compareTo(@NonNull HeadsUpEntry headsUpEntry) { int nonTimeCompareResult = compareNonTimeFields(headsUpEntry); if (nonTimeCompareResult != 0) { return nonTimeCompareResult; } if (mPostTime > headsUpEntry.mPostTime) { return -1; } else if (mPostTime == headsUpEntry.mPostTime) { Loading Loading @@ -929,10 +936,8 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { int requestedTimeOutMs; if (isStickyForSomeTime()) { requestedTimeOutMs = mStickyForSomeTimeAutoDismissTime; } else if (mAvalancheController.shortenDuration(this)) { requestedTimeOutMs = 1000; } else { requestedTimeOutMs = mAutoDismissTime; requestedTimeOutMs = mAvalancheController.getDurationMs(this, mAutoDismissTime); } final long duration = getRecommendedHeadsUpTimeoutMs(requestedTimeOutMs); return mPostTime + duration; Loading