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

Commit 71464f4f authored by Daniel Kim's avatar Daniel Kim Committed by Android (Google) Code Review
Browse files

Merge "Return inline presentations of credential entries" into main

parents a21d4297 9c2bd2ee
Loading
Loading
Loading
Loading
+82 −3
Original line number Diff line number Diff line
@@ -27,14 +27,21 @@ import android.os.Bundle
import android.os.CancellationSignal
import android.os.OutcomeReceiver
import android.service.autofill.AutofillService
import android.service.autofill.Dataset
import android.service.autofill.Field
import android.service.autofill.FillCallback
import android.service.autofill.FillRequest
import android.service.autofill.FillResponse
import android.service.autofill.InlinePresentation
import android.service.autofill.Presentations
import android.service.autofill.SaveCallback
import android.service.autofill.SaveRequest
import android.service.credentials.CredentialProviderService
import android.util.Log
import android.view.autofill.AutofillId
import android.widget.inline.InlinePresentationSpec
import androidx.autofill.inline.v1.InlineSuggestionUi
import com.android.credentialmanager.GetFlowUtils
import org.json.JSONObject
import java.util.concurrent.Executors

@@ -74,8 +81,13 @@ class CredentialAutofillService : AutofillService() {
                GetCandidateCredentialsException> {
            override fun onResult(result: GetCandidateCredentialsResponse) {
                Log.i(TAG, "getCandidateCredentials onResponse")
                val fillResponse: FillResponse? = convertToFillResponse(result, request)
                val fillResponse = convertToFillResponse(result, request)
                if (fillResponse != null) {
                    callback.onSuccess(fillResponse)
                } else {
                    Log.e(TAG, "Failed to create a FillResponse from the CredentialResponse.")
                    callback.onFailure("No dataset was created from the CredentialResponse")
                }
            }

            override fun onError(error: GetCandidateCredentialsException) {
@@ -97,7 +109,74 @@ class CredentialAutofillService : AutofillService() {
            getCredResponse: GetCandidateCredentialsResponse,
            filLRequest: FillRequest
    ): FillResponse? {
        TODO("Not yet implemented")
        val providerList = GetFlowUtils.toProviderList(
                getCredResponse.candidateProviderDataList,
                this@CredentialAutofillService)
        var totalEntryCount = 0
        providerList.forEach { provider ->
            totalEntryCount += provider.credentialEntryList.size
        }
        val inlineSuggestionsRequest = filLRequest.inlineSuggestionsRequest
        val inlineMaxSuggestedCount = inlineSuggestionsRequest?.maxSuggestionCount ?: 0
        val inlinePresentationSpecs = inlineSuggestionsRequest?.inlinePresentationSpecs
        val inlinePresentationSpecsCount = inlinePresentationSpecs?.size ?: 0
        var maxItemCount = totalEntryCount
        if (inlineMaxSuggestedCount > 0) {
            maxItemCount = maxItemCount.coerceAtMost(inlineMaxSuggestedCount)
        }
        var i = 0
        val fillResponseBuilder = FillResponse.Builder()
        var emptyFillResponse = true
        providerList.forEach {provider ->
            // TODO(b/299321128): Before iterating the list, sort the list so that
            //  the relevant entries don't get truncated
            provider.credentialEntryList.forEach entryLoop@ {entry ->
                val autofillId: AutofillId? = entry.fillInIntent?.getParcelableExtra(
                        CredentialProviderService.EXTRA_AUTOFILL_ID,
                        AutofillId::class.java)
                val pendingIntent = entry.pendingIntent
                if (autofillId == null || pendingIntent == null) {
                    return@entryLoop
                }
                var inlinePresentation: InlinePresentation? = null
                // Create inline presentation
                if (inlinePresentationSpecs != null && i < maxItemCount) {
                    val spec: InlinePresentationSpec
                    if (i < inlinePresentationSpecsCount) {
                        spec = inlinePresentationSpecs[i]
                    } else {
                        spec = inlinePresentationSpecs[inlinePresentationSpecsCount - 1]
                    }
                    val sliceBuilder = InlineSuggestionUi
                            .newContentBuilder(pendingIntent)
                            .setTitle(entry.userName)
                    inlinePresentation = InlinePresentation(
                            sliceBuilder.build().slice, spec, /* pinned= */ false)
                }
                i++

                val dataSetBuilder = Dataset.Builder()
                val presentationBuilder = Presentations.Builder()
                if (inlinePresentation != null) {
                    presentationBuilder.setInlinePresentation(inlinePresentation)
                }
                fillResponseBuilder.addDataset(
                        dataSetBuilder
                                .setField(
                                        autofillId,
                                        Field.Builder().setPresentations(
                                                presentationBuilder.build())
                                                .build())
                                .setAuthentication(entry.pendingIntent.intentSender)
                                .setAuthenticationExtras(entry.fillInIntent.extras)
                                .build())
                emptyFillResponse = false
            }
        }
        if (emptyFillResponse) {
            return null
        }
        return fillResponseBuilder.build()
    }

    override fun onSaveRequest(request: SaveRequest, callback: SaveCallback) {