Loading packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt +20 −14 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.credentials.selection.AuthenticationEntry import android.credentials.selection.Entry import android.credentials.selection.GetCredentialProviderData import android.graphics.drawable.Drawable import android.os.Bundle import android.text.TextUtils import android.util.Log import androidx.activity.result.IntentSenderRequest Loading Loading @@ -227,27 +228,32 @@ private fun getCredentialOptionInfoList( * and get flows utilize slice params; includes the final '.' before the name of the type (e.g. * androidx.credentials.provider.credentialEntry.SLICE_HINT_ALLOWED_AUTHENTICATORS must have * 'hintPrefix' up to "androidx.credentials.provider.credentialEntry.") * // 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. */ fun retrieveEntryBiometricRequest( entry: Entry, hintPrefix: String, hintPrefix: String ): BiometricRequestInfo? { // TODO(b/326243754) : When available, use the official jetpack structured type val allowedAuthenticators: Int? = entry.slice.items.firstOrNull { it.hasHint(hintPrefix + "SLICE_HINT_ALLOWED_AUTHENTICATORS") }?.int // TODO(b/326243754) : When available, use the official jetpack structured typLo val biometricPromptDataBundleKey = "SLICE_HINT_BIOMETRIC_PROMPT_DATA" val biometricPromptDataBundle: Bundle = entry.slice.items.firstOrNull { it.hasHint(hintPrefix + biometricPromptDataBundleKey) }?.bundle ?: return null val allowedAuthConstantKey = "androidx.credentials.provider.BUNDLE_HINT_ALLOWED_AUTHENTICATORS" val cryptoOpIdKey = "androidx.credentials.provider.BUNDLE_HINT_CRYPTO_OP_ID" if (!biometricPromptDataBundle.containsKey(allowedAuthConstantKey)) { return null } val allowedAuthenticators: Int = biometricPromptDataBundle.getInt(allowedAuthConstantKey) // This is optional and does not affect validating the biometric flow in any case val opId: Int? = entry.slice.items.firstOrNull { it.hasHint(hintPrefix + "SLICE_HINT_CRYPTO_OP_ID") }?.int if (allowedAuthenticators != null) { val opId: Long? = if (biometricPromptDataBundle.containsKey(cryptoOpIdKey)) biometricPromptDataBundle.getLong(cryptoOpIdKey) else null return BiometricRequestInfo(opId = opId, allowedAuthenticators = allowedAuthenticators) } return null } val Slice.credentialEntry: CredentialEntry? get() = Loading packages/CredentialManager/shared/src/com/android/credentialmanager/model/BiometricRequestInfo.kt +1 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,6 @@ package com.android.credentialmanager.model * null. */ data class BiometricRequestInfo( val opId: Int? = null, val opId: Long? = null, val allowedAuthenticators: Int ) No newline at end of file packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt +3 −1 Original line number Diff line number Diff line Loading @@ -135,16 +135,18 @@ class CredentialSelectorViewModel( Log.w(Constants.LOG_TAG, "Unexpected biometric result exists when " + "autoSelect is preferred.") } // TODO(b/333445754) : Decide whether to propagate info on prompt launch // TODO(b/333445754) : Change the fm option to false in qpr after discussion if (biometricState.biometricResult != null) { entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_RESULT, biometricState.biometricResult.biometricAuthenticationResult .authenticationType) entryIntent?.putExtra(Constants.BIOMETRIC_FRAMEWORK_OPTION, true) } else if (biometricState.biometricError != null){ entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_ERROR_CODE, biometricState.biometricError.errorCode) entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_ERROR_MESSAGE, biometricState.biometricError.errorMessage) entryIntent?.putExtra(Constants.BIOMETRIC_FRAMEWORK_OPTION, true) } } val intentSenderRequest = IntentSenderRequest.Builder(pendingIntent) Loading packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt +2 −2 Original line number Diff line number Diff line Loading @@ -230,7 +230,7 @@ private fun runBiometricFlow( val cryptoOpId = getCryptoOpId(biometricDisplayInfo) if (cryptoOpId != null) { biometricPrompt.authenticate( BiometricPrompt.CryptoObject(cryptoOpId.toLong()), BiometricPrompt.CryptoObject(cryptoOpId), cancellationSignal, executor, callback) } else { biometricPrompt.authenticate(cancellationSignal, executor, callback) Loading @@ -243,7 +243,7 @@ private fun runBiometricFlow( return true } private fun getCryptoOpId(biometricDisplayInfo: BiometricDisplayInfo): Int? { private fun getCryptoOpId(biometricDisplayInfo: BiometricDisplayInfo): Long? { return biometricDisplayInfo.biometricRequestInfo.opId } Loading packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt +7 −4 Original line number Diff line number Diff line Loading @@ -22,9 +22,12 @@ class Constants { const val BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS = "androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED" const val IS_AUTO_SELECTED_KEY = "IS_AUTO_SELECTED" // TODO(b/333445772) : Qualify error codes fully for propagation const val BIOMETRIC_AUTH_RESULT = "BIOMETRIC_AUTH_RESULT" const val BIOMETRIC_AUTH_ERROR_CODE = "BIOMETRIC_AUTH_ERROR_CODE" const val BIOMETRIC_AUTH_ERROR_MESSAGE = "BIOMETRIC_AUTH_ERROR_MESSAGE" const val BIOMETRIC_AUTH_RESULT = "androidx.credentials.provider.BIOMETRIC_AUTH_RESULT" const val BIOMETRIC_AUTH_ERROR_CODE = "androidx.credentials.provider.BIOMETRIC_AUTH_ERROR_CODE" const val BIOMETRIC_AUTH_ERROR_MESSAGE = "androidx.credentials.provider.BIOMETRIC_AUTH_ERROR_MESSAGE" const val BIOMETRIC_FRAMEWORK_OPTION = "androidx.credentials.provider.BIOMETRIC_FRAMEWORK_OPTION" } } Loading
packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt +20 −14 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.credentials.selection.AuthenticationEntry import android.credentials.selection.Entry import android.credentials.selection.GetCredentialProviderData import android.graphics.drawable.Drawable import android.os.Bundle import android.text.TextUtils import android.util.Log import androidx.activity.result.IntentSenderRequest Loading Loading @@ -227,27 +228,32 @@ private fun getCredentialOptionInfoList( * and get flows utilize slice params; includes the final '.' before the name of the type (e.g. * androidx.credentials.provider.credentialEntry.SLICE_HINT_ALLOWED_AUTHENTICATORS must have * 'hintPrefix' up to "androidx.credentials.provider.credentialEntry.") * // 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. */ fun retrieveEntryBiometricRequest( entry: Entry, hintPrefix: String, hintPrefix: String ): BiometricRequestInfo? { // TODO(b/326243754) : When available, use the official jetpack structured type val allowedAuthenticators: Int? = entry.slice.items.firstOrNull { it.hasHint(hintPrefix + "SLICE_HINT_ALLOWED_AUTHENTICATORS") }?.int // TODO(b/326243754) : When available, use the official jetpack structured typLo val biometricPromptDataBundleKey = "SLICE_HINT_BIOMETRIC_PROMPT_DATA" val biometricPromptDataBundle: Bundle = entry.slice.items.firstOrNull { it.hasHint(hintPrefix + biometricPromptDataBundleKey) }?.bundle ?: return null val allowedAuthConstantKey = "androidx.credentials.provider.BUNDLE_HINT_ALLOWED_AUTHENTICATORS" val cryptoOpIdKey = "androidx.credentials.provider.BUNDLE_HINT_CRYPTO_OP_ID" if (!biometricPromptDataBundle.containsKey(allowedAuthConstantKey)) { return null } val allowedAuthenticators: Int = biometricPromptDataBundle.getInt(allowedAuthConstantKey) // This is optional and does not affect validating the biometric flow in any case val opId: Int? = entry.slice.items.firstOrNull { it.hasHint(hintPrefix + "SLICE_HINT_CRYPTO_OP_ID") }?.int if (allowedAuthenticators != null) { val opId: Long? = if (biometricPromptDataBundle.containsKey(cryptoOpIdKey)) biometricPromptDataBundle.getLong(cryptoOpIdKey) else null return BiometricRequestInfo(opId = opId, allowedAuthenticators = allowedAuthenticators) } return null } val Slice.credentialEntry: CredentialEntry? get() = Loading
packages/CredentialManager/shared/src/com/android/credentialmanager/model/BiometricRequestInfo.kt +1 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,6 @@ package com.android.credentialmanager.model * null. */ data class BiometricRequestInfo( val opId: Int? = null, val opId: Long? = null, val allowedAuthenticators: Int ) No newline at end of file
packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt +3 −1 Original line number Diff line number Diff line Loading @@ -135,16 +135,18 @@ class CredentialSelectorViewModel( Log.w(Constants.LOG_TAG, "Unexpected biometric result exists when " + "autoSelect is preferred.") } // TODO(b/333445754) : Decide whether to propagate info on prompt launch // TODO(b/333445754) : Change the fm option to false in qpr after discussion if (biometricState.biometricResult != null) { entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_RESULT, biometricState.biometricResult.biometricAuthenticationResult .authenticationType) entryIntent?.putExtra(Constants.BIOMETRIC_FRAMEWORK_OPTION, true) } else if (biometricState.biometricError != null){ entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_ERROR_CODE, biometricState.biometricError.errorCode) entryIntent?.putExtra(Constants.BIOMETRIC_AUTH_ERROR_MESSAGE, biometricState.biometricError.errorMessage) entryIntent?.putExtra(Constants.BIOMETRIC_FRAMEWORK_OPTION, true) } } val intentSenderRequest = IntentSenderRequest.Builder(pendingIntent) Loading
packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt +2 −2 Original line number Diff line number Diff line Loading @@ -230,7 +230,7 @@ private fun runBiometricFlow( val cryptoOpId = getCryptoOpId(biometricDisplayInfo) if (cryptoOpId != null) { biometricPrompt.authenticate( BiometricPrompt.CryptoObject(cryptoOpId.toLong()), BiometricPrompt.CryptoObject(cryptoOpId), cancellationSignal, executor, callback) } else { biometricPrompt.authenticate(cancellationSignal, executor, callback) Loading @@ -243,7 +243,7 @@ private fun runBiometricFlow( return true } private fun getCryptoOpId(biometricDisplayInfo: BiometricDisplayInfo): Int? { private fun getCryptoOpId(biometricDisplayInfo: BiometricDisplayInfo): Long? { return biometricDisplayInfo.biometricRequestInfo.opId } Loading
packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt +7 −4 Original line number Diff line number Diff line Loading @@ -22,9 +22,12 @@ class Constants { const val BUNDLE_KEY_PREFER_IMMEDIATELY_AVAILABLE_CREDENTIALS = "androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED" const val IS_AUTO_SELECTED_KEY = "IS_AUTO_SELECTED" // TODO(b/333445772) : Qualify error codes fully for propagation const val BIOMETRIC_AUTH_RESULT = "BIOMETRIC_AUTH_RESULT" const val BIOMETRIC_AUTH_ERROR_CODE = "BIOMETRIC_AUTH_ERROR_CODE" const val BIOMETRIC_AUTH_ERROR_MESSAGE = "BIOMETRIC_AUTH_ERROR_MESSAGE" const val BIOMETRIC_AUTH_RESULT = "androidx.credentials.provider.BIOMETRIC_AUTH_RESULT" const val BIOMETRIC_AUTH_ERROR_CODE = "androidx.credentials.provider.BIOMETRIC_AUTH_ERROR_CODE" const val BIOMETRIC_AUTH_ERROR_MESSAGE = "androidx.credentials.provider.BIOMETRIC_AUTH_ERROR_MESSAGE" const val BIOMETRIC_FRAMEWORK_OPTION = "androidx.credentials.provider.BIOMETRIC_FRAMEWORK_OPTION" } }