diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index 91ffc4435ae47..81505e1393cc2 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -5,63 +5,49 @@
Credential Manager
-
+
Cancel
-
+
Continue
-
+
More options
-
- Create in another place
-
- Save to another place
-
- Use another device
-
- Save to another device
-
+
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
-
- Choose where to %1$s
-
- create your passkeys
- save your password
- save your sign-in info
+
+ Choose where to save your %1$s
- Select a password manager to save your info and sign in faster next time.
+ Select a password manager to save your info and sign in faster next time
Create passkey for %1$s?
Save password for %1$s?
Save sign-in info for %1$s?
-
- You can use your %1$s %2$s on any device. It is saved to %3$s for %4$s.
passkey
password
+ passkeys
+ passwords
sign-ins
sign-in info
-
+
Save %1$s to
- Create a passkey in another device?
+ Create passkey in another device?
Use %1$s for all your sign-ins?
- This password manager will store your passwords and passkeys to help you easily sign in.
-
+ This password manager will store your passwords and passkeys to help you easily sign in
+
Set as default
-
+
Use once
%1$s passwords • %2$s passkeys
@@ -73,7 +59,7 @@
%1$s credentials
Passkey
-
+
Another device
Other password managers
@@ -91,15 +77,15 @@
Use your saved sign-in for %1$s?
Choose a saved sign-in for %1$s
-
+
Sign in another way
-
+
View options
-
+
Continue
" - "
-
+
Sign-in options
For %1$s
@@ -111,6 +97,6 @@
Manage sign-ins
From another device
-
+
Use a different device
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index 3f4f178868135..1e5bd7bf843e9 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -176,9 +176,11 @@ class CredentialManagerRepo(
.setSaveEntries(
listOf(
newCreateEntry("key1", "subkey-1", "elisa.beckett@gmail.com",
- 20, 7, 27, 10L),
+ 20, 7, 27, 10L,
+ "Optional footer description"),
newCreateEntry("key1", "subkey-2", "elisa.work@google.com",
- 20, 7, 27, 12L),
+ 20, 7, 27, 12L,
+ null),
)
)
.setRemoteEntry(
@@ -190,9 +192,11 @@ class CredentialManagerRepo(
.setSaveEntries(
listOf(
newCreateEntry("key1", "subkey-3", "elisa.beckett@dashlane.com",
- 20, 7, 27, 11L),
+ 20, 7, 27, 11L,
+ null),
newCreateEntry("key1", "subkey-4", "elisa.work@dashlane.com",
- 20, 7, 27, 14L),
+ 20, 7, 27, 14L,
+ null),
)
)
.build(),
@@ -337,6 +341,7 @@ class CredentialManagerRepo(
passkeyCount: Int,
totalCredentialCount: Int,
lastUsedTimeMillis: Long,
+ footerDescription: String?,
): Entry {
val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
.setPackage("com.androidauth.androidvault")
@@ -360,7 +365,7 @@ class CredentialManagerRepo(
listOf(
CredentialCountInformation.createPasswordCountInformation(passwordCount),
CredentialCountInformation.createPublicKeyCountInformation(passkeyCount),
- ))
+ ), footerDescription)
return Entry(
key,
subkey,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index 3cd42171d3327..9803fc64cd2fd 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -431,6 +431,7 @@ class CreateFlowUtils {
totalCredentialCount = CredentialCountInformation.getTotalCount(
createEntry.credentialCountInformationList) ?: 0,
lastUsedTimeMillis = createEntry.lastUsedTimeMillis ?: 0,
+ footerDescription = createEntry.footerDescription?.toString()
)
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index 0c11e91da7717..498f0a193af15 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -264,11 +264,12 @@ fun ProviderSelectionCard(
text = stringResource(
R.string.choose_provider_title,
when (requestDisplayInfo.type) {
- TYPE_PUBLIC_KEY_CREDENTIAL -> stringResource(R.string.create_your_passkeys)
- TYPE_PASSWORD_CREDENTIAL -> stringResource(R.string.save_your_password)
- else -> stringResource(R.string.save_your_sign_in_info)
- },
- ),
+ TYPE_PUBLIC_KEY_CREDENTIAL ->
+ stringResource(R.string.passkeys)
+ TYPE_PASSWORD_CREDENTIAL ->
+ stringResource(R.string.passwords)
+ else -> stringResource(R.string.sign_in_info)
+ }),
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(horizontal = 24.dp)
.align(alignment = Alignment.CenterHorizontally),
@@ -604,27 +605,17 @@ fun CreationSelectionCard(
onClick = onConfirm
)
}
- Divider(
- thickness = 1.dp,
- color = Color.LightGray,
- modifier = Modifier.padding(start = 24.dp, end = 24.dp, top = 18.dp)
- )
- if (createOptionInfo.userProviderDisplayName != null) {
+ if (createOptionInfo.footerDescription != null) {
+ Divider(
+ thickness = 1.dp,
+ color = Color.LightGray,
+ modifier = Modifier.padding(start = 24.dp, end = 24.dp, top = 18.dp)
+ )
TextSecondary(
- text = stringResource(
- R.string.choose_create_option_description,
- requestDisplayInfo.appName,
- when (requestDisplayInfo.type) {
- TYPE_PUBLIC_KEY_CREDENTIAL -> stringResource(R.string.passkey)
- TYPE_PASSWORD_CREDENTIAL -> stringResource(R.string.password)
- else -> stringResource(R.string.sign_ins)
- },
- providerInfo.displayName,
- createOptionInfo.userProviderDisplayName
- ),
+ text = createOptionInfo.footerDescription,
style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.padding(
- start = 24.dp, top = 8.dp, bottom = 18.dp, end = 24.dp)
+ start = 29.dp, top = 8.dp, bottom = 18.dp, end = 28.dp)
)
}
Divider(
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
index 04cd26bb517dd..97477a75f8bfa 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
@@ -60,6 +60,7 @@ class CreateOptionInfo(
val passkeyCount: Int?,
val totalCredentialCount: Int?,
val lastUsedTimeMillis: Long?,
+ val footerDescription: String?,
) : EntryInfo(providerId, entryKey, entrySubkey, pendingIntent, fillInIntent)
class RemoteInfo(
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CreateEntry.kt b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CreateEntry.kt
index bed02f8e22a46..0ec91d67241f1 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CreateEntry.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/CreateEntry.kt
@@ -36,7 +36,8 @@ class CreateEntry internal constructor(
val pendingIntent: PendingIntent?,
val icon: Icon?,
val lastUsedTimeMillis: Long,
- val credentialCountInformationList: List
+ val credentialCountInformationList: List,
+ val footerDescription: CharSequence?,
) {
init {
@@ -61,6 +62,7 @@ class CreateEntry internal constructor(
mutableListOf()
private var icon: Icon? = null
private var lastUsedTimeMillis: Long = 0
+ private var footerDescription: CharSequence? = null
/** Adds a [CredentialCountInformation] denoting a given credential
* type and the count of credentials that the provider has stored for that
@@ -99,6 +101,12 @@ class CreateEntry internal constructor(
return this
}
+ /** Sets the footer description of this */
+ fun setFooterDescription(footerDescription: CharSequence): Builder {
+ this.footerDescription = footerDescription
+ return this
+ }
+
/**
* Builds an instance of [CreateEntry]
*
@@ -106,7 +114,7 @@ class CreateEntry internal constructor(
*/
fun build(): CreateEntry {
return CreateEntry(accountName, pendingIntent, icon, lastUsedTimeMillis,
- credentialCountInformationList)
+ credentialCountInformationList, footerDescription)
}
}
@@ -122,6 +130,8 @@ class CreateEntry internal constructor(
"androidx.credentials.provider.createEntry.SLICE_HINT_LAST_USED_TIME_MILLIS"
internal const val SLICE_HINT_PENDING_INTENT =
"androidx.credentials.provider.createEntry.SLICE_HINT_PENDING_INTENT"
+ internal const val SLICE_HINT_FOOTER_DESCRIPTION =
+ "androidx.credentials.provider.createEntry.SLICE_HINT_FOOTER_DESCRIPTION"
@JvmStatic
fun toSlice(createEntry: CreateEntry): Slice {
@@ -150,6 +160,10 @@ class CreateEntry internal constructor(
.build(),
/*subType=*/null)
}
+ if (createEntry.footerDescription != null) {
+ sliceBuilder.addText(createEntry.footerDescription, /*subType=*/null,
+ listOf(SLICE_HINT_FOOTER_DESCRIPTION))
+ }
return sliceBuilder.build()
}
@@ -167,6 +181,7 @@ class CreateEntry internal constructor(
var pendingIntent: PendingIntent? = null
var credentialCountInfo: List = listOf()
var lastUsedTimeMillis: Long = 0
+ var footerDescription: CharSequence? = null
slice.items.forEach {
if (it.hasHint(SLICE_HINT_ACCOUNT_NAME)) {
@@ -179,12 +194,14 @@ class CreateEntry internal constructor(
credentialCountInfo = convertBundleToCredentialCountInfo(it.bundle)
} else if (it.hasHint(SLICE_HINT_LAST_USED_TIME_MILLIS)) {
lastUsedTimeMillis = it.long
+ } else if (it.hasHint(SLICE_HINT_FOOTER_DESCRIPTION)) {
+ footerDescription = it.text
}
}
return try {
CreateEntry(accountName, pendingIntent, icon,
- lastUsedTimeMillis, credentialCountInfo)
+ lastUsedTimeMillis, credentialCountInfo, footerDescription)
} catch (e: Exception) {
Log.i(TAG, "fromSlice failed with: " + e.message)
null