diff options
| author | 2023-05-09 10:40:35 +0000 | |
|---|---|---|
| committer | 2023-05-09 10:40:35 +0000 | |
| commit | 138d4601d1ba3bcdaee4c81bcdf4b7543e4720db (patch) | |
| tree | 4d7b4cf1aaf89f457fd14ff4e61b6adea0e499c0 | |
| parent | 41fb0a688ac51875760f997d137a8fa974b109f3 (diff) | |
| parent | cc339e22e98eb58f6eae2c226212dc0948929c2f (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>
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, ) } |