diff options
4 files changed, 99 insertions, 47 deletions
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index fb1b17bd23d4..89199ca0d493 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -1,5 +1,7 @@ package android.app.assist; +import static android.credentials.Constants.FAILURE_CREDMAN_SELECTOR; +import static android.credentials.Constants.SUCCESS_CREDMAN_SELECTOR; import static android.service.autofill.Flags.FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION; import android.annotation.FlaggedApi; @@ -20,14 +22,17 @@ import android.net.Uri; import android.os.BadParcelableException; import android.os.Binder; import android.os.Bundle; +import android.os.Handler; import android.os.IBinder; import android.os.LocaleList; +import android.os.Looper; import android.os.OutcomeReceiver; import android.os.Parcel; import android.os.Parcelable; import android.os.PooledStringReader; import android.os.PooledStringWriter; import android.os.RemoteException; +import android.os.ResultReceiver; import android.os.SystemClock; import android.service.autofill.FillRequest; import android.service.credentials.CredentialProviderService; @@ -37,6 +42,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.Pair; +import android.util.Slog; import android.view.View; import android.view.View.AutofillImportance; import android.view.ViewRootImpl; @@ -652,6 +658,9 @@ public class AssistStructure implements Parcelable { @Nullable OutcomeReceiver<GetCredentialResponse, GetCredentialException> mGetCredentialCallback; + @Nullable ResultReceiver mGetCredentialResultReceiver; + + AutofillValue mAutofillValue; CharSequence[] mAutofillOptions; boolean mSanitized; @@ -916,6 +925,7 @@ public class AssistStructure implements Parcelable { mExtras = in.readBundle(); } mGetCredentialRequest = in.readTypedObject(GetCredentialRequest.CREATOR); + mGetCredentialResultReceiver = in.readTypedObject(ResultReceiver.CREATOR); } /** @@ -1153,6 +1163,7 @@ public class AssistStructure implements Parcelable { out.writeBundle(mExtras); } out.writeTypedObject(mGetCredentialRequest, flags); + out.writeTypedObject(mGetCredentialResultReceiver, flags); return flags; } @@ -1295,9 +1306,8 @@ public class AssistStructure implements Parcelable { */ @FlaggedApi(FLAG_AUTOFILL_CREDMAN_DEV_INTEGRATION) @Nullable - public OutcomeReceiver<GetCredentialResponse, - GetCredentialException> getCredentialManagerCallback() { - return mGetCredentialCallback; + public ResultReceiver getCredentialManagerCallback() { + return mGetCredentialResultReceiver; } /** @@ -1894,6 +1904,7 @@ public class AssistStructure implements Parcelable { final AssistStructure mAssist; final ViewNode mNode; final boolean mAsync; + private Handler mHandler; /** * Used to instantiate a builder for a stand-alone {@link ViewNode} which is not associated @@ -2271,6 +2282,56 @@ public class AssistStructure implements Parcelable { option.getCandidateQueryData() .putParcelableArrayList(CredentialProviderService.EXTRA_AUTOFILL_ID, ids); } + setUpResultReceiver(callback); + } + + private void setUpResultReceiver( + OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback) { + + if (mHandler == null) { + mHandler = new Handler(Looper.getMainLooper(), null, true); + } + final ResultReceiver resultReceiver = new ResultReceiver(mHandler) { + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + if (resultCode == SUCCESS_CREDMAN_SELECTOR) { + Slog.d(TAG, "onReceiveResult from Credential Manager"); + GetCredentialResponse getCredentialResponse = + resultData.getParcelable( + CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE, + GetCredentialResponse.class); + + callback.onResult(getCredentialResponse); + } else if (resultCode == FAILURE_CREDMAN_SELECTOR) { + String[] exception = resultData.getStringArray( + CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION); + if (exception != null && exception.length >= 2) { + Slog.w(TAG, "Credman bottom sheet from pinned " + + "entry failed with: + " + exception[0] + " , " + + exception[1]); + callback.onError(new GetCredentialException( + exception[0], exception[1])); + } + } else { + Slog.d(TAG, "Unknown resultCode from credential " + + "manager bottom sheet: " + resultCode); + } + } + }; + ResultReceiver ipcFriendlyResultReceiver = + toIpcFriendlyResultReceiver(resultReceiver); + mNode.mGetCredentialResultReceiver = ipcFriendlyResultReceiver; + } + + private ResultReceiver toIpcFriendlyResultReceiver(ResultReceiver resultReceiver) { + final Parcel parcel = Parcel.obtain(); + resultReceiver.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + + final ResultReceiver ipcFriendly = ResultReceiver.CREATOR.createFromParcel(parcel); + parcel.recycle(); + + return ipcFriendly; } @Override diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java index 131fca7d923a..1efd37591ee4 100644 --- a/core/java/android/view/ViewStructure.java +++ b/core/java/android/view/ViewStructure.java @@ -315,7 +315,8 @@ public abstract class ViewStructure { /** * Add to this view's child count. This increases the current child count by * <var>num</var> children beyond what was last set by {@link #setChildCount} - * or {@link #addChildCount}. The index at which the new child starts in the child + * or {@link #addChildCount}. The index at which the new + * child starts in the child * array is returned. * * @param num The number of new children to add. diff --git a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt index 293e1112636e..32e2dd98db74 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt @@ -21,8 +21,6 @@ import android.app.assist.AssistStructure import android.content.Context import android.credentials.CredentialManager import android.credentials.GetCredentialRequest -import android.credentials.GetCredentialResponse -import android.credentials.GetCredentialException import android.credentials.GetCandidateCredentialsResponse import android.credentials.GetCandidateCredentialsException import android.credentials.CredentialOption @@ -33,7 +31,6 @@ import android.graphics.drawable.Icon import android.os.Bundle import android.os.CancellationSignal import android.os.OutcomeReceiver -import android.provider.Settings import android.service.autofill.AutofillService import android.service.autofill.Dataset import android.service.autofill.Field @@ -124,13 +121,10 @@ class CredentialAutofillService : AutofillService() { // TODO(b/324635774): Use callback for validating. If the request is coming // directly from the view, there should be a corresponding callback, otherwise // we should fail fast, - val getCredCallback = getCredManCallback(structure) if (getCredRequest == null) { Log.i(TAG, "No credential manager request found") callback.onFailure("No credential manager request found") return - } else if (getCredCallback == null) { - Log.i(TAG, "No credential manager callback found") } val credentialManager: CredentialManager = getSystemService(Context.CREDENTIAL_SERVICE) as CredentialManager @@ -524,42 +518,6 @@ class CredentialAutofillService : AutofillService() { TODO("Not yet implemented") } - private fun getCredManCallback(structure: AssistStructure): OutcomeReceiver< - GetCredentialResponse, GetCredentialException>? { - return traverseStructureForCallback(structure) - } - - private fun traverseStructureForCallback( - structure: AssistStructure - ): OutcomeReceiver<GetCredentialResponse, GetCredentialException>? { - val windowNodes: List<AssistStructure.WindowNode> = - structure.run { - (0 until windowNodeCount).map { getWindowNodeAt(it) } - } - - windowNodes.forEach { windowNode: AssistStructure.WindowNode -> - return traverseNodeForCallback(windowNode.rootViewNode) - } - return null - } - - private fun traverseNodeForCallback( - viewNode: AssistStructure.ViewNode - ): OutcomeReceiver<GetCredentialResponse, GetCredentialException>? { - val children: List<AssistStructure.ViewNode> = - viewNode.run { - (0 until childCount).map { getChildAt(it) } - } - - children.forEach { childNode: AssistStructure.ViewNode -> - if (childNode.isFocused() && childNode.credentialManagerCallback != null) { - return childNode.credentialManagerCallback - } - return traverseNodeForCallback(childNode) - } - return null - } - private fun getCredManRequest( structure: AssistStructure, sessionId: Int, diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index d779fbf2eabc..b92d8f562319 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -3935,6 +3935,24 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState */ @GuardedBy("mLock") @Nullable + private ViewNode getViewNodeFromContextsLocked(@NonNull AutofillId autofillId) { + final int numContexts = mContexts.size(); + for (int i = numContexts - 1; i >= 0; i--) { + final FillContext context = mContexts.get(i); + final ViewNode node = Helper.findViewNodeByAutofillId(context.getStructure(), + autofillId); + if (node != null) { + return node; + } + } + return null; + } + + /** + * Gets the latest non-empty value for the given id in the autofill contexts. + */ + @GuardedBy("mLock") + @Nullable private AutofillValue getValueFromContextsLocked(@NonNull AutofillId autofillId) { final int numContexts = mContexts.size(); for (int i = numContexts - 1; i >= 0; i--) { @@ -6419,7 +6437,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mClient.onGetCredentialException(id, viewId, exception.getType(), exception.getMessage()); } else if (response != null) { - mClient.onGetCredentialResponse(id, viewId, response); + if (viewId.isVirtualInt()) { + ViewNode viewNode = getViewNodeFromContextsLocked(viewId); + if (viewNode != null && viewNode.getCredentialManagerCallback() != null) { + Bundle resultData = new Bundle(); + resultData.putParcelable( + CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE, + response); + viewNode.getCredentialManagerCallback().send(SUCCESS_CREDMAN_SELECTOR, + resultData); + } else { + Slog.w(TAG, "View node not found after GetCredentialResponse"); + } + } else { + mClient.onGetCredentialResponse(id, viewId, response); + } } else { Slog.w(TAG, "sendCredentialManagerResponseToApp called with null response" + "and exception"); |