diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index 81505e1393cc2..d690971997128 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -11,13 +11,34 @@
Continue
More options
+
+ Learn more
Safer with passkeys
-
+
With passkeys, you don’t need to create or remember complex passwords
+
Passkeys are encrypted digital keys you create using your fingerprint, face, or screen lock
+
They are saved to a password manager, so you can sign in on other devices
-
+
+ More about passkeys
+
+ Passwordless technology
+
+ Passkeys allow you to sign in without relying on passwords. You just need to use your fingerprint, face recognition, PIN, or swipe pattern to verify your identity and create a passkey.
+
+ Public key cryptography
+
+ Based on FIDO Alliance (which includes Google, Apple, Microsoft, and more) and W3C standards, passkeys use cryptographic key pairs. Unlike the username and string of characters we use for passwords, a private-public key pair is created for an app or website. The private key is safely stored on your device or password manager and it confirms your identity. The public key is shared with the app or website server. With corresponding keys, you can instantly register and sign in.
+
+ Improved account security
+
+ Each key is exclusively linked with the app or website they were created for, so you can never sign in to a fraudulent app or website by mistake. Plus, with servers only keeping public keys, hacking is a lot harder.
+
+ Seamless transition
+
+ As we move towards a passwordless future, passwords will still be available alongside passkeys.
Choose where to save your %1$s
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index 498f0a193af15..03d7de5457a79 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -70,7 +70,7 @@ fun CreateCredentialScreen(
when (uiState.currentScreenState) {
CreateScreenState.PASSKEY_INTRO -> ConfirmationCard(
onConfirm = viewModel::onConfirmIntro,
- onCancel = viewModel::onCancel,
+ onLearnMore = viewModel::onLearnMore,
)
CreateScreenState.PROVIDER_SELECTION -> ProviderSelectionCard(
requestDisplayInfo = uiState.requestDisplayInfo,
@@ -115,7 +115,10 @@ fun CreateCredentialScreen(
activeRemoteEntry = uiState.activeEntry?.activeEntryInfo!!,
onOptionSelected = viewModel::onEntrySelected,
onConfirm = viewModel::onConfirmEntrySelected,
- onCancel = viewModel::onCancel,
+ )
+ CreateScreenState.MORE_ABOUT_PASSKEYS_INTRO -> MoreAboutPasskeysIntroCard(
+ onBackPasskeyIntroButtonSelected =
+ viewModel::onBackPasskeyIntroButtonSelected,
)
}
} else if (uiState.selectedEntry != null && !uiState.providerActivityPending) {
@@ -136,7 +139,7 @@ fun CreateCredentialScreen(
@Composable
fun ConfirmationCard(
onConfirm: () -> Unit,
- onCancel: () -> Unit,
+ onLearnMore: () -> Unit,
) {
ContainerCard() {
Column() {
@@ -223,8 +226,8 @@ fun ConfirmationCard(
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
) {
ActionButton(
- stringResource(R.string.string_cancel),
- onClick = onCancel
+ stringResource(R.string.string_learn_more),
+ onClick = onLearnMore
)
ConfirmButton(
stringResource(R.string.string_continue),
@@ -396,8 +399,7 @@ fun MoreOptionsSelectionCard(
)
}
},
- colors = TopAppBarDefaults.smallTopAppBarColors
- (containerColor = Color.Transparent),
+ colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
modifier = Modifier.padding(top = 12.dp)
)
Divider(
@@ -634,7 +636,6 @@ fun ExternalOnlySelectionCard(
activeRemoteEntry: EntryInfo,
onOptionSelected: (EntryInfo) -> Unit,
onConfirm: () -> Unit,
- onCancel: () -> Unit,
) {
ContainerCard() {
Column() {
@@ -673,13 +674,9 @@ fun ExternalOnlySelectionCard(
color = Color.Transparent
)
Row(
- horizontalArrangement = Arrangement.SpaceBetween,
+ horizontalArrangement = Arrangement.End,
modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
) {
- ActionButton(
- stringResource(R.string.string_cancel),
- onClick = onCancel
- )
ConfirmButton(
stringResource(R.string.string_continue),
onClick = onConfirm
@@ -694,6 +691,92 @@ fun ExternalOnlySelectionCard(
}
}
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun MoreAboutPasskeysIntroCard(
+ onBackPasskeyIntroButtonSelected: () -> Unit,
+) {
+ ContainerCard() {
+ Column() {
+ TopAppBar(
+ title = {
+ TextOnSurface(
+ text =
+ stringResource(
+ R.string.more_about_passkeys_title),
+ style = MaterialTheme.typography.titleMedium,
+ )
+ },
+ navigationIcon = {
+ IconButton(
+ onClick = onBackPasskeyIntroButtonSelected
+ ) {
+ Icon(
+ Icons.Filled.ArrowBack,
+ stringResource(R.string.accessibility_back_arrow_button)
+ )
+ }
+ },
+ colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
+ modifier = Modifier.padding(top = 12.dp)
+ )
+ Column(
+ modifier = Modifier.fillMaxWidth().padding(start = 24.dp, end = 68.dp)
+ ) {
+ TextOnSurfaceVariant(
+ text = stringResource(R.string.passwordless_technology_title),
+ style = MaterialTheme.typography.titleLarge,
+ )
+ TextSecondary(
+ text = stringResource(R.string.passwordless_technology_detail),
+ style = MaterialTheme.typography.bodyMedium,
+ )
+ Divider(
+ thickness = 24.dp,
+ color = Color.Transparent
+ )
+ TextOnSurfaceVariant(
+ text = stringResource(R.string.public_key_cryptography_title),
+ style = MaterialTheme.typography.titleLarge,
+ )
+ TextSecondary(
+ text = stringResource(R.string.public_key_cryptography_detail),
+ style = MaterialTheme.typography.bodyMedium,
+ )
+ Divider(
+ thickness = 24.dp,
+ color = Color.Transparent
+ )
+ TextOnSurfaceVariant(
+ text = stringResource(R.string.improved_account_security_title),
+ style = MaterialTheme.typography.titleLarge,
+ )
+ TextSecondary(
+ text = stringResource(R.string.improved_account_security_detail),
+ style = MaterialTheme.typography.bodyMedium,
+ )
+ Divider(
+ thickness = 24.dp,
+ color = Color.Transparent
+ )
+ TextOnSurfaceVariant(
+ text = stringResource(R.string.seamless_transition_title),
+ style = MaterialTheme.typography.titleLarge,
+ )
+ TextSecondary(
+ text = stringResource(R.string.seamless_transition_detail),
+ style = MaterialTheme.typography.bodyMedium,
+ )
+ }
+ Divider(
+ thickness = 18.dp,
+ color = Color.Transparent,
+ modifier = Modifier.padding(bottom = 24.dp)
+ )
+ }
+ }
+}
+
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PrimaryCreateOptionRow(
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
index ac84503583a8a..7a04a8e0e045a 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
@@ -122,6 +122,12 @@ class CreateCredentialViewModel(
)
}
+ fun onBackPasskeyIntroButtonSelected() {
+ uiState = uiState.copy(
+ currentScreenState = CreateScreenState.PASSKEY_INTRO,
+ )
+ }
+
fun onEntrySelectedFromMoreOptionScreen(activeEntry: ActiveEntry) {
uiState = uiState.copy(
currentScreenState = if (
@@ -150,6 +156,12 @@ class CreateCredentialViewModel(
dialogResult.tryEmit(DialogResult(ResultState.NORMAL_CANCELED))
}
+ fun onLearnMore() {
+ uiState = uiState.copy(
+ currentScreenState = CreateScreenState.MORE_ABOUT_PASSKEYS_INTRO,
+ )
+ }
+
fun onChangeDefaultSelected() {
uiState = uiState.copy(
currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
index 97477a75f8bfa..957488ffcbcc1 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
@@ -91,6 +91,7 @@ data class ActiveEntry (
/** The name of the current screen. */
enum class CreateScreenState {
PASSKEY_INTRO,
+ MORE_ABOUT_PASSKEYS_INTRO,
PROVIDER_SELECTION,
CREATION_OPTION_SELECTION,
MORE_OPTIONS_SELECTION,