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

Commit d458675f authored by Arpan Kaphle's avatar Arpan Kaphle Committed by Android (Google) Code Review
Browse files

Merge changes from topic "getFlow_bio" into main

* changes:
  Communicate Get Flow Biometric Success to Provider
  Get Flow States, Conversion, and Biometric
parents b231a189 19033e95
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
    <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.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] -->
+34 −1
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import com.android.credentialmanager.model.get.ProviderInfo
import com.android.credentialmanager.model.get.RemoteEntryInfo
import com.android.credentialmanager.shared.R
import com.android.credentialmanager.TAG
import com.android.credentialmanager.model.BiometricRequestInfo
import com.android.credentialmanager.model.EntryInfo

fun EntryInfo.getIntentSenderRequest(
@@ -139,6 +140,7 @@ private fun getCredentialOptionInfoList(
                    isDefaultIconPreferredAsSingleProvider =
                            credentialEntry.isDefaultIconPreferredAsSingleProvider,
                    affiliatedDomain = credentialEntry.affiliatedDomain?.toString(),
                    biometricRequest = predetermineAndValidateBiometricFlow(it),
                )
                )
            }
@@ -167,6 +169,7 @@ private fun getCredentialOptionInfoList(
                    isDefaultIconPreferredAsSingleProvider =
                            credentialEntry.isDefaultIconPreferredAsSingleProvider,
                    affiliatedDomain = credentialEntry.affiliatedDomain?.toString(),
                    biometricRequest = predetermineAndValidateBiometricFlow(it),
                )
                )
            }
@@ -194,6 +197,7 @@ private fun getCredentialOptionInfoList(
                    isDefaultIconPreferredAsSingleProvider =
                            credentialEntry.isDefaultIconPreferredAsSingleProvider,
                    affiliatedDomain = credentialEntry.affiliatedDomain?.toString(),
                    biometricRequest = predetermineAndValidateBiometricFlow(it),
                )
                )
            }
@@ -205,6 +209,36 @@ private fun getCredentialOptionInfoList(
    }
    return result
}

/**
 * This validates if this is a biometric flow or not, and if it is, this returns the expected
 * [BiometricRequestInfo]. Namely, the biometric flow must have at least the
 * ALLOWED_AUTHENTICATORS bit passed from Jetpack.
 * Note that the required values, such as the provider info's icon or display name, or the entries
 * credential type or userName, and finally the display info's app name, are non-null and must
 * exist to run through the flow.
 * // TODO(b/326243754) : Presently, due to dependencies, the opId bit is parsed but is never
 * // expected to be used. When it is added, it should be lightly validated.
 */
private fun predetermineAndValidateBiometricFlow(
    it: Entry
): BiometricRequestInfo? {
    // TODO(b/326243754) : When available, use the official jetpack structured type
    val allowedAuthenticators: Int? = it.slice.items.firstOrNull {
        it.hasHint("androidx.credentials." +
                "provider.credentialEntry.SLICE_HINT_ALLOWED_AUTHENTICATORS")
    }?.int

    // This is optional and does not affect validating the biometric flow in any case
    val opId: Int? = it.slice.items.firstOrNull {
        it.hasHint("androidx.credentials.provider.credentialEntry.SLICE_HINT_CRYPTO_OP_ID")
    }?.int
    if (allowedAuthenticators != null) {
        return BiometricRequestInfo(opId = opId, allowedAuthenticators = allowedAuthenticators)
    }
    return null
}

val Slice.credentialEntry: CredentialEntry?
    get() =
        try {
@@ -221,7 +255,6 @@ val Slice.credentialEntry: CredentialEntry?
            CustomCredentialEntry.fromSlice(this)
        }


/**
 * Note: caller required handle empty list due to parsing error.
 */
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.credentialmanager.model

/**
 * This allows reading the data from the request, and holding that state around the framework.
 * The [opId] bit is required for some authentication flows where CryptoObjects are used.
 * The [allowedAuthenticators] is needed for all flows, and our flow ensures this value is never
 * null.
 */
data class BiometricRequestInfo(
    val opId: Int? = null,
    val allowedAuthenticators: Int
)
 No newline at end of file
+2 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.credentialmanager.model.creation
import android.app.PendingIntent
import android.content.Intent
import android.graphics.drawable.Drawable
import com.android.credentialmanager.model.BiometricRequestInfo
import com.android.credentialmanager.model.EntryInfo
import java.time.Instant

@@ -36,6 +37,7 @@ class CreateOptionInfo(
    val lastUsedTime: Instant,
    val footerDescription: String?,
    val allowAutoSelect: Boolean,
    val biometricRequest: BiometricRequestInfo? = null,
) : EntryInfo(
    providerId,
    entryKey,
Loading