Merge "Remove test data fallback from the UI app." into udc-dev

This commit is contained in:
Helen Qin
2023-04-04 04:19:52 +00:00
committed by Android (Google) Code Review
6 changed files with 45 additions and 533 deletions

View File

@@ -18,14 +18,8 @@ package com.android.credentialmanager
import android.content.Context
import android.content.Intent
import android.credentials.CreateCredentialRequest
import android.credentials.Credential.TYPE_PASSWORD_CREDENTIAL
import android.credentials.CredentialOption
import android.credentials.GetCredentialRequest
import android.credentials.ui.AuthenticationEntry
import android.credentials.ui.CancelUiRequest
import android.credentials.ui.Constants
import android.credentials.ui.Entry
import android.credentials.ui.CreateCredentialProviderData
import android.credentials.ui.GetCredentialProviderData
import android.credentials.ui.DisabledProviderData
@@ -35,23 +29,16 @@ import android.credentials.ui.BaseDialogResult
import android.credentials.ui.ProviderPendingIntentResponse
import android.credentials.ui.UserSelectionDialogResult
import android.os.IBinder
import android.os.Binder
import android.os.Bundle
import android.os.ResultReceiver
import android.util.Log
import com.android.credentialmanager.createflow.DisabledProviderInfo
import com.android.credentialmanager.createflow.EnabledProviderInfo
import com.android.credentialmanager.createflow.RequestDisplayInfo
import com.android.credentialmanager.getflow.GetCredentialUiState
import com.android.credentialmanager.getflow.findAutoSelectEntry
import androidx.credentials.CreateCredentialRequest.DisplayInfo
import androidx.credentials.CreatePublicKeyCredentialRequest
import androidx.credentials.CreatePasswordRequest
import androidx.credentials.GetPasswordOption
import androidx.credentials.GetPublicKeyCredentialOption
import com.android.credentialmanager.common.ProviderActivityState
import java.time.Instant
/**
* Client for interacting with Credential Manager. Also holds data inputs from it.
*
@@ -63,7 +50,7 @@ class CredentialManagerRepo(
intent: Intent,
userConfigRepo: UserConfigRepo,
) {
val requestInfo: RequestInfo
val requestInfo: RequestInfo?
private val providerEnabledList: List<ProviderData>
private val providerDisabledList: List<DisabledProviderData>?
// TODO: require non-null.
@@ -75,27 +62,30 @@ class CredentialManagerRepo(
requestInfo = intent.extras?.getParcelable(
RequestInfo.EXTRA_REQUEST_INFO,
RequestInfo::class.java
) ?: testGetRequestInfo()
)
val originName: String? = when (requestInfo.type) {
RequestInfo.TYPE_CREATE -> requestInfo.createCredentialRequest?.origin
RequestInfo.TYPE_GET -> requestInfo.getCredentialRequest?.origin
val originName: String? = when (requestInfo?.type) {
RequestInfo.TYPE_CREATE -> requestInfo?.createCredentialRequest?.origin
RequestInfo.TYPE_GET -> requestInfo?.getCredentialRequest?.origin
else -> null
}
providerEnabledList = when (requestInfo.type) {
providerEnabledList = when (requestInfo?.type) {
RequestInfo.TYPE_CREATE ->
intent.extras?.getParcelableArrayList(
ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST,
CreateCredentialProviderData::class.java
) ?: testCreateCredentialEnabledProviderList()
) ?: emptyList()
RequestInfo.TYPE_GET ->
intent.extras?.getParcelableArrayList(
ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST,
GetCredentialProviderData::class.java
) ?: testGetCredentialProviderList()
) ?: emptyList()
else -> {
throw IllegalStateException("Unrecognized request type: ${requestInfo.type}")
Log.d(
com.android.credentialmanager.common.Constants.LOG_TAG,
"Unrecognized request type: ${requestInfo?.type}")
emptyList()
}
}
@@ -103,7 +93,7 @@ class CredentialManagerRepo(
intent.extras?.getParcelableArrayList(
ProviderData.EXTRA_DISABLED_PROVIDER_DATA_LIST,
DisabledProviderData::class.java
) ?: testDisabledProviderList()
)
resultReceiver = intent.getParcelableExtra(
Constants.EXTRA_RESULT_RECEIVER,
@@ -115,7 +105,7 @@ class CredentialManagerRepo(
CancelUiRequestState(getAppLabel(context.getPackageManager(), it.appPackageName))
}
initialUiState = when (requestInfo.type) {
initialUiState = when (requestInfo?.type) {
RequestInfo.TYPE_CREATE -> {
val defaultProviderId = userConfigRepo.getDefaultProviderId()
val isPasskeyFirstUse = userConfigRepo.getIsPasskeyFirstUse()
@@ -151,7 +141,17 @@ class CredentialManagerRepo(
cancelRequestState = cancelUiRequestState
)
}
else -> throw IllegalStateException("Unrecognized request type: ${requestInfo.type}")
else -> {
if (cancellationRequest != null) {
UiState(
createCredentialUiState = null,
getCredentialUiState = null,
cancelRequestState = cancelUiRequestState,
)
} else {
throw IllegalStateException("Unrecognized request type: ${requestInfo?.type}")
}
}
}
}
@@ -174,7 +174,7 @@ class CredentialManagerRepo(
}
fun onCancel(cancelCode: Int) {
sendCancellationCode(cancelCode, requestInfo.token, resultReceiver)
sendCancellationCode(cancelCode, requestInfo?.token, resultReceiver)
}
fun onOptionSelected(
@@ -185,7 +185,7 @@ class CredentialManagerRepo(
resultData: Intent? = null,
) {
val userSelectionDialogResult = UserSelectionDialogResult(
requestInfo.token,
requestInfo?.token,
providerId,
entryKey,
entrySubkey,
@@ -213,10 +213,9 @@ class CredentialManagerRepo(
// IMPORTANT: new invocation should be mindful that this method can throw.
private fun getCreateProviderEnableListInitialUiState(): List<EnabledProviderInfo> {
val providerEnabledList = CreateFlowUtils.toEnabledProviderList(
return CreateFlowUtils.toEnabledProviderList(
providerEnabledList as List<CreateCredentialProviderData>, context
)
return providerEnabledList
}
private fun getCreateProviderDisableListInitialUiState(): List<DisabledProviderInfo> {
@@ -253,242 +252,4 @@ class CredentialManagerRepo(
)
}
}
// TODO: below are prototype functionalities. To be removed for productionization.
private fun testCreateCredentialEnabledProviderList(): List<CreateCredentialProviderData> {
return listOf(
CreateCredentialProviderData
.Builder("io.enpass.app")
.setSaveEntries(
listOf<Entry>(
CreateTestUtils.newCreateEntry(
context,
"key1", "subkey-1", "elisa.beckett@gmail.com",
20, 7, 27, Instant.ofEpochSecond(10L),
"You can use your passkey on this or other devices. It is saved to " +
"the Password Manager for elisa.beckett@gmail.com."
),
CreateTestUtils.newCreateEntry(
context,
"key1", "subkey-2", "elisa.work@google.com",
20, 7, 27, Instant.ofEpochSecond(12L),
null
),
)
).setRemoteEntry(
CreateTestUtils.newRemoteCreateEntry(context, "key2", "subkey-1")
).build(),
CreateCredentialProviderData
.Builder("com.dashlane")
.setSaveEntries(
listOf<Entry>(
CreateTestUtils.newCreateEntry(
context,
"key1", "subkey-3", "elisa.beckett@dashlane.com",
20, 7, 27, Instant.ofEpochSecond(11L),
null
),
CreateTestUtils.newCreateEntry(
context,
"key1", "subkey-4", "elisa.work@dashlane.com",
20, 7, 27, Instant.ofEpochSecond(14L),
"You can use your passkey on this or other devices. It is saved to " +
"the Password Manager for elisa.work@dashlane.com"
),
)
).build(),
)
}
private fun testDisabledProviderList(): List<DisabledProviderData>? {
return listOf(
DisabledProviderData("com.lastpass.lpandroid"),
DisabledProviderData("com.google.android.youtube")
)
}
private fun testGetCredentialProviderList(): List<GetCredentialProviderData> {
return listOf(
GetCredentialProviderData.Builder("io.enpass.app")
.setCredentialEntries(
listOf(
GetTestUtils.newPasswordEntry(
context, "key1", "subkey-1", "elisa.family@outlook.com", null,
Instant.ofEpochSecond(8000L)
),
GetTestUtils.newPasskeyEntry(
context, "key1", "subkey-1", "elisa.bakery@gmail.com", "Elisa Beckett",
null
),
GetTestUtils.newPasswordEntry(
context, "key1", "subkey-2", "elisa.bakery@gmail.com", null,
Instant.ofEpochSecond(10000L)
),
GetTestUtils.newPasskeyEntry(
context, "key1", "subkey-3", "elisa.family@outlook.com",
"Elisa Beckett", Instant.ofEpochSecond(500L)
),
)
).setAuthenticationEntries(
listOf(
GetTestUtils.newAuthenticationEntry(
context, "key2", "subkey-1", "locked-user1@gmail.com",
AuthenticationEntry.STATUS_LOCKED
),
GetTestUtils.newAuthenticationEntry(
context, "key2", "subkey-2", "locked-user2@gmail.com",
AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_MOST_RECENT
),
)
).setActionChips(
listOf(
GetTestUtils.newActionEntry(
context, "key3", "subkey-1",
"Open Google Password Manager", "elisa.beckett@gmail.com"
),
GetTestUtils.newActionEntry(
context, "key3", "subkey-2",
"Open Google Password Manager", "beckett-family@gmail.com"
),
)
).setRemoteEntry(
GetTestUtils.newRemoteCredentialEntry(context, "key4", "subkey-1")
).build(),
GetCredentialProviderData.Builder("com.dashlane")
.setCredentialEntries(
listOf<Entry>(
GetTestUtils.newPasswordEntry(
context, "key1", "subkey-2", "elisa.family@outlook.com", null,
Instant.ofEpochSecond(9000L)
),
GetTestUtils.newPasswordEntry(
context, "key1", "subkey-3", "elisa.work@outlook.com", null,
Instant.ofEpochSecond(11000L)
),
)
).setAuthenticationEntries(
listOf(
GetTestUtils.newAuthenticationEntry(
context, "key2", "subkey-1", "foo@email.com",
AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT,
)
)
).setActionChips(
listOf(
GetTestUtils.newActionEntry(
context, "key3", "subkey-1", "Open Enpass",
"Manage passwords"
),
)
).build(),
)
}
private fun testCreatePasskeyRequestInfo(): RequestInfo {
val request = CreatePublicKeyCredentialRequest(
"{\"extensions\": {\n" +
" \"webauthn.loc\": true\n" +
" },\n" +
" \"attestation\": \"direct\",\n" +
" \"challenge\":" +
" \"-rSQHXSQUdaK1N-La5bE-JPt6EVAW4SxX1K_tXhZ_Gk\",\n" +
" \"user\": {\n" +
" \"displayName\": \"testName\",\n" +
" \"name\": \"credManTesting@gmail.com\",\n" +
" \"id\": \"eD4o2KoXLpgegAtnM5cDhhUPvvk2\"\n" +
" },\n" +
" \"excludeCredentials\": [],\n" +
" \"rp\": {\n" +
" \"name\": \"Address Book\",\n" +
" \"id\": \"addressbook-c7876.uc.r.appspot.com\"\n" +
" },\n" +
" \"timeout\": 60000,\n" +
" \"pubKeyCredParams\": [\n" +
" {\n" +
" \"type\": \"public-key\",\n" +
" \"alg\": -7\n" +
" },\n" +
" {\n" +
" \"type\": \"public-key\",\n" +
" \"alg\": -257\n" +
" },\n" +
" {\n" +
" \"type\": \"public-key\",\n" +
" \"alg\": -37\n" +
" }\n" +
" ],\n" +
" \"authenticatorSelection\": {\n" +
" \"residentKey\": \"required\",\n" +
" \"requireResidentKey\": true\n" +
" }}",
preferImmediatelyAvailableCredentials = true,
)
val credentialData = request.credentialData
return RequestInfo.newCreateRequestInfo(
Binder(),
CreateCredentialRequest.Builder("androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
credentialData, Bundle())
.setIsSystemProviderRequired(false)
.setAlwaysSendAppInfoToProvider(true)
.build(),
"com.google.android.youtube"
)
}
private fun testCreatePasswordRequestInfo(): RequestInfo {
val request = CreatePasswordRequest("beckett-bakert@gmail.com", "password123")
return RequestInfo.newCreateRequestInfo(
Binder(),
CreateCredentialRequest.Builder(TYPE_PASSWORD_CREDENTIAL,
request.credentialData, request.candidateQueryData)
.setIsSystemProviderRequired(false)
.setAlwaysSendAppInfoToProvider(true)
.build(),
"com.google.android.youtube"
)
}
private fun testCreateOtherCredentialRequestInfo(): RequestInfo {
val data = Bundle()
val displayInfo = DisplayInfo("my-username00", "Joe")
data.putBundle(
"androidx.credentials.BUNDLE_KEY_REQUEST_DISPLAY_INFO",
displayInfo.toBundle()
)
return RequestInfo.newCreateRequestInfo(
Binder(),
CreateCredentialRequest.Builder("other-sign-ins", data, Bundle())
.setIsSystemProviderRequired(false)
.setAlwaysSendAppInfoToProvider(true)
.build(),
"com.google.android.youtube"
)
}
private fun testGetRequestInfo(): RequestInfo {
val passwordOption = GetPasswordOption()
val passkeyOption = GetPublicKeyCredentialOption(
"json", preferImmediatelyAvailableCredentials = false)
return RequestInfo.newGetRequestInfo(
Binder(),
GetCredentialRequest.Builder(
Bundle()
).addCredentialOption(
CredentialOption.Builder(
passwordOption.type,
passwordOption.requestData,
passwordOption.candidateQueryData,
).setIsSystemProviderRequired(passwordOption.isSystemProviderRequired)
.build()
).addCredentialOption(
CredentialOption.Builder(
passkeyOption.type,
passkeyOption.requestData,
passkeyOption.candidateQueryData,
).setIsSystemProviderRequired(passkeyOption.isSystemProviderRequired)
.build()
).build(),
"com.google.android.youtube"
)
}
}

View File

@@ -111,7 +111,7 @@ class CredentialSelectorActivity : ComponentActivity() {
?: return Triple(false, false, null)
if (viewModel != null && !viewModel.shouldCancelCurrentUi(cancelUiRequest.token)) {
// Cancellation was for a different request, don't cancel the current UI.
return Triple(false, false, null)
return Triple(true, false, null)
}
val shouldShowCancellationUi = cancelUiRequest.shouldShowCancellationUi()
Log.d(

View File

@@ -69,7 +69,7 @@ class CredentialSelectorViewModel(
init{
uiMetrics.logNormal(LifecycleEvent.CREDMAN_ACTIVITY_INIT,
credManRepo.requestInfo.appPackageName)
credManRepo.requestInfo?.appPackageName)
}
/**************************************************************************/
@@ -97,10 +97,10 @@ class CredentialSelectorViewModel(
this.credManRepo = credManRepo
uiState = credManRepo.initState()
if (this.credManRepo.requestInfo.token != credManRepo.requestInfo.token) {
if (this.credManRepo.requestInfo?.token != credManRepo.requestInfo?.token) {
this.uiMetrics.resetInstanceId()
this.uiMetrics.logNormal(LifecycleEvent.CREDMAN_ACTIVITY_NEW_REQUEST,
credManRepo.requestInfo.appPackageName)
credManRepo.requestInfo?.appPackageName)
}
}
@@ -174,14 +174,14 @@ class CredentialSelectorViewModel(
private fun onInternalError() {
Log.w(Constants.LOG_TAG, "UI closed due to illegal internal state")
this.uiMetrics.logNormal(LifecycleEvent.CREDMAN_ACTIVITY_INTERNAL_ERROR,
credManRepo.requestInfo.appPackageName)
credManRepo.requestInfo?.appPackageName)
credManRepo.onParsingFailureCancel()
uiState = uiState.copy(dialogState = DialogState.COMPLETE)
}
/** Return true if the current UI's request token matches the UI cancellation request token. */
fun shouldCancelCurrentUi(cancelRequestToken: IBinder): Boolean {
return credManRepo.requestInfo.token.equals(cancelRequestToken)
return credManRepo.requestInfo?.token?.equals(cancelRequestToken) ?: false
}
/**************************************************************************/
@@ -405,6 +405,6 @@ class CredentialSelectorViewModel(
@Composable
fun logUiEvent(uiEventEnum: UiEventEnum) {
this.uiMetrics.log(uiEventEnum, credManRepo.requestInfo.appPackageName)
this.uiMetrics.log(uiEventEnum, credManRepo.requestInfo?.appPackageName)
}
}

View File

@@ -188,11 +188,11 @@ class GetFlowUtils {
}
fun toRequestDisplayInfo(
requestInfo: RequestInfo,
requestInfo: RequestInfo?,
context: Context,
originName: String?,
): com.android.credentialmanager.getflow.RequestDisplayInfo? {
val getCredentialRequest = requestInfo.getCredentialRequest ?: return null
val getCredentialRequest = requestInfo?.getCredentialRequest ?: return null
val preferImmediatelyAvailableCredentials = getCredentialRequest.credentialOptions.any {
val credentialOptionJetpack = CredentialOption.createFrom(
it.type,
@@ -450,10 +450,13 @@ class CreateFlowUtils {
}
fun toRequestDisplayInfo(
requestInfo: RequestInfo,
requestInfo: RequestInfo?,
context: Context,
originName: String?,
): RequestDisplayInfo? {
if (requestInfo == null) {
return null
}
val appLabel = originName
?: getAppLabel(context.packageManager, requestInfo.appPackageName)
?: return null

View File

@@ -1,252 +0,0 @@
/*
* Copyright (C) 2023 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.
*/
package com.android.credentialmanager
import android.app.PendingIntent
import android.app.slice.Slice
import android.app.slice.SliceSpec
import android.content.Context
import android.content.Intent
import android.credentials.Credential.TYPE_PASSWORD_CREDENTIAL
import android.credentials.ui.AuthenticationEntry
import android.credentials.ui.Entry
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import androidx.credentials.provider.BeginGetPasswordOption
import androidx.credentials.provider.BeginGetPublicKeyCredentialOption
import androidx.credentials.provider.CreateEntry
import androidx.credentials.provider.PasswordCredentialEntry
import androidx.credentials.provider.PublicKeyCredentialEntry
import androidx.credentials.provider.RemoteEntry
import java.time.Instant
// TODO: remove once testing is complete
class GetTestUtils {
companion object {
internal fun newAuthenticationEntry(
context: Context,
key: String,
subkey: String,
title: String,
status: Int
): AuthenticationEntry {
val slice = Slice.Builder(
Uri.EMPTY, SliceSpec("AuthenticationAction", 0)
)
val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
val pendingIntent =
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
slice.addAction(
pendingIntent,
Slice.Builder(slice)
.addHints(listOf("androidx.credentials.provider.authenticationAction" +
".SLICE_HINT_PENDING_INTENT"))
.build(),
/*subType=*/null
)
slice.addText(
title,
null,
listOf("androidx.credentials.provider.authenticationAction.SLICE_HINT_TITLE")
)
return AuthenticationEntry(
key,
subkey,
slice.build(),
status
)
}
internal fun newRemoteCredentialEntry(
context: Context,
key: String,
subkey: String,
): Entry {
val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
val pendingIntent =
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
return Entry(
key,
subkey,
RemoteEntry.toSlice(RemoteEntry(pendingIntent))
)
}
internal fun newActionEntry(
context: Context,
key: String,
subkey: String,
text: String,
subtext: String? = null,
): Entry {
val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
val pendingIntent =
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val sliceBuilder = Slice.Builder(Uri.EMPTY, SliceSpec("Action", 0))
.addText(
text, /*subType=*/null,
listOf("androidx.credentials.provider.action.HINT_ACTION_TITLE")
)
.addText(
subtext, /*subType=*/null,
listOf("androidx.credentials.provider.action.HINT_ACTION_SUBTEXT")
)
sliceBuilder.addAction(
pendingIntent,
Slice.Builder(sliceBuilder)
.addHints(
listOf("androidx.credentials.provider.action.SLICE_HINT_PENDING_INTENT")
)
.build(),
/*subType=*/null
)
return Entry(
key,
subkey,
sliceBuilder.build()
)
}
internal fun newPasswordEntry(
context: Context,
key: String,
subkey: String,
userName: String,
userDisplayName: String?,
lastUsedTime: Instant?,
): Entry {
val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
.setPackage("com.androidauth.androidvault")
intent.putExtra("provider_extra_sample", "testprovider")
val pendingIntent = PendingIntent.getActivity(
context, 1,
intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
or PendingIntent.FLAG_ONE_SHOT)
)
val passwordEntry = PasswordCredentialEntry.Builder(
context, userName, pendingIntent, BeginGetPasswordOption(Bundle(), "id"))
.setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime).build()
return Entry(key, subkey, passwordEntry.slice, Intent())
}
internal fun newPasskeyEntry(
context: Context,
key: String,
subkey: String,
userName: String,
userDisplayName: String?,
lastUsedTime: Instant?,
isAutoSelectAllowed: Boolean = false,
): Entry {
val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
val pendingIntent =
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val candidateQueryData = Bundle()
candidateQueryData.putBoolean(
"androidx.credentials.BUNDLE_KEY_IS_AUTO_SELECT_ALLOWED",
isAutoSelectAllowed
)
val passkeyEntry = PublicKeyCredentialEntry.Builder(
context,
userName,
pendingIntent,
BeginGetPublicKeyCredentialOption(candidateQueryData, "id", "requestjson")
).setDisplayName(userDisplayName).setLastUsedTime(lastUsedTime)
.setAutoSelectAllowed(isAutoSelectAllowed).build()
return Entry(key, subkey, passkeyEntry.slice, Intent())
}
}
}
class CreateTestUtils {
companion object {
private const val TYPE_TOTAL_CREDENTIAL = "TOTAL_CREDENTIAL_COUNT_TYPE"
private const val SLICE_HINT_ACCOUNT_NAME =
"androidx.credentials.provider.createEntry.SLICE_HINT_USER_PROVIDER_ACCOUNT_NAME"
private const val SLICE_HINT_NOTE =
"androidx.credentials.provider.createEntry.SLICE_HINT_NOTE"
private const val SLICE_HINT_ICON =
"androidx.credentials.provider.createEntry.SLICE_HINT_PROFILE_ICON"
private const val SLICE_HINT_CREDENTIAL_COUNT_INFORMATION =
"androidx.credentials.provider.createEntry.SLICE_HINT_CREDENTIAL_COUNT_INFORMATION"
private const val SLICE_HINT_LAST_USED_TIME_MILLIS =
"androidx.credentials.provider.createEntry.SLICE_HINT_LAST_USED_TIME_MILLIS"
private const val SLICE_HINT_PENDING_INTENT =
"androidx.credentials.provider.createEntry.SLICE_HINT_PENDING_INTENT"
internal fun newCreateEntry(
context: Context,
key: String,
subkey: String,
providerUserDisplayName: String,
passwordCount: Int?,
passkeyCount: Int?,
totalCredentialCount: Int?,
lastUsedTime: Instant?,
footerDescription: String?,
): Entry {
val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
.setPackage("com.androidauth.androidvault")
intent.putExtra("provider_extra_sample", "testprovider")
val pendingIntent = PendingIntent.getActivity(
context, 1,
intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
or PendingIntent.FLAG_ONE_SHOT)
)
val credCountMap = mutableMapOf<String, Int>()
passwordCount?.let { credCountMap.put(TYPE_PASSWORD_CREDENTIAL, it) }
passkeyCount?.let {
credCountMap.put("androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL", it)
}
totalCredentialCount?.let { credCountMap.put(TYPE_TOTAL_CREDENTIAL, it) }
return Entry(
key,
subkey,
CreateEntry.toSlice(
CreateEntry(
accountName = providerUserDisplayName,
pendingIntent = pendingIntent,
description = footerDescription,
lastUsedTime = lastUsedTime,
icon = null,
passwordCredentialCount = passwordCount,
publicKeyCredentialCount = passkeyCount,
totalCredentialCount = totalCredentialCount,
)
),
Intent()
)
}
internal fun newRemoteCreateEntry(
context: Context,
key: String,
subkey: String,
): Entry {
val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
val pendingIntent =
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
return Entry(
key,
subkey,
RemoteEntry.toSlice(RemoteEntry(pendingIntent))
)
}
}
}

View File

@@ -43,7 +43,7 @@ class UIMetrics() {
}
@Composable
fun log(event: UiEventLogger.UiEventEnum, packageName: String) {
fun log(event: UiEventLogger.UiEventEnum, packageName: String?) {
val instanceId: InstanceId = mInstanceId
LaunchedEffect(true) {
mUiEventLogger.logWithInstanceId(event, /*uid=*/0, packageName, instanceId)
@@ -51,13 +51,13 @@ class UIMetrics() {
}
@Composable
fun log(event: UiEventLogger.UiEventEnum, instanceId: InstanceId, packageName: String) {
fun log(event: UiEventLogger.UiEventEnum, instanceId: InstanceId, packageName: String?) {
LaunchedEffect(true) {
mUiEventLogger.logWithInstanceId(event, /*uid=*/0, packageName, instanceId)
}
}
fun logNormal(event: UiEventLogger.UiEventEnum, packageName: String) {
fun logNormal(event: UiEventLogger.UiEventEnum, packageName: String?) {
mUiEventLogger.logWithInstanceId(event, /*uid=*/0, packageName, mInstanceId)
}
}