Support for unavailable and disabled affordances. am: af8fd1b3c5
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20441246 Change-Id: I6282dd626c1d84815aabf567ee144330954b417c Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
committed by
Automerger Merge Worker
commit
4459e7dcbc
@@ -2679,4 +2679,50 @@
|
||||
|
||||
<!-- Time format for the Dream Time Complication for 24-hour time format [CHAR LIMIT=NONE] -->
|
||||
<string name="dream_time_complication_24_hr_time_format">kk:mm</string>
|
||||
|
||||
<!--
|
||||
Template for an action that opens a specific app. [CHAR LIMIT=16]
|
||||
-->
|
||||
<string name="keyguard_affordance_enablement_dialog_action_template">Open <xliff:g id="appName" example="Wallet">%1$s</xliff:g></string>
|
||||
|
||||
<!--
|
||||
Template for a message shown right before a list of instructions that tell the user what to do
|
||||
in order to enable a shortcut to a specific app. [CHAR LIMIT=NONE]
|
||||
-->
|
||||
<string name="keyguard_affordance_enablement_dialog_message">To add the <xliff:g id="appName" example="Wallet">%1$s</xliff:g> app as a shortcut, make sure</string>
|
||||
|
||||
<!--
|
||||
Requirement for the wallet app to be available for the user to use. This is shown as part of a
|
||||
bulleted list of requirements. When all requirements are met, the app can be accessed through a
|
||||
shortcut button on the lock screen. [CHAR LIMIT=NONE].
|
||||
-->
|
||||
<string name="keyguard_affordance_enablement_dialog_wallet_instruction_1">• The app is set up</string>
|
||||
|
||||
<!--
|
||||
Requirement for the wallet app to be available for the user to use. This is shown as part of a
|
||||
bulleted list of requirements. When all requirements are met, the app can be accessed through a
|
||||
shortcut button on the lock screen. [CHAR LIMIT=NONE].
|
||||
-->
|
||||
<string name="keyguard_affordance_enablement_dialog_wallet_instruction_2">• At least one card has been added to Wallet</string>
|
||||
|
||||
<!--
|
||||
Requirement for the QR code scanner functionality to be available for the user to use. This is
|
||||
shown as part of a bulleted list of requirements. When all requirements are met, the piece of
|
||||
functionality can be accessed through a shortcut button on the lock screen. [CHAR LIMIT=NONE].
|
||||
-->
|
||||
<string name="keyguard_affordance_enablement_dialog_qr_scanner_instruction">• Install a camera app</string>
|
||||
|
||||
<!--
|
||||
Requirement for the home app to be available for the user to use. This is shown as part of a
|
||||
bulleted list of requirements. When all requirements are met, the app can be accessed through a
|
||||
shortcut button on the lock screen. [CHAR LIMIT=NONE].
|
||||
-->
|
||||
<string name="keyguard_affordance_enablement_dialog_home_instruction_1">• The app is set up</string>
|
||||
|
||||
<!--
|
||||
Requirement for the home app to be available for the user to use. This is shown as part of a
|
||||
bulleted list of requirements. When all requirements are met, the app can be accessed through a
|
||||
shortcut button on the lock screen. [CHAR LIMIT=NONE].
|
||||
-->
|
||||
<string name="keyguard_affordance_enablement_dialog_home_instruction_2">• At least one device is available</string>
|
||||
</resources>
|
||||
|
||||
@@ -67,6 +67,8 @@ object KeyguardQuickAffordanceProviderContract {
|
||||
object AffordanceTable {
|
||||
const val TABLE_NAME = "affordances"
|
||||
val URI: Uri = BASE_URI.buildUpon().path(TABLE_NAME).build()
|
||||
const val ENABLEMENT_INSTRUCTIONS_DELIMITER = "]["
|
||||
const val COMPONENT_NAME_SEPARATOR = "/"
|
||||
|
||||
object Columns {
|
||||
/** String. Unique ID for this affordance. */
|
||||
@@ -78,6 +80,25 @@ object KeyguardQuickAffordanceProviderContract {
|
||||
* ID from the system UI package.
|
||||
*/
|
||||
const val ICON = "icon"
|
||||
/** Integer. `1` if the affordance is enabled or `0` if it disabled. */
|
||||
const val IS_ENABLED = "is_enabled"
|
||||
/**
|
||||
* String. List of strings, delimited by [ENABLEMENT_INSTRUCTIONS_DELIMITER] to be shown
|
||||
* to the user if the affordance is disabled and the user selects the affordance. The
|
||||
* first one is a title while the rest are the steps needed to re-enable the affordance.
|
||||
*/
|
||||
const val ENABLEMENT_INSTRUCTIONS = "enablement_instructions"
|
||||
/**
|
||||
* String. Optional label for a button that, when clicked, opens a destination activity
|
||||
* where the user can re-enable the disabled affordance.
|
||||
*/
|
||||
const val ENABLEMENT_ACTION_TEXT = "enablement_action_text"
|
||||
/**
|
||||
* String. Optional package name and activity action string, delimited by
|
||||
* [COMPONENT_NAME_SEPARATOR] to use with an `Intent` to start an activity that opens a
|
||||
* destination where the user can re-enable the disabled affordance.
|
||||
*/
|
||||
const val ENABLEMENT_COMPONENT_NAME = "enablement_action_intent"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.android.systemui.SystemUIAppComponentFactoryBase.ContextAvailableCall
|
||||
import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
|
||||
import com.android.systemui.shared.keyguard.data.content.KeyguardQuickAffordanceProviderContract as Contract
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
class KeyguardQuickAffordanceProvider :
|
||||
ContentProvider(), SystemUIAppComponentFactoryBase.ContextInitializer {
|
||||
@@ -118,9 +119,9 @@ class KeyguardQuickAffordanceProvider :
|
||||
sortOrder: String?,
|
||||
): Cursor? {
|
||||
return when (uriMatcher.match(uri)) {
|
||||
MATCH_CODE_ALL_AFFORDANCES -> queryAffordances()
|
||||
MATCH_CODE_ALL_AFFORDANCES -> runBlocking { queryAffordances() }
|
||||
MATCH_CODE_ALL_SLOTS -> querySlots()
|
||||
MATCH_CODE_ALL_SELECTIONS -> querySelections()
|
||||
MATCH_CODE_ALL_SELECTIONS -> runBlocking { querySelections() }
|
||||
MATCH_CODE_ALL_FLAGS -> queryFlags()
|
||||
else -> null
|
||||
}
|
||||
@@ -194,7 +195,7 @@ class KeyguardQuickAffordanceProvider :
|
||||
}
|
||||
}
|
||||
|
||||
private fun querySelections(): Cursor {
|
||||
private suspend fun querySelections(): Cursor {
|
||||
return MatrixCursor(
|
||||
arrayOf(
|
||||
Contract.SelectionTable.Columns.SLOT_ID,
|
||||
@@ -219,12 +220,16 @@ class KeyguardQuickAffordanceProvider :
|
||||
}
|
||||
}
|
||||
|
||||
private fun queryAffordances(): Cursor {
|
||||
private suspend fun queryAffordances(): Cursor {
|
||||
return MatrixCursor(
|
||||
arrayOf(
|
||||
Contract.AffordanceTable.Columns.ID,
|
||||
Contract.AffordanceTable.Columns.NAME,
|
||||
Contract.AffordanceTable.Columns.ICON,
|
||||
Contract.AffordanceTable.Columns.IS_ENABLED,
|
||||
Contract.AffordanceTable.Columns.ENABLEMENT_INSTRUCTIONS,
|
||||
Contract.AffordanceTable.Columns.ENABLEMENT_ACTION_TEXT,
|
||||
Contract.AffordanceTable.Columns.ENABLEMENT_COMPONENT_NAME,
|
||||
)
|
||||
)
|
||||
.apply {
|
||||
@@ -234,6 +239,12 @@ class KeyguardQuickAffordanceProvider :
|
||||
representation.id,
|
||||
representation.name,
|
||||
representation.iconResourceId,
|
||||
if (representation.isEnabled) 1 else 0,
|
||||
representation.instructions?.joinToString(
|
||||
Contract.AffordanceTable.ENABLEMENT_INSTRUCTIONS_DELIMITER
|
||||
),
|
||||
representation.actionText,
|
||||
representation.actionComponentName,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package com.android.systemui.keyguard.data.quickaffordance
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.animation.Expandable
|
||||
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
|
||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||
@@ -45,7 +46,7 @@ import kotlinx.coroutines.flow.flowOf
|
||||
class HomeControlsKeyguardQuickAffordanceConfig
|
||||
@Inject
|
||||
constructor(
|
||||
@Application context: Context,
|
||||
@Application private val context: Context,
|
||||
private val component: ControlsComponent,
|
||||
) : KeyguardQuickAffordanceConfig {
|
||||
|
||||
@@ -66,6 +67,36 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
|
||||
if (!component.isEnabled()) {
|
||||
return KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
|
||||
}
|
||||
|
||||
val currentServices =
|
||||
component.getControlsListingController().getOrNull()?.getCurrentServices()
|
||||
val hasFavorites =
|
||||
component.getControlsController().getOrNull()?.getFavorites()?.isNotEmpty() == true
|
||||
if (currentServices.isNullOrEmpty() || !hasFavorites) {
|
||||
return KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
|
||||
instructions =
|
||||
listOf(
|
||||
context.getString(
|
||||
R.string.keyguard_affordance_enablement_dialog_message,
|
||||
pickerName,
|
||||
),
|
||||
context.getString(
|
||||
R.string.keyguard_affordance_enablement_dialog_home_instruction_1
|
||||
),
|
||||
context.getString(
|
||||
R.string.keyguard_affordance_enablement_dialog_home_instruction_2
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return KeyguardQuickAffordanceConfig.PickerScreenState.Default
|
||||
}
|
||||
|
||||
override fun onTriggered(
|
||||
expandable: Expandable?,
|
||||
): KeyguardQuickAffordanceConfig.OnTriggeredResult {
|
||||
|
||||
@@ -21,6 +21,7 @@ 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.ActivationState
|
||||
import com.android.systemui.shared.keyguard.data.content.KeyguardQuickAffordanceProviderContract as Contract
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/** Defines interface that can act as data source for a single quick affordance model. */
|
||||
@@ -40,6 +41,12 @@ interface KeyguardQuickAffordanceConfig {
|
||||
*/
|
||||
val lockScreenState: Flow<LockScreenState>
|
||||
|
||||
/**
|
||||
* Returns the [PickerScreenState] representing the affordance in the settings or selector
|
||||
* experience.
|
||||
*/
|
||||
suspend fun getPickerScreenState(): PickerScreenState = PickerScreenState.Default
|
||||
|
||||
/**
|
||||
* Notifies that the affordance was clicked by the user.
|
||||
*
|
||||
@@ -48,6 +55,58 @@ interface KeyguardQuickAffordanceConfig {
|
||||
*/
|
||||
fun onTriggered(expandable: Expandable?): OnTriggeredResult
|
||||
|
||||
/**
|
||||
* Encapsulates the state of a quick affordance within the context of the settings or selector
|
||||
* experience.
|
||||
*/
|
||||
sealed class PickerScreenState {
|
||||
|
||||
/** The picker shows the item for selecting this affordance as it normally would. */
|
||||
object Default : PickerScreenState()
|
||||
|
||||
/**
|
||||
* The picker does not show an item for selecting this affordance as it is not supported on
|
||||
* the device at all. For example, missing hardware requirements.
|
||||
*/
|
||||
object UnavailableOnDevice : PickerScreenState()
|
||||
|
||||
/**
|
||||
* The picker shows the item for selecting this affordance as disabled. Clicking on it will
|
||||
* show the given instructions to the user. If [actionText] and [actionComponentName] are
|
||||
* provided (optional) a button will be shown to open an activity to help the user complete
|
||||
* the steps described in the instructions.
|
||||
*/
|
||||
data class Disabled(
|
||||
/** List of human-readable instructions for setting up the quick affordance. */
|
||||
val instructions: List<String>,
|
||||
/**
|
||||
* Optional text to display on a button that the user can click to start a flow to go
|
||||
* and set up the quick affordance and make it enabled.
|
||||
*/
|
||||
val actionText: String? = null,
|
||||
/**
|
||||
* Optional component name to be able to build an `Intent` that opens an `Activity` for
|
||||
* the user to be able to set up the quick affordance and make it enabled.
|
||||
*
|
||||
* This is either just an action for the `Intent` or a package name and action,
|
||||
* separated by [Contract.AffordanceTable.COMPONENT_NAME_SEPARATOR] for convenience, you
|
||||
* can use the [componentName] function.
|
||||
*/
|
||||
val actionComponentName: String? = null,
|
||||
) : PickerScreenState() {
|
||||
init {
|
||||
check(instructions.isNotEmpty()) { "Instructions must not be empty!" }
|
||||
check(
|
||||
(actionText.isNullOrEmpty() && actionComponentName.isNullOrEmpty()) ||
|
||||
(!actionText.isNullOrEmpty() && !actionComponentName.isNullOrEmpty())
|
||||
) {
|
||||
"actionText and actionComponentName must either both be null/empty or both be" +
|
||||
" non-empty!"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encapsulates the state of a "quick affordance" in the keyguard bottom area (for example, a
|
||||
* button on the lock-screen).
|
||||
@@ -83,4 +142,18 @@ interface KeyguardQuickAffordanceConfig {
|
||||
val canShowWhileLocked: Boolean,
|
||||
) : OnTriggeredResult()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun componentName(
|
||||
packageName: String? = null,
|
||||
action: String?,
|
||||
): String? {
|
||||
return when {
|
||||
action.isNullOrEmpty() -> null
|
||||
!packageName.isNullOrEmpty() ->
|
||||
"$packageName${Contract.AffordanceTable.COMPONENT_NAME_SEPARATOR}$action"
|
||||
else -> action
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
class QrCodeScannerKeyguardQuickAffordanceConfig
|
||||
@Inject
|
||||
constructor(
|
||||
@Application context: Context,
|
||||
@Application private val context: Context,
|
||||
private val controller: QRCodeScannerController,
|
||||
) : KeyguardQuickAffordanceConfig {
|
||||
|
||||
@@ -75,6 +75,28 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
|
||||
return when {
|
||||
!controller.isAvailableOnDevice ->
|
||||
KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
|
||||
!controller.isAbleToOpenCameraApp ->
|
||||
KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
|
||||
instructions =
|
||||
listOf(
|
||||
context.getString(
|
||||
R.string.keyguard_affordance_enablement_dialog_message,
|
||||
pickerName,
|
||||
),
|
||||
context.getString(
|
||||
R.string
|
||||
.keyguard_affordance_enablement_dialog_qr_scanner_instruction
|
||||
),
|
||||
),
|
||||
)
|
||||
else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTriggered(
|
||||
expandable: Expandable?,
|
||||
): KeyguardQuickAffordanceConfig.OnTriggeredResult {
|
||||
|
||||
@@ -18,10 +18,12 @@
|
||||
package com.android.systemui.keyguard.data.quickaffordance
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.service.quickaccesswallet.GetWalletCardsError
|
||||
import android.service.quickaccesswallet.GetWalletCardsResponse
|
||||
import android.service.quickaccesswallet.QuickAccessWalletClient
|
||||
import android.service.quickaccesswallet.WalletCard
|
||||
import android.util.Log
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.animation.Expandable
|
||||
@@ -31,25 +33,27 @@ import com.android.systemui.common.shared.model.ContentDescription
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.Companion.componentName
|
||||
import com.android.systemui.plugins.ActivityStarter
|
||||
import com.android.systemui.wallet.controller.QuickAccessWalletController
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
|
||||
/** Quick access wallet quick affordance data source. */
|
||||
@SysUISingleton
|
||||
class QuickAccessWalletKeyguardQuickAffordanceConfig
|
||||
@Inject
|
||||
constructor(
|
||||
@Application context: Context,
|
||||
@Application private val context: Context,
|
||||
private val walletController: QuickAccessWalletController,
|
||||
private val activityStarter: ActivityStarter,
|
||||
) : KeyguardQuickAffordanceConfig {
|
||||
|
||||
override val key: String = BuiltInKeyguardQuickAffordanceKeys.QUICK_ACCESS_WALLET
|
||||
|
||||
override val pickerName = context.getString(R.string.accessibility_wallet_button)
|
||||
override val pickerName: String = context.getString(R.string.accessibility_wallet_button)
|
||||
|
||||
override val pickerIconResourceId = R.drawable.ic_wallet_lockscreen
|
||||
|
||||
@@ -58,10 +62,11 @@ constructor(
|
||||
val callback =
|
||||
object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
|
||||
override fun onWalletCardsRetrieved(response: GetWalletCardsResponse?) {
|
||||
val hasCards = response?.walletCards?.isNotEmpty() == true
|
||||
trySendWithFailureLogging(
|
||||
state(
|
||||
isFeatureEnabled = walletController.isWalletEnabled,
|
||||
hasCard = response?.walletCards?.isNotEmpty() == true,
|
||||
hasCard = hasCards,
|
||||
tileIcon = walletController.walletClient.tileIcon,
|
||||
),
|
||||
TAG,
|
||||
@@ -93,6 +98,44 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
|
||||
return when {
|
||||
!walletController.isWalletEnabled ->
|
||||
KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
|
||||
walletController.walletClient.tileIcon == null || queryCards().isEmpty() -> {
|
||||
val componentName =
|
||||
walletController.walletClient.createWalletSettingsIntent().toComponentName()
|
||||
val actionText =
|
||||
if (componentName != null) {
|
||||
context.getString(
|
||||
R.string.keyguard_affordance_enablement_dialog_action_template,
|
||||
pickerName,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
|
||||
instructions =
|
||||
listOf(
|
||||
context.getString(
|
||||
R.string.keyguard_affordance_enablement_dialog_message,
|
||||
pickerName,
|
||||
),
|
||||
context.getString(
|
||||
R.string.keyguard_affordance_enablement_dialog_wallet_instruction_1
|
||||
),
|
||||
context.getString(
|
||||
R.string.keyguard_affordance_enablement_dialog_wallet_instruction_2
|
||||
),
|
||||
),
|
||||
actionText = actionText,
|
||||
actionComponentName = componentName,
|
||||
)
|
||||
}
|
||||
else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTriggered(
|
||||
expandable: Expandable?,
|
||||
): KeyguardQuickAffordanceConfig.OnTriggeredResult {
|
||||
@@ -104,6 +147,24 @@ constructor(
|
||||
return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
|
||||
}
|
||||
|
||||
private suspend fun queryCards(): List<WalletCard> {
|
||||
return suspendCancellableCoroutine { continuation ->
|
||||
val callback =
|
||||
object : QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
|
||||
override fun onWalletCardsRetrieved(response: GetWalletCardsResponse?) {
|
||||
continuation.resumeWith(
|
||||
Result.success(response?.walletCards ?: emptyList())
|
||||
)
|
||||
}
|
||||
|
||||
override fun onWalletCardRetrievalError(error: GetWalletCardsError?) {
|
||||
continuation.resumeWith(Result.success(emptyList()))
|
||||
}
|
||||
}
|
||||
walletController.queryWalletCards(callback)
|
||||
}
|
||||
}
|
||||
|
||||
private fun state(
|
||||
isFeatureEnabled: Boolean,
|
||||
hasCard: Boolean,
|
||||
@@ -125,6 +186,14 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun Intent?.toComponentName(): String? {
|
||||
if (this == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
return componentName(packageName = `package`, action = action)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "QuickAccessWalletKeyguardQuickAffordanceConfig"
|
||||
}
|
||||
|
||||
@@ -121,18 +121,32 @@ constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of representation objects for all known affordances, regardless of what is
|
||||
* selected. This is useful for building experiences like the picker/selector or user settings
|
||||
* so the user can see everything that can be selected in a menu.
|
||||
* Returns the list of representation objects for all known, device-available affordances,
|
||||
* regardless of what is selected. This is useful for building experiences like the
|
||||
* picker/selector or user settings so the user can see everything that can be selected in a
|
||||
* menu.
|
||||
*/
|
||||
fun getAffordancePickerRepresentations(): List<KeyguardQuickAffordancePickerRepresentation> {
|
||||
return configs.map { config ->
|
||||
KeyguardQuickAffordancePickerRepresentation(
|
||||
id = config.key,
|
||||
name = config.pickerName,
|
||||
iconResourceId = config.pickerIconResourceId,
|
||||
)
|
||||
}
|
||||
suspend fun getAffordancePickerRepresentations():
|
||||
List<KeyguardQuickAffordancePickerRepresentation> {
|
||||
return configs
|
||||
.associateWith { config -> config.getPickerScreenState() }
|
||||
.filterNot { (_, pickerState) ->
|
||||
pickerState is KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
|
||||
}
|
||||
.map { (config, pickerState) ->
|
||||
val disabledPickerState =
|
||||
pickerState as? KeyguardQuickAffordanceConfig.PickerScreenState.Disabled
|
||||
KeyguardQuickAffordancePickerRepresentation(
|
||||
id = config.key,
|
||||
name = config.pickerName,
|
||||
iconResourceId = config.pickerIconResourceId,
|
||||
isEnabled =
|
||||
pickerState is KeyguardQuickAffordanceConfig.PickerScreenState.Default,
|
||||
instructions = disabledPickerState?.instructions,
|
||||
actionText = disabledPickerState?.actionText,
|
||||
actionComponentName = disabledPickerState?.actionComponentName,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -189,7 +189,7 @@ constructor(
|
||||
}
|
||||
|
||||
/** Returns affordance IDs indexed by slot ID, for all known slots. */
|
||||
fun getSelections(): Map<String, List<KeyguardQuickAffordancePickerRepresentation>> {
|
||||
suspend fun getSelections(): Map<String, List<KeyguardQuickAffordancePickerRepresentation>> {
|
||||
check(isUsingRepository)
|
||||
|
||||
val slots = repository.get().getSlotPickerRepresentations()
|
||||
@@ -310,7 +310,8 @@ constructor(
|
||||
return Pair(splitUp[0], splitUp[1])
|
||||
}
|
||||
|
||||
fun getAffordancePickerRepresentations(): List<KeyguardQuickAffordancePickerRepresentation> {
|
||||
suspend fun getAffordancePickerRepresentations():
|
||||
List<KeyguardQuickAffordancePickerRepresentation> {
|
||||
check(isUsingRepository)
|
||||
|
||||
return repository.get().getAffordancePickerRepresentations()
|
||||
|
||||
@@ -27,4 +27,22 @@ data class KeyguardQuickAffordancePickerRepresentation(
|
||||
val id: String,
|
||||
val name: String,
|
||||
@DrawableRes val iconResourceId: Int,
|
||||
|
||||
/** Whether this quick affordance is enabled. */
|
||||
val isEnabled: Boolean = true,
|
||||
|
||||
/** If not enabled, the list of user-visible steps to re-enable it. */
|
||||
val instructions: List<String>? = null,
|
||||
|
||||
/**
|
||||
* If not enabled, an optional label for a button that takes the user to a destination where
|
||||
* they can re-enable it.
|
||||
*/
|
||||
val actionText: String? = null,
|
||||
|
||||
/**
|
||||
* If not enabled, an optional component name (package and action) for a button that takes the
|
||||
* user to a destination where they can re-enable it.
|
||||
*/
|
||||
val actionComponentName: String? = null,
|
||||
)
|
||||
|
||||
@@ -158,14 +158,18 @@ public class QRCodeScannerController implements
|
||||
* Returns true if lock screen entry point for QR Code Scanner is to be enabled.
|
||||
*/
|
||||
public boolean isEnabledForLockScreenButton() {
|
||||
return mQRCodeScannerEnabled && mIntent != null && mConfigEnableLockScreenButton
|
||||
&& isActivityCallable(mIntent);
|
||||
return mQRCodeScannerEnabled && isAbleToOpenCameraApp() && isAvailableOnDevice();
|
||||
}
|
||||
|
||||
/** Returns whether the feature is available on the device. */
|
||||
public boolean isAvailableOnDevice() {
|
||||
return mConfigEnableLockScreenButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if quick settings entry point for QR Code Scanner is to be enabled.
|
||||
* Returns true if the feature can open a camera app on the device.
|
||||
*/
|
||||
public boolean isEnabledForQuickSettings() {
|
||||
public boolean isAbleToOpenCameraApp() {
|
||||
return mIntent != null && isActivityCallable(mIntent);
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ public class QRCodeScannerTile extends QSTileImpl<QSTile.State> {
|
||||
state.label = mContext.getString(R.string.qr_code_scanner_title);
|
||||
state.contentDescription = state.label;
|
||||
state.icon = ResourceIcon.get(R.drawable.ic_qr_code_scanner);
|
||||
state.state = mQRCodeScannerController.isEnabledForQuickSettings() ? Tile.STATE_INACTIVE
|
||||
state.state = mQRCodeScannerController.isAbleToOpenCameraApp() ? Tile.STATE_INACTIVE
|
||||
: Tile.STATE_UNAVAILABLE;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,9 @@ import com.android.systemui.controls.controller.ControlsController
|
||||
import com.android.systemui.controls.dagger.ControlsComponent
|
||||
import com.android.systemui.controls.management.ControlsListingController
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import java.util.Optional
|
||||
import java.util.*
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
@@ -40,7 +41,6 @@ import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Captor
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
@@ -93,6 +93,14 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes
|
||||
whenever(component.getControlsController()).thenReturn(Optional.of(controlsController))
|
||||
whenever(component.getControlsListingController())
|
||||
.thenReturn(Optional.of(controlsListingController))
|
||||
whenever(controlsListingController.getCurrentServices())
|
||||
.thenReturn(
|
||||
if (hasServiceInfos) {
|
||||
listOf(mock(), mock())
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
)
|
||||
whenever(component.canShowWhileLockedSetting)
|
||||
.thenReturn(MutableStateFlow(canShowWhileLocked))
|
||||
whenever(component.getVisibility())
|
||||
@@ -144,6 +152,17 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes
|
||||
KeyguardQuickAffordanceConfig.LockScreenState.Hidden::class.java
|
||||
}
|
||||
)
|
||||
assertThat(underTest.getPickerScreenState())
|
||||
.isInstanceOf(
|
||||
when {
|
||||
!isFeatureEnabled ->
|
||||
KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice::class
|
||||
.java
|
||||
hasServiceInfos && hasFavorites ->
|
||||
KeyguardQuickAffordanceConfig.PickerScreenState.Default::class.java
|
||||
else -> KeyguardQuickAffordanceConfig.PickerScreenState.Disabled::class.java
|
||||
}
|
||||
)
|
||||
job.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,18 @@ import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanc
|
||||
import com.android.systemui.qrcodescanner.controller.QRCodeScannerController
|
||||
import com.android.systemui.util.mockito.argumentCaptor
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
@@ -134,6 +135,33 @@ class QrCodeScannerKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPickerScreenState - enabled if configured on device - can open camera`() = runTest {
|
||||
whenever(controller.isAvailableOnDevice).thenReturn(true)
|
||||
whenever(controller.isAbleToOpenCameraApp).thenReturn(true)
|
||||
|
||||
assertThat(underTest.getPickerScreenState())
|
||||
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPickerScreenState - disabled if configured on device - cannot open camera`() = runTest {
|
||||
whenever(controller.isAvailableOnDevice).thenReturn(true)
|
||||
whenever(controller.isAbleToOpenCameraApp).thenReturn(false)
|
||||
|
||||
assertThat(underTest.getPickerScreenState())
|
||||
.isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Disabled::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPickerScreenState - unavailable if not configured on device`() = runTest {
|
||||
whenever(controller.isAvailableOnDevice).thenReturn(false)
|
||||
whenever(controller.isAbleToOpenCameraApp).thenReturn(true)
|
||||
|
||||
assertThat(underTest.getPickerScreenState())
|
||||
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
|
||||
}
|
||||
|
||||
private fun assertVisibleState(latest: KeyguardQuickAffordanceConfig.LockScreenState?) {
|
||||
assertThat(latest)
|
||||
.isInstanceOf(KeyguardQuickAffordanceConfig.LockScreenState.Visible::class.java)
|
||||
|
||||
@@ -33,9 +33,11 @@ import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.android.systemui.wallet.controller.QuickAccessWalletController
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -44,6 +46,7 @@ import org.mockito.Mock
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@SmallTest
|
||||
@RunWith(JUnit4::class)
|
||||
class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
|
||||
@@ -59,7 +62,7 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
|
||||
|
||||
underTest =
|
||||
QuickAccessWalletKeyguardQuickAffordanceConfig(
|
||||
mock(),
|
||||
context,
|
||||
walletController,
|
||||
activityStarter,
|
||||
)
|
||||
@@ -151,6 +154,44 @@ class QuickAccessWalletKeyguardQuickAffordanceConfigTest : SysuiTestCase() {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPickerScreenState - default`() = runTest {
|
||||
setUpState()
|
||||
|
||||
assertThat(underTest.getPickerScreenState())
|
||||
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPickerScreenState - unavailable`() = runTest {
|
||||
setUpState(
|
||||
isWalletEnabled = false,
|
||||
)
|
||||
|
||||
assertThat(underTest.getPickerScreenState())
|
||||
.isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPickerScreenState - disabled when there is no icon`() = runTest {
|
||||
setUpState(
|
||||
hasWalletIcon = false,
|
||||
)
|
||||
|
||||
assertThat(underTest.getPickerScreenState())
|
||||
.isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Disabled::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getPickerScreenState - disabled when there is no card`() = runTest {
|
||||
setUpState(
|
||||
hasSelectedCard = false,
|
||||
)
|
||||
|
||||
assertThat(underTest.getPickerScreenState())
|
||||
.isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Disabled::class.java)
|
||||
}
|
||||
|
||||
private fun setUpState(
|
||||
isWalletEnabled: Boolean = true,
|
||||
isWalletQuerySuccessful: Boolean = true,
|
||||
|
||||
@@ -133,23 +133,24 @@ class KeyguardQuickAffordanceRepositoryTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getAffordancePickerRepresentations() {
|
||||
assertThat(underTest.getAffordancePickerRepresentations())
|
||||
.isEqualTo(
|
||||
listOf(
|
||||
KeyguardQuickAffordancePickerRepresentation(
|
||||
id = config1.key,
|
||||
name = config1.pickerName,
|
||||
iconResourceId = config1.pickerIconResourceId,
|
||||
),
|
||||
KeyguardQuickAffordancePickerRepresentation(
|
||||
id = config2.key,
|
||||
name = config2.pickerName,
|
||||
iconResourceId = config2.pickerIconResourceId,
|
||||
),
|
||||
fun getAffordancePickerRepresentations() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
assertThat(underTest.getAffordancePickerRepresentations())
|
||||
.isEqualTo(
|
||||
listOf(
|
||||
KeyguardQuickAffordancePickerRepresentation(
|
||||
id = config1.key,
|
||||
name = config1.pickerName,
|
||||
iconResourceId = config1.pickerIconResourceId,
|
||||
),
|
||||
KeyguardQuickAffordancePickerRepresentation(
|
||||
id = config2.key,
|
||||
name = config2.pickerName,
|
||||
iconResourceId = config2.pickerIconResourceId,
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getSlotPickerRepresentations() {
|
||||
|
||||
@@ -31,7 +31,6 @@ import static org.mockito.Mockito.when;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
@@ -133,7 +132,7 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
/* enableOnLockScreen */ true);
|
||||
verifyActivityDetails(null);
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isFalse();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isFalse();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -152,7 +151,7 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
/* enableOnLockScreen */ true);
|
||||
verifyActivityDetails("abc/.def");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isTrue();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -162,7 +161,7 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
/* enableOnLockScreen */ true);
|
||||
verifyActivityDetails("abc/.def");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isTrue();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -172,7 +171,7 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
/* enableOnLockScreen */ true);
|
||||
verifyActivityDetails("abc/.def");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isTrue();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -182,7 +181,7 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
/* enableOnLockScreen */ true);
|
||||
verifyActivityDetails("abc/abc.def");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isTrue();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -192,7 +191,7 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
/* enableOnLockScreen */ true);
|
||||
verifyActivityDetails(null);
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isFalse();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isFalse();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -202,21 +201,21 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
/* enableOnLockScreen */ true);
|
||||
verifyActivityDetails("abc/.def");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isTrue();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
|
||||
mProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.DEFAULT_QR_CODE_SCANNER,
|
||||
"def/.ijk", false);
|
||||
verifyActivityDetails("def/.ijk");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isTrue();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
|
||||
mProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.DEFAULT_QR_CODE_SCANNER,
|
||||
null, false);
|
||||
verifyActivityDetails("abc/.def");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isTrue();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
|
||||
// Once from setup + twice from this function
|
||||
verify(mCallback, times(3)).onQRCodeScannerActivityChanged();
|
||||
@@ -229,7 +228,7 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
/* enableOnLockScreen */ true);
|
||||
verifyActivityDetails(null);
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isFalse();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isFalse();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isFalse();
|
||||
|
||||
mProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.DEFAULT_QR_CODE_SCANNER,
|
||||
@@ -237,14 +236,14 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
|
||||
verifyActivityDetails("def/.ijk");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isTrue();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
|
||||
mProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.DEFAULT_QR_CODE_SCANNER,
|
||||
null, false);
|
||||
verifyActivityDetails(null);
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isFalse();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isFalse();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isFalse();
|
||||
verify(mCallback, times(2)).onQRCodeScannerActivityChanged();
|
||||
}
|
||||
|
||||
@@ -296,19 +295,19 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
/* enableOnLockScreen */ true);
|
||||
verifyActivityDetails("abc/.def");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isTrue();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
|
||||
mSecureSettings.putStringForUser(LOCK_SCREEN_SHOW_QR_CODE_SCANNER, "0",
|
||||
UserHandle.USER_CURRENT);
|
||||
verifyActivityDetails("abc/.def");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isFalse();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
|
||||
mSecureSettings.putStringForUser(LOCK_SCREEN_SHOW_QR_CODE_SCANNER, "1",
|
||||
UserHandle.USER_CURRENT);
|
||||
verifyActivityDetails("abc/.def");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isTrue();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
// Once from setup + twice from this function
|
||||
verify(mCallback, times(3)).onQRCodeScannerPreferenceChanged();
|
||||
}
|
||||
@@ -320,13 +319,13 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
/* enableOnLockScreen */ true);
|
||||
verifyActivityDetails("abc/.def");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isTrue();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
|
||||
mController.unregisterQRCodeScannerChangeObservers(DEFAULT_QR_CODE_SCANNER_CHANGE,
|
||||
QR_CODE_SCANNER_PREFERENCE_CHANGE);
|
||||
verifyActivityDetails(null);
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isFalse();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isFalse();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isFalse();
|
||||
|
||||
// Unregister once again and make sure it affects the next register event
|
||||
mController.unregisterQRCodeScannerChangeObservers(DEFAULT_QR_CODE_SCANNER_CHANGE,
|
||||
@@ -335,7 +334,7 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
QR_CODE_SCANNER_PREFERENCE_CHANGE);
|
||||
verifyActivityDetails("abc/.def");
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isTrue();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -345,7 +344,7 @@ public class QRCodeScannerControllerTest extends SysuiTestCase {
|
||||
/* enableOnLockScreen */ false);
|
||||
assertThat(mController.getIntent()).isNotNull();
|
||||
assertThat(mController.isEnabledForLockScreenButton()).isFalse();
|
||||
assertThat(mController.isEnabledForQuickSettings()).isTrue();
|
||||
assertThat(mController.isAbleToOpenCameraApp()).isTrue();
|
||||
assertThat(getSettingsQRCodeDefaultComponent()).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ public class QRCodeScannerTileTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testQRCodeTileUnavailable() {
|
||||
when(mController.isEnabledForQuickSettings()).thenReturn(false);
|
||||
when(mController.isAbleToOpenCameraApp()).thenReturn(false);
|
||||
QSTile.State state = new QSTile.State();
|
||||
mTile.handleUpdateState(state, null);
|
||||
assertEquals(state.state, Tile.STATE_UNAVAILABLE);
|
||||
@@ -116,7 +116,7 @@ public class QRCodeScannerTileTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testQRCodeTileAvailable() {
|
||||
when(mController.isEnabledForQuickSettings()).thenReturn(true);
|
||||
when(mController.isAbleToOpenCameraApp()).thenReturn(true);
|
||||
QSTile.State state = new QSTile.State();
|
||||
mTile.handleUpdateState(state, null);
|
||||
assertEquals(state.state, Tile.STATE_INACTIVE);
|
||||
|
||||
Reference in New Issue
Block a user