Merge "Add the passwords/sign in icons to the create flow"

This commit is contained in:
Qinmei Du
2022-11-29 18:55:55 +00:00
committed by Android (Google) Code Review
7 changed files with 155 additions and 31 deletions

View File

@@ -0,0 +1,36 @@
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="VectorPath"
android:name="vector"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:name="path"
android:pathData="M 20 19 L 12 19 L 12 21 L 20 21 C 21.1 21 22 20.1 22 19 L 22 5 C 22 3.9 21.1 3 20 3 L 12 3 L 12 5 L 20 5 L 20 19 Z"
android:fillColor="#000"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 12 7 L 10.6 8.4 L 13.2 11 L 8.85 11 C 8.42 9.55 7.09 8.5 5.5 8.5 C 3.57 8.5 2 10.07 2 12 C 2 13.93 3.57 15.5 5.5 15.5 C 7.09 15.5 8.42 14.45 8.85 13 L 13.2 13 L 10.6 15.6 L 12 17 L 17 12 L 12 7 Z M 5.5 13.5 C 4.67 13.5 4 12.83 4 12 C 4 11.17 4.67 10.5 5.5 10.5 C 6.33 10.5 7 11.17 7 12 C 7 12.83 6.33 13.5 5.5 13.5 Z"
android:fillColor="#000"
android:strokeWidth="1"/>
</vector>

View File

@@ -0,0 +1,31 @@
<!--
~ Copyright (C) 2022 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="VectorPath"
android:name="vector"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:name="path"
android:pathData="M 8.71 10.29 C 8.52 10.1 8.28 10 8 10 L 7.75 10 L 7.75 8.75 C 7.75 7.98 7.48 7.33 6.95 6.8 C 6.42 6.27 5.77 6 5 6 C 4.23 6 3.58 6.27 3.05 6.8 C 2.52 7.33 2.25 7.98 2.25 8.75 L 2.25 10 L 2 10 C 1.72 10 1.48 10.1 1.29 10.29 C 1.1 10.48 1 10.72 1 11 L 1 16 C 1 16.28 1.1 16.52 1.29 16.71 C 1.48 16.9 1.72 17 2 17 L 8 17 C 8.28 17 8.52 16.9 8.71 16.71 C 8.9 16.52 9 16.28 9 16 L 9 11 C 9 10.72 8.9 10.48 8.71 10.29 Z M 6.25 10 L 3.75 10 L 3.75 8.75 C 3.75 8.4 3.87 8.1 4.11 7.86 C 4.35 7.62 4.65 7.5 5 7.5 C 5.35 7.5 5.65 7.62 5.89 7.86 C 6.13 8.1 6.25 8.4 6.25 8.75 L 6.25 10 Z M 10 14 L 23 14 L 23 16 L 10 16 Z M 21.5 9 C 21.102 9 20.721 9.158 20.439 9.439 C 20.158 9.721 20 10.102 20 10.5 C 20 10.898 20.158 11.279 20.439 11.561 C 20.721 11.842 21.102 12 21.5 12 C 21.898 12 22.279 11.842 22.561 11.561 C 22.842 11.279 23 10.898 23 10.5 C 23 10.102 22.842 9.721 22.561 9.439 C 22.279 9.158 21.898 9 21.5 9 Z M 16.5 9 C 16.102 9 15.721 9.158 15.439 9.439 C 15.158 9.721 15 10.102 15 10.5 C 15 10.898 15.158 11.279 15.439 11.561 C 15.721 11.842 16.102 12 16.5 12 C 16.898 12 17.279 11.842 17.561 11.561 C 17.842 11.279 18 10.898 18 10.5 C 18 10.102 17.842 9.721 17.561 9.439 C 17.279 9.158 16.898 9 16.5 9 Z M 11.5 9 C 11.102 9 10.721 9.158 10.439 9.439 C 10.158 9.721 10 10.102 10 10.5 C 10 10.898 10.158 11.279 10.439 11.561 C 10.721 11.842 11.102 12 11.5 12 C 11.898 12 12.279 11.842 12.561 11.561 C 12.842 11.279 13 10.898 13 10.5 C 13 10.102 12.842 9.721 12.561 9.439 C 12.279 9.158 11.898 9 11.5 9 Z"
android:fillColor="#000"
android:strokeWidth="1"/>
</vector>

View File

