Loading packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +19 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading @@ -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, ) } Loading packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt +34 −19 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -168,26 +168,30 @@ fun PrimarySelectionCard( providerDisplayInfo.sortedUserNameToCredentialEntryList val authenticationEntryList = providerDisplayInfo.authenticationEntryList SheetContainerCard { 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. 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 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) } } } } Loading Loading @@ -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( Loading packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt +7 −0 Original line number Diff line number Diff line Loading @@ -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, ) /** Loading Loading
packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +19 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading @@ -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, ) } Loading
packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt +34 −19 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -168,26 +168,30 @@ fun PrimarySelectionCard( providerDisplayInfo.sortedUserNameToCredentialEntryList val authenticationEntryList = providerDisplayInfo.authenticationEntryList SheetContainerCard { 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. 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 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) } } } } Loading Loading @@ -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( Loading
packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt +7 −0 Original line number Diff line number Diff line Loading @@ -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, ) /** Loading