Loading core/java/android/app/Activity.java +4 −3 Original line number Diff line number Diff line Loading @@ -7261,7 +7261,7 @@ public class Activity extends ContextThemeWrapper } } else if (who.startsWith(AUTO_FILL_AUTH_WHO_PREFIX)) { Intent resultData = (resultCode == Activity.RESULT_OK) ? data : null; getAutofillManager().onAuthenticationResult(resultData); getAutofillManager().onAuthenticationResult(requestCode, resultData); } else { Fragment frag = mFragments.findFragmentByWho(who); if (frag != null) { Loading Loading @@ -7406,10 +7406,11 @@ public class Activity extends ContextThemeWrapper /** @hide */ @Override final public void autofillCallbackAuthenticate(IntentSender intent, Intent fillInIntent) { final public void autofillCallbackAuthenticate(int authenticationId, IntentSender intent, Intent fillInIntent) { try { startIntentSenderForResultInner(intent, AUTO_FILL_AUTH_WHO_PREFIX, 0, fillInIntent, 0, 0, null); authenticationId, fillInIntent, 0, 0, null); } catch (IntentSender.SendIntentException e) { Log.e(TAG, "authenticate() failed for intent:" + intent, e); } Loading core/java/android/service/autofill/Dataset.java +22 −13 Original line number Diff line number Diff line Loading @@ -162,14 +162,18 @@ public final class Dataset implements Parcelable { * * <p>When a user triggers autofill, the system launches the provided intent * whose extras will have the {@link * android.view.autofill.AutofillManager#EXTRA_ASSIST_STRUCTURE screen content}. Once * you complete your authentication flow you should set the activity result to {@link * android.app.Activity#RESULT_OK} and provide the fully populated {@link Dataset * dataset} by setting it to the {@link * android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra. For example, * if you provided credit card information without the CVV for the data set in the * {@link FillResponse response} then the returned data set should contain the * CVV entry.</p> * android.view.autofill.AutofillManager#EXTRA_ASSIST_STRUCTURE screen content}, * and your {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE client * state}. Once you complete your authentication flow you should set the activity * result to {@link android.app.Activity#RESULT_OK} and provide the fully populated * {@link Dataset dataset} or a fully-populated {@link FillResponse response} by * setting it to the {@link * android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra. If you * provide a dataset in the result, it will replace the authenticated dataset and * will be immediately filled in. If you provide a response, it will replace the * current response and the UI will be refreshed. For example, if you provided * credit card information without the CVV for the data set in the {@link FillResponse * response} then the returned data set should contain the CVV entry. * * <p></><strong>Note:</strong> Do not make the provided pending intent * immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the Loading Loading @@ -210,12 +214,15 @@ public final class Dataset implements Parcelable { * * @param id id returned by {@link * android.app.assist.AssistStructure.ViewNode#getAutofillId()}. * @param value value to be auto filled. * @param value value to be auto filled. Pass {@code null} if you do not have the value * but the target view is a logical part of the dataset. For example, if * the dataset needs an authentication and you have no access to the value. * Filtering matches any user typed string to {@code null} values. * @return This builder. * @throws IllegalStateException if the builder was constructed without a presentation * ({@link RemoteViews}). */ public @NonNull Builder setValue(@NonNull AutofillId id, @NonNull AutofillValue value) { public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value) { throwIfDestroyed(); if (mPresentation == null) { throw new IllegalStateException("Dataset presentation not set on constructor"); Loading @@ -229,11 +236,14 @@ public final class Dataset implements Parcelable { * * @param id id returned by {@link * android.app.assist.AssistStructure.ViewNode#getAutofillId()}. * @param value value to be auto filled. * @param value value to be auto filled. Pass {@code null} if you do not have the value * but the target view is a logical part of the dataset. For example, if * the dataset needs an authentication and you have no access to the value. * Filtering matches any user typed string to {@code null} values. * @param presentation The presentation used to visualize this field. * @return This builder. */ public @NonNull Builder setValue(@NonNull AutofillId id, @NonNull AutofillValue value, public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value, @NonNull RemoteViews presentation) { throwIfDestroyed(); Preconditions.checkNotNull(presentation, "presentation cannot be null"); Loading @@ -244,7 +254,6 @@ public final class Dataset implements Parcelable { private void setValueAndPresentation(AutofillId id, AutofillValue value, RemoteViews presentation) { Preconditions.checkNotNull(id, "id cannot be null"); Preconditions.checkNotNull(value, "value cannot be null"); if (mFieldIds != null) { final int existingIdx = mFieldIds.indexOf(id); if (existingIdx >= 0) { Loading core/java/android/service/autofill/FillResponse.java +2 −1 Original line number Diff line number Diff line Loading @@ -236,7 +236,8 @@ public final class FillResponse implements Parcelable { * * <p>When a user triggers autofill, the system launches the provided intent * whose extras will have the {@link AutofillManager#EXTRA_ASSIST_STRUCTURE screen * content}. Once you complete your authentication flow you should set the activity * content} and your {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE * client state}. Once you complete your authentication flow you should set the activity * result to {@link android.app.Activity#RESULT_OK} and provide the fully populated * {@link FillResponse response} by setting it to the {@link * AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra. Loading core/java/android/view/autofill/AutofillManager.java +54 −7 Original line number Diff line number Diff line Loading @@ -117,6 +117,48 @@ public final class AutofillManager { /** @hide */ public static final int FLAG_ADD_CLIENT_DEBUG = 0x2; /** @hide */ public static final int FLAG_ADD_CLIENT_VERBOSE = 0x4; /** Which bits in an authentication id are used for the dataset id */ private static final int AUTHENTICATION_ID_DATASET_ID_MASK = 0xFFFF; /** How many bits in an authentication id are used for the dataset id */ private static final int AUTHENTICATION_ID_DATASET_ID_SHIFT = 16; /** @hide The index for an undefined data set */ public static final int AUTHENTICATION_ID_DATASET_ID_UNDEFINED = 0xFFFF; /** * Makes an authentication id from a request id and a dataset id. * * @param requestId The request id. * @param datasetId The dataset id. * @return The authentication id. * @hide */ public static int makeAuthenticationId(int requestId, int datasetId) { return (requestId << AUTHENTICATION_ID_DATASET_ID_SHIFT) | (datasetId & AUTHENTICATION_ID_DATASET_ID_MASK); } /** * Gets the request id from an authentication id. * * @param authRequestId The authentication id. * @return The request id. * @hide */ public static int getRequestIdFromAuthenticationId(int authRequestId) { return (authRequestId >> AUTHENTICATION_ID_DATASET_ID_SHIFT); } /** * Gets the dataset id from an authentication id. * * @param authRequestId The authentication id. * @return The dataset id. * @hide */ public static int getDatasetIdFromAuthenticationId(int authRequestId) { return (authRequestId & AUTHENTICATION_ID_DATASET_ID_MASK); } private final MetricsLogger mMetricsLogger = new MetricsLogger(); /** Loading Loading @@ -156,10 +198,12 @@ public final class AutofillManager { /** * Asks the client to start an authentication flow. * * @param authenticationId A unique id of the authentication operation. * @param intent The authentication intent. * @param fillInIntent The authentication fill-in intent. */ void autofillCallbackAuthenticate(IntentSender intent, Intent fillInIntent); void autofillCallbackAuthenticate(int authenticationId, IntentSender intent, Intent fillInIntent); /** * Tells the client this manager has state to be reset. Loading Loading @@ -675,7 +719,7 @@ public final class AutofillManager { } /** @hide */ public void onAuthenticationResult(Intent data) { public void onAuthenticationResult(int authenticationId, Intent data) { if (!hasAutofillFeature()) { return; } Loading @@ -694,7 +738,8 @@ public final class AutofillManager { final Bundle responseData = new Bundle(); responseData.putParcelable(EXTRA_AUTHENTICATION_RESULT, result); try { mService.setAuthenticationResult(responseData, mSessionId, mContext.getUserId()); mService.setAuthenticationResult(responseData, mSessionId, authenticationId, mContext.getUserId()); } catch (RemoteException e) { Log.e(TAG, "Error delivering authentication result", e); } Loading Loading @@ -870,12 +915,13 @@ public final class AutofillManager { } } private void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) { private void authenticate(int sessionId, int authenticationId, IntentSender intent, Intent fillInIntent) { synchronized (mLock) { if (sessionId == mSessionId) { AutofillClient client = getClientLocked(); if (client != null) { client.autofillCallbackAuthenticate(intent, fillInIntent); client.autofillCallbackAuthenticate(authenticationId, intent, fillInIntent); } } } Loading Loading @@ -1393,11 +1439,12 @@ public final class AutofillManager { } @Override public void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) { public void authenticate(int sessionId, int authenticationId, IntentSender intent, Intent fillInIntent) { final AutofillManager afm = mAfm.get(); if (afm != null) { afm.mContext.getMainThreadHandler().post( () -> afm.authenticate(sessionId, intent, fillInIntent)); () -> afm.authenticate(sessionId, authenticationId, intent, fillInIntent)); } } Loading core/java/android/view/autofill/IAutoFillManager.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ interface IAutoFillManager { in AutofillValue value, int action, int flags, int userId); void finishSession(int sessionId, int userId); void cancelSession(int sessionId, int userId); void setAuthenticationResult(in Bundle data, int sessionId, int userId); void setAuthenticationResult(in Bundle data, int sessionId, int authenticationId, int userId); void setHasCallback(int sessionId, int userId, boolean hasIt); void disableOwnedAutofillServices(int userId); boolean isServiceSupported(int userId); Loading Loading
core/java/android/app/Activity.java +4 −3 Original line number Diff line number Diff line Loading @@ -7261,7 +7261,7 @@ public class Activity extends ContextThemeWrapper } } else if (who.startsWith(AUTO_FILL_AUTH_WHO_PREFIX)) { Intent resultData = (resultCode == Activity.RESULT_OK) ? data : null; getAutofillManager().onAuthenticationResult(resultData); getAutofillManager().onAuthenticationResult(requestCode, resultData); } else { Fragment frag = mFragments.findFragmentByWho(who); if (frag != null) { Loading Loading @@ -7406,10 +7406,11 @@ public class Activity extends ContextThemeWrapper /** @hide */ @Override final public void autofillCallbackAuthenticate(IntentSender intent, Intent fillInIntent) { final public void autofillCallbackAuthenticate(int authenticationId, IntentSender intent, Intent fillInIntent) { try { startIntentSenderForResultInner(intent, AUTO_FILL_AUTH_WHO_PREFIX, 0, fillInIntent, 0, 0, null); authenticationId, fillInIntent, 0, 0, null); } catch (IntentSender.SendIntentException e) { Log.e(TAG, "authenticate() failed for intent:" + intent, e); } Loading
core/java/android/service/autofill/Dataset.java +22 −13 Original line number Diff line number Diff line Loading @@ -162,14 +162,18 @@ public final class Dataset implements Parcelable { * * <p>When a user triggers autofill, the system launches the provided intent * whose extras will have the {@link * android.view.autofill.AutofillManager#EXTRA_ASSIST_STRUCTURE screen content}. Once * you complete your authentication flow you should set the activity result to {@link * android.app.Activity#RESULT_OK} and provide the fully populated {@link Dataset * dataset} by setting it to the {@link * android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra. For example, * if you provided credit card information without the CVV for the data set in the * {@link FillResponse response} then the returned data set should contain the * CVV entry.</p> * android.view.autofill.AutofillManager#EXTRA_ASSIST_STRUCTURE screen content}, * and your {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE client * state}. Once you complete your authentication flow you should set the activity * result to {@link android.app.Activity#RESULT_OK} and provide the fully populated * {@link Dataset dataset} or a fully-populated {@link FillResponse response} by * setting it to the {@link * android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra. If you * provide a dataset in the result, it will replace the authenticated dataset and * will be immediately filled in. If you provide a response, it will replace the * current response and the UI will be refreshed. For example, if you provided * credit card information without the CVV for the data set in the {@link FillResponse * response} then the returned data set should contain the CVV entry. * * <p></><strong>Note:</strong> Do not make the provided pending intent * immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the Loading Loading @@ -210,12 +214,15 @@ public final class Dataset implements Parcelable { * * @param id id returned by {@link * android.app.assist.AssistStructure.ViewNode#getAutofillId()}. * @param value value to be auto filled. * @param value value to be auto filled. Pass {@code null} if you do not have the value * but the target view is a logical part of the dataset. For example, if * the dataset needs an authentication and you have no access to the value. * Filtering matches any user typed string to {@code null} values. * @return This builder. * @throws IllegalStateException if the builder was constructed without a presentation * ({@link RemoteViews}). */ public @NonNull Builder setValue(@NonNull AutofillId id, @NonNull AutofillValue value) { public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value) { throwIfDestroyed(); if (mPresentation == null) { throw new IllegalStateException("Dataset presentation not set on constructor"); Loading @@ -229,11 +236,14 @@ public final class Dataset implements Parcelable { * * @param id id returned by {@link * android.app.assist.AssistStructure.ViewNode#getAutofillId()}. * @param value value to be auto filled. * @param value value to be auto filled. Pass {@code null} if you do not have the value * but the target view is a logical part of the dataset. For example, if * the dataset needs an authentication and you have no access to the value. * Filtering matches any user typed string to {@code null} values. * @param presentation The presentation used to visualize this field. * @return This builder. */ public @NonNull Builder setValue(@NonNull AutofillId id, @NonNull AutofillValue value, public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value, @NonNull RemoteViews presentation) { throwIfDestroyed(); Preconditions.checkNotNull(presentation, "presentation cannot be null"); Loading @@ -244,7 +254,6 @@ public final class Dataset implements Parcelable { private void setValueAndPresentation(AutofillId id, AutofillValue value, RemoteViews presentation) { Preconditions.checkNotNull(id, "id cannot be null"); Preconditions.checkNotNull(value, "value cannot be null"); if (mFieldIds != null) { final int existingIdx = mFieldIds.indexOf(id); if (existingIdx >= 0) { Loading
core/java/android/service/autofill/FillResponse.java +2 −1 Original line number Diff line number Diff line Loading @@ -236,7 +236,8 @@ public final class FillResponse implements Parcelable { * * <p>When a user triggers autofill, the system launches the provided intent * whose extras will have the {@link AutofillManager#EXTRA_ASSIST_STRUCTURE screen * content}. Once you complete your authentication flow you should set the activity * content} and your {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE * client state}. Once you complete your authentication flow you should set the activity * result to {@link android.app.Activity#RESULT_OK} and provide the fully populated * {@link FillResponse response} by setting it to the {@link * AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra. Loading
core/java/android/view/autofill/AutofillManager.java +54 −7 Original line number Diff line number Diff line Loading @@ -117,6 +117,48 @@ public final class AutofillManager { /** @hide */ public static final int FLAG_ADD_CLIENT_DEBUG = 0x2; /** @hide */ public static final int FLAG_ADD_CLIENT_VERBOSE = 0x4; /** Which bits in an authentication id are used for the dataset id */ private static final int AUTHENTICATION_ID_DATASET_ID_MASK = 0xFFFF; /** How many bits in an authentication id are used for the dataset id */ private static final int AUTHENTICATION_ID_DATASET_ID_SHIFT = 16; /** @hide The index for an undefined data set */ public static final int AUTHENTICATION_ID_DATASET_ID_UNDEFINED = 0xFFFF; /** * Makes an authentication id from a request id and a dataset id. * * @param requestId The request id. * @param datasetId The dataset id. * @return The authentication id. * @hide */ public static int makeAuthenticationId(int requestId, int datasetId) { return (requestId << AUTHENTICATION_ID_DATASET_ID_SHIFT) | (datasetId & AUTHENTICATION_ID_DATASET_ID_MASK); } /** * Gets the request id from an authentication id. * * @param authRequestId The authentication id. * @return The request id. * @hide */ public static int getRequestIdFromAuthenticationId(int authRequestId) { return (authRequestId >> AUTHENTICATION_ID_DATASET_ID_SHIFT); } /** * Gets the dataset id from an authentication id. * * @param authRequestId The authentication id. * @return The dataset id. * @hide */ public static int getDatasetIdFromAuthenticationId(int authRequestId) { return (authRequestId & AUTHENTICATION_ID_DATASET_ID_MASK); } private final MetricsLogger mMetricsLogger = new MetricsLogger(); /** Loading Loading @@ -156,10 +198,12 @@ public final class AutofillManager { /** * Asks the client to start an authentication flow. * * @param authenticationId A unique id of the authentication operation. * @param intent The authentication intent. * @param fillInIntent The authentication fill-in intent. */ void autofillCallbackAuthenticate(IntentSender intent, Intent fillInIntent); void autofillCallbackAuthenticate(int authenticationId, IntentSender intent, Intent fillInIntent); /** * Tells the client this manager has state to be reset. Loading Loading @@ -675,7 +719,7 @@ public final class AutofillManager { } /** @hide */ public void onAuthenticationResult(Intent data) { public void onAuthenticationResult(int authenticationId, Intent data) { if (!hasAutofillFeature()) { return; } Loading @@ -694,7 +738,8 @@ public final class AutofillManager { final Bundle responseData = new Bundle(); responseData.putParcelable(EXTRA_AUTHENTICATION_RESULT, result); try { mService.setAuthenticationResult(responseData, mSessionId, mContext.getUserId()); mService.setAuthenticationResult(responseData, mSessionId, authenticationId, mContext.getUserId()); } catch (RemoteException e) { Log.e(TAG, "Error delivering authentication result", e); } Loading Loading @@ -870,12 +915,13 @@ public final class AutofillManager { } } private void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) { private void authenticate(int sessionId, int authenticationId, IntentSender intent, Intent fillInIntent) { synchronized (mLock) { if (sessionId == mSessionId) { AutofillClient client = getClientLocked(); if (client != null) { client.autofillCallbackAuthenticate(intent, fillInIntent); client.autofillCallbackAuthenticate(authenticationId, intent, fillInIntent); } } } Loading Loading @@ -1393,11 +1439,12 @@ public final class AutofillManager { } @Override public void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) { public void authenticate(int sessionId, int authenticationId, IntentSender intent, Intent fillInIntent) { final AutofillManager afm = mAfm.get(); if (afm != null) { afm.mContext.getMainThreadHandler().post( () -> afm.authenticate(sessionId, intent, fillInIntent)); () -> afm.authenticate(sessionId, authenticationId, intent, fillInIntent)); } } Loading
core/java/android/view/autofill/IAutoFillManager.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ interface IAutoFillManager { in AutofillValue value, int action, int flags, int userId); void finishSession(int sessionId, int userId); void cancelSession(int sessionId, int userId); void setAuthenticationResult(in Bundle data, int sessionId, int userId); void setAuthenticationResult(in Bundle data, int sessionId, int authenticationId, int userId); void setHasCallback(int sessionId, int userId, boolean hasIt); void disableOwnedAutofillServices(int userId); boolean isServiceSupported(int userId); Loading