Loading packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt +73 −3 Original line number Original line Diff line number Diff line Loading @@ -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.impl.custom.QSTileStateSubject import com.android.systemui.qs.tiles.viewmodel.QSTileState import com.android.systemui.qs.tiles.viewmodel.QSTileState import com.android.systemui.res.R import com.android.systemui.res.R import com.android.systemui.util.time.FakeSystemClock import java.time.Instant import java.time.Instant import java.time.LocalDateTime import java.time.LocalDateTime import java.util.TimeZone import java.util.TimeZone import org.junit.Before import org.junit.Test import org.junit.Test import org.junit.runner.RunWith import org.junit.runner.RunWith @SmallTest @SmallTest @RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class) class AlarmTileMapperTest : SysuiTestCase() { class AlarmTileMapperTest : SysuiTestCase() { private val oneMinute = 60000L private val kosmos = Kosmos() private val kosmos = Kosmos() private val alarmTileConfig = kosmos.qsAlarmTileConfig private val alarmTileConfig = kosmos.qsAlarmTileConfig private val fakeClock = FakeSystemClock() // Using lazy (versus =) to make sure we override the right context -- see b/311612168 // Using lazy (versus =) to make sure we override the right context -- see b/311612168 private val mapper by lazy { private val mapper by lazy { AlarmTileMapper( AlarmTileMapper( context.orCreateTestableResources context.orCreateTestableResources .apply { addOverride(R.drawable.ic_alarm, TestStubDrawable()) } .apply { addOverride(R.drawable.ic_alarm, TestStubDrawable()) } .resources, .resources, context.theme context.theme, fakeClock ) ) } } @Before fun setup() { fakeClock.setCurrentTimeMillis(0) // same time both in test & map() } @Test @Test fun notAlarmSet() { fun notAlarmSet() { val inputModel = AlarmTileModel.NoAlarmSet val inputModel = AlarmTileModel.NoAlarmSet Loading @@ -66,7 +76,7 @@ class AlarmTileMapperTest : SysuiTestCase() { @Test @Test fun nextAlarmSet24HourFormat() { fun nextAlarmSet24HourFormat() { val triggerTime = 1L val triggerTime = fakeClock.currentTimeMillis() + oneMinute val inputModel = val inputModel = AlarmTileModel.NextAlarmSet(true, AlarmManager.AlarmClockInfo(triggerTime, null)) AlarmTileModel.NextAlarmSet(true, AlarmManager.AlarmClockInfo(triggerTime, null)) Loading @@ -85,7 +95,7 @@ class AlarmTileMapperTest : SysuiTestCase() { @Test @Test fun nextAlarmSet12HourFormat() { fun nextAlarmSet12HourFormat() { val triggerTime = 1L val triggerTime = fakeClock.currentTimeMillis() + oneMinute val inputModel = val inputModel = AlarmTileModel.NextAlarmSet(false, AlarmManager.AlarmClockInfo(triggerTime, null)) AlarmTileModel.NextAlarmSet(false, AlarmManager.AlarmClockInfo(triggerTime, null)) Loading @@ -102,6 +112,66 @@ class AlarmTileMapperTest : SysuiTestCase() { QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState) 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( private fun createAlarmTileState( activationState: QSTileState.ActivationState, activationState: QSTileState.ActivationState, secondaryLabel: String secondaryLabel: String Loading packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt +25 −4 Original line number Original line Diff line number Diff line Loading @@ -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.QSTileConfig import com.android.systemui.qs.tiles.viewmodel.QSTileState import com.android.systemui.qs.tiles.viewmodel.QSTileState import com.android.systemui.res.R import com.android.systemui.res.R import com.android.systemui.util.time.SystemClock import java.time.Instant import java.time.Instant import java.time.LocalDateTime import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter Loading @@ -36,10 +37,12 @@ class AlarmTileMapper constructor( constructor( @Main private val resources: Resources, @Main private val resources: Resources, private val theme: Theme, private val theme: Theme, private val clock: SystemClock, ) : QSTileDataToStateMapper<AlarmTileModel> { ) : QSTileDataToStateMapper<AlarmTileModel> { companion object { companion object { val formatter12Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E hh:mm a") val formatter12Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E hh:mm a") val formatter24Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E HH:mm") val formatter24Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E HH:mm") val formatterDateOnly: DateTimeFormatter = DateTimeFormatter.ofPattern("E MMM d") } } override fun map(config: QSTileConfig, data: AlarmTileModel): QSTileState = override fun map(config: QSTileConfig, data: AlarmTileModel): QSTileState = QSTileState.build(resources, theme, config.uiConfig) { QSTileState.build(resources, theme, config.uiConfig) { Loading @@ -47,14 +50,32 @@ constructor( is AlarmTileModel.NextAlarmSet -> { is AlarmTileModel.NextAlarmSet -> { activationState = QSTileState.ActivationState.ACTIVE activationState = QSTileState.ActivationState.ACTIVE val localDateTime = val alarmDateTime = LocalDateTime.ofInstant( LocalDateTime.ofInstant( Instant.ofEpochMilli(data.alarmClockInfo.triggerTime), Instant.ofEpochMilli(data.alarmClockInfo.triggerTime), TimeZone.getDefault().toZoneId() TimeZone.getDefault().toZoneId() ) ) 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 = secondaryLabel = if (data.is24HourFormat) formatter24Hour.format(localDateTime) if (data.is24HourFormat) formatter24Hour.format(alarmDateTime) else formatter12Hour.format(localDateTime) else formatter12Hour.format(alarmDateTime) } } } is AlarmTileModel.NoAlarmSet -> { is AlarmTileModel.NoAlarmSet -> { activationState = QSTileState.ActivationState.INACTIVE activationState = QSTileState.ActivationState.INACTIVE Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt +73 −3 Original line number Original line Diff line number Diff line Loading @@ -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.impl.custom.QSTileStateSubject import com.android.systemui.qs.tiles.viewmodel.QSTileState import com.android.systemui.qs.tiles.viewmodel.QSTileState import com.android.systemui.res.R import com.android.systemui.res.R import com.android.systemui.util.time.FakeSystemClock import java.time.Instant import java.time.Instant import java.time.LocalDateTime import java.time.LocalDateTime import java.util.TimeZone import java.util.TimeZone import org.junit.Before import org.junit.Test import org.junit.Test import org.junit.runner.RunWith import org.junit.runner.RunWith @SmallTest @SmallTest @RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class) class AlarmTileMapperTest : SysuiTestCase() { class AlarmTileMapperTest : SysuiTestCase() { private val oneMinute = 60000L private val kosmos = Kosmos() private val kosmos = Kosmos() private val alarmTileConfig = kosmos.qsAlarmTileConfig private val alarmTileConfig = kosmos.qsAlarmTileConfig private val fakeClock = FakeSystemClock() // Using lazy (versus =) to make sure we override the right context -- see b/311612168 // Using lazy (versus =) to make sure we override the right context -- see b/311612168 private val mapper by lazy { private val mapper by lazy { AlarmTileMapper( AlarmTileMapper( context.orCreateTestableResources context.orCreateTestableResources .apply { addOverride(R.drawable.ic_alarm, TestStubDrawable()) } .apply { addOverride(R.drawable.ic_alarm, TestStubDrawable()) } .resources, .resources, context.theme context.theme, fakeClock ) ) } } @Before fun setup() { fakeClock.setCurrentTimeMillis(0) // same time both in test & map() } @Test @Test fun notAlarmSet() { fun notAlarmSet() { val inputModel = AlarmTileModel.NoAlarmSet val inputModel = AlarmTileModel.NoAlarmSet Loading @@ -66,7 +76,7 @@ class AlarmTileMapperTest : SysuiTestCase() { @Test @Test fun nextAlarmSet24HourFormat() { fun nextAlarmSet24HourFormat() { val triggerTime = 1L val triggerTime = fakeClock.currentTimeMillis() + oneMinute val inputModel = val inputModel = AlarmTileModel.NextAlarmSet(true, AlarmManager.AlarmClockInfo(triggerTime, null)) AlarmTileModel.NextAlarmSet(true, AlarmManager.AlarmClockInfo(triggerTime, null)) Loading @@ -85,7 +95,7 @@ class AlarmTileMapperTest : SysuiTestCase() { @Test @Test fun nextAlarmSet12HourFormat() { fun nextAlarmSet12HourFormat() { val triggerTime = 1L val triggerTime = fakeClock.currentTimeMillis() + oneMinute val inputModel = val inputModel = AlarmTileModel.NextAlarmSet(false, AlarmManager.AlarmClockInfo(triggerTime, null)) AlarmTileModel.NextAlarmSet(false, AlarmManager.AlarmClockInfo(triggerTime, null)) Loading @@ -102,6 +112,66 @@ class AlarmTileMapperTest : SysuiTestCase() { QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState) 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( private fun createAlarmTileState( activationState: QSTileState.ActivationState, activationState: QSTileState.ActivationState, secondaryLabel: String secondaryLabel: String Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt +25 −4 Original line number Original line Diff line number Diff line Loading @@ -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.QSTileConfig import com.android.systemui.qs.tiles.viewmodel.QSTileState import com.android.systemui.qs.tiles.viewmodel.QSTileState import com.android.systemui.res.R import com.android.systemui.res.R import com.android.systemui.util.time.SystemClock import java.time.Instant import java.time.Instant import java.time.LocalDateTime import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter Loading @@ -36,10 +37,12 @@ class AlarmTileMapper constructor( constructor( @Main private val resources: Resources, @Main private val resources: Resources, private val theme: Theme, private val theme: Theme, private val clock: SystemClock, ) : QSTileDataToStateMapper<AlarmTileModel> { ) : QSTileDataToStateMapper<AlarmTileModel> { companion object { companion object { val formatter12Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E hh:mm a") val formatter12Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E hh:mm a") val formatter24Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E HH:mm") val formatter24Hour: DateTimeFormatter = DateTimeFormatter.ofPattern("E HH:mm") val formatterDateOnly: DateTimeFormatter = DateTimeFormatter.ofPattern("E MMM d") } } override fun map(config: QSTileConfig, data: AlarmTileModel): QSTileState = override fun map(config: QSTileConfig, data: AlarmTileModel): QSTileState = QSTileState.build(resources, theme, config.uiConfig) { QSTileState.build(resources, theme, config.uiConfig) { Loading @@ -47,14 +50,32 @@ constructor( is AlarmTileModel.NextAlarmSet -> { is AlarmTileModel.NextAlarmSet -> { activationState = QSTileState.ActivationState.ACTIVE activationState = QSTileState.ActivationState.ACTIVE val localDateTime = val alarmDateTime = LocalDateTime.ofInstant( LocalDateTime.ofInstant( Instant.ofEpochMilli(data.alarmClockInfo.triggerTime), Instant.ofEpochMilli(data.alarmClockInfo.triggerTime), TimeZone.getDefault().toZoneId() TimeZone.getDefault().toZoneId() ) ) 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 = secondaryLabel = if (data.is24HourFormat) formatter24Hour.format(localDateTime) if (data.is24HourFormat) formatter24Hour.format(alarmDateTime) else formatter12Hour.format(localDateTime) else formatter12Hour.format(alarmDateTime) } } } is AlarmTileModel.NoAlarmSet -> { is AlarmTileModel.NoAlarmSet -> { activationState = QSTileState.ActivationState.INACTIVE activationState = QSTileState.ActivationState.INACTIVE Loading