summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2023-05-09 10:40:35 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2023-05-09 10:40:35 +0000
commit138d4601d1ba3bcdaee4c81bcdf4b7543e4720db (patch)
tree4d7b4cf1aaf89f457fd14ff4e61b6adea0e499c0
parent41fb0a688ac51875760f997d137a8fa974b109f3 (diff)
parentcc339e22e98eb58f6eae2c226212dc0948929c2f (diff)
Merge "Support autoselect for create flows." into udc-dev am: fcdac40e64 am: cc339e22e9
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23089737 Change-Id: I78a81af5fb1ac37748f492d4787677a010fcd897 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt32
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt36
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt15
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt6
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt1
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt18
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt1
7 files changed, 81 insertions, 28 deletions
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index 78ee81921f25..c85ffd459bd8 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -38,6 +38,7 @@ import com.android.credentialmanager.createflow.RequestDisplayInfo
import com.android.credentialmanager.getflow.GetCredentialUiState
import com.android.credentialmanager.getflow.findAutoSelectEntry
import com.android.credentialmanager.common.ProviderActivityState
+import com.android.credentialmanager.createflow.isFlowAutoSelectable
/**
* Client for interacting with Credential Manager. Also holds data inputs from it.
@@ -113,21 +114,30 @@ class CredentialManagerRepo(
val providerDisableListUiState = getCreateProviderDisableListInitialUiState()
val requestDisplayInfoUiState =
getCreateRequestDisplayInfoInitialUiState(originName)!!
+ val createCredentialUiState = CreateFlowUtils.toCreateCredentialUiState(
+ enabledProviders = providerEnableListUiState,
+ disabledProviders = providerDisableListUiState,
+ defaultProviderIdPreferredByApp =
+ requestDisplayInfoUiState.appPreferredDefaultProviderId,
+ defaultProviderIdsSetByUser =
+ requestDisplayInfoUiState.userSetDefaultProviderIds,
+ requestDisplayInfo = requestDisplayInfoUiState,
+ isOnPasskeyIntroStateAlready = false,
+ isPasskeyFirstUse = isPasskeyFirstUse,
+ )!!
+ val isFlowAutoSelectable = isFlowAutoSelectable(createCredentialUiState)
UiState(
- createCredentialUiState = CreateFlowUtils.toCreateCredentialUiState(
- enabledProviders = providerEnableListUiState,
- disabledProviders = providerDisableListUiState,
- defaultProviderIdPreferredByApp =
- requestDisplayInfoUiState.appPreferredDefaultProviderId,
- defaultProviderIdsSetByUser =
- requestDisplayInfoUiState.userSetDefaultProviderIds,
- requestDisplayInfo = requestDisplayInfoUiState,
- isOnPasskeyIntroStateAlready = false,
- isPasskeyFirstUse = isPasskeyFirstUse,
- )!!,
+ createCredentialUiState = createCredentialUiState,
getCredentialUiState = null,
cancelRequestState = cancelUiRequestState,
isInitialRender = isNewActivity,
+ isAutoSelectFlow = isFlowAutoSelectable,
+ providerActivityState =
+ if (isFlowAutoSelectable) ProviderActivityState.READY_TO_LAUNCH
+ else ProviderActivityState.NOT_APPLICABLE,
+ selectedEntry =
+ if (isFlowAutoSelectable) createCredentialUiState.activeEntry?.activeEntryInfo
+ else null,
)
}
RequestInfo.TYPE_GET -> {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
index e96e536c00d5..3aa8a6c327fa 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
@@ -34,6 +34,7 @@ import com.android.credentialmanager.common.DialogState
import com.android.credentialmanager.common.ProviderActivityResult
import com.android.credentialmanager.common.ProviderActivityState
import com.android.credentialmanager.createflow.ActiveEntry
+import com.android.credentialmanager.createflow.isFlowAutoSelectable
import com.android.credentialmanager.createflow.CreateCredentialUiState
import com.android.credentialmanager.createflow.CreateScreenState
import com.android.credentialmanager.getflow.GetCredentialUiState
@@ -262,30 +263,39 @@ class CredentialSelectorViewModel(
/***** Create Flow Callbacks *****/
/**************************************************************************/
fun createFlowOnConfirmIntro() {
+ userConfigRepo.setIsPasskeyFirstUse(false)
val prevUiState = uiState.createCredentialUiState
if (prevUiState == null) {
Log.d(Constants.LOG_TAG, "Encountered unexpected null create ui state")
onInternalError()
return
}
- val newUiState = CreateFlowUtils.toCreateCredentialUiState(
- enabledProviders = prevUiState.enabledProviders,
- disabledProviders = prevUiState.disabledProviders,
- defaultProviderIdPreferredByApp =
- prevUiState.requestDisplayInfo.appPreferredDefaultProviderId,
- defaultProviderIdsSetByUser =
- prevUiState.requestDisplayInfo.userSetDefaultProviderIds,
- requestDisplayInfo = prevUiState.requestDisplayInfo,
+ val newScreenState = CreateFlowUtils.toCreateScreenState(
+ createOptionSize = prevUiState.sortedCreateOptionsPairs.size,
isOnPasskeyIntroStateAlready = true,
- isPasskeyFirstUse = userConfigRepo.getIsPasskeyFirstUse()
+ requestDisplayInfo = prevUiState.requestDisplayInfo,
+ remoteEntry = prevUiState.remoteEntry,
+ isPasskeyFirstUse = true,
)
- if (newUiState == null) {
- Log.d(Constants.LOG_TAG, "Unable to update create ui state")
+ if (newScreenState == null) {
+ Log.d(Constants.LOG_TAG, "Unexpected: couldn't resolve new screen state")
onInternalError()
return
}
- uiState = uiState.copy(createCredentialUiState = newUiState)
- userConfigRepo.setIsPasskeyFirstUse(false)
+ val newCreateCredentialUiState = prevUiState.copy(
+ currentScreenState = newScreenState,
+ )
+ val isFlowAutoSelectable = isFlowAutoSelectable(newCreateCredentialUiState)
+ uiState = uiState.copy(
+ createCredentialUiState = newCreateCredentialUiState,
+ isAutoSelectFlow = isFlowAutoSelectable,
+ providerActivityState =
+ if (isFlowAutoSelectable) ProviderActivityState.READY_TO_LAUNCH
+ else ProviderActivityState.NOT_APPLICABLE,
+ selectedEntry =
+ if (isFlowAutoSelectable) newCreateCredentialUiState.activeEntry?.activeEntryInfo
+ else null,
+ )
}
fun createFlowOnMoreOptionsSelectedOnCreationSelection() {
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index ba20a5e779fd..c64ebda2eb5c 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -487,6 +487,7 @@ class CreateFlowUtils {
createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
appPreferredDefaultProviderId = appPreferredDefaultProviderId,
userSetDefaultProviderIds = requestInfo.defaultProviderIds.toSet(),
+ isAutoSelectRequest = createCredentialRequestJetpack.isAutoSelectAllowed,
)
is CreatePublicKeyCredentialRequest -> {
newRequestDisplayInfoFromPasskeyJson(
@@ -497,6 +498,7 @@ class CreateFlowUtils {
createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
appPreferredDefaultProviderId = appPreferredDefaultProviderId,
userSetDefaultProviderIds = requestInfo.defaultProviderIds.toSet(),
+ isAutoSelectRequest = createCredentialRequestJetpack.isAutoSelectAllowed,
)
}
is CreateCustomCredentialRequest -> {
@@ -515,6 +517,7 @@ class CreateFlowUtils {
createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
appPreferredDefaultProviderId = appPreferredDefaultProviderId,
userSetDefaultProviderIds = requestInfo.defaultProviderIds.toSet(),
+ isAutoSelectRequest = createCredentialRequestJetpack.isAutoSelectAllowed,
)
}
else -> null
@@ -602,7 +605,7 @@ class CreateFlowUtils {
)
}
- private fun toCreateScreenState(
+ fun toCreateScreenState(
createOptionSize: Int,
isOnPasskeyIntroStateAlready: Boolean,
requestDisplayInfo: RequestDisplayInfo,
@@ -662,7 +665,13 @@ class CreateFlowUtils {
passkeyCount = createEntry.getPublicKeyCredentialCount(),
totalCredentialCount = createEntry.getTotalCredentialCount(),
lastUsedTime = createEntry.lastUsedTime ?: Instant.MIN,
- footerDescription = createEntry.description?.toString()
+ footerDescription = createEntry.description?.toString(),
+ // TODO(b/281065680): replace with official library constant once available
+ allowAutoSelect =
+ it.slice.items.firstOrNull {
+ it.hasHint("androidx.credentials.provider.createEntry.SLICE_HINT_AUTO_" +
+ "SELECT_ALLOWED")
+ }?.text == "true",
))
}
return result.sortedWith(
@@ -694,6 +703,7 @@ class CreateFlowUtils {
preferImmediatelyAvailableCredentials: Boolean,
appPreferredDefaultProviderId: String?,
userSetDefaultProviderIds: Set<String>,
+ isAutoSelectRequest: Boolean
): RequestDisplayInfo? {
val json = JSONObject(requestJson)
var passkeyUsername = ""
@@ -716,6 +726,7 @@ class CreateFlowUtils {
preferImmediatelyAvailableCredentials,
appPreferredDefaultProviderId,
userSetDefaultProviderIds,
+ isAutoSelectRequest,
)
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
index bd4375f4513e..a5998faa68ad 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/BottomSheet.kt
@@ -39,14 +39,16 @@ fun ModalBottomSheet(
onDismiss: () -> Unit,
isInitialRender: Boolean,
onInitialRenderComplete: () -> Unit,
+ isAutoSelectFlow: Boolean,
) {
val scope = rememberCoroutineScope()
val state = rememberModalBottomSheetState(
- initialValue = ModalBottomSheetValue.Hidden,
+ initialValue = if (isAutoSelectFlow) ModalBottomSheetValue.Expanded
+ else ModalBottomSheetValue.Hidden,
skipHalfExpanded = true
)
val sysUiController = rememberSystemUiController()
- if (state.targetValue == ModalBottomSheetValue.Hidden) {
+ if (state.targetValue == ModalBottomSheetValue.Hidden || isAutoSelectFlow) {
setTransparentSystemBarsColor(sysUiController)
} else {
setBottomSheetSystemBarsColor(sysUiController)
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index a378f1c16753..a3087cf8004c 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -166,6 +166,7 @@ fun CreateCredentialScreen(
},
onDismiss = viewModel::onUserCancel,
isInitialRender = viewModel.uiState.isInitialRender,
+ isAutoSelectFlow = viewModel.uiState.isAutoSelectFlow,
onInitialRenderComplete = viewModel::onInitialRenderComplete,
)
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
index 8f3f3c87d93c..cf7a943f2c66 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
@@ -34,6 +34,21 @@ data class CreateCredentialUiState(
val foundCandidateFromUserDefaultProvider: Boolean,
)
+internal fun isFlowAutoSelectable(
+ uiState: CreateCredentialUiState
+): Boolean {
+ return uiState.requestDisplayInfo.isAutoSelectRequest &&
+ // Even if the flow is auto selectable, still allow passkey intro screen to show once if
+ // applicable.
+ uiState.currentScreenState != CreateScreenState.PASSKEY_INTRO &&
+ uiState.currentScreenState != CreateScreenState.MORE_ABOUT_PASSKEYS_INTRO &&
+ uiState.remoteEntry == null &&
+ uiState.sortedCreateOptionsPairs.size == 1 &&
+ uiState.activeEntry?.activeEntryInfo?.let {
+ it is CreateOptionInfo && it.allowAutoSelect
+ } ?: false
+}
+
internal fun hasContentToDisplay(state: CreateCredentialUiState): Boolean {
return state.sortedCreateOptionsPairs.isNotEmpty() ||
(!state.requestDisplayInfo.preferImmediatelyAvailableCredentials &&
@@ -74,6 +89,7 @@ class CreateOptionInfo(
val totalCredentialCount: Int?,
val lastUsedTime: Instant,
val footerDescription: String?,
+ val allowAutoSelect: Boolean,
) : BaseEntry(
providerId,
entryKey,
@@ -107,6 +123,8 @@ data class RequestDisplayInfo(
val preferImmediatelyAvailableCredentials: Boolean,
val appPreferredDefaultProviderId: String?,
val userSetDefaultProviderIds: Set<String>,
+ // Whether the given CreateCredentialRequest allows auto select.
+ val isAutoSelectRequest: Boolean,
)
/**
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index 40c99ee07d69..4183a5211556 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -149,6 +149,7 @@ fun GetCredentialScreen(
},
onDismiss = viewModel::onUserCancel,
isInitialRender = viewModel.uiState.isInitialRender,
+ isAutoSelectFlow = viewModel.uiState.isAutoSelectFlow,
onInitialRenderComplete = viewModel::onInitialRenderComplete,
)
}