Adds toggle support for quick affordances.

Introduces the ability to toggle quick affordance buttons on the
lock-screen.

Developers of keyguard quick affordances will now have the option of
providing an ON or OFF state for their toggle (or leave it unset) and
the reset of the system will reflect that state onto the UI.

Bug: 253094565
Test: Temporarily added a fake toggle config to the collection of
keyguard quick affordances and made sure it looks correct on both dark
and light themes on the lock-screen and toggles appropriately. Also
expansed existing unit tests to cover for the new state.

Change-Id: Idddb4baeb19c603a6663347a7b4319751f02fd2f
This commit is contained in:
Alejandro Nijamkin
2022-10-11 16:04:49 -07:00
parent f4ceebbadd
commit e7e879deb6
9 changed files with 67 additions and 2 deletions

View File

@@ -104,6 +104,7 @@ constructor(
KeyguardQuickAffordanceModel.Visible(
configKey = configs[index]::class,
icon = visibleState.icon,
toggle = visibleState.toggle,
)
} else {
KeyguardQuickAffordanceModel.Hidden

View File

@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.domain.model
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.keyguard.domain.quickaffordance.KeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordanceToggleState
import kotlin.reflect.KClass
/**
@@ -35,5 +36,7 @@ sealed class KeyguardQuickAffordanceModel {
val configKey: KClass<out KeyguardQuickAffordanceConfig>,
/** An icon for the affordance. */
val icon: Icon,
/** The toggle state for the affordance. */
val toggle: KeyguardQuickAffordanceToggleState,
) : KeyguardQuickAffordanceModel()
}

View File

@@ -20,6 +20,7 @@ package com.android.systemui.keyguard.domain.quickaffordance
import android.content.Intent
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordanceToggleState
import kotlinx.coroutines.flow.Flow
/** Defines interface that can act as data source for a single quick affordance model. */
@@ -44,6 +45,9 @@ interface KeyguardQuickAffordanceConfig {
data class Visible(
/** An icon for the affordance. */
val icon: Icon,
/** The toggle state for the affordance. */
val toggle: KeyguardQuickAffordanceToggleState =
KeyguardQuickAffordanceToggleState.NotSupported,
) : State()
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2022 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.keyguard.shared.quickaffordance
/** Enumerates all possible toggle states for a quick affordance on the lock-screen. */
sealed class KeyguardQuickAffordanceToggleState {
/** Toggling is not supported. */
object NotSupported : KeyguardQuickAffordanceToggleState()
/** The quick affordance is on. */
object On : KeyguardQuickAffordanceToggleState()
/** The quick affordance is off. */
object Off : KeyguardQuickAffordanceToggleState()
}

View File

@@ -238,14 +238,26 @@ object KeyguardBottomAreaViewBinder {
IconViewBinder.bind(viewModel.icon, view)
view.isActivated = viewModel.isActivated
view.drawable.setTint(
Utils.getColorAttrDefaultColor(
view.context,
com.android.internal.R.attr.textColorPrimary
if (viewModel.isActivated) {
com.android.internal.R.attr.textColorPrimaryInverse
} else {
com.android.internal.R.attr.textColorPrimary
},
)
)
view.backgroundTintList =
Utils.getColorAttr(view.context, com.android.internal.R.attr.colorSurface)
Utils.getColorAttr(
view.context,
if (viewModel.isActivated) {
com.android.internal.R.attr.colorAccentPrimary
} else {
com.android.internal.R.attr.colorSurface
}
)
view.isClickable = viewModel.isClickable
if (viewModel.isClickable) {

View File

@@ -23,6 +23,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordanceModel
import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordancePosition
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordanceToggleState
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -123,6 +124,7 @@ constructor(
)
},
isClickable = isClickable,
isActivated = toggle is KeyguardQuickAffordanceToggleState.On,
)
is KeyguardQuickAffordanceModel.Hidden -> KeyguardQuickAffordanceViewModel()
}

View File

@@ -30,6 +30,7 @@ data class KeyguardQuickAffordanceViewModel(
val icon: Icon = Icon.Resource(res = 0, contentDescription = null),
val onClicked: (OnClickedParameters) -> Unit = {},
val isClickable: Boolean = false,
val isActivated: Boolean = false,
) {
data class OnClickedParameters(
val configKey: KClass<out KeyguardQuickAffordanceConfig>,

View File

@@ -29,6 +29,7 @@ import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordancePositio
import com.android.systemui.keyguard.domain.quickaffordance.FakeKeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.domain.quickaffordance.FakeKeyguardQuickAffordanceRegistry
import com.android.systemui.keyguard.domain.quickaffordance.KeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordanceToggleState
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -103,6 +104,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
homeControls.setState(
KeyguardQuickAffordanceConfig.State.Visible(
icon = ICON,
toggle = KeyguardQuickAffordanceToggleState.On,
)
)
@@ -123,6 +125,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
assertThat(visibleModel.icon).isEqualTo(ICON)
assertThat(visibleModel.icon.contentDescription)
.isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID))
assertThat(visibleModel.toggle).isEqualTo(KeyguardQuickAffordanceToggleState.On)
job.cancel()
}
@@ -152,6 +155,7 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
assertThat(visibleModel.icon).isEqualTo(ICON)
assertThat(visibleModel.icon.contentDescription)
.isEqualTo(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID))
assertThat(visibleModel.toggle).isEqualTo(KeyguardQuickAffordanceToggleState.NotSupported)
job.cancel()
}

View File

@@ -31,6 +31,7 @@ import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordancePositio
import com.android.systemui.keyguard.domain.quickaffordance.FakeKeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.domain.quickaffordance.FakeKeyguardQuickAffordanceRegistry
import com.android.systemui.keyguard.domain.quickaffordance.KeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordanceToggleState
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -130,6 +131,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
TestConfig(
isVisible = true,
isClickable = true,
isActivated = true,
icon = mock(),
canShowWhileLocked = false,
intent = Intent("action"),
@@ -505,6 +507,12 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
}
KeyguardQuickAffordanceConfig.State.Visible(
icon = testConfig.icon ?: error("Icon is unexpectedly null!"),
toggle =
when (testConfig.isActivated) {
true -> KeyguardQuickAffordanceToggleState.On
false -> KeyguardQuickAffordanceToggleState.Off
null -> KeyguardQuickAffordanceToggleState.NotSupported
}
)
} else {
KeyguardQuickAffordanceConfig.State.Hidden
@@ -521,6 +529,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
checkNotNull(viewModel)
assertThat(viewModel.isVisible).isEqualTo(testConfig.isVisible)
assertThat(viewModel.isClickable).isEqualTo(testConfig.isClickable)
assertThat(viewModel.isActivated).isEqualTo(testConfig.isActivated)
if (testConfig.isVisible) {
assertThat(viewModel.icon).isEqualTo(testConfig.icon)
viewModel.onClicked.invoke(
@@ -542,6 +551,7 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
private data class TestConfig(
val isVisible: Boolean,
val isClickable: Boolean = false,
val isActivated: Boolean = false,
val icon: Icon? = null,
val canShowWhileLocked: Boolean = false,
val intent: Intent? = null,