Merge "Hide time on Tile for alarms further than a week" into main
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 00405d0..c2ce392 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.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 @@
 
     @Test
     fun nextAlarmSet24HourFormat() {
-        val triggerTime = 1L
+        val triggerTime = fakeClock.currentTimeMillis() + oneMinute
         val inputModel =
             AlarmTileModel.NextAlarmSet(true, AlarmManager.AlarmClockInfo(triggerTime, null))
 
@@ -85,7 +95,7 @@
 
     @Test
     fun nextAlarmSet12HourFormat() {
-        val triggerTime = 1L
+        val triggerTime = fakeClock.currentTimeMillis() + oneMinute
         val inputModel =
             AlarmTileModel.NextAlarmSet(false, AlarmManager.AlarmClockInfo(triggerTime, null))
 
@@ -102,6 +112,66 @@
         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 e075e76..2b8c335 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.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 @@
 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 @@
                 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