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

Commit d333c91c authored by Qinmei Du's avatar Qinmei Du Committed by Android (Google) Code Review
Browse files

Merge "Update the logic and storage about isFirstTimeUse and defaultProvider"

parents cbc1cb61 53270521
Loading
Loading
Loading
Loading
+6 −30
Original line number Diff line number Diff line
@@ -41,8 +41,6 @@ import android.os.Bundle
import android.os.ResultReceiver
import android.service.credentials.CredentialProviderService
import com.android.credentialmanager.createflow.CreateCredentialUiState
import com.android.credentialmanager.createflow.EnabledProviderInfo
import com.android.credentialmanager.createflow.RemoteInfo
import com.android.credentialmanager.getflow.GetCredentialUiState
import com.android.credentialmanager.jetpack.developer.CreatePasswordRequest.Companion.toBundle
import com.android.credentialmanager.jetpack.developer.CreatePublicKeyCredentialRequest
@@ -63,7 +61,7 @@ class CredentialManagerRepo(
    requestInfo = intent.extras?.getParcelable(
      RequestInfo.EXTRA_REQUEST_INFO,
      RequestInfo::class.java
    ) ?: testGetRequestInfo()
    ) ?: testCreatePasskeyRequestInfo()

    providerEnabledList = when (requestInfo.type) {
      RequestInfo.TYPE_CREATE ->
@@ -101,7 +99,7 @@ class CredentialManagerRepo(
  }

  fun onOptionSelected(
    providerPackageName: String,
    providerId: String,
    entryKey: String,
    entrySubkey: String,
    resultCode: Int? = null,
@@ -109,7 +107,7 @@ class CredentialManagerRepo(
  ) {
    val userSelectionDialogResult = UserSelectionDialogResult(
      requestInfo.token,
      providerPackageName,
      providerId,
      entryKey,
      entrySubkey,
      if (resultCode != null) ProviderPendingIntentResponse(resultCode, resultData) else null
@@ -138,36 +136,15 @@ class CredentialManagerRepo(
    val providerDisabledList = CreateFlowUtils.toDisabledProviderList(
      // Handle runtime cast error
      providerDisabledList, context)
    var defaultProvider: EnabledProviderInfo? = null
    var remoteEntry: RemoteInfo? = null
    var createOptionSize = 0
    var lastSeenProviderWithNonEmptyCreateOptions: EnabledProviderInfo? = null
    providerEnabledList.forEach{providerInfo -> providerInfo.createOptions =
      providerInfo.createOptions.sortedWith(compareBy { it.lastUsedTimeMillis }).reversed()
      if (providerInfo.isDefault) {defaultProvider = providerInfo}
      if (providerInfo.remoteEntry != null) {
        remoteEntry = providerInfo.remoteEntry!!
    }
      if (providerInfo.createOptions.isNotEmpty()) {
        createOptionSize += providerInfo.createOptions.size
        lastSeenProviderWithNonEmptyCreateOptions = providerInfo
      }
    }
    return CreateCredentialUiState(
      enabledProviders = providerEnabledList,
      disabledProviders = providerDisabledList,
      CreateFlowUtils.toCreateScreenState(
        createOptionSize, false,
        requestDisplayInfo, defaultProvider, remoteEntry),
      requestDisplayInfo,
      false,
      CreateFlowUtils.toActiveEntry(
        /*defaultProvider=*/defaultProvider, createOptionSize,
        lastSeenProviderWithNonEmptyCreateOptions, remoteEntry),
    )
    return CreateFlowUtils.toCreateCredentialUiState(
      providerEnabledList, providerDisabledList, requestDisplayInfo, false)
  }

  companion object {
    // TODO: find a way to resolve this static field leak problem
    lateinit var repo: CredentialManagerRepo

    fun setup(
@@ -198,7 +175,6 @@ class CredentialManagerRepo(
        .setRemoteEntry(
          newRemoteEntry("key2", "subkey-1")
        )
        .setIsDefaultProvider(true)
        .build(),
      CreateCredentialProviderData
        .Builder("com.dashlane")
+1 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ class CredentialSelectorActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    CredentialManagerRepo.setup(this, intent)
    UserConfigRepo.setup(this)
    val requestInfo = CredentialManagerRepo.getInstance().requestInfo
    setContent {
      CredentialSelectorTheme {
+52 −13
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ import com.android.credentialmanager.createflow.RequestDisplayInfo
import com.android.credentialmanager.createflow.EnabledProviderInfo
import com.android.credentialmanager.createflow.CreateScreenState
import com.android.credentialmanager.createflow.ActiveEntry
import com.android.credentialmanager.createflow.DisabledProviderInfo
import com.android.credentialmanager.createflow.CreateCredentialUiState
import com.android.credentialmanager.getflow.ActionEntryInfo
import com.android.credentialmanager.getflow.AuthenticationEntryInfo
import com.android.credentialmanager.getflow.CredentialEntryInfo
@@ -208,14 +210,13 @@ class CreateFlowUtils {
        val pkgInfo = packageManager
          .getPackageInfo(packageName!!,
            PackageManager.PackageInfoFlags.of(0))
        com.android.credentialmanager.createflow.EnabledProviderInfo(
        EnabledProviderInfo(
          // TODO: decide what to do when failed to load a provider icon
          icon = pkgInfo.applicationInfo.loadIcon(packageManager)!!,
          name = it.providerFlattenedComponentName,
          displayName = pkgInfo.applicationInfo.loadLabel(packageManager).toString(),
          createOptions = toCreationOptionInfoList(
            it.providerFlattenedComponentName, it.saveEntries, requestDisplayInfo, context),
          isDefault = it.isDefaultProvider,
          remoteEntry = toRemoteInfo(it.providerFlattenedComponentName, it.remoteEntry),
        )
      }
@@ -256,8 +257,7 @@ class CreateFlowUtils {
            createCredentialRequestJetpack.password,
            createCredentialRequestJetpack.type,
            requestInfo.appPackageName,
            context.getDrawable(R.drawable.ic_password)!!,
            requestInfo.isFirstUsage
            context.getDrawable(R.drawable.ic_password)!!
          )
        }
        is CreatePublicKeyCredentialRequest -> {
@@ -275,8 +275,7 @@ class CreateFlowUtils {
            displayName,
            createCredentialRequestJetpack.type,
            requestInfo.appPackageName,
            context.getDrawable(R.drawable.ic_passkey)!!,
            requestInfo.isFirstUsage)
            context.getDrawable(R.drawable.ic_passkey)!!)
        }
        // TODO: correctly parsing for other sign-ins
        else -> {
@@ -285,20 +284,60 @@ class CreateFlowUtils {
            "Elisa Beckett",
            "other-sign-ins",
            requestInfo.appPackageName,
            context.getDrawable(R.drawable.ic_other_sign_in)!!,
            requestInfo.isFirstUsage)
            context.getDrawable(R.drawable.ic_other_sign_in)!!)
        }
      }
    }

    fun toCreateScreenState(
    fun toCreateCredentialUiState(
      enabledProviders: List<EnabledProviderInfo>,
      disabledProviders: List<DisabledProviderInfo>?,
      requestDisplayInfo: RequestDisplayInfo,
      isOnPasskeyIntroStateAlready: Boolean,
    ): CreateCredentialUiState {
      var createOptionSize = 0
      var lastSeenProviderWithNonEmptyCreateOptions: EnabledProviderInfo? = null
      var remoteEntry: RemoteInfo? = null
      var defaultProvider: EnabledProviderInfo? = null
      val defaultProviderId = UserConfigRepo.getInstance().getDefaultProviderId()
      enabledProviders.forEach {
          enabledProvider ->
        if (defaultProviderId != null) {
          if (enabledProvider.name == defaultProviderId) {
            defaultProvider = enabledProvider
          }
        }
        if (enabledProvider.createOptions.isNotEmpty()) {
          createOptionSize += enabledProvider.createOptions.size
          lastSeenProviderWithNonEmptyCreateOptions = enabledProvider
        }
        if (enabledProvider.remoteEntry != null) {
          remoteEntry = enabledProvider.remoteEntry!!
        }
      }
      return CreateCredentialUiState(
        enabledProviders = enabledProviders,
        disabledProviders = disabledProviders,
        toCreateScreenState(
          createOptionSize, isOnPasskeyIntroStateAlready,
          requestDisplayInfo, defaultProvider, remoteEntry),
        requestDisplayInfo,
        isOnPasskeyIntroStateAlready,
        toActiveEntry(
          /*defaultProvider=*/defaultProvider, createOptionSize,
          lastSeenProviderWithNonEmptyCreateOptions, remoteEntry),
      )
    }

    private fun toCreateScreenState(
      createOptionSize: Int,
      isOnPasskeyIntroStateAlready: Boolean,
      requestDisplayInfo: RequestDisplayInfo,
      defaultProvider: EnabledProviderInfo?,
      remoteEntry: RemoteInfo?,
    ): CreateScreenState {
      return if (requestDisplayInfo.isFirstUsage && requestDisplayInfo
      return if (
        UserConfigRepo.getInstance().getIsFirstUse() && requestDisplayInfo
          .type == TYPE_PUBLIC_KEY_CREDENTIAL && !isOnPasskeyIntroStateAlready) {
        CreateScreenState.PASSKEY_INTRO
      } else if (
@@ -318,7 +357,7 @@ class CreateFlowUtils {
      }
    }

   fun toActiveEntry(
    private fun toActiveEntry(
      defaultProvider: EnabledProviderInfo?,
      createOptionSize: Int,
      lastSeenProviderWithNonEmptyCreateOptions: EnabledProviderInfo?,
+70 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

package com.android.credentialmanager

import android.content.Context
import android.content.SharedPreferences

class UserConfigRepo(context: Context) {
    val sharedPreferences: SharedPreferences = context.getSharedPreferences(
        context.packageName, Context.MODE_PRIVATE)

    fun setDefaultProvider(
        providerId: String
    ) {
        sharedPreferences.edit().apply {
            putString(DEFAULT_PROVIDER, providerId)
            apply()
        }
    }

    fun setIsFirstUse(
        isFirstUse: Boolean
    ) {
        sharedPreferences.edit().apply {
            putBoolean(IS_PASSKEY_FIRST_USE, isFirstUse)
            apply()
        }
    }

    fun getDefaultProviderId(): String? {
        return sharedPreferences.getString(DEFAULT_PROVIDER, null)
    }

    fun getIsFirstUse(): Boolean {
        return sharedPreferences.getBoolean(IS_PASSKEY_FIRST_USE, true)
    }

    companion object {
        lateinit var repo: UserConfigRepo

        const val DEFAULT_PROVIDER = "default_provider"
        // This first use value only applies to passkeys, not related with if generally
        // credential manager is first use or not
        const val IS_PASSKEY_FIRST_USE = "is_passkey_first_use"

        fun setup(
            context: Context,
        ) {
            repo = UserConfigRepo(context)
        }

        fun getInstance(): UserConfigRepo {
            return repo
        }
    }
}
+6 −4
Original line number Diff line number Diff line
@@ -108,7 +108,8 @@ fun CreateCredentialScreen(
                    )
                    CreateScreenState.MORE_OPTIONS_ROW_INTRO -> MoreOptionsRowIntroCard(
                        providerInfo = uiState.activeEntry?.activeProvider!!,
                        onDefaultOrNotSelected = viewModel::onDefaultOrNotSelected
                        onChangeDefaultSelected = viewModel::onChangeDefaultSelected,
                        onUseOnceSelected = viewModel::onUseOnceSelected,
                    )
                    CreateScreenState.EXTERNAL_ONLY_SELECTION -> ExternalOnlySelectionCard(
                        requestDisplayInfo = uiState.requestDisplayInfo,
@@ -464,7 +465,8 @@ fun MoreOptionsSelectionCard(
@Composable
fun MoreOptionsRowIntroCard(
    providerInfo: EnabledProviderInfo,
    onDefaultOrNotSelected: () -> Unit,
    onChangeDefaultSelected: () -> Unit,
    onUseOnceSelected: () -> Unit,
) {
    ContainerCard() {
        Column() {
@@ -496,11 +498,11 @@ fun MoreOptionsRowIntroCard(
            ) {
                CancelButton(
                    stringResource(R.string.use_once),
                    onClick = onDefaultOrNotSelected
                    onClick = onUseOnceSelected
                )
                ConfirmButton(
                    stringResource(R.string.set_as_default),
                    onClick = onDefaultOrNotSelected
                    onClick = onChangeDefaultSelected
                )
            }
            Divider(
Loading