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

Commit e635e5d1 authored by Behnam Heydarshahi's avatar Behnam Heydarshahi
Browse files

Migrate ColorInversionTile

Fixes: 301055918
Flag: LEGACY QS_PIPELINE_NEW_TILES DISABLED
Test: atest SystemUiRoboTests
Test: atest ColorInversionTileDataInteractor ColorInversionTileUserActionInteractor ColorInversionTileMapper ColorInversionRepositoryImpl
Change-Id: I385dc619542def1eaa6f56fc70472b8c00cab496
parent 992170bd
Loading
Loading
Loading
Loading
+140 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.accessibility.data.repository

import android.os.UserHandle
import android.provider.Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class ColorInversionRepositoryImplTest : SysuiTestCase() {

    private val testDispatcher = StandardTestDispatcher()
    private val scope = TestScope(testDispatcher)
    private val settings: FakeSettings = FakeSettings()

    private lateinit var underTest: ColorInversionRepository

    @Before
    fun setUp() {
        underTest =
            ColorInversionRepositoryImpl(
                testDispatcher,
                settings,
            )
    }

    @Test
    fun isEnabled_initiallyGetsSettingsValue() =
        scope.runTest {
            settings.putIntForUser(SETTING_NAME, 1, TEST_USER_1.identifier)

            underTest =
                ColorInversionRepositoryImpl(
                    testDispatcher,
                    settings,
                )

            underTest.isEnabled(TEST_USER_1).launchIn(backgroundScope)
            runCurrent()

            val actualValue: Boolean = underTest.isEnabled(TEST_USER_1).first()
            assertThat(actualValue).isTrue()
        }

    @Test
    fun isEnabled_settingUpdated_valueUpdated() =
        scope.runTest {
            underTest.isEnabled(TEST_USER_1).launchIn(backgroundScope)

            settings.putIntForUser(SETTING_NAME, DISABLED, TEST_USER_1.identifier)
            runCurrent()
            assertThat(underTest.isEnabled(TEST_USER_1).first()).isFalse()

            settings.putIntForUser(SETTING_NAME, ENABLED, TEST_USER_1.identifier)
            runCurrent()
            assertThat(underTest.isEnabled(TEST_USER_1).first()).isTrue()

            settings.putIntForUser(SETTING_NAME, DISABLED, TEST_USER_1.identifier)
            runCurrent()
            assertThat(underTest.isEnabled(TEST_USER_1).first()).isFalse()
        }

    @Test
    fun isEnabled_settingForUserOneOnly_valueUpdatedForUserOneOnly() =
        scope.runTest {
            underTest.isEnabled(TEST_USER_1).launchIn(backgroundScope)
            settings.putIntForUser(SETTING_NAME, DISABLED, TEST_USER_1.identifier)
            underTest.isEnabled(TEST_USER_2).launchIn(backgroundScope)
            settings.putIntForUser(SETTING_NAME, DISABLED, TEST_USER_2.identifier)

            runCurrent()
            assertThat(underTest.isEnabled(TEST_USER_1).first()).isFalse()
            assertThat(underTest.isEnabled(TEST_USER_2).first()).isFalse()

            settings.putIntForUser(SETTING_NAME, ENABLED, TEST_USER_1.identifier)
            runCurrent()
            assertThat(underTest.isEnabled(TEST_USER_1).first()).isTrue()
            assertThat(underTest.isEnabled(TEST_USER_2).first()).isFalse()
        }

    @Test
    fun setEnabled() =
        scope.runTest {
            val success = underTest.setIsEnabled(true, TEST_USER_1)
            runCurrent()
            assertThat(success).isTrue()

            val actualValue = settings.getIntForUser(SETTING_NAME, TEST_USER_1.identifier)
            assertThat(actualValue).isEqualTo(ENABLED)
        }

    @Test
    fun setDisabled() =
        scope.runTest {
            val success = underTest.setIsEnabled(false, TEST_USER_1)
            runCurrent()
            assertThat(success).isTrue()

            val actualValue = settings.getIntForUser(SETTING_NAME, TEST_USER_1.identifier)
            assertThat(actualValue).isEqualTo(DISABLED)
        }

    companion object {
        private const val SETTING_NAME = ACCESSIBILITY_DISPLAY_INVERSION_ENABLED
        private const val DISABLED = 0
        private const val ENABLED = 1
        private val TEST_USER_1 = UserHandle.of(1)!!
        private val TEST_USER_2 = UserHandle.of(2)!!
    }
}
+105 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.qs.tiles.impl.inversion.domain

import android.graphics.drawable.TestStubDrawable
import android.widget.Switch
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.qs.tileimpl.SubtitleArrayMapping
import com.android.systemui.qs.tiles.impl.custom.QSTileStateSubject
import com.android.systemui.qs.tiles.impl.inversion.domain.model.ColorInversionTileModel
import com.android.systemui.qs.tiles.impl.inversion.qsColorInversionTileConfig
import com.android.systemui.qs.tiles.viewmodel.QSTileState
import com.android.systemui.res.R
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidJUnit4::class)
class ColorInversionTileMapperTest : SysuiTestCase() {
    private val kosmos = Kosmos()
    private val colorInversionTileConfig = kosmos.qsColorInversionTileConfig
    private val subtitleArrayId =
        SubtitleArrayMapping.getSubtitleId(colorInversionTileConfig.tileSpec.spec)
    private val subtitleArray = context.resources.getStringArray(subtitleArrayId)
    // Using lazy (versus =) to make sure we override the right context -- see b/311612168
    private val mapper by lazy {
        ColorInversionTileMapper(
            context.orCreateTestableResources
                .apply {
                    addOverride(R.drawable.qs_invert_colors_icon_off, TestStubDrawable())
                    addOverride(R.drawable.qs_invert_colors_icon_on, TestStubDrawable())
                }
                .resources,
            context.theme
        )
    }

    @Test
    fun disabledModel() {
        val inputModel = ColorInversionTileModel(false)

        val outputState = mapper.map(colorInversionTileConfig, inputModel)

        val expectedState =
            createColorInversionTileState(
                QSTileState.ActivationState.INACTIVE,
                subtitleArray[1],
                R.drawable.qs_invert_colors_icon_off
            )
        QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
    }

    @Test
    fun enabledModel() {
        val inputModel = ColorInversionTileModel(true)

        val outputState = mapper.map(colorInversionTileConfig, inputModel)

        val expectedState =
            createColorInversionTileState(
                QSTileState.ActivationState.ACTIVE,
                subtitleArray[2],
                R.drawable.qs_invert_colors_icon_on
            )
        QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
    }

    private fun createColorInversionTileState(
        activationState: QSTileState.ActivationState,
        secondaryLabel: String,
        iconRes: Int,
    ): QSTileState {
        val label = context.getString(R.string.quick_settings_inversion_label)
        return QSTileState(
            { Icon.Loaded(context.getDrawable(iconRes)!!, null) },
            label,
            activationState,
            secondaryLabel,
            setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK),
            label,
            null,
            QSTileState.SideViewIcon.None,
            QSTileState.EnabledState.ENABLED,
            Switch::class.qualifiedName
        )
    }
}
+72 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.qs.tiles.impl.inversion.domain.interactor

import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.accessibility.data.repository.FakeColorInversionRepository
import com.android.systemui.coroutines.collectValues
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.impl.inversion.domain.model.ColorInversionTileModel
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.toCollection
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class ColorInversionTileDataInteractorTest : SysuiTestCase() {

    private val colorInversionRepository = FakeColorInversionRepository()
    private val underTest: ColorInversionTileDataInteractor =
        ColorInversionTileDataInteractor(colorInversionRepository)

    @Test
    fun alwaysAvailable() = runTest {
        val availability = underTest.availability(TEST_USER).toCollection(mutableListOf())

        assertThat(availability).hasSize(1)
        assertThat(availability.last()).isTrue()
    }

    @Test
    fun dataMatchesTheRepository() = runTest {
        val dataList: List<ColorInversionTileModel> by
            collectValues(underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest)))
        runCurrent()

        colorInversionRepository.setIsEnabled(true, TEST_USER)
        runCurrent()

        colorInversionRepository.setIsEnabled(false, TEST_USER)
        runCurrent()

        assertThat(dataList).hasSize(3)
        assertThat(dataList.map { it.isEnabled }).isEqualTo(listOf(false, true, false))
    }

    private companion object {
        val TEST_USER = UserHandle.of(1)!!
    }
}
+89 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.qs.tiles.impl.inversion.domain.interactor

import android.os.UserHandle
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.accessibility.data.repository.FakeColorInversionRepository
import com.android.systemui.qs.tiles.base.actions.FakeQSTileIntentUserInputHandler
import com.android.systemui.qs.tiles.base.actions.QSTileIntentUserInputHandlerSubject
import com.android.systemui.qs.tiles.base.interactor.QSTileInputTestKtx
import com.android.systemui.qs.tiles.impl.inversion.domain.model.ColorInversionTileModel
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidJUnit4::class)
class ColorInversionUserActionInteractorTest : SysuiTestCase() {

    private val testUser = UserHandle.CURRENT
    private val repository = FakeColorInversionRepository()
    private val inputHandler = FakeQSTileIntentUserInputHandler()

    private val underTest =
        ColorInversionUserActionInteractor(
            repository,
            inputHandler,
        )

    @Test
    fun handleClickWhenEnabled() = runTest {
        val wasEnabled = true
        repository.setIsEnabled(wasEnabled, testUser)

        underTest.handleInput(QSTileInputTestKtx.click(ColorInversionTileModel(wasEnabled)))

        assertThat(repository.isEnabled(testUser).value).isEqualTo(!wasEnabled)
    }

    @Test
    fun handleClickWhenDisabled() = runTest {
        val wasEnabled = false
        repository.setIsEnabled(wasEnabled, testUser)

        underTest.handleInput(QSTileInputTestKtx.click(ColorInversionTileModel(wasEnabled)))

        assertThat(repository.isEnabled(testUser).value).isEqualTo(!wasEnabled)
    }

    @Test
    fun handleLongClickWhenDisabled() = runTest {
        val enabled = false

        underTest.handleInput(QSTileInputTestKtx.longClick(ColorInversionTileModel(enabled)))

        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
            assertThat(it.intent.action).isEqualTo(Settings.ACTION_COLOR_INVERSION_SETTINGS)
        }
    }

    @Test
    fun handleLongClickWhenEnabled() = runTest {
        val enabled = true

        underTest.handleInput(QSTileInputTestKtx.longClick(ColorInversionTileModel(enabled)))

        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
            assertThat(it.intent.action).isEqualTo(Settings.ACTION_COLOR_INVERSION_SETTINGS)
        }
    }
}
+6 −3
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.systemui.accessibility

import com.android.systemui.accessibility.data.repository.ColorCorrectionRepository
import com.android.systemui.accessibility.data.repository.ColorCorrectionRepositoryImpl
import com.android.systemui.accessibility.data.repository.ColorInversionRepository
import com.android.systemui.accessibility.data.repository.ColorInversionRepositoryImpl
import com.android.systemui.accessibility.qs.QSAccessibilityModule
import dagger.Binds
import dagger.Module
@@ -25,7 +27,8 @@ import dagger.Module
@Module(includes = [QSAccessibilityModule::class])
interface AccessibilityModule {
    @Binds
    abstract fun colorCorrectionRepository(
        impl: ColorCorrectionRepositoryImpl
    ): ColorCorrectionRepository
    fun colorCorrectionRepository(impl: ColorCorrectionRepositoryImpl): ColorCorrectionRepository

    @Binds
    fun colorInversionRepository(impl: ColorInversionRepositoryImpl): ColorInversionRepository
}
Loading