Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca7b0517 authored by Andre Le's avatar Andre Le Committed by Android (Google) Code Review
Browse files

Merge "ComposeClock: Set clock's content description" into main

parents d8acfd7e 11c0b809
Loading
Loading
Loading
Loading
+20 −14
Original line number Diff line number Diff line
@@ -57,34 +57,36 @@ class ClockViewModelTest : SysuiTestCase() {
    }

    @Test
    fun is24HourFormatTrue_clockText_equalsCurrentTime() =
    fun is24HourFormatTrue_clockTextAndDescription_equalsCurrentTime() =
        kosmos.runTest {
            fakeSystemClock.setCurrentTimeMillis(CURRENT_TIME_MILLIS)
            whenever(dateFormatUtil.is24HourFormat).thenReturn(true)
            underTest.activateIn(testScope)

            assertThat(underTest.clockText).isEqualTo("23:12")
            assertThat(underTest.contentDescriptionText).isEqualTo("23:12")
        }

    @Test
    fun is24HourFormatFalse_clockText_equalsCurrentTime() =
    fun is24HourFormatFalse_clockTextAndDescription_equalsCurrentTime() =
        kosmos.runTest {
            fakeSystemClock.setCurrentTimeMillis(CURRENT_TIME_MILLIS)
            whenever(dateFormatUtil.is24HourFormat).thenReturn(false)
            underTest.activateIn(testScope)

            assertThat(underTest.clockText).isEqualTo("11:12\u202FPM")
            assertThat(underTest.contentDescriptionText).isEqualTo("11:12\u202FPM")
        }

    @Test
    fun clockText_updatesWhenTimeTick() =
    fun clockTextAndDescription_updatesWhenTimeTick() =
        kosmos.runTest {
            fakeSystemClock.setCurrentTimeMillis(CURRENT_TIME_MILLIS)
            whenever(dateFormatUtil.is24HourFormat).thenReturn(true)
            underTest.activateIn(testScope)
            val earlierTime = underTest.clockText

            assertThat(earlierTime).isEqualTo("23:12")
            assertThat(underTest.clockText).isEqualTo("23:12")
            assertThat(underTest.contentDescriptionText).isEqualTo("23:12")

            fakeSystemClock.advanceTime(2.minutes.inWholeMilliseconds)
            broadcastDispatcher.sendIntentToMatchingReceiversOnly(
@@ -94,17 +96,18 @@ class ClockViewModelTest : SysuiTestCase() {
            runCurrent()

            assertThat(underTest.clockText).isEqualTo("23:14")
            assertThat(underTest.contentDescriptionText).isEqualTo("23:14")
        }

    @Test
    fun clockText_updatesWhenTimeChanged() =
    fun clockTextAndDescription_updatesWhenTimeChanged() =
        kosmos.runTest {
            fakeSystemClock.setCurrentTimeMillis(CURRENT_TIME_MILLIS)
            whenever(dateFormatUtil.is24HourFormat).thenReturn(true)
            underTest.activateIn(testScope)
            val earlierTime = underTest.clockText

            assertThat(earlierTime).isEqualTo("23:12")
            assertThat(underTest.clockText).isEqualTo("23:12")
            assertThat(underTest.contentDescriptionText).isEqualTo("23:12")

            fakeSystemClock.advanceTime(2.minutes.inWholeMilliseconds)
            broadcastDispatcher.sendIntentToMatchingReceiversOnly(
@@ -114,17 +117,18 @@ class ClockViewModelTest : SysuiTestCase() {
            runCurrent()

            assertThat(underTest.clockText).isEqualTo("23:14")
            assertThat(underTest.contentDescriptionText).isEqualTo("23:14")
        }

    @Test
    fun clockText_updatesWhenTimezoneChanged() =
    fun clockTextAndDescription_updatesWhenTimezoneChanged() =
        kosmos.runTest {
            fakeSystemClock.setCurrentTimeMillis(CURRENT_TIME_MILLIS)
            whenever(dateFormatUtil.is24HourFormat).thenReturn(true)
            underTest.activateIn(testScope)
            val earlierTime = underTest.clockText

            assertThat(earlierTime).isEqualTo("23:12")
            assertThat(underTest.clockText).isEqualTo("23:12")
            assertThat(underTest.contentDescriptionText).isEqualTo("23:12")

            TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("Asia/Tokyo")))
            broadcastDispatcher.sendIntentToMatchingReceiversOnly(
@@ -134,16 +138,17 @@ class ClockViewModelTest : SysuiTestCase() {
            runCurrent()

            assertThat(underTest.clockText).isEqualTo("08:12")
            assertThat(underTest.contentDescriptionText).isEqualTo("08:12")
        }

    @Test
    fun clockText_updatesWhenLocaleChanged() =
    fun clockTextAndDescription_updatesWhenLocaleChanged() =
        kosmos.runTest {
            fakeSystemClock.setCurrentTimeMillis(CURRENT_TIME_MILLIS)
            underTest.activateIn(testScope)
            val earlierTime = underTest.clockText

            assertThat(earlierTime).isEqualTo("11:12\u202FPM")
            assertThat(underTest.clockText).isEqualTo("11:12\u202FPM")
            assertThat(underTest.contentDescriptionText).isEqualTo("11:12\u202FPM")

            Locale.setDefault(Locale.TRADITIONAL_CHINESE)
            broadcastDispatcher.sendIntentToMatchingReceiversOnly(
@@ -153,6 +158,7 @@ class ClockViewModelTest : SysuiTestCase() {
            runCurrent()

            assertThat(underTest.clockText).isEqualTo("下午11:12")
            assertThat(underTest.contentDescriptionText).isEqualTo("下午11:12")
        }

    companion object {
+6 −1
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.systemui.clock.ui.composable
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import com.android.systemui.clock.ui.viewmodel.ClockViewModel
import com.android.systemui.lifecycle.rememberViewModel

@@ -26,5 +28,8 @@ import com.android.systemui.lifecycle.rememberViewModel
@Composable
fun Clock(viewModelFactory: ClockViewModel.Factory, modifier: Modifier = Modifier) {
    val clockViewModel = rememberViewModel("Clock-viewModel") { viewModelFactory.create() }
    Text(text = clockViewModel.clockText, modifier = modifier)
    Text(
        text = clockViewModel.clockText,
        modifier = modifier.semantics { contentDescription = clockViewModel.contentDescriptionText },
    )
}
+33 −5
Original line number Diff line number Diff line
@@ -46,12 +46,33 @@ constructor(clockInteractor: ClockInteractor, private val dateFormatUtil: DateFo
    private val formatString: Flow<String> =
        clockInteractor.onTimezoneOrLocaleChanged.mapLatest { getFormatString() }

    private val clockFormat: Flow<SimpleDateFormat> =
        formatString.mapLatest { format -> SimpleDateFormat(format) }
    private val contentDescriptionFormat: Flow<SimpleDateFormat> =
        formatString.mapLatest { format ->
            // We already provide the locale value in `DateTimePatternGenerator`, so it is okay to
            // not provide the locale in `SimpleDateFormat` here.
            @Suppress("SimpleDateFormat") SimpleDateFormat(format)
        }

    private val _contentDescriptionText: Flow<String> =
        combine(contentDescriptionFormat, clockInteractor.currentTime) {
            contentDescriptionFormat,
            time ->
            contentDescriptionFormat.format(time)
        }

    val contentDescriptionText: String by
        hydrator.hydratedStateOf(
            traceName = "clockContentDescriptionText",
            initialValue = clockInteractor.currentTime.value.toString(),
            source = _contentDescriptionText,
        )

    private val clockTextFormat: Flow<SimpleDateFormat> =
        formatString.mapLatest { format -> getClockTextFormat(format) }

    private val _clockText: Flow<String> =
        combine(clockFormat, clockInteractor.currentTime) { clockFormat, time ->
            clockFormat.format(time)
        combine(clockTextFormat, clockInteractor.currentTime) { clockTextFormat, time ->
            clockTextFormat.format(time)
        }

    val clockText: String by
@@ -80,7 +101,14 @@ constructor(clockInteractor: ClockInteractor, private val dateFormatUtil: DateFo
        // TODO(b/390204943): use different value depending on if the system want to show seconds.
        val formatSkeleton = if (dateFormatUtil.is24HourFormat) "Hm" else "hm"

        // TODO(b/390204943): handle ContentDescriptionFormat and AM/PM style
        return dateTimePatternGenerator.getBestPattern(formatSkeleton)
    }

    private fun getClockTextFormat(format: String): SimpleDateFormat {
        // TODO(b/390204943): handle AM/PM style
        // We already provide the locale value in `DateTimePatternGenerator` above, so it is okay
        // to not provide the locale in `SimpleDateFormat` here.
        @Suppress("SimpleDateFormat")
        return SimpleDateFormat(format)
    }
}