Loading packages/SystemUI/res/values/config.xml +11 −0 Original line number Diff line number Diff line Loading @@ -806,4 +806,15 @@ <!-- Whether the device should display hotspot UI. If true, UI will display only when tethering is available. If false, UI will never show regardless of tethering availability" --> <bool name="config_show_wifi_tethering">true</bool> <!-- A collection of "slots" for placing quick affordance actions on the lock screen when the device is locked. Each item is a string consisting of two parts, separated by the ':' character. The first part is the unique ID for the slot, it is not a human-visible name, but should still be unique across all slots specified. The second part is the capacity and must be a positive integer; this is how many quick affordance actions that user is allowed to add to the slot. --> <string-array name="config_keyguardQuickAffordanceSlots" translatable="false"> <item>bottom_start:1</item> <item>bottom_end:1</item> </string-array> </resources> packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt +32 −10 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.systemui.keyguard.data.repository import android.content.Context import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background Loading @@ -24,7 +26,6 @@ import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanc import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope Loading @@ -39,6 +40,7 @@ import kotlinx.coroutines.launch class KeyguardQuickAffordanceRepository @Inject constructor( @Application private val appContext: Context, @Application private val scope: CoroutineScope, @Background private val backgroundDispatcher: CoroutineDispatcher, private val selectionManager: KeyguardQuickAffordanceSelectionManager, Loading @@ -61,6 +63,30 @@ constructor( initialValue = emptyMap(), ) private val _slotPickerRepresentations: List<KeyguardSlotPickerRepresentation> by lazy { fun parseSlot(unparsedSlot: String): Pair<String, Int> { val split = unparsedSlot.split(SLOT_CONFIG_DELIMITER) check(split.size == 2) val slotId = split[0] val slotCapacity = split[1].toInt() return slotId to slotCapacity } val unparsedSlots = appContext.resources.getStringArray(R.array.config_keyguardQuickAffordanceSlots) val seenSlotIds = mutableSetOf<String>() unparsedSlots.mapNotNull { unparsedSlot -> val (slotId, slotCapacity) = parseSlot(unparsedSlot) check(!seenSlotIds.contains(slotId)) { "Duplicate slot \"$slotId\"!" } seenSlotIds.add(slotId) KeyguardSlotPickerRepresentation( id = slotId, maxSelectedAffordances = slotCapacity, ) } } /** * Returns a snapshot of the [KeyguardQuickAffordanceConfig] instances of the affordances at the * slot with the given ID. The configs are sorted in descending priority order. Loading Loading @@ -115,14 +141,10 @@ constructor( * each slot and select which affordance(s) is/are installed in each slot on the keyguard. */ fun getSlotPickerRepresentations(): List<KeyguardSlotPickerRepresentation> { // TODO(b/256195304): source these from a config XML file. return listOf( KeyguardSlotPickerRepresentation( id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, ), KeyguardSlotPickerRepresentation( id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, ), ) return _slotPickerRepresentations } companion object { private const val SLOT_CONFIG_DELIMITER = ":" } } packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt +22 −5 Original line number Diff line number Diff line Loading @@ -18,13 +18,13 @@ package com.android.systemui.keyguard.data.repository import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers Loading Loading @@ -53,6 +53,7 @@ class KeyguardQuickAffordanceRepositoryTest : SysuiTestCase() { config2 = FakeKeyguardQuickAffordanceConfig("built_in:2") underTest = KeyguardQuickAffordanceRepository( appContext = context, scope = CoroutineScope(IMMEDIATE), backgroundDispatcher = IMMEDIATE, selectionManager = KeyguardQuickAffordanceSelectionManager(), Loading Loading @@ -119,16 +120,32 @@ class KeyguardQuickAffordanceRepositoryTest : SysuiTestCase() { @Test fun getSlotPickerRepresentations() { val slot1 = "slot1" val slot2 = "slot2" val slot3 = "slot3" context.orCreateTestableResources.addOverride( R.array.config_keyguardQuickAffordanceSlots, arrayOf( "$slot1:2", "$slot2:4", "$slot3:5", ), ) assertThat(underTest.getSlotPickerRepresentations()) .isEqualTo( listOf( KeyguardSlotPickerRepresentation( id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, maxSelectedAffordances = 1, id = slot1, maxSelectedAffordances = 2, ), KeyguardSlotPickerRepresentation( id = slot2, maxSelectedAffordances = 4, ), KeyguardSlotPickerRepresentation( id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, maxSelectedAffordances = 1, id = slot3, maxSelectedAffordances = 5, ), ) ) Loading packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt +1 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() { FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER) val quickAffordanceRepository = KeyguardQuickAffordanceRepository( appContext = context, scope = CoroutineScope(IMMEDIATE), backgroundDispatcher = IMMEDIATE, selectionManager = KeyguardQuickAffordanceSelectionManager(), Loading packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { val quickAffordanceRepository = KeyguardQuickAffordanceRepository( appContext = context, scope = CoroutineScope(IMMEDIATE), backgroundDispatcher = IMMEDIATE, selectionManager = KeyguardQuickAffordanceSelectionManager(), Loading Loading
packages/SystemUI/res/values/config.xml +11 −0 Original line number Diff line number Diff line Loading @@ -806,4 +806,15 @@ <!-- Whether the device should display hotspot UI. If true, UI will display only when tethering is available. If false, UI will never show regardless of tethering availability" --> <bool name="config_show_wifi_tethering">true</bool> <!-- A collection of "slots" for placing quick affordance actions on the lock screen when the device is locked. Each item is a string consisting of two parts, separated by the ':' character. The first part is the unique ID for the slot, it is not a human-visible name, but should still be unique across all slots specified. The second part is the capacity and must be a positive integer; this is how many quick affordance actions that user is allowed to add to the slot. --> <string-array name="config_keyguardQuickAffordanceSlots" translatable="false"> <item>bottom_start:1</item> <item>bottom_end:1</item> </string-array> </resources>
packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepository.kt +32 −10 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.systemui.keyguard.data.repository import android.content.Context import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background Loading @@ -24,7 +26,6 @@ import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanc import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope Loading @@ -39,6 +40,7 @@ import kotlinx.coroutines.launch class KeyguardQuickAffordanceRepository @Inject constructor( @Application private val appContext: Context, @Application private val scope: CoroutineScope, @Background private val backgroundDispatcher: CoroutineDispatcher, private val selectionManager: KeyguardQuickAffordanceSelectionManager, Loading @@ -61,6 +63,30 @@ constructor( initialValue = emptyMap(), ) private val _slotPickerRepresentations: List<KeyguardSlotPickerRepresentation> by lazy { fun parseSlot(unparsedSlot: String): Pair<String, Int> { val split = unparsedSlot.split(SLOT_CONFIG_DELIMITER) check(split.size == 2) val slotId = split[0] val slotCapacity = split[1].toInt() return slotId to slotCapacity } val unparsedSlots = appContext.resources.getStringArray(R.array.config_keyguardQuickAffordanceSlots) val seenSlotIds = mutableSetOf<String>() unparsedSlots.mapNotNull { unparsedSlot -> val (slotId, slotCapacity) = parseSlot(unparsedSlot) check(!seenSlotIds.contains(slotId)) { "Duplicate slot \"$slotId\"!" } seenSlotIds.add(slotId) KeyguardSlotPickerRepresentation( id = slotId, maxSelectedAffordances = slotCapacity, ) } } /** * Returns a snapshot of the [KeyguardQuickAffordanceConfig] instances of the affordances at the * slot with the given ID. The configs are sorted in descending priority order. Loading Loading @@ -115,14 +141,10 @@ constructor( * each slot and select which affordance(s) is/are installed in each slot on the keyguard. */ fun getSlotPickerRepresentations(): List<KeyguardSlotPickerRepresentation> { // TODO(b/256195304): source these from a config XML file. return listOf( KeyguardSlotPickerRepresentation( id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, ), KeyguardSlotPickerRepresentation( id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, ), ) return _slotPickerRepresentations } companion object { private const val SLOT_CONFIG_DELIMITER = ":" } }
packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt +22 −5 Original line number Diff line number Diff line Loading @@ -18,13 +18,13 @@ package com.android.systemui.keyguard.data.repository import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerRepresentation import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers Loading Loading @@ -53,6 +53,7 @@ class KeyguardQuickAffordanceRepositoryTest : SysuiTestCase() { config2 = FakeKeyguardQuickAffordanceConfig("built_in:2") underTest = KeyguardQuickAffordanceRepository( appContext = context, scope = CoroutineScope(IMMEDIATE), backgroundDispatcher = IMMEDIATE, selectionManager = KeyguardQuickAffordanceSelectionManager(), Loading Loading @@ -119,16 +120,32 @@ class KeyguardQuickAffordanceRepositoryTest : SysuiTestCase() { @Test fun getSlotPickerRepresentations() { val slot1 = "slot1" val slot2 = "slot2" val slot3 = "slot3" context.orCreateTestableResources.addOverride( R.array.config_keyguardQuickAffordanceSlots, arrayOf( "$slot1:2", "$slot2:4", "$slot3:5", ), ) assertThat(underTest.getSlotPickerRepresentations()) .isEqualTo( listOf( KeyguardSlotPickerRepresentation( id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START, maxSelectedAffordances = 1, id = slot1, maxSelectedAffordances = 2, ), KeyguardSlotPickerRepresentation( id = slot2, maxSelectedAffordances = 4, ), KeyguardSlotPickerRepresentation( id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, maxSelectedAffordances = 1, id = slot3, maxSelectedAffordances = 5, ), ) ) Loading
packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt +1 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() { FakeKeyguardQuickAffordanceConfig(BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER) val quickAffordanceRepository = KeyguardQuickAffordanceRepository( appContext = context, scope = CoroutineScope(IMMEDIATE), backgroundDispatcher = IMMEDIATE, selectionManager = KeyguardQuickAffordanceSelectionManager(), Loading
packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { val quickAffordanceRepository = KeyguardQuickAffordanceRepository( appContext = context, scope = CoroutineScope(IMMEDIATE), backgroundDispatcher = IMMEDIATE, selectionManager = KeyguardQuickAffordanceSelectionManager(), Loading