@@ -44,12 +44,10 @@ import com.android.credentialmanager.createflow.ActiveEntry
import com.android.credentialmanager.createflow.CreateCredentialUiState
import com.android.credentialmanager.createflow.CreateScreenState
import com.android.credentialmanager.createflow.EnabledProviderInfo
import com.android.credentialmanager.createflow.RequestDisplayInfo
import com.android.credentialmanager.getflow.GetCredentialUiState
import com.android.credentialmanager.getflow.GetScreenState
import com.android.credentialmanager.jetpack.developer.CreateCredentialRequest.Companion.createFrom
import com.android.credentialmanager.jetpack.developer.CreatePasswordRequest
import com.android.credentialmanager.jetpack.developer.CreatePasswordRequest.Companion.toBundle
import com.android.credentialmanager.jetpack.developer.CreatePublicKeyCredentialRequest
import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
// Consider repo per screen, similar to view model?
@@ -67,7 +65,7 @@ class CredentialManagerRepo(
requestInfo = intent.extras?.getParcelable(
RequestInfo.EXTRA_REQUEST_INFO,
RequestInfo::class.java
) ?: testCreateRequestInfo()
) ?: testCreatePasskeyRequestInfo()
providerEnabledList = when (requestInfo.type) {
RequestInfo.TYPE_CREATE ->
@@ -137,9 +135,10 @@ class CredentialManagerRepo(
}
fun createCredentialInitialUiState(): CreateCredentialUiState {
val requestDisplayInfo = CreateFlowUtils.toRequestDisplayInfo(requestInfo, context)
val providerEnabledList = CreateFlowUtils.toEnabledProviderList(
// Handle runtime cast error
providerEnabledList as List<CreateCredentialProviderData>, context)
providerEnabledList as List<CreateCredentialProviderData>, requestDisplayInfo, context)
val providerDisabledList = CreateFlowUtils.toDisabledProviderList(
// Handle runtime cast error
providerDisabledList as List<DisabledProviderData>, context)
@@ -148,21 +147,6 @@ class CredentialManagerRepo(
providerEnabledList.forEach{providerInfo -> providerInfo.createOptions =
providerInfo.createOptions.sortedWith(compareBy { it.lastUsedTimeMillis }).reversed()
if (providerInfo.isDefault) {hasDefault = true; defaultProvider = providerInfo} }
// TODO: covert from real requestInfo for create passkey
var requestDisplayInfo = RequestDisplayInfo(
"beckett-bakert@gmail.com",
"Elisa Beckett",
TYPE_PUBLIC_KEY_CREDENTIAL,
"tribank")
val createCredentialRequest = requestInfo.createCredentialRequest
val createCredentialRequestJetpack = createCredentialRequest?.let { createFrom(it) }
if (createCredentialRequestJetpack is CreatePasswordRequest) {
requestDisplayInfo = RequestDisplayInfo(
createCredentialRequestJetpack.id,
createCredentialRequestJetpack.password,
TYPE_PASSWORD_CREDENTIAL,
"tribank")
}
return CreateCredentialUiState(
enabledProviders = providerEnabledList,
disabledProviders = providerDisabledList,
@@ -440,8 +424,9 @@ class CredentialManagerRepo(
)
}
private fun testCreateRequestInfo(): RequestInfo {
val data = toBundle("beckett-bakert@gmail.com", "password123")
private fun testCreatePasskeyRequestInfo(): RequestInfo {
val request = CreatePublicKeyCredentialRequest("json")
val data = request.data
return RequestInfo.newCreateRequestInfo(
Binder(),
CreateCredentialRequest(
@@ -453,6 +438,32 @@ class CredentialManagerRepo(
)
}
private fun testCreatePasswordRequestInfo(): RequestInfo {
val data = toBundle("beckett-bakert@gmail.com", "password123")
return RequestInfo.newCreateRequestInfo(
Binder(),
CreateCredentialRequest(
TYPE_PASSWORD_CREDENTIAL,
data
),
/*isFirstUsage=*/false,
"tribank"
)
}
private fun testCreateOtherCredentialRequestInfo(): RequestInfo {
val data = Bundle()
return RequestInfo.newCreateRequestInfo(
Binder(),
CreateCredentialRequest(
"other-sign-ins",
data
),
/*isFirstUsage=*/false,
"tribank"
)
}
private fun testGetRequestInfo(): RequestInfo {
return RequestInfo.newGetRequestInfo(
Binder(),

View File

@@ -23,14 +23,19 @@ import android.credentials.ui.Entry
import android.credentials.ui.GetCredentialProviderData
import android.credentials.ui.CreateCredentialProviderData
import android.credentials.ui.DisabledProviderData
import android.credentials.ui.RequestInfo
import android.graphics.drawable.Drawable
import com.android.credentialmanager.createflow.CreateOptionInfo
import com.android.credentialmanager.createflow.RemoteInfo
import com.android.credentialmanager.createflow.RequestDisplayInfo
import com.android.credentialmanager.getflow.ActionEntryInfo
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.jetpack.developer.CreateCredentialRequest
import com.android.credentialmanager.jetpack.developer.CreatePasswordRequest
import com.android.credentialmanager.jetpack.developer.CreatePublicKeyCredentialRequest
import com.android.credentialmanager.jetpack.provider.ActionUi
import com.android.credentialmanager.jetpack.provider.CredentialEntryUi
import com.android.credentialmanager.jetpack.provider.SaveEntryUi
@@ -172,6 +177,7 @@ class CreateFlowUtils {
fun toEnabledProviderList(
providerDataList: List<CreateCredentialProviderData>,
requestDisplayInfo: RequestDisplayInfo,
context: Context,
): List<com.android.credentialmanager.createflow.EnabledProviderInfo> {
// TODO: get from the actual service info
@@ -194,7 +200,7 @@ class CreateFlowUtils {
name = it.providerFlattenedComponentName,
displayName = pkgInfo.applicationInfo.loadLabel(packageManager).toString(),
createOptions = toCreationOptionInfoList(
it.providerFlattenedComponentName, it.saveEntries, context),
it.providerFlattenedComponentName, it.saveEntries, requestDisplayInfo, context),
isDefault = it.isDefaultProvider,
remoteEntry = toRemoteInfo(it.providerFlattenedComponentName, it.remoteEntry),
)
@@ -219,9 +225,50 @@ class CreateFlowUtils {
}
}
fun toRequestDisplayInfo(
requestInfo: RequestInfo,
context: Context,
): RequestDisplayInfo {
val createCredentialRequest = requestInfo.createCredentialRequest
val createCredentialRequestJetpack = createCredentialRequest?.let {
CreateCredentialRequest.createFrom(
it
)
}
// TODO: covert from real requestInfo
when (createCredentialRequestJetpack) {
is CreatePasswordRequest -> {
return RequestDisplayInfo(
createCredentialRequestJetpack.id,
createCredentialRequestJetpack.password,
createCredentialRequestJetpack.type,
"tribank",
context.getDrawable(R.drawable.ic_password)!!
)
}
is CreatePublicKeyCredentialRequest -> {
return RequestDisplayInfo(
"beckett-bakert@gmail.com",
"Elisa Beckett",
createCredentialRequestJetpack.type,
"tribank",
context.getDrawable(R.drawable.ic_passkey)!!)
}
else -> {
return RequestDisplayInfo(
"beckett-bakert@gmail.com",
"Elisa Beckett",
"other-sign-ins",
"tribank",
context.getDrawable(R.drawable.ic_other_sign_in)!!)
}
}
}
private fun toCreationOptionInfoList(
providerId: String,
creationEntries: List<Entry>,
requestDisplayInfo: RequestDisplayInfo,
context: Context,
): List<CreateOptionInfo> {
return creationEntries.map {
@@ -236,7 +283,7 @@ class CreateFlowUtils {
fillInIntent = it.frameworkExtrasIntent,
userProviderDisplayName = saveEntryUi.userProviderAccountName as String,
profileIcon = saveEntryUi.profileIcon?.loadDrawable(context)
?: context.getDrawable(R.drawable.ic_profile)!!,
?: requestDisplayInfo.typeIcon,
passwordCount = saveEntryUi.passwordCount ?: 0,
passkeyCount = saveEntryUi.passkeyCount ?: 0,
totalCredentialCount = saveEntryUi.totalCredentialCount ?: 0,

View File

@@ -191,13 +191,12 @@ fun ProviderSelectionCard(
) {
Card() {
Column() {
// TODO: Change the icon for create passwords and sign-ins
Icon(
painter = painterResource(R.drawable.ic_passkey),
bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap(),
contentDescription = null,
tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
.padding(top = 24.dp, bottom = 16.dp)
.padding(top = 24.dp, bottom = 16.dp).size(32.dp)
)
Text(
text = stringResource(
@@ -567,12 +566,11 @@ fun PrimaryCreateOptionRow(
Entry(
onClick = {onOptionSelected(createOptionInfo)},
icon = {
// TODO: Upload the other two types icons and change it according to request types
Icon(
painter = painterResource(R.drawable.ic_passkey),
bitmap = createOptionInfo.profileIcon.toBitmap().asImageBitmap(),
contentDescription = null,
tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
modifier = Modifier.padding(start = 18.dp)
modifier = Modifier.padding(start = 18.dp).size(32.dp)
)
},
label = {

View File

@@ -76,6 +76,7 @@ data class RequestDisplayInfo(
val subtitle: String,
val type: String,
val appDomainName: String,
val typeIcon: Drawable,
)
/**

View File

@@ -47,7 +47,7 @@ abstract class CreatePublicKeyCredentialBaseRequest constructor(
return when (data.getString(BUNDLE_KEY_SUBTYPE)) {
CreatePublicKeyCredentialRequest
.BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST ->
CreatePublicKeyCredentialRequestPrivileged.createFrom(data)
CreatePublicKeyCredentialRequest.createFrom(data)
CreatePublicKeyCredentialRequestPrivileged
.BUNDLE_VALUE_SUBTYPE_CREATE_PUBLIC_KEY_CREDENTIAL_REQUEST_PRIVILEGED ->
CreatePublicKeyCredentialRequestPrivileged.createFrom(data)