diff options
2 files changed, 98 insertions, 7 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt index 00405d0a07e7..c2ce39249f9e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt @@ -29,27 +29,37 @@ import com.android.systemui.qs.tiles.impl.alarm.qsAlarmTileConfig import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject import com.android.systemui.qs.tiles.viewmodel.QSTileState import com.android.systemui.res.R +import com.android.systemui.util.time.FakeSystemClock import java.time.Instant import java.time.LocalDateTime import java.util.TimeZone +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class AlarmTileMapperTest : SysuiTestCase() { + private val oneMinute = 60000L private val kosmos = Kosmos() private val alarmTileConfig = kosmos.qsAlarmTileConfig + private val fakeClock = FakeSystemClock() // Using lazy (versus =) to make sure we override the right context -- see b/311612168 private val mapper by lazy { AlarmTileMapper( context.orCreateTestableResources .apply { addOverride(R.drawable.ic_alarm, TestStubDrawable()) } .resources, - context.theme + context.theme, + fakeClock ) } + @Before + fun setup() { + fakeClock.setCurrentTimeMillis(0) // same time both in test & map() + } + @Test fun notAlarmSet() { val inputModel = AlarmTileModel.NoAlarmSet @@ -66,7 +76,7 @@ class AlarmTileMapperTest : SysuiTestCase() { @Test fun nextAlarmSet24HourFormat() { - val triggerTime = 1L + val triggerTime = fakeClock.currentTimeMillis() + oneMinute val inputModel = AlarmTileModel.NextAlarmSet(true, AlarmManager.AlarmClockInfo(triggerTime, null)) @@ -85,7 +95,7 @@ class AlarmTileMapperTest : SysuiTestCase() { @Test fun nextAlarmSet12HourFormat() { - val triggerTime = 1L + val triggerTime = fakeClock.currentTimeMillis() + oneMinute val inputModel = AlarmTileModel.NextAlarmSet(false, AlarmManager.AlarmClockInfo(triggerTime, null)) @@ -102,6 +112,66 @@ class AlarmTileMapperTest : SysuiTestCase() { QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState) } + @Test + fun nextAlarmSetMoreThanAWeekLater_mapsSecondaryLabelToDisplayDateOnly() { + val oneWeekAndOneMinute = 7 * 24 * 60 * 60 * 1000L + oneMinute + val triggerTime = fakeClock.currentTimeMillis() + oneWeekAndOneMinute + val inputModel = + AlarmTileModel.NextAlarmSet(false, AlarmManager.AlarmClockInfo(triggerTime, null)) + + val outputState = mapper.map(alarmTileConfig, inputModel) + + val localDateTime = + LocalDateTime.ofInstant( + Instant.ofEpochMilli(triggerTime), + TimeZone.getDefault().toZoneId() + ) + val expectedSecondaryLabel = AlarmTileMapper.formatterDateOnly.format(localDateTime) + val expectedState = + createAlarmTileState(QSTileState.ActivationState.ACTIVE, expectedSecondaryLabel) + QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState) + } + + @Test + fun nextAlarmSetOneMinuteLessThanAWeekLater_mapsSecondaryLabelToDisplayTime() { + val oneWeekMinusOneMinute = 7 * 24 * 60 * 60 * 1000L - oneMinute + val triggerTime = fakeClock.currentTimeMillis() + oneWeekMinusOneMinute + val inputModel = + AlarmTileModel.NextAlarmSet(false, AlarmManager.AlarmClockInfo(triggerTime, null)) + + val outputState = mapper.map(alarmTileConfig, inputModel) + + val localDateTime = + LocalDateTime.ofInstant( + Instant.ofEpochMilli(triggerTime), + TimeZone.getDefault().toZoneId() + ) + val expectedSecondaryLabel = AlarmTileMapper.formatter12Hour.format(localDateTime) + val expectedState = + createAlarmTileState(QSTileState.ActivationState.ACTIVE, expectedSecondaryLabel) + QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState) + } + + @Test + fun nextAlarmSetExactlyAWeekLater_mapsSecondaryLabelToDisplayDateOnly() { + val oneWeek = 7 * 24 * 60 * 60 * 1000L + val triggerTime = fakeClock.currentTimeMillis() + oneWeek + val inputModel = + AlarmTileModel.NextAlarmSet(false, AlarmManager.AlarmClockInfo(triggerTime, null)) + + val outputState = mapper.map(alarmTileConfig, inputModel) + + val localDateTime = + LocalDateTime.ofInstant( + Instant.ofEpochMilli(triggerTime), + TimeZone.getDefault().toZoneId() + ) + val expectedSecondaryLabel = AlarmTileMapper.formatterDateOnly.format(localDateTime) + val expectedState = + createAlarmTileState(QSTileState.ActivationState.ACTIVE, expectedSecondaryLabel) + QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState) + } + private fun createAlarmTileState( activationState: QSTileState.ActivationState, secondaryLabel: String diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt index e075e76595d4..2b8c335cb0ad 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt @@ -24,6 +24,7 @@ import com.android.systemui.qs.tiles.impl.alarm.domain.model.AlarmTileModel import com.android.systemui.qs.tiles.viewmodel.QSTileConfig import com.android.systemui.qs.tiles.viewmodel.QSTileState import com.android.systemui.res.R +import com.android.systemui.util.time.SystemClock import java.time.Instant import java.time.LocalDateTime import java.time.format.DateTimeFormatter @@ -36,10 +37,12 @@ class AlarmTileMapper constructor( @Main private val resources: Resources, private val theme: Theme, + private val clock: SystemClock, ) : QSTileDataToStateMapper<AlarmTileModel> { companion object { val formatter12Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E hh:mm a") val formatter24Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E HH:mm") + val formatterDateOnly: DateTimeFormatter = DateTimeFormatter.ofPattern("E MMM d") } override fun map(config: QSTileConfig, data: AlarmTileModel): QSTileState = QSTileState.build(resources, theme, config.uiConfig) { @@ -47,14 +50,32 @@ constructor( is AlarmTileModel.NextAlarmSet -> { activationState = QSTileState.ActivationState.ACTIVE - val localDateTime = + val alarmDateTime = LocalDateTime.ofInstant( Instant.ofEpochMilli(data.alarmClockInfo.triggerTime), TimeZone.getDefault().toZoneId() ) - secondaryLabel = - if (data.is24HourFormat) formatter24Hour.format(localDateTime) - else formatter12Hour.format(localDateTime) + + val nowDateTime = + LocalDateTime.ofInstant( + Instant.ofEpochMilli(clock.currentTimeMillis()), + TimeZone.getDefault().toZoneId() + ) + + // Edge case: If it's 8:00:30 right now and alarm is requested for next week at + // 8:00:29, we still want to show the date. Same at nanosecond level. + val nextWeekThisTime = nowDateTime.plusWeeks(1).withSecond(0).withNano(0) + + // is the alarm over a week away? + val shouldShowDateAndHideTime = alarmDateTime >= nextWeekThisTime + + if (shouldShowDateAndHideTime) { + secondaryLabel = formatterDateOnly.format(alarmDateTime) + } else { + secondaryLabel = + if (data.is24HourFormat) formatter24Hour.format(alarmDateTime) + else formatter12Hour.format(alarmDateTime) + } } is AlarmTileModel.NoAlarmSet -> { activationState = QSTileState.ActivationState.INACTIVE |