Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58e33aa4 authored by Arpan Kaphle's avatar Arpan Kaphle Committed by Arpan
Browse files

Get Flow States, Conversion, and Biometric

Given the tight deadline, I've merged 4 previously already scoped out
bugs into one CL. For the Get flow, here's what we have in this CL:

1. We handle the state management for the Get Flow. That involves
   editing the [GetModel] and using those values within the
[GetCredentialComponents] as well as within the [ViewModel] and the
[Repo]. The conditionals for when the flows happen were clarified.

2. We handle the UI for the Get Flow - this involves setting up a
   composable within the [GetCredentialComponents] that calls into the
[BiometricHandler] to launch the Biometric API with default values.

3. We then specify the default values to be properly parsed within the
   [BiometricHandler]. This involves ensuring conditionals are correct,
and pulling the right dynamic objects from the flow that contain the
necessary information.

4. Finally, while this is still NOT callable from any flows in practice,
   the conversion from the input was clarified (but always set to
'false') within the [CredentialKtx]. This will be further iterated with
slice based flows as we continue checking in code (or, the team may
decide to suggest addition in this immediate bug).

Bug: 327621520
Bug: 327620300
Bug: 327619284
Bug: 327620327
Test: Unit Tests will follow, and b/326243754 will contain manual tests
Change-Id: Ib42c1f7fb95c7d8ef776416a1e9131b6e9d73d29
parent ca993002
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -22,7 +22,9 @@
    <uses-permission android:name="android.permission.LAUNCH_CREDENTIAL_SELECTOR"/>
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
    <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"/>
    <uses-permission android:name="android.permission.SET_BIOMETRIC_DIALOG_ADVANCED"/>
    <uses-permission android:name="android.permission.ACCESS_INSTANT_APPS" />
    <uses-permission android:name="android.permission.USE_BIOMETRIC" />

    <application
        android:allowBackup="true"
+5 −3
Original line number Diff line number Diff line
@@ -63,11 +63,11 @@
  <!-- This appears as the description body of the modal bottom sheet which provides all available providers for users to choose. [CHAR LIMIT=200] -->
  <string name="choose_provider_body">Select a password manager to save your info and sign in faster next time</string>
  <!-- This appears as the title of the modal bottom sheet for users to choose the create option inside a provider when the credential type is passkey. [CHAR LIMIT=200] -->
  <string name="choose_create_option_passkey_title">Create passkey to sign in to <xliff:g id="appName" example="Tribank">%1$s</xliff:g>?</string>
  <string name="choose_create_option_passkey_title">Create passkey to sign in to <xliff:g id="app_name" example="Tribank">%1$s</xliff:g>?</string>
  <!-- This appears as the title of the modal bottom sheet for users to choose the create option inside a provider when the credential type is password. [CHAR LIMIT=200] -->
  <string name="choose_create_option_password_title">Save password to sign in to <xliff:g id="appName" example="Tribank">%1$s</xliff:g>?</string>
  <string name="choose_create_option_password_title">Save password to sign in to <xliff:g id="app_name" example="Tribank">%1$s</xliff:g>?</string>
  <!-- This appears as the title of the modal bottom sheet for users to choose the create option inside a provider when the credential type is others. [CHAR LIMIT=200] -->
  <string name="choose_create_option_sign_in_title">Save sign-in info for <xliff:g id="appName" example="Tribank">%1$s</xliff:g>?</string>
  <string name="choose_create_option_sign_in_title">Save sign-in info for <xliff:g id="app_name" example="Tribank">%1$s</xliff:g>?</string>
  <!-- Types which are inserted as a placeholder as credentialTypes for other strings. [CHAR LIMIT=200] -->
  <string name="passkey">passkey</string>
  <string name="password">password</string>
@@ -122,6 +122,8 @@
  <string name="get_dialog_title_use_passkey_for">Use your saved passkey for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
  <!-- This appears as the title of the modal bottom sheet asking for user confirmation to use the single previously saved password to sign in to the app. [CHAR LIMIT=200] -->
  <string name="get_dialog_title_use_password_for">Use your saved password for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
  <!-- This appears as a description of the modal bottom sheet when the single tap sign in flow is used for the get flow. [CHAR LIMIT=200] -->
  <string name="get_dialog_title_single_tap_for">Use your screen lock to sign in to <xliff:g id="app_name" example="Shrine">%1$s</xliff:g> with <xliff:g id="username" example="beckett-bakery@gmail.com">%2$s</xliff:g></string>
  <!-- This appears as the title of the dialog asking for user confirmation to use the single user credential (previously saved or to be created) to sign in to the app. [CHAR LIMIT=200] -->
  <string name="get_dialog_title_use_sign_in_for">Use your sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
  <!-- This appears as the title of the dialog asking for user confirmation to unlock / authenticate (e.g. via fingerprint, faceId, passcode etc.) so that we can retrieve their sign-in options. [CHAR LIMIT=200] -->
+5 −0
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ private fun getCredentialOptionInfoList(
                    isDefaultIconPreferredAsSingleProvider =
                            credentialEntry.isDefaultIconPreferredAsSingleProvider,
                    affiliatedDomain = credentialEntry.affiliatedDomain?.toString(),
                    isSupportingSingleTap = false, // TODO(b/326243754) : Fill in as product built
                )
                )
            }
@@ -167,6 +168,7 @@ private fun getCredentialOptionInfoList(
                    isDefaultIconPreferredAsSingleProvider =
                            credentialEntry.isDefaultIconPreferredAsSingleProvider,
                    affiliatedDomain = credentialEntry.affiliatedDomain?.toString(),
                    isSupportingSingleTap = false, // TODO(b/326243754) : Fill in as product built
                )
                )
            }
@@ -194,6 +196,9 @@ private fun getCredentialOptionInfoList(
                    isDefaultIconPreferredAsSingleProvider =
                            credentialEntry.isDefaultIconPreferredAsSingleProvider,
                    affiliatedDomain = credentialEntry.affiliatedDomain?.toString(),
                    isSupportingSingleTap = false, // TODO(b/326243754) : Fill in as product built
                    // TODO(b/326243754) : If required info above is missing, force condition to
                    // false.
                )
                )
            }
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ class CredentialEntryInfo(
                              // "For <value-of-entryGroupId>" on the more-option screen.
    val isDefaultIconPreferredAsSingleProvider: Boolean,
    val affiliatedDomain: String?,
    val isSupportingSingleTap: Boolean,
) : EntryInfo(
    providerId,
    entryKey,
+10 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.credentialmanager

import android.app.Activity
import android.hardware.biometrics.BiometricPrompt
import android.os.IBinder
import android.text.TextUtils
import android.util.Log
@@ -28,6 +29,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import com.android.credentialmanager.common.BiometricState
import com.android.credentialmanager.model.EntryInfo
import com.android.credentialmanager.common.Constants
import com.android.credentialmanager.common.DialogState
@@ -54,6 +56,7 @@ data class UiState(
    val isAutoSelectFlow: Boolean = false,
    val cancelRequestState: CancelUiRequestState?,
    val isInitialRender: Boolean,
    val biometricState: BiometricState? = null
)

data class CancelUiRequestState(
@@ -200,13 +203,19 @@ class CredentialSelectorViewModel(
    /**************************************************************************/
    /*****                      Get Flow Callbacks                        *****/
    /**************************************************************************/
    fun getFlowOnEntrySelected(entry: EntryInfo) {
    fun getFlowOnEntrySelected(
        entry: EntryInfo,
        authResult: BiometricPrompt.AuthenticationResult? = null
    ) {
        Log.d(Constants.LOG_TAG, "credential selected: {provider=${entry.providerId}" +
            ", key=${entry.entryKey}, subkey=${entry.entrySubkey}}")
        uiState = if (entry.pendingIntent != null) {
            uiState.copy(
                selectedEntry = entry,
                providerActivityState = ProviderActivityState.READY_TO_LAUNCH,
                biometricState = uiState.biometricState?.copy(
                    biometricAuthenticationResult = authResult
                )
            )
        } else {
            credManRepo.onOptionSelected(entry.providerId, entry.entryKey, entry.entrySubkey)
Loading