From 636fea079a308317cdd387c3defcaa8543e8781b Mon Sep 17 00:00:00 2001 From: Helen Qin Date: Thu, 13 Apr 2023 19:18:33 +0000 Subject: [PATCH] [CredManUi] App can specify preferred top level branding for sign-in flow Bug: 277129959 Test: manual (see bug for recording) Change-Id: I95e6bb832d1e6b24addc660fb4a315515dabcfce --- .../credentialmanager/DataConverter.kt | 19 +++++++ .../getflow/GetCredentialComponents.kt | 53 ++++++++++++------- .../credentialmanager/getflow/GetModel.kt | 7 +++ 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt index 108f4945c9e9e..f08bbf430440a 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt @@ -46,6 +46,7 @@ import com.android.credentialmanager.getflow.AuthenticationEntryInfo import com.android.credentialmanager.getflow.CredentialEntryInfo import com.android.credentialmanager.getflow.ProviderInfo import com.android.credentialmanager.getflow.RemoteEntryInfo +import com.android.credentialmanager.getflow.TopBrandingContent import androidx.credentials.CreateCredentialRequest import androidx.credentials.CreateCustomCredentialRequest import androidx.credentials.CreatePasswordRequest @@ -207,6 +208,23 @@ class GetFlowUtils { false } } + val preferUiBrandingComponentName = + getCredentialRequest.data.getParcelable( + "androidx.credentials.BUNDLE_KEY_PREFER_UI_BRANDING_COMPONENT_NAME", + ComponentName::class.java + ) + val preferTopBrandingContent: TopBrandingContent? = + if (preferUiBrandingComponentName == null) null + else { + val (displayName, icon) = getServiceLabelAndIcon( + context.packageManager, preferUiBrandingComponentName.flattenToString()) + ?: Pair(null, null) + if (displayName != null && icon != null) { + TopBrandingContent(icon, displayName) + } else { + null + } + } return com.android.credentialmanager.getflow.RequestDisplayInfo( appName = originName ?: getAppLabel(context.packageManager, requestInfo.appPackageName) @@ -216,6 +234,7 @@ class GetFlowUtils { // TODO(b/276777444): replace with direct library constant reference once // exposed. "androidx.credentials.BUNDLE_KEY_PREFER_IDENTITY_DOC_UI"), + preferTopBrandingContent = preferTopBrandingContent, ) } diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt index 98bd020b234b6..516c1a3bb1e35 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt @@ -16,6 +16,7 @@ package com.android.credentialmanager.getflow +import android.graphics.drawable.Drawable import android.text.TextUtils import androidx.activity.compose.ManagedActivityResultLauncher import androidx.activity.result.ActivityResult @@ -34,7 +35,6 @@ import androidx.compose.material3.Divider import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier @@ -168,26 +168,30 @@ fun PrimarySelectionCard( providerDisplayInfo.sortedUserNameToCredentialEntryList val authenticationEntryList = providerDisplayInfo.authenticationEntryList SheetContainerCard { - // When only one provider (not counting the remote-only provider) exists, display that - // provider's icon + name up top. - if (providerInfoList.size <= 2) { // It's only possible to be the single provider case - // if we are started with no more than 2 providers. - val nonRemoteProviderList = providerInfoList.filter( - { it.credentialEntryList.isNotEmpty() || it.authenticationEntryList.isNotEmpty() } - ) - if (nonRemoteProviderList.size == 1) { - val providerInfo = nonRemoteProviderList.firstOrNull() // First should always work - // but just to be safe. + val preferTopBrandingContent = requestDisplayInfo.preferTopBrandingContent + if (preferTopBrandingContent != null) { + item { + HeadlineProviderIconAndName( + preferTopBrandingContent.icon, + preferTopBrandingContent.displayName + ) + } + } else { + // When only one provider (not counting the remote-only provider) exists, display that + // provider's icon + name up top. + val providersWithActualEntries = providerInfoList.filter { + it.credentialEntryList.isNotEmpty() || it.authenticationEntryList.isNotEmpty() + } + if (providersWithActualEntries.size == 1) { + // First should always work but just to be safe. + val providerInfo = providersWithActualEntries.firstOrNull() if (providerInfo != null) { item { - HeadlineIcon( - bitmap = providerInfo.icon.toBitmap().asImageBitmap(), - tint = Color.Unspecified, + HeadlineProviderIconAndName( + providerInfo.icon, + providerInfo.displayName ) } - item { Divider(thickness = 4.dp, color = Color.Transparent) } - item { LargeLabelTextOnSurfaceVariant(text = providerInfo.displayName) } - item { Divider(thickness = 16.dp, color = Color.Transparent) } } } } @@ -369,8 +373,19 @@ fun AllSignInOptionCard( onLog(GetCredentialEvent.CREDMAN_GET_CRED_ALL_SIGN_IN_OPTION_CARD) } -// TODO: create separate rows for primary and secondary pages. -// TODO: reuse rows and columns across types. +@Composable +fun HeadlineProviderIconAndName( + icon: Drawable, + name: String, +) { + HeadlineIcon( + bitmap = icon.toBitmap().asImageBitmap(), + tint = Color.Unspecified, + ) + Divider(thickness = 4.dp, color = Color.Transparent) + LargeLabelTextOnSurfaceVariant(text = name) + Divider(thickness = 16.dp, color = Color.Transparent) +} @Composable fun ActionChips( diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt index c9c62a48d1302..a4a163bbabc30 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt @@ -173,6 +173,13 @@ data class RequestDisplayInfo( val appName: String, val preferImmediatelyAvailableCredentials: Boolean, val preferIdentityDocUi: Boolean, + // A top level branding icon + display name preferred by the app. + val preferTopBrandingContent: TopBrandingContent?, +) + +data class TopBrandingContent( + val icon: Drawable, + val displayName: String, ) /**