Loading packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt +10 −10 Original line number Diff line number Diff line Loading @@ -53,19 +53,19 @@ constructor( override val key: String = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS override val state: Flow<KeyguardQuickAffordanceConfig.State> = override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = component.canShowWhileLockedSetting.flatMapLatest { canShowWhileLocked -> if (canShowWhileLocked) { stateInternal(component.getControlsListingController().getOrNull()) } else { flowOf(KeyguardQuickAffordanceConfig.State.Hidden) flowOf(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) } } override fun onQuickAffordanceClicked( override fun onTriggered( expandable: Expandable?, ): KeyguardQuickAffordanceConfig.OnClickedResult { return KeyguardQuickAffordanceConfig.OnClickedResult.StartActivity( ): KeyguardQuickAffordanceConfig.OnTriggeredResult { return KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity( intent = Intent(appContext, ControlsActivity::class.java) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) Loading @@ -79,9 +79,9 @@ constructor( private fun stateInternal( listingController: ControlsListingController?, ): Flow<KeyguardQuickAffordanceConfig.State> { ): Flow<KeyguardQuickAffordanceConfig.LockScreenState> { if (listingController == null) { return flowOf(KeyguardQuickAffordanceConfig.State.Hidden) return flowOf(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) } return conflatedCallbackFlow { Loading Loading @@ -116,7 +116,7 @@ constructor( hasServiceInfos: Boolean, visibility: ControlsComponent.Visibility, @DrawableRes iconResourceId: Int?, ): KeyguardQuickAffordanceConfig.State { ): KeyguardQuickAffordanceConfig.LockScreenState { return if ( isFeatureEnabled && hasFavorites && Loading @@ -124,7 +124,7 @@ constructor( iconResourceId != null && visibility == ControlsComponent.Visibility.AVAILABLE ) { KeyguardQuickAffordanceConfig.State.Visible( KeyguardQuickAffordanceConfig.LockScreenState.Visible( icon = Icon.Resource( res = iconResourceId, Loading @@ -135,7 +135,7 @@ constructor( ), ) } else { KeyguardQuickAffordanceConfig.State.Hidden KeyguardQuickAffordanceConfig.LockScreenState.Hidden } } Loading packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt +22 −19 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ package com.android.systemui.keyguard.data.quickaffordance import android.content.Intent import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.Icon import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordanceToggleState import com.android.systemui.keyguard.shared.quickaffordance.ActivationState import kotlinx.coroutines.flow.Flow /** Defines interface that can act as data source for a single quick affordance model. */ Loading @@ -29,51 +29,54 @@ interface KeyguardQuickAffordanceConfig { /** Unique identifier for this quick affordance. It must be globally unique. */ val key: String /** The observable [State] of the affordance. */ val state: Flow<State> /** * The ever-changing state of the affordance. * * Used to populate the lock screen. */ val lockScreenState: Flow<LockScreenState> /** * Notifies that the affordance was clicked by the user. * * @param expandable An [Expandable] to use when animating dialogs or activities * @return An [OnClickedResult] telling the caller what to do next * @return An [OnTriggeredResult] telling the caller what to do next */ fun onQuickAffordanceClicked(expandable: Expandable?): OnClickedResult fun onTriggered(expandable: Expandable?): OnTriggeredResult /** * Encapsulates the state of a "quick affordance" in the keyguard bottom area (for example, a * button on the lock-screen). */ sealed class State { sealed class LockScreenState { /** No affordance should show up. */ object Hidden : State() object Hidden : LockScreenState() /** An affordance is visible. */ data class Visible( /** An icon for the affordance. */ val icon: Icon, /** The toggle state for the affordance. */ val toggle: KeyguardQuickAffordanceToggleState = KeyguardQuickAffordanceToggleState.NotSupported, ) : State() /** The activation state of the affordance. */ val activationState: ActivationState = ActivationState.NotSupported, ) : LockScreenState() } sealed class OnClickedResult { sealed class OnTriggeredResult { /** * Returning this as a result from the [onQuickAffordanceClicked] method means that the * implementation has taken care of the click, the system will do nothing. * Returning this as a result from the [onTriggered] method means that the implementation * has taken care of the action, the system will do nothing. */ object Handled : OnClickedResult() object Handled : OnTriggeredResult() /** * Returning this as a result from the [onQuickAffordanceClicked] method means that the * implementation has _not_ taken care of the click and the system should start an activity * using the given [Intent]. * Returning this as a result from the [onTriggered] method means that the implementation * has _not_ taken care of the action and the system should start an activity using the * given [Intent]. */ data class StartActivity( val intent: Intent, val canShowWhileLocked: Boolean, ) : OnClickedResult() ) : OnTriggeredResult() } } packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt +28 −27 Original line number Diff line number Diff line Loading @@ -39,7 +39,8 @@ constructor( override val key: String = BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER override val state: Flow<KeyguardQuickAffordanceConfig.State> = conflatedCallbackFlow { override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = conflatedCallbackFlow { val callback = object : QRCodeScannerController.Callback { override fun onQRCodeScannerActivityChanged() { Loading Loading @@ -67,18 +68,18 @@ constructor( } } override fun onQuickAffordanceClicked( override fun onTriggered( expandable: Expandable?, ): KeyguardQuickAffordanceConfig.OnClickedResult { return KeyguardQuickAffordanceConfig.OnClickedResult.StartActivity( ): KeyguardQuickAffordanceConfig.OnTriggeredResult { return KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity( intent = controller.intent, canShowWhileLocked = true, ) } private fun state(): KeyguardQuickAffordanceConfig.State { private fun state(): KeyguardQuickAffordanceConfig.LockScreenState { return if (controller.isEnabledForLockScreenButton) { KeyguardQuickAffordanceConfig.State.Visible( KeyguardQuickAffordanceConfig.LockScreenState.Visible( icon = Icon.Resource( res = R.drawable.ic_qr_code_scanner, Loading @@ -89,7 +90,7 @@ constructor( ), ) } else { KeyguardQuickAffordanceConfig.State.Hidden KeyguardQuickAffordanceConfig.LockScreenState.Hidden } } Loading packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt +38 −37 Original line number Diff line number Diff line Loading @@ -46,7 +46,8 @@ constructor( override val key: String = BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET override val state: Flow<KeyguardQuickAffordanceConfig.State> = conflatedCallbackFlow { override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = conflatedCallbackFlow { val callback = object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback { override fun onWalletCardsRetrieved(response: GetWalletCardsResponse?) { Loading @@ -63,7 +64,7 @@ constructor( override fun onWalletCardRetrievalError(error: GetWalletCardsError?) { Log.e(TAG, "Wallet card retrieval error, message: \"${error?.message}\"") trySendWithFailureLogging( KeyguardQuickAffordanceConfig.State.Hidden, KeyguardQuickAffordanceConfig.LockScreenState.Hidden, TAG, ) } Loading @@ -85,24 +86,24 @@ constructor( } } override fun onQuickAffordanceClicked( override fun onTriggered( expandable: Expandable?, ): KeyguardQuickAffordanceConfig.OnClickedResult { ): KeyguardQuickAffordanceConfig.OnTriggeredResult { walletController.startQuickAccessUiIntent( activityStarter, expandable?.activityLaunchController(), /* hasCard= */ true, ) return KeyguardQuickAffordanceConfig.OnClickedResult.Handled return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled } private fun state( isFeatureEnabled: Boolean, hasCard: Boolean, tileIcon: Drawable?, ): KeyguardQuickAffordanceConfig.State { ): KeyguardQuickAffordanceConfig.LockScreenState { return if (isFeatureEnabled && hasCard && tileIcon != null) { KeyguardQuickAffordanceConfig.State.Visible( KeyguardQuickAffordanceConfig.LockScreenState.Visible( icon = Icon.Loaded( drawable = tileIcon, Loading @@ -113,7 +114,7 @@ constructor( ), ) } else { KeyguardQuickAffordanceConfig.State.Hidden KeyguardQuickAffordanceConfig.LockScreenState.Hidden } } Loading packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt +13 −9 Original line number Diff line number Diff line Loading @@ -62,25 +62,25 @@ constructor( } /** * Notifies that a quick affordance has been clicked by the user. * Notifies that a quick affordance has been "triggered" (clicked) by the user. * * @param configKey The configuration key corresponding to the [KeyguardQuickAffordanceModel] of * the affordance that was clicked * @param expandable An optional [Expandable] for the activity- or dialog-launch animation */ fun onQuickAffordanceClicked( fun onQuickAffordanceTriggered( configKey: String, expandable: Expandable?, ) { @Suppress("UNCHECKED_CAST") val config = registry.get(configKey) when (val result = config.onQuickAffordanceClicked(expandable)) { is KeyguardQuickAffordanceConfig.OnClickedResult.StartActivity -> when (val result = config.onTriggered(expandable)) { is KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity -> launchQuickAffordance( intent = result.intent, canShowWhileLocked = result.canShowWhileLocked, expandable = expandable, ) is KeyguardQuickAffordanceConfig.OnClickedResult.Handled -> Unit is KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled -> Unit } } Loading @@ -94,16 +94,20 @@ constructor( // value and avoid subtle bugs where the downstream isn't receiving any values // because one config implementation is not emitting an initial value. For example, // see b/244296596. config.state.onStart { emit(KeyguardQuickAffordanceConfig.State.Hidden) } config.lockScreenState.onStart { emit(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) } } ) { states -> val index = states.indexOfFirst { it is KeyguardQuickAffordanceConfig.State.Visible } val index = states.indexOfFirst { it is KeyguardQuickAffordanceConfig.LockScreenState.Visible } if (index != -1) { val visibleState = states[index] as KeyguardQuickAffordanceConfig.State.Visible val visibleState = states[index] as KeyguardQuickAffordanceConfig.LockScreenState.Visible KeyguardQuickAffordanceModel.Visible( configKey = configs[index].key, icon = visibleState.icon, toggle = visibleState.toggle, activationState = visibleState.activationState, ) } else { KeyguardQuickAffordanceModel.Hidden Loading Loading
packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt +10 −10 Original line number Diff line number Diff line Loading @@ -53,19 +53,19 @@ constructor( override val key: String = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS override val state: Flow<KeyguardQuickAffordanceConfig.State> = override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = component.canShowWhileLockedSetting.flatMapLatest { canShowWhileLocked -> if (canShowWhileLocked) { stateInternal(component.getControlsListingController().getOrNull()) } else { flowOf(KeyguardQuickAffordanceConfig.State.Hidden) flowOf(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) } } override fun onQuickAffordanceClicked( override fun onTriggered( expandable: Expandable?, ): KeyguardQuickAffordanceConfig.OnClickedResult { return KeyguardQuickAffordanceConfig.OnClickedResult.StartActivity( ): KeyguardQuickAffordanceConfig.OnTriggeredResult { return KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity( intent = Intent(appContext, ControlsActivity::class.java) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) Loading @@ -79,9 +79,9 @@ constructor( private fun stateInternal( listingController: ControlsListingController?, ): Flow<KeyguardQuickAffordanceConfig.State> { ): Flow<KeyguardQuickAffordanceConfig.LockScreenState> { if (listingController == null) { return flowOf(KeyguardQuickAffordanceConfig.State.Hidden) return flowOf(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) } return conflatedCallbackFlow { Loading Loading @@ -116,7 +116,7 @@ constructor( hasServiceInfos: Boolean, visibility: ControlsComponent.Visibility, @DrawableRes iconResourceId: Int?, ): KeyguardQuickAffordanceConfig.State { ): KeyguardQuickAffordanceConfig.LockScreenState { return if ( isFeatureEnabled && hasFavorites && Loading @@ -124,7 +124,7 @@ constructor( iconResourceId != null && visibility == ControlsComponent.Visibility.AVAILABLE ) { KeyguardQuickAffordanceConfig.State.Visible( KeyguardQuickAffordanceConfig.LockScreenState.Visible( icon = Icon.Resource( res = iconResourceId, Loading @@ -135,7 +135,7 @@ constructor( ), ) } else { KeyguardQuickAffordanceConfig.State.Hidden KeyguardQuickAffordanceConfig.LockScreenState.Hidden } } Loading
packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt +22 −19 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ package com.android.systemui.keyguard.data.quickaffordance import android.content.Intent import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.Icon import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordanceToggleState import com.android.systemui.keyguard.shared.quickaffordance.ActivationState import kotlinx.coroutines.flow.Flow /** Defines interface that can act as data source for a single quick affordance model. */ Loading @@ -29,51 +29,54 @@ interface KeyguardQuickAffordanceConfig { /** Unique identifier for this quick affordance. It must be globally unique. */ val key: String /** The observable [State] of the affordance. */ val state: Flow<State> /** * The ever-changing state of the affordance. * * Used to populate the lock screen. */ val lockScreenState: Flow<LockScreenState> /** * Notifies that the affordance was clicked by the user. * * @param expandable An [Expandable] to use when animating dialogs or activities * @return An [OnClickedResult] telling the caller what to do next * @return An [OnTriggeredResult] telling the caller what to do next */ fun onQuickAffordanceClicked(expandable: Expandable?): OnClickedResult fun onTriggered(expandable: Expandable?): OnTriggeredResult /** * Encapsulates the state of a "quick affordance" in the keyguard bottom area (for example, a * button on the lock-screen). */ sealed class State { sealed class LockScreenState { /** No affordance should show up. */ object Hidden : State() object Hidden : LockScreenState() /** An affordance is visible. */ data class Visible( /** An icon for the affordance. */ val icon: Icon, /** The toggle state for the affordance. */ val toggle: KeyguardQuickAffordanceToggleState = KeyguardQuickAffordanceToggleState.NotSupported, ) : State() /** The activation state of the affordance. */ val activationState: ActivationState = ActivationState.NotSupported, ) : LockScreenState() } sealed class OnClickedResult { sealed class OnTriggeredResult { /** * Returning this as a result from the [onQuickAffordanceClicked] method means that the * implementation has taken care of the click, the system will do nothing. * Returning this as a result from the [onTriggered] method means that the implementation * has taken care of the action, the system will do nothing. */ object Handled : OnClickedResult() object Handled : OnTriggeredResult() /** * Returning this as a result from the [onQuickAffordanceClicked] method means that the * implementation has _not_ taken care of the click and the system should start an activity * using the given [Intent]. * Returning this as a result from the [onTriggered] method means that the implementation * has _not_ taken care of the action and the system should start an activity using the * given [Intent]. */ data class StartActivity( val intent: Intent, val canShowWhileLocked: Boolean, ) : OnClickedResult() ) : OnTriggeredResult() } }
packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfig.kt +28 −27 Original line number Diff line number Diff line Loading @@ -39,7 +39,8 @@ constructor( override val key: String = BuiltInKeyguardQuickAffordanceKeys.QR_CODE_SCANNER override val state: Flow<KeyguardQuickAffordanceConfig.State> = conflatedCallbackFlow { override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = conflatedCallbackFlow { val callback = object : QRCodeScannerController.Callback { override fun onQRCodeScannerActivityChanged() { Loading Loading @@ -67,18 +68,18 @@ constructor( } } override fun onQuickAffordanceClicked( override fun onTriggered( expandable: Expandable?, ): KeyguardQuickAffordanceConfig.OnClickedResult { return KeyguardQuickAffordanceConfig.OnClickedResult.StartActivity( ): KeyguardQuickAffordanceConfig.OnTriggeredResult { return KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity( intent = controller.intent, canShowWhileLocked = true, ) } private fun state(): KeyguardQuickAffordanceConfig.State { private fun state(): KeyguardQuickAffordanceConfig.LockScreenState { return if (controller.isEnabledForLockScreenButton) { KeyguardQuickAffordanceConfig.State.Visible( KeyguardQuickAffordanceConfig.LockScreenState.Visible( icon = Icon.Resource( res = R.drawable.ic_qr_code_scanner, Loading @@ -89,7 +90,7 @@ constructor( ), ) } else { KeyguardQuickAffordanceConfig.State.Hidden KeyguardQuickAffordanceConfig.LockScreenState.Hidden } } Loading
packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt +38 −37 Original line number Diff line number Diff line Loading @@ -46,7 +46,8 @@ constructor( override val key: String = BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET override val state: Flow<KeyguardQuickAffordanceConfig.State> = conflatedCallbackFlow { override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = conflatedCallbackFlow { val callback = object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback { override fun onWalletCardsRetrieved(response: GetWalletCardsResponse?) { Loading @@ -63,7 +64,7 @@ constructor( override fun onWalletCardRetrievalError(error: GetWalletCardsError?) { Log.e(TAG, "Wallet card retrieval error, message: \"${error?.message}\"") trySendWithFailureLogging( KeyguardQuickAffordanceConfig.State.Hidden, KeyguardQuickAffordanceConfig.LockScreenState.Hidden, TAG, ) } Loading @@ -85,24 +86,24 @@ constructor( } } override fun onQuickAffordanceClicked( override fun onTriggered( expandable: Expandable?, ): KeyguardQuickAffordanceConfig.OnClickedResult { ): KeyguardQuickAffordanceConfig.OnTriggeredResult { walletController.startQuickAccessUiIntent( activityStarter, expandable?.activityLaunchController(), /* hasCard= */ true, ) return KeyguardQuickAffordanceConfig.OnClickedResult.Handled return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled } private fun state( isFeatureEnabled: Boolean, hasCard: Boolean, tileIcon: Drawable?, ): KeyguardQuickAffordanceConfig.State { ): KeyguardQuickAffordanceConfig.LockScreenState { return if (isFeatureEnabled && hasCard && tileIcon != null) { KeyguardQuickAffordanceConfig.State.Visible( KeyguardQuickAffordanceConfig.LockScreenState.Visible( icon = Icon.Loaded( drawable = tileIcon, Loading @@ -113,7 +114,7 @@ constructor( ), ) } else { KeyguardQuickAffordanceConfig.State.Hidden KeyguardQuickAffordanceConfig.LockScreenState.Hidden } } Loading
packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt +13 −9 Original line number Diff line number Diff line Loading @@ -62,25 +62,25 @@ constructor( } /** * Notifies that a quick affordance has been clicked by the user. * Notifies that a quick affordance has been "triggered" (clicked) by the user. * * @param configKey The configuration key corresponding to the [KeyguardQuickAffordanceModel] of * the affordance that was clicked * @param expandable An optional [Expandable] for the activity- or dialog-launch animation */ fun onQuickAffordanceClicked( fun onQuickAffordanceTriggered( configKey: String, expandable: Expandable?, ) { @Suppress("UNCHECKED_CAST") val config = registry.get(configKey) when (val result = config.onQuickAffordanceClicked(expandable)) { is KeyguardQuickAffordanceConfig.OnClickedResult.StartActivity -> when (val result = config.onTriggered(expandable)) { is KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity -> launchQuickAffordance( intent = result.intent, canShowWhileLocked = result.canShowWhileLocked, expandable = expandable, ) is KeyguardQuickAffordanceConfig.OnClickedResult.Handled -> Unit is KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled -> Unit } } Loading @@ -94,16 +94,20 @@ constructor( // value and avoid subtle bugs where the downstream isn't receiving any values // because one config implementation is not emitting an initial value. For example, // see b/244296596. config.state.onStart { emit(KeyguardQuickAffordanceConfig.State.Hidden) } config.lockScreenState.onStart { emit(KeyguardQuickAffordanceConfig.LockScreenState.Hidden) } } ) { states -> val index = states.indexOfFirst { it is KeyguardQuickAffordanceConfig.State.Visible } val index = states.indexOfFirst { it is KeyguardQuickAffordanceConfig.LockScreenState.Visible } if (index != -1) { val visibleState = states[index] as KeyguardQuickAffordanceConfig.State.Visible val visibleState = states[index] as KeyguardQuickAffordanceConfig.LockScreenState.Visible KeyguardQuickAffordanceModel.Visible( configKey = configs[index].key, icon = visibleState.icon, toggle = visibleState.toggle, activationState = visibleState.activationState, ) } else { KeyguardQuickAffordanceModel.Hidden Loading