diff options
| author | TreeHugger Robot <treehugger-gerrit@google.com> | 2020-02-15 02:41:58 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-02-15 02:41:58 +0000 |
| commit | 575d7ad93c06ecf853887b5411d9adf7d70e29cd (patch) | |
| tree | 61ed065f0a04ba42178a04aebac726450acd7504 /core/java | |
| parent | d8c867b117d96dcb0159800fc1c43e5342bb4da7 (diff) | |
| parent | 5be0f15801033f463c965d7b71eafcf13c6b337e (diff) | |
Merge "Response and Dataset authentication via inline autofill."
Diffstat (limited to 'core/java')
4 files changed, 90 insertions, 9 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 395a196420fa..5df67bc624fd 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1907,6 +1907,7 @@ public class Activity extends ContextThemeWrapper if (!mAutoFillIgnoreFirstResumePause) { View focus = getCurrentFocus(); if (focus != null && focus.canNotifyAutofillEnterExitEvent()) { + // TODO(b/148815880): Bring up keyboard if resumed from inline authentication. // TODO: in Activity killed/recreated case, i.e. SessionLifecycleTest# // testDatasetVisibleWhileAutofilledAppIsLifecycled: the View's initial // window visibility after recreation is INVISIBLE in onResume() and next frame @@ -8467,7 +8468,7 @@ public class Activity extends ContextThemeWrapper /** @hide */ @Override public final void autofillClientAuthenticate(int authenticationId, IntentSender intent, - Intent fillInIntent) { + Intent fillInIntent, boolean authenticateInline) { try { startIntentSenderForResultInner(intent, AUTO_FILL_AUTH_WHO_PREFIX, authenticationId, fillInIntent, 0, 0, null); diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java index 7032825c3c62..e8e1223a29d0 100644 --- a/core/java/android/service/autofill/FillResponse.java +++ b/core/java/android/service/autofill/FillResponse.java @@ -75,6 +75,7 @@ public final class FillResponse implements Parcelable { private final @Nullable SaveInfo mSaveInfo; private final @Nullable Bundle mClientState; private final @Nullable RemoteViews mPresentation; + private final @Nullable InlinePresentation mInlinePresentation; private final @Nullable RemoteViews mHeader; private final @Nullable RemoteViews mFooter; private final @Nullable IntentSender mAuthentication; @@ -95,6 +96,7 @@ public final class FillResponse implements Parcelable { mSaveInfo = builder.mSaveInfo; mClientState = builder.mClientState; mPresentation = builder.mPresentation; + mInlinePresentation = builder.mInlinePresentation; mHeader = builder.mHeader; mFooter = builder.mFooter; mAuthentication = builder.mAuthentication; @@ -131,6 +133,11 @@ public final class FillResponse implements Parcelable { } /** @hide */ + public @Nullable InlinePresentation getInlinePresentation() { + return mInlinePresentation; + } + + /** @hide */ public @Nullable RemoteViews getHeader() { return mHeader; } @@ -219,6 +226,7 @@ public final class FillResponse implements Parcelable { private SaveInfo mSaveInfo; private Bundle mClientState; private RemoteViews mPresentation; + private InlinePresentation mInlinePresentation; private RemoteViews mHeader; private RemoteViews mFooter; private IntentSender mAuthentication; @@ -318,6 +326,67 @@ public final class FillResponse implements Parcelable { } /** + * Triggers a custom UI before before autofilling the screen with any data set in this + * response. + * + * <p><b>Note:</b> Although the name of this method suggests that it should be used just for + * authentication flow, it can be used for other advanced flows; see {@link AutofillService} + * for examples. + * + * <p>This method is similar to + * {@link #setAuthentication(AutofillId[], IntentSender, RemoteViews)}, but also accepts + * an {@link InlinePresentation} presentation which is required for authenticating through + * the inline autofill flow. + * + * <p><b>Note:</b> {@link #setHeader(RemoteViews)} or {@link #setFooter(RemoteViews)} does + * not work with {@link InlinePresentation}.</p> + * + * @param authentication Intent to an activity with your authentication flow. + * @param presentation The presentation to visualize the response. + * @param inlinePresentation The inlinePresentation to visualize the response inline. + * @param ids id of Views that when focused will display the authentication UI. + * + * @return This builder. + * + * @throws IllegalArgumentException if any of the following occurs: + * <ul> + * <li>{@code ids} is {@code null}</li> + * <li>{@code ids} is empty</li> + * <li>{@code ids} contains a {@code null} element</li> + * <li>both {@code authentication} and {@code presentation} are {@code null}</li> + * <li>both {@code authentication} and {@code presentation} are non-{@code null}</li> + * <li>both {@code authentication} and {@code inlinePresentation} are {@code null}</li> + * <li>both {@code authentication} and {@code inlinePresentation} are + * non-{@code null}</li> + * </ul> + * + * @throws IllegalStateException if a {@link #setHeader(RemoteViews) header} or a + * {@link #setFooter(RemoteViews) footer} are already set for this builder. + * + * @see android.app.PendingIntent#getIntentSender() + */ + @NonNull + public Builder setAuthentication(@NonNull AutofillId[] ids, + @Nullable IntentSender authentication, @Nullable RemoteViews presentation, + @Nullable InlinePresentation inlinePresentation) { + throwIfDestroyed(); + throwIfDisableAutofillCalled(); + if (mHeader != null || mFooter != null) { + throw new IllegalStateException("Already called #setHeader() or #setFooter()"); + } + + if (authentication == null ^ (presentation == null && inlinePresentation == null)) { + throw new IllegalArgumentException("authentication and presentation " + + "(dropdown or inline), must be both non-null or null"); + } + mAuthentication = authentication; + mPresentation = presentation; + mInlinePresentation = inlinePresentation; + mAuthenticationIds = assertValid(ids); + return this; + } + + /** * Specifies views that should not trigger new * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, * FillCallback)} requests. @@ -644,6 +713,8 @@ public final class FillResponse implements Parcelable { break; } } + } else if (mInlinePresentation != null) { + mSupportsInlineSuggestions = true; } mDestroyed = true; @@ -691,6 +762,9 @@ public final class FillResponse implements Parcelable { if (mPresentation != null) { builder.append(", hasPresentation"); } + if (mInlinePresentation != null) { + builder.append(", hasInlinePresentation"); + } if (mHeader != null) { builder.append(", hasHeader"); } @@ -740,6 +814,7 @@ public final class FillResponse implements Parcelable { parcel.writeParcelableArray(mAuthenticationIds, flags); parcel.writeParcelable(mAuthentication, flags); parcel.writeParcelable(mPresentation, flags); + parcel.writeParcelable(mInlinePresentation, flags); parcel.writeParcelable(mHeader, flags); parcel.writeParcelable(mFooter, flags); parcel.writeParcelable(mUserData, flags); @@ -774,8 +849,10 @@ public final class FillResponse implements Parcelable { AutofillId.class); final IntentSender authentication = parcel.readParcelable(null); final RemoteViews presentation = parcel.readParcelable(null); + final InlinePresentation inlinePresentation = parcel.readParcelable(null); if (authenticationIds != null) { - builder.setAuthentication(authenticationIds, authentication, presentation); + builder.setAuthentication(authenticationIds, authentication, presentation, + inlinePresentation); } final RemoteViews header = parcel.readParcelable(null); if (header != null) { diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index c159f89cf2ac..e9a8a7300777 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -86,9 +86,10 @@ import java.util.List; import java.util.Objects; import java.util.Set; -//TODO: use java.lang.ref.Cleaner once Android supports Java 9 import sun.misc.Cleaner; +//TODO: use java.lang.ref.Cleaner once Android supports Java 9 + /** * <p>The {@link AutofillManager} class provides ways for apps and custom views to * integrate with the Autofill Framework lifecycle. @@ -547,7 +548,7 @@ public final class AutofillManager { * @param fillInIntent The authentication fill-in intent. */ void autofillClientAuthenticate(int authenticationId, IntentSender intent, - Intent fillInIntent); + Intent fillInIntent, boolean authenticateInline); /** * Tells the client this manager has state to be reset. @@ -2070,7 +2071,7 @@ public final class AutofillManager { } private void authenticate(int sessionId, int authenticationId, IntentSender intent, - Intent fillInIntent) { + Intent fillInIntent, boolean authenticateInline) { synchronized (mLock) { if (sessionId == mSessionId) { final AutofillClient client = getClient(); @@ -2078,7 +2079,8 @@ public final class AutofillManager { // clear mOnInvisibleCalled and we will see if receive onInvisibleForAutofill() // before onAuthenticationResult() mOnInvisibleCalled = false; - client.autofillClientAuthenticate(authenticationId, intent, fillInIntent); + client.autofillClientAuthenticate(authenticationId, intent, fillInIntent, + authenticateInline); } } } @@ -3250,10 +3252,11 @@ public final class AutofillManager { @Override public void authenticate(int sessionId, int authenticationId, IntentSender intent, - Intent fillInIntent) { + Intent fillInIntent, boolean authenticateInline) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.post(() -> afm.authenticate(sessionId, authenticationId, intent, fillInIntent)); + afm.post(() -> afm.authenticate(sessionId, authenticationId, intent, fillInIntent, + authenticateInline)); } } diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl index 84949c87377b..3903665f2cde 100644 --- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl +++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl @@ -50,7 +50,7 @@ oneway interface IAutoFillManagerClient { * Authenticates a fill response or a data set. */ void authenticate(int sessionId, int authenticationId, in IntentSender intent, - in Intent fillInIntent); + in Intent fillInIntent, boolean authenticateInline); /** * Sets the views to track. If saveOnAllViewsInvisible is set and all these view are invisible |
