Loading core/java/android/app/assist/AssistStructure.java +64 −3 Original line number Diff line number Diff line 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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -652,6 +658,9 @@ public class AssistStructure implements Parcelable { @Nullable OutcomeReceiver<GetCredentialResponse, GetCredentialException> mGetCredentialCallback; @Nullable ResultReceiver mGetCredentialResultReceiver; AutofillValue mAutofillValue; CharSequence[] mAutofillOptions; boolean mSanitized; Loading Loading @@ -916,6 +925,7 @@ public class AssistStructure implements Parcelable { mExtras = in.readBundle(); } mGetCredentialRequest = in.readTypedObject(GetCredentialRequest.CREATOR); mGetCredentialResultReceiver = in.readTypedObject(ResultReceiver.CREATOR); } /** Loading Loading @@ -1153,6 +1163,7 @@ public class AssistStructure implements Parcelable { out.writeBundle(mExtras); } out.writeTypedObject(mGetCredentialRequest, flags); out.writeTypedObject(mGetCredentialResultReceiver, flags); return flags; } Loading Loading @@ -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; } /** Loading Loading @@ -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 Loading Loading @@ -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 Loading core/java/android/view/ViewStructure.java +2 −1 Original line number Diff line number Diff line Loading @@ -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. Loading packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt +0 −41 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -124,13 +122,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 Loading Loading @@ -528,42 +523,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, Loading services/autofill/java/com/android/server/autofill/Session.java +33 −1 Original line number Diff line number Diff line Loading @@ -3930,6 +3930,24 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return mSessionFlags.mShowingSaveUi; } /** * Gets the latest non-empty value for the given id in the autofill contexts. */ @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. */ Loading Loading @@ -6417,7 +6435,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mClient.onGetCredentialException(id, viewId, exception.getType(), exception.getMessage()); } else if (response != null) { 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"); Loading Loading
core/java/android/app/assist/AssistStructure.java +64 −3 Original line number Diff line number Diff line 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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -652,6 +658,9 @@ public class AssistStructure implements Parcelable { @Nullable OutcomeReceiver<GetCredentialResponse, GetCredentialException> mGetCredentialCallback; @Nullable ResultReceiver mGetCredentialResultReceiver; AutofillValue mAutofillValue; CharSequence[] mAutofillOptions; boolean mSanitized; Loading Loading @@ -916,6 +925,7 @@ public class AssistStructure implements Parcelable { mExtras = in.readBundle(); } mGetCredentialRequest = in.readTypedObject(GetCredentialRequest.CREATOR); mGetCredentialResultReceiver = in.readTypedObject(ResultReceiver.CREATOR); } /** Loading Loading @@ -1153,6 +1163,7 @@ public class AssistStructure implements Parcelable { out.writeBundle(mExtras); } out.writeTypedObject(mGetCredentialRequest, flags); out.writeTypedObject(mGetCredentialResultReceiver, flags); return flags; } Loading Loading @@ -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; } /** Loading Loading @@ -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 Loading Loading @@ -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 Loading
core/java/android/view/ViewStructure.java +2 −1 Original line number Diff line number Diff line Loading @@ -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. Loading
packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt +0 −41 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -124,13 +122,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 Loading Loading @@ -528,42 +523,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, Loading
services/autofill/java/com/android/server/autofill/Session.java +33 −1 Original line number Diff line number Diff line Loading @@ -3930,6 +3930,24 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return mSessionFlags.mShowingSaveUi; } /** * Gets the latest non-empty value for the given id in the autofill contexts. */ @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. */ Loading Loading @@ -6417,7 +6435,21 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mClient.onGetCredentialException(id, viewId, exception.getType(), exception.getMessage()); } else if (response != null) { 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"); Loading