summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Qinmei Du <duqinmei@google.com> 2022-11-11 23:31:12 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-11-11 23:31:12 +0000
commitb49bde447f4e476412fd28c3f9a832a5b6db859d (patch)
tree863448379f08ca0c27537f5af21a5d3aa10f9c32
parent53ac99950762fdef4afe3d81071fa3a80a3e619a (diff)
parentdf17e143d39d8b6fefe54ae3a1300e76abb97c80 (diff)
Merge changes Ie96bf43d,Ib0572d4b
* changes: Update the intro screen after select on a more options row Add the Another device row in the more options screen
-rw-r--r--core/java/android/credentials/ui/CreateCredentialProviderData.java7
-rw-r--r--packages/CredentialManager/res/drawable/ic_other_devices.xml15
-rw-r--r--packages/CredentialManager/res/values/strings.xml3
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt16
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt14
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt6
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyComponents.kt95
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyViewModel.kt6
8 files changed, 145 insertions, 17 deletions
diff --git a/core/java/android/credentials/ui/CreateCredentialProviderData.java b/core/java/android/credentials/ui/CreateCredentialProviderData.java
index 98157d73ad42..044427894d01 100644
--- a/core/java/android/credentials/ui/CreateCredentialProviderData.java
+++ b/core/java/android/credentials/ui/CreateCredentialProviderData.java
@@ -131,6 +131,13 @@ public class CreateCredentialProviderData extends ProviderData implements Parcel
return this;
}
+ /** Sets the remote entry of the provider. */
+ @NonNull
+ public Builder setRemoteEntry(@Nullable Entry remoteEntry) {
+ mRemoteEntry = remoteEntry;
+ return this;
+ }
+
/** Builds a {@link CreateCredentialProviderData}. */
@NonNull
public CreateCredentialProviderData build() {
diff --git a/packages/CredentialManager/res/drawable/ic_other_devices.xml b/packages/CredentialManager/res/drawable/ic_other_devices.xml
new file mode 100644
index 000000000000..754648cbca1d
--- /dev/null
+++ b/packages/CredentialManager/res/drawable/ic_other_devices.xml
@@ -0,0 +1,15 @@
+<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="20dp"
+ android:height="20dp"
+ android:viewportWidth="20"
+ android:viewportHeight="20">
+ <path
+ android:name="path"
+ android:pathData="M 7.6 4.72 L 7.6 7.6 L 4.72 7.6 L 4.72 4.72 L 7.6 4.72 Z M 9.04 3.28 L 3.28 3.28 L 3.28 9.04 L 9.04 9.04 L 9.04 3.28 Z M 7.6 12.4 L 7.6 15.28 L 4.72 15.28 L 4.72 12.4 L 7.6 12.4 Z M 9.04 10.96 L 3.28 10.96 L 3.28 16.72 L 9.04 16.72 L 9.04 10.96 Z M 15.28 4.72 L 15.28 7.6 L 12.4 7.6 L 12.4 4.72 L 15.28 4.72 Z M 16.72 3.28 L 10.96 3.28 L 10.96 9.04 L 16.72 9.04 L 16.72 3.28 Z M 10.96 10.96 L 12.4 10.96 L 12.4 12.4 L 10.96 12.4 L 10.96 10.96 Z M 12.4 12.4 L 13.84 12.4 L 13.84 13.84 L 12.4 13.84 L 12.4 12.4 Z M 13.84 10.96 L 15.28 10.96 L 15.28 12.4 L 13.84 12.4 L 13.84 10.96 Z M 10.96 13.84 L 12.4 13.84 L 12.4 15.28 L 10.96 15.28 L 10.96 13.84 Z M 12.4 15.28 L 13.84 15.28 L 13.84 16.72 L 12.4 16.72 L 12.4 15.28 Z M 13.84 13.84 L 15.28 13.84 L 15.28 15.28 L 13.84 15.28 L 13.84 13.84 Z M 15.28 12.4 L 16.72 12.4 L 16.72 13.84 L 15.28 13.84 L 15.28 12.4 Z M 15.28 15.28 L 16.72 15.28 L 16.72 16.72 L 15.28 16.72 L 15.28 15.28 Z M 19.6 5.2 L 17.68 5.2 L 17.68 2.32 L 14.8 2.32 L 14.8 0.4 L 19.6 0.4 L 19.6 5.2 Z M 19.6 19.6 L 19.6 14.8 L 17.68 14.8 L 17.68 17.68 L 14.8 17.68 L 14.8 19.6 L 19.6 19.6 Z M 0.4 19.6 L 5.2 19.6 L 5.2 17.68 L 2.32 17.68 L 2.32 14.8 L 0.4 14.8 L 0.4 19.6 Z M 0.4 0.4 L 0.4 5.2 L 2.32 5.2 L 2.32 2.32 L 5.2 2.32 L 5.2 0.4 L 0.4 0.4 Z"
+ android:fillColor="#000000"
+ android:strokeWidth="1"/>
+</vector> \ No newline at end of file
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index cdd1a8964b2b..d47e3f49242c 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -28,7 +28,10 @@
<string name="passkey">passkey</string>
<string name="password">password</string>
<string name="sign_ins">sign-ins</string>
+ <string name="another_device">Another device</string>
<string name="other_password_manager">Other password manager</string>
+ <!-- TODO: Check the wording here. -->
+ <string name="confirm_default_or_use_once_description">This password manager will store your passwords and passkeys to help you easily sign in.</string>
<!-- Spoken content description of an element which will close the sheet when clicked. -->
<string name="close_sheet">"Close sheet"</string>
<!-- Spoken content description of the back arrow button. -->
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index b71af2b654e4..0d5009a3bf80 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -181,6 +181,9 @@ class CredentialManagerRepo(
20, 7, 27, 11000),
)
)
+ .setRemoteEntry(
+ newRemoteEntry("key1", "subkey-1")
+ )
.setIsDefaultProvider(true)
.build(),
CreateCredentialProviderData
@@ -308,6 +311,19 @@ class CredentialManagerRepo(
)
}
+ private fun newRemoteEntry(
+ key: String,
+ subkey: String,
+ ): Entry {
+ return Entry(
+ key,
+ subkey,
+ Slice.Builder(
+ Entry.CREDENTIAL_MANAGER_ENTRY_URI, SliceSpec(Entry.VERSION, 1)
+ ).build()
+ )
+ }
+
private fun testCreateRequestInfo(): RequestInfo {
val data = Bundle()
return RequestInfo.newCreateRequestInfo(
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index 53e817e1a03a..1e43d541ac13 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -23,6 +23,7 @@ import android.credentials.ui.GetCredentialProviderData
import android.credentials.ui.CreateCredentialProviderData
import android.credentials.ui.DisabledProviderData
import com.android.credentialmanager.createflow.CreateOptionInfo
+import com.android.credentialmanager.createflow.RemoteInfo
import com.android.credentialmanager.getflow.ActionEntryInfo
import com.android.credentialmanager.getflow.AuthenticationEntryInfo
import com.android.credentialmanager.getflow.CredentialEntryInfo
@@ -120,6 +121,7 @@ class CreateFlowUtils {
displayName = pkgInfo.applicationInfo.loadLabel(packageManager).toString(),
createOptions = toCreationOptionInfoList(it.saveEntries, context),
isDefault = it.isDefaultProvider,
+ remoteEntry = toRemoteInfo(it.remoteEntry),
)
}
}
@@ -164,5 +166,17 @@ class CreateFlowUtils {
)
}
}
+
+ private fun toRemoteInfo(
+ remoteEntry: Entry?,
+ ): RemoteInfo? {
+ // TODO: should also call fromSlice after getting the official jetpack code.
+ return if (remoteEntry != null) {
+ RemoteInfo(
+ entryKey = remoteEntry.key,
+ entrySubkey = remoteEntry.subkey,
+ )
+ } else null
+ }
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
index 0c3447f02b14..123c3d454905 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
@@ -30,6 +30,7 @@ class EnabledProviderInfo(
displayName: String,
var createOptions: List<CreateOptionInfo>,
val isDefault: Boolean,
+ var remoteEntry: RemoteInfo?,
) : ProviderInfo(icon, name, displayName)
class DisabledProviderInfo(
@@ -55,6 +56,11 @@ class CreateOptionInfo(
val lastUsedTimeMillis: Long?,
) : EntryInfo(entryKey, entrySubkey)
+class RemoteInfo(
+ entryKey: String,
+ entrySubkey: String,
+) : EntryInfo(entryKey, entrySubkey)
+
data class RequestDisplayInfo(
val userName: String,
val displayName: String,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyComponents.kt
index 4769a26b8eb1..67b704f5d787 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyComponents.kt
@@ -21,6 +21,7 @@ import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
+import androidx.compose.material.icons.outlined.NewReleases
import androidx.compose.material.icons.filled.Add
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -80,7 +81,8 @@ fun CreatePasskeyScreen(
disabledProviderList = uiState.disabledProviders,
onBackButtonSelected = viewModel::onBackButtonSelected,
onOptionSelected = viewModel::onMoreOptionsRowSelected,
- onDisabledPasswordManagerSelected = viewModel::onDisabledPasswordManagerSelected
+ onDisabledPasswordManagerSelected = viewModel::onDisabledPasswordManagerSelected,
+ onRemoteEntrySelected = viewModel::onRemoteEntrySelected
)
CreateScreenState.MORE_OPTIONS_ROW_INTRO -> MoreOptionsRowIntroCard(
providerInfo = uiState.activeEntry?.activeProvider!!,
@@ -216,10 +218,11 @@ fun ProviderSelectionCard(
fun MoreOptionsSelectionCard(
requestDisplayInfo: RequestDisplayInfo,
enabledProviderList: List<EnabledProviderInfo>,
- disabledProviderList: List<DisabledProviderInfo>,
+ disabledProviderList: List<DisabledProviderInfo>?,
onBackButtonSelected: () -> Unit,
onOptionSelected: (ActiveEntry) -> Unit,
onDisabledPasswordManagerSelected: () -> Unit,
+ onRemoteEntrySelected: () -> Unit,
) {
Card() {
Column() {
@@ -267,11 +270,26 @@ fun MoreOptionsSelectionCard(
}
}
}
- item {
- MoreOptionsDisabledProvidersRow(
- disabledProviders = disabledProviderList,
- onDisabledPasswordManagerSelected = onDisabledPasswordManagerSelected,
- )
+ if (disabledProviderList != null) {
+ item {
+ MoreOptionsDisabledProvidersRow(
+ disabledProviders = disabledProviderList,
+ onDisabledPasswordManagerSelected = onDisabledPasswordManagerSelected,
+ )
+ }
+ }
+ var hasRemoteInfo = false
+ enabledProviderList.forEach {
+ if (it.remoteEntry != null) {
+ hasRemoteInfo = true
+ }
+ }
+ if (hasRemoteInfo) {
+ item {
+ RemoteEntryRow(
+ onRemoteEntrySelected = onRemoteEntrySelected,
+ )
+ }
}
}
}
@@ -292,9 +310,21 @@ fun MoreOptionsRowIntroCard(
) {
Card() {
Column() {
+ Icon(
+ Icons.Outlined.NewReleases,
+ contentDescription = null,
+ modifier = Modifier.align(alignment = Alignment.CenterHorizontally).padding(all = 24.dp)
+ )
Text(
text = stringResource(R.string.use_provider_for_all_title, providerInfo.displayName),
style = MaterialTheme.typography.titleMedium,
+ modifier = Modifier.padding(horizontal = 24.dp)
+ .align(alignment = Alignment.CenterHorizontally),
+ textAlign = TextAlign.Center,
+ )
+ Text(
+ text = stringResource(R.string.confirm_default_or_use_once_description),
+ style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.padding(all = 24.dp).align(alignment = Alignment.CenterHorizontally)
)
Row(
@@ -498,7 +528,7 @@ fun MoreOptionsInfoRow(
modifier = Modifier.fillMaxWidth(),
onClick = onOptionSelected,
icon = {
- Image(modifier = Modifier.size(32.dp, 32.dp).padding(start = 10.dp),
+ Image(modifier = Modifier.size(32.dp, 32.dp).padding(start = 16.dp),
bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
contentDescription = null)
},
@@ -508,12 +538,14 @@ fun MoreOptionsInfoRow(
Text(
text = providerInfo.displayName,
style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp)
+ modifier = Modifier.padding(top = 16.dp, start = 16.dp)
)
if (createOptionInfo.userProviderDisplayName != null) {
Text(
text = createOptionInfo.userProviderDisplayName,
- style = MaterialTheme.typography.bodyMedium)
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(start = 16.dp)
+ )
}
if (createOptionInfo.passwordCount != null && createOptionInfo.passkeyCount != null) {
Text(
@@ -524,7 +556,7 @@ fun MoreOptionsInfoRow(
createOptionInfo.passkeyCount
),
style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp)
+ modifier = Modifier.padding(bottom = 16.dp, start = 16.dp)
)
} else if (createOptionInfo.passwordCount != null) {
Text(
@@ -534,7 +566,7 @@ fun MoreOptionsInfoRow(
createOptionInfo.passwordCount
),
style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp)
+ modifier = Modifier.padding(bottom = 16.dp, start = 16.dp)
)
} else if (createOptionInfo.passkeyCount != null) {
Text(
@@ -544,7 +576,7 @@ fun MoreOptionsInfoRow(
createOptionInfo.passkeyCount
),
style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp)
+ modifier = Modifier.padding(bottom = 16.dp, start = 16.dp)
)
} else if (createOptionInfo.totalCredentialCount != null) {
// TODO: Handle the case when there is total count
@@ -567,7 +599,8 @@ fun MoreOptionsDisabledProvidersRow(
icon = {
Icon(
Icons.Filled.Add,
- contentDescription = null
+ contentDescription = null,
+ modifier = Modifier.padding(start = 16.dp)
)
},
shape = MaterialTheme.shapes.large,
@@ -576,12 +609,42 @@ fun MoreOptionsDisabledProvidersRow(
Text(
text = stringResource(R.string.other_password_manager),
style = MaterialTheme.typography.titleLarge,
- modifier = Modifier.padding(top = 16.dp)
+ modifier = Modifier.padding(top = 16.dp, start = 16.dp)
)
Text(
text = disabledProviders.joinToString(separator = ", "){ it.displayName },
style = MaterialTheme.typography.bodyMedium,
- modifier = Modifier.padding(bottom = 16.dp)
+ modifier = Modifier.padding(bottom = 16.dp, start = 16.dp)
+ )
+ }
+ }
+ )
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun RemoteEntryRow(
+ onRemoteEntrySelected: () -> Unit,
+) {
+ SuggestionChip(
+ modifier = Modifier.fillMaxWidth(),
+ onClick = onRemoteEntrySelected,
+ icon = {
+ Icon(
+ painter = painterResource(R.drawable.ic_other_devices),
+ contentDescription = null,
+ tint = Color.Unspecified,
+ modifier = Modifier.padding(start = 18.dp)
+ )
+ },
+ shape = MaterialTheme.shapes.large,
+ label = {
+ Column() {
+ Text(
+ text = stringResource(R.string.another_device),
+ style = MaterialTheme.typography.titleLarge,
+ modifier = Modifier.padding(start = 16.dp, top = 18.dp, bottom = 18.dp)
+ .align(alignment = Alignment.CenterHorizontally)
)
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyViewModel.kt
index 8b94201ad787..af74b8ea4de1 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreatePasskeyViewModel.kt
@@ -29,7 +29,7 @@ import com.android.credentialmanager.common.ResultState
data class CreatePasskeyUiState(
val enabledProviders: List<EnabledProviderInfo>,
- val disabledProviders: List<DisabledProviderInfo>,
+ val disabledProviders: List<DisabledProviderInfo>? = null,
val currentScreenState: CreateScreenState,
val requestDisplayInfo: RequestDisplayInfo,
val activeEntry: ActiveEntry? = null,
@@ -103,6 +103,10 @@ class CreatePasskeyViewModel(
// TODO: Complete this function
}
+ fun onRemoteEntrySelected() {
+ // TODO: Complete this function
+ }
+
fun onCancel() {
CredentialManagerRepo.getInstance().onCancel()
dialogResult.value = DialogResult(ResultState.CANCELED)