diff --git a/api/current.txt b/api/current.txt index d68610edf9fdd..e997dce8ed806 100644 --- a/api/current.txt +++ b/api/current.txt @@ -47436,17 +47436,27 @@ package android.view.autofill { } public final class AutoFillManager { + method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback); method public void reset(); method public void startAutoFillRequest(android.view.View); method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect); method public void stopAutoFillRequest(android.view.View); method public void stopAutoFillRequestOnVirtualView(android.view.View, int); + method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback); method public void valueChanged(android.view.View); method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue); field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE"; field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT"; } + public static abstract class AutoFillManager.AutofillCallback { + ctor public AutoFillManager.AutofillCallback(); + method public void onAutofillEvent(android.view.View, int); + method public void onAutofillEventVirtual(android.view.View, int, int); + field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2 + field public static final int EVENT_INPUT_SHOWN = 1; // 0x1 + } + public final class AutoFillType implements android.os.Parcelable { method public int describeContents(); method public static android.view.autofill.AutoFillType forDate(); diff --git a/api/system-current.txt b/api/system-current.txt index cb0d7b1371b02..4ab9d1d9ae3b3 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -50899,17 +50899,27 @@ package android.view.autofill { } public final class AutoFillManager { + method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback); method public void reset(); method public void startAutoFillRequest(android.view.View); method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect); method public void stopAutoFillRequest(android.view.View); method public void stopAutoFillRequestOnVirtualView(android.view.View, int); + method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback); method public void valueChanged(android.view.View); method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue); field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE"; field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT"; } + public static abstract class AutoFillManager.AutofillCallback { + ctor public AutoFillManager.AutofillCallback(); + method public void onAutofillEvent(android.view.View, int); + method public void onAutofillEventVirtual(android.view.View, int, int); + field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2 + field public static final int EVENT_INPUT_SHOWN = 1; // 0x1 + } + public final class AutoFillType implements android.os.Parcelable { method public int describeContents(); method public static android.view.autofill.AutoFillType forDate(); diff --git a/api/test-current.txt b/api/test-current.txt index f8e6785345c4a..ebf950e9d29c2 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -47805,17 +47805,27 @@ package android.view.autofill { } public final class AutoFillManager { + method public void registerCallback(android.view.autofill.AutoFillManager.AutofillCallback); method public void reset(); method public void startAutoFillRequest(android.view.View); method public void startAutoFillRequestOnVirtualView(android.view.View, int, android.graphics.Rect); method public void stopAutoFillRequest(android.view.View); method public void stopAutoFillRequestOnVirtualView(android.view.View, int); + method public void unregisterCallback(android.view.autofill.AutoFillManager.AutofillCallback); method public void valueChanged(android.view.View); method public void virtualValueChanged(android.view.View, int, android.view.autofill.AutoFillValue); field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE"; field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT"; } + public static abstract class AutoFillManager.AutofillCallback { + ctor public AutoFillManager.AutofillCallback(); + method public void onAutofillEvent(android.view.View, int); + method public void onAutofillEventVirtual(android.view.View, int, int); + field public static final int EVENT_INPUT_HIDDEN = 2; // 0x2 + field public static final int EVENT_INPUT_SHOWN = 1; // 0x1 + } + public final class AutoFillType implements android.os.Parcelable { method public int describeContents(); method public static android.view.autofill.AutoFillType forDate(); diff --git a/core/java/android/view/autofill/AutoFillManager.java b/core/java/android/view/autofill/AutoFillManager.java index e8325e89f39a7..8beaf4e423cb8 100644 --- a/core/java/android/view/autofill/AutoFillManager.java +++ b/core/java/android/view/autofill/AutoFillManager.java @@ -19,7 +19,9 @@ package android.view.autofill; import static android.view.autofill.Helper.DEBUG; import static android.view.autofill.Helper.VERBOSE; +import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.content.Intent; import android.content.IntentSender; @@ -30,7 +32,10 @@ import android.os.Parcelable; import android.os.RemoteException; import android.util.Log; import android.view.View; +import android.view.WindowManagerGlobal; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.List; @@ -76,6 +81,8 @@ public final class AutoFillManager { private final IAutoFillManager mService; private IAutoFillManagerClient mServiceClient; + private AutofillCallback mCallback; + private Context mContext; private boolean mHasSession; @@ -276,11 +283,11 @@ public final class AutoFillManager { } } - private AutoFillId getAutoFillId(View view) { + private static AutoFillId getAutoFillId(View view) { return new AutoFillId(view.getAccessibilityViewId()); } - private AutoFillId getAutoFillId(View parent, int childId) { + private static AutoFillId getAutoFillId(View parent, int childId) { return new AutoFillId(parent.getAccessibilityViewId(), childId); } @@ -289,10 +296,12 @@ public final class AutoFillManager { if (DEBUG) { Log.d(TAG, "startSession(): id=" + id + ", bounds=" + bounds + ", value=" + value); } + try { mService.startSession(mContext.getActivityToken(), windowToken, - mServiceClient.asBinder(), id, bounds, value, mContext.getUserId()); - AutoFillClient client = getClient(); + mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(), + mCallback != null); + final AutoFillClient client = getClient(); if (client != null) { client.resetableStateAvailable(); } @@ -344,6 +353,119 @@ public final class AutoFillManager { } } + /** + * Registers a {@link AutofillCallback} to receive autofill events. + * + * @param callback callback to receive events. + */ + public void registerCallback(@Nullable AutofillCallback callback) { + if (callback == null) return; + + final boolean hadCallback = mCallback != null; + mCallback = callback; + + if (mHasSession && !hadCallback) { + try { + mService.setHasCallback(mContext.getActivityToken(), mContext.getUserId(), true); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + /** + * Unregisters a {@link AutofillCallback} to receive autofill events. + * + * @param callback callback to stop receiving events. + */ + public void unregisterCallback(@Nullable AutofillCallback callback) { + if (callback == null || mCallback == null || callback != mCallback) return; + + mCallback = null; + + if (mHasSession) { + try { + mService.setHasCallback(mContext.getActivityToken(), mContext.getUserId(), false); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + private void onAutofillEvent(IBinder windowToken, AutoFillId id, int event) { + if (mCallback == null) return; + if (id == null) { + Log.w(TAG, "onAutofillEvent(): no id for event " + event); + return; + } + + final View root = WindowManagerGlobal.getInstance().getWindowView(windowToken); + if (root == null) { + Log.w(TAG, "onAutofillEvent() for " + id + ": root view gone"); + return; + } + final View view = root.findViewByAccessibilityIdTraversal(id.getViewId()); + if (view == null) { + Log.w(TAG, "onAutofillEvent() for " + id + ": view gone"); + return; + } + if (id.isVirtual()) { + mCallback.onAutofillEventVirtual(view, id.getVirtualChildId(), event); + } else { + mCallback.onAutofillEvent(view, event); + } + } + + /** + * Callback for auto-fill related events. + * + *
Typically used for applications that display their own "auto-complete" views, so they can + * enable / disable such views when the auto-fill UI affordance is shown / hidden. + */ + public abstract static class AutofillCallback { + + /** @hide */ + @IntDef({EVENT_INPUT_SHOWN, EVENT_INPUT_HIDDEN}) + @Retention(RetentionPolicy.SOURCE) + public @interface AutofillEventType {} + + /** + * The auto-fill input UI affordance associated with the view was shown. + * + *
If the view provides its own auto-complete UI affordance and its currently shown, it + * should be hidden upon receiving this event. + */ + public static final int EVENT_INPUT_SHOWN = 1; + + /** + * The auto-fill input UI affordance associated with the view was hidden. + * + *
If the view provides its own auto-complete UI affordance that was hidden upon a
+ * {@link #EVENT_INPUT_SHOWN} event, it could be shown again now.
+ */
+ public static final int EVENT_INPUT_HIDDEN = 2;
+
+ /**
+ * Called after a change in the autofill state associated with a view.
+ *
+ * @param view view associated with the change.
+ *
+ * @param event currently either {@link #EVENT_INPUT_SHOWN} or {@link #EVENT_INPUT_HIDDEN}.
+ */
+ public void onAutofillEvent(@NonNull View view, @AutofillEventType int event) {}
+
+ /**
+ * Called after a change in the autofill state associated with a virtual view.
+ *
+ * @param view parent view associated with the change.
+ * @param childId id identifying the virtual child inside the parent view.
+ *
+ * @param event currently either {@link #EVENT_INPUT_SHOWN} or {@link #EVENT_INPUT_HIDDEN}.
+ */
+ public void onAutofillEventVirtual(@NonNull View view, int childId,
+ @AutofillEventType int event) {}
+ }
+
private static final class AutoFillManagerClient extends IAutoFillManagerClient.Stub {
private final WeakReference