Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a953470 authored by Helen Qin's avatar Helen Qin Committed by Android (Google) Code Review
Browse files

Merge "UI bug fixes."

parents c5f7aa5f cbac773c
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@
      android:supportsRtl="true"
      android:theme="@style/Theme.CredentialSelector">

    <!--TODO: make sure implementing singleTop on NewIntent-->
    <activity
        android:name=".CredentialSelectorActivity"
        android:exported="true"
+17 −12
Original line number Diff line number Diff line
@@ -49,7 +49,12 @@ import androidx.credentials.CreatePasswordRequest

import java.time.Instant

// Consider repo per screen, similar to view model?
/**
 * Client for interacting with Credential Manager. Also holds data inputs from it.
 *
 * IMPORTANT: instantiation of the object can fail if the data inputs aren't valid. Callers need
 * to be equipped to handle this gracefully.
 */
class CredentialManagerRepo(
    private val context: Context,
    intent: Intent,
@@ -81,7 +86,6 @@ class CredentialManagerRepo(
                    GetCredentialProviderData::class.java
                ) ?: testGetCredentialProviderList()
            else -> {
                // TODO: fail gracefully
                throw IllegalStateException("Unrecognized request type: ${requestInfo.type}")
            }
        }
@@ -167,9 +171,9 @@ class CredentialManagerRepo(
        )
    }

    // IMPORTANT: new invocation should be mindful that this method can throw.
    private fun getCredentialInitialUiState(): GetCredentialUiState? {
        val providerEnabledList = GetFlowUtils.toProviderList(
            // TODO: handle runtime cast error
            providerEnabledList as List<GetCredentialProviderData>, context
        )
        val requestDisplayInfo = GetFlowUtils.toRequestDisplayInfo(requestInfo, context)
@@ -179,9 +183,9 @@ class CredentialManagerRepo(
        )
    }

    // IMPORTANT: new invocation should be mindful that this method can throw.
    private fun getCreateProviderEnableListInitialUiState(): List<EnabledProviderInfo> {
        val providerEnabledList = CreateFlowUtils.toEnabledProviderList(
            // Handle runtime cast error
            providerEnabledList as List<CreateCredentialProviderData>, context
        )
        return providerEnabledList
@@ -266,7 +270,7 @@ class CredentialManagerRepo(
        return listOf(
            GetCredentialProviderData.Builder("io.enpass.app")
                .setCredentialEntries(
                    listOf<Entry>(
                    listOf(
                        GetTestUtils.newPasswordEntry(
                            context, "key1", "subkey-1", "elisa.family@outlook.com", null,
                            Instant.ofEpochSecond(8000L)
@@ -285,8 +289,11 @@ class CredentialManagerRepo(
                        ),
                    )
                ).setAuthenticationEntries(
            listOf<Entry>(
                    GetTestUtils.newAuthenticationEntry(context, "key2", "subkey-1"),
                    listOf(
                        GetTestUtils.newAuthenticationEntry(
                            context, "key2", "subkey-1", "locked-user1@gmail.com"),
                        GetTestUtils.newAuthenticationEntry(
                            context, "key2", "subkey-2", "locked-user2@gmail.com"),
                    )
                ).setActionChips(
                    listOf(
@@ -315,9 +322,8 @@ class CredentialManagerRepo(
                        ),
                    )
                ).setAuthenticationEntries(
                     listOf<Entry>(
                    GetTestUtils.newAuthenticationEntry(context, "key2", "subkey-1"),
                     )
                     listOf(GetTestUtils.newAuthenticationEntry(
                         context, "key2", "subkey-1", "foo@email.com"))
                ).setActionChips(
                    listOf(
                        GetTestUtils.newActionEntry(
@@ -388,7 +394,6 @@ class CredentialManagerRepo(
            CreateCredentialRequest(
                "androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
                credentialData,
                // TODO: populate with actual data
                /*candidateQueryData=*/ Bundle(),
                /*isSystemProviderRequired=*/ false
            ),
+10 −3
Original line number Diff line number Diff line
@@ -92,13 +92,20 @@ class CredentialSelectorActivity : ComponentActivity() {
            handleDialogState(viewModel.uiState.dialogState)
        }

        if (viewModel.uiState.createCredentialUiState != null) {
        val createCredentialUiState = viewModel.uiState.createCredentialUiState
        val getCredentialUiState = viewModel.uiState.getCredentialUiState
        if (createCredentialUiState != null) {
            CreateCredentialScreen(
                viewModel = viewModel,
                createCredentialUiState = createCredentialUiState,
                providerActivityLauncher = launcher
            )
        } else if (getCredentialUiState != null) {
            GetCredentialScreen(
                viewModel = viewModel,
                getCredentialUiState = getCredentialUiState,
                providerActivityLauncher = launcher
            )
        } else if (viewModel.uiState.getCredentialUiState != null) {
            GetCredentialScreen(viewModel = viewModel, providerActivityLauncher = launcher)
        } else {
            Log.d(Constants.LOG_TAG, "UI wasn't able to render neither get nor create flow")
            reportInstantiationErrorAndFinishActivity(credManRepo)
+2 −2
Original line number Diff line number Diff line
@@ -255,14 +255,14 @@ class CredentialSelectorViewModel(
    }

    fun createFlowOnEntrySelectedFromFirstUseScreen(activeEntry: ActiveEntry) {
        val providerId = activeEntry.activeProvider.id
        createFlowOnDefaultChanged(providerId)
        uiState = uiState.copy(
            createCredentialUiState = uiState.createCredentialUiState?.copy(
                currentScreenState = CreateScreenState.CREATION_OPTION_SELECTION,
                activeEntry = activeEntry
            )
        )
        val providerId = uiState.createCredentialUiState?.activeEntry?.activeProvider?.id
        createFlowOnDefaultChanged(providerId)
    }

    fun createFlowOnDisabledProvidersSelected() {
+33 −10
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.credentialmanager

import android.app.slice.Slice
import android.app.slice.SliceItem
import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
@@ -176,7 +177,9 @@ class GetFlowUtils {
        }


        /* From service data structure to UI credential entry list representation. */
        /**
         * Note: caller required handle empty list due to parsing error.
         */
        private fun getCredentialOptionInfoList(
            providerId: String,
            credentialEntries: List<Entry>,
@@ -255,6 +258,9 @@ class GetFlowUtils {
            }
        }

        /**
         * Note: caller required handle empty list due to parsing error.
         */
        private fun getAuthenticationEntryList(
            providerId: String,
            providerDisplayName: String,
@@ -262,16 +268,24 @@ class GetFlowUtils {
            authEntryList: List<Entry>,
        ): List<AuthenticationEntryInfo> {
            val result: MutableList<AuthenticationEntryInfo> = mutableListOf()
            authEntryList.forEach {
            authEntryList.forEach { entry ->
                val structuredAuthEntry =
                    AuthenticationAction.fromSlice(it.slice) ?: return@forEach
                    AuthenticationAction.fromSlice(entry.slice) ?: return@forEach

                // TODO: replace with official jetpack code.
                val titleItem: SliceItem? = entry.slice.items.firstOrNull {
                    it.hasHint(
                        "androidx.credentials.provider.authenticationAction.SLICE_HINT_TITLE")
                }
                val title: String = titleItem?.text?.toString() ?: providerDisplayName

                result.add(AuthenticationEntryInfo(
                    providerId = providerId,
                    entryKey = it.key,
                    entrySubkey = it.subkey,
                    entryKey = entry.key,
                    entrySubkey = entry.subkey,
                    pendingIntent = structuredAuthEntry.pendingIntent,
                    fillInIntent = it.frameworkExtrasIntent,
                    title = providerDisplayName,
                    fillInIntent = entry.frameworkExtrasIntent,
                    title = title,
                    icon = providerIcon,
                ))
            }
@@ -279,7 +293,6 @@ class GetFlowUtils {
        }

        private fun getRemoteEntry(providerId: String, remoteEntry: Entry?): RemoteEntryInfo? {
            // TODO: should also call fromSlice after getting the official jetpack code.
            if (remoteEntry == null) {
                return null
            }
@@ -294,6 +307,9 @@ class GetFlowUtils {
            )
        }

        /**
         * Note: caller required handle empty list due to parsing error.
         */
        private fun getActionEntryList(
            providerId: String,
            actionEntries: List<Entry>,
@@ -321,7 +337,9 @@ class GetFlowUtils {

class CreateFlowUtils {
    companion object {
        // Returns the list (potentially empty) of enabled provider.
        /**
         * Note: caller required handle empty list due to parsing error.
         */
        fun toEnabledProviderList(
            providerDataList: List<CreateCredentialProviderData>,
            context: Context,
@@ -346,7 +364,9 @@ class CreateFlowUtils {
            return providerList
        }

        // Returns the list (potentially empty) of disabled provider.
        /**
         * Note: caller required handle empty list due to parsing error.
         */
        fun toDisabledProviderList(
            providerDataList: List<DisabledProviderData>?,
            context: Context,
@@ -532,6 +552,9 @@ class CreateFlowUtils {
            } else null
        }

        /**
         * Note: caller required handle empty list due to parsing error.
         */
        private fun toCreationOptionInfoList(
            providerId: String,
            creationEntries: List<Entry>,
Loading