diff options
author | Jeff Davidson <jpd@google.com> | 2018-02-08 15:30:06 -0800 |
---|---|---|
committer | Jeff Davidson <jpd@google.com> | 2018-02-08 15:30:06 -0800 |
commit | a192cc2a132cb0ee8588e2df755563ec7008c179 (patch) | |
tree | 380e4db22df19c819bd37df34bf06e7568916a50 /android/view/autofill/AutofillManager.java | |
parent | 98fe7819c6d14f4f464a5cac047f9e82dee5da58 (diff) | |
download | android-28-a192cc2a132cb0ee8588e2df755563ec7008c179.tar.gz |
Update fullsdk to 4575844
/google/data/ro/projects/android/fetch_artifact \
--bid 4575844 \
--target sdk_phone_x86_64-sdk \
sdk-repo-linux-sources-4575844.zip
Test: TreeHugger
Change-Id: I81e0eb157b4ac3b38408d0ef86f9d6286471f87a
Diffstat (limited to 'android/view/autofill/AutofillManager.java')
-rw-r--r-- | android/view/autofill/AutofillManager.java | 211 |
1 files changed, 173 insertions, 38 deletions
diff --git a/android/view/autofill/AutofillManager.java b/android/view/autofill/AutofillManager.java index 26974545..4b24a71c 100644 --- a/android/view/autofill/AutofillManager.java +++ b/android/view/autofill/AutofillManager.java @@ -53,6 +53,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -168,7 +170,6 @@ public final class AutofillManager { public static final String EXTRA_CLIENT_STATE = "android.view.autofill.extra.CLIENT_STATE"; - /** @hide */ public static final String EXTRA_RESTORE_SESSION_TOKEN = "android.view.autofill.extra.RESTORE_SESSION_TOKEN"; @@ -258,6 +259,12 @@ public final class AutofillManager { public static final int STATE_DISABLED_BY_SERVICE = 4; /** + * Timeout in ms for calls to the field classification service. + * @hide + */ + public static final int FC_SERVICE_TIMEOUT = 5000; + + /** * Makes an authentication id from a request id and a dataset id. * * @param requestId The request id. @@ -340,6 +347,10 @@ public final class AutofillManager { @GuardedBy("mLock") @Nullable private AutofillId mSaveTriggerId; + /** set to true when onInvisibleForAutofill is called, used by onAuthenticationResult */ + @GuardedBy("mLock") + private boolean mOnInvisibleCalled; + /** If set, session is commited when the activity is finished; otherwise session is canceled. */ @GuardedBy("mLock") private boolean mSaveOnFinish; @@ -396,6 +407,11 @@ public final class AutofillManager { boolean isVisibleForAutofill(); /** + * Client might disable enter/exit event e.g. when activity is paused. + */ + boolean isDisablingEnterExitEventForAutofill(); + + /** * Finds views by traversing the hierarchies of the client. * * @param viewIds The autofill ids of the views to find @@ -498,6 +514,19 @@ public final class AutofillManager { } /** + * Called once the client becomes invisible. + * + * @see AutofillClient#isVisibleForAutofill() + * + * {@hide} + */ + public void onInvisibleForAutofill() { + synchronized (mLock) { + mOnInvisibleCalled = true; + } + } + + /** * Save state before activity lifecycle * * @param outState Place to store the state @@ -622,21 +651,45 @@ public final class AutofillManager { return false; } + private boolean isClientVisibleForAutofillLocked() { + final AutofillClient client = getClient(); + return client != null && client.isVisibleForAutofill(); + } + + private boolean isClientDisablingEnterExitEvent() { + final AutofillClient client = getClient(); + return client != null && client.isDisablingEnterExitEventForAutofill(); + } + private void notifyViewEntered(@NonNull View view, int flags) { if (!hasAutofillFeature()) { return; } - AutofillCallback callback = null; + AutofillCallback callback; synchronized (mLock) { - if (shouldIgnoreViewEnteredLocked(view, flags)) return; + callback = notifyViewEnteredLocked(view, flags); + } - ensureServiceClientAddedIfNeededLocked(); + if (callback != null) { + mCallback.onAutofillEvent(view, AutofillCallback.EVENT_INPUT_UNAVAILABLE); + } + } - if (!mEnabled) { - if (mCallback != null) { - callback = mCallback; - } - } else { + /** Returns AutofillCallback if need fire EVENT_INPUT_UNAVAILABLE */ + private AutofillCallback notifyViewEnteredLocked(@NonNull View view, int flags) { + if (shouldIgnoreViewEnteredLocked(view, flags)) return null; + + AutofillCallback callback = null; + + ensureServiceClientAddedIfNeededLocked(); + + if (!mEnabled) { + if (mCallback != null) { + callback = mCallback; + } + } else { + // don't notify entered when Activity is already in background + if (!isClientDisablingEnterExitEvent()) { final AutofillId id = getAutofillId(view); final AutofillValue value = view.getAutofillValue(); @@ -649,10 +702,7 @@ public final class AutofillManager { } } } - - if (callback != null) { - mCallback.onAutofillEvent(view, AutofillCallback.EVENT_INPUT_UNAVAILABLE); - } + return callback; } /** @@ -665,9 +715,16 @@ public final class AutofillManager { return; } synchronized (mLock) { - ensureServiceClientAddedIfNeededLocked(); + notifyViewExitedLocked(view); + } + } - if (mEnabled && isActiveLocked()) { + void notifyViewExitedLocked(@NonNull View view) { + ensureServiceClientAddedIfNeededLocked(); + + if (mEnabled && isActiveLocked()) { + // dont notify exited when Activity is already in background + if (!isClientDisablingEnterExitEvent()) { final AutofillId id = getAutofillId(view); // Update focus on existing session. @@ -718,7 +775,7 @@ public final class AutofillManager { } } if (mTrackedViews != null) { - mTrackedViews.notifyViewVisibilityChanged(id, isVisible); + mTrackedViews.notifyViewVisibilityChangedLocked(id, isVisible); } } } @@ -751,17 +808,32 @@ public final class AutofillManager { if (!hasAutofillFeature()) { return; } - AutofillCallback callback = null; + AutofillCallback callback; synchronized (mLock) { - if (shouldIgnoreViewEnteredLocked(view, flags)) return; + callback = notifyViewEnteredLocked(view, virtualId, bounds, flags); + } - ensureServiceClientAddedIfNeededLocked(); + if (callback != null) { + callback.onAutofillEvent(view, virtualId, + AutofillCallback.EVENT_INPUT_UNAVAILABLE); + } + } - if (!mEnabled) { - if (mCallback != null) { - callback = mCallback; - } - } else { + /** Returns AutofillCallback if need fire EVENT_INPUT_UNAVAILABLE */ + private AutofillCallback notifyViewEnteredLocked(View view, int virtualId, Rect bounds, + int flags) { + AutofillCallback callback = null; + if (shouldIgnoreViewEnteredLocked(view, flags)) return callback; + + ensureServiceClientAddedIfNeededLocked(); + + if (!mEnabled) { + if (mCallback != null) { + callback = mCallback; + } + } else { + // don't notify entered when Activity is already in background + if (!isClientDisablingEnterExitEvent()) { final AutofillId id = getAutofillId(view, virtualId); if (!isActiveLocked()) { @@ -773,11 +845,7 @@ public final class AutofillManager { } } } - - if (callback != null) { - callback.onAutofillEvent(view, virtualId, - AutofillCallback.EVENT_INPUT_UNAVAILABLE); - } + return callback; } /** @@ -791,9 +859,16 @@ public final class AutofillManager { return; } synchronized (mLock) { - ensureServiceClientAddedIfNeededLocked(); + notifyViewExitedLocked(view, virtualId); + } + } - if (mEnabled && isActiveLocked()) { + private void notifyViewExitedLocked(@NonNull View view, int virtualId) { + ensureServiceClientAddedIfNeededLocked(); + + if (mEnabled && isActiveLocked()) { + // don't notify exited when Activity is already in background + if (!isClientDisablingEnterExitEvent()) { final AutofillId id = getAutofillId(view, virtualId); // Update focus on existing session. @@ -1027,7 +1102,9 @@ public final class AutofillManager { * Gets the user data used for * <a href="AutofillService.html#FieldClassification">field classification</a>. * - * <p><b>Note:</b> This method should only be called by an app providing an autofill service. + * <p><b>Note:</b> This method should only be called by an app providing an autofill service, + * and it's ignored if the caller currently doesn't have an enabled autofill service for + * the user. * * @return value previously set by {@link #setUserData(UserData)} or {@code null} if it was * reset or if the caller currently does not have an enabled autofill service for the user. @@ -1079,6 +1156,47 @@ public final class AutofillManager { } /** + * Gets the name of the default algorithm used for + * <a href="AutofillService.html#FieldClassification">field classification</a>. + * + * <p>The default algorithm is used when the algorithm on {@link UserData} is invalid or not + * set. + * + * <p><b>Note:</b> This method should only be called by an app providing an autofill service, + * and it's ignored if the caller currently doesn't have an enabled autofill service for + * the user. + */ + @Nullable + public String getDefaultFieldClassificationAlgorithm() { + try { + return mService.getDefaultFieldClassificationAlgorithm(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + return null; + } + } + + /** + * Gets the name of all algorithms currently available for + * <a href="AutofillService.html#FieldClassification">field classification</a>. + * + * <p><b>Note:</b> This method should only be called by an app providing an autofill service, + * and it returns an empty list if the caller currently doesn't have an enabled autofill service + * for the user. + */ + @NonNull + public List<String> getAvailableFieldClassificationAlgorithms() { + final String[] algorithms; + try { + algorithms = mService.getAvailableFieldClassificationAlgorithms(); + return algorithms != null ? Arrays.asList(algorithms) : Collections.emptyList(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + return null; + } + } + + /** * Returns {@code true} if autofill is supported by the current device and * is supported for this user. * @@ -1109,7 +1227,7 @@ public final class AutofillManager { } /** @hide */ - public void onAuthenticationResult(int authenticationId, Intent data) { + public void onAuthenticationResult(int authenticationId, Intent data, View focusView) { if (!hasAutofillFeature()) { return; } @@ -1121,9 +1239,24 @@ public final class AutofillManager { if (sDebug) Log.d(TAG, "onAuthenticationResult(): d=" + data); synchronized (mLock) { - if (!isActiveLocked() || data == null) { + if (!isActiveLocked()) { + return; + } + // If authenticate activity closes itself during onCreate(), there is no onStop/onStart + // of app activity. We enforce enter event to re-show fill ui in such case. + // CTS example: + // LoginActivityTest#testDatasetAuthTwoFieldsUserCancelsFirstAttempt + // LoginActivityTest#testFillResponseAuthBothFieldsUserCancelsFirstAttempt + if (!mOnInvisibleCalled && focusView != null + && focusView.canNotifyAutofillEnterExitEvent()) { + notifyViewExitedLocked(focusView); + notifyViewEnteredLocked(focusView, 0); + } + if (data == null) { + // data is set to null when result is not RESULT_OK return; } + final Parcelable result = data.getParcelableExtra(EXTRA_AUTHENTICATION_RESULT); final Bundle responseData = new Bundle(); responseData.putParcelable(EXTRA_AUTHENTICATION_RESULT, result); @@ -1356,6 +1489,9 @@ public final class AutofillManager { if (sessionId == mSessionId) { final AutofillClient client = getClient(); if (client != null) { + // clear mOnInvisibleCalled and we will see if receive onInvisibleForAutofill() + // before onAuthenticationResult() + mOnInvisibleCalled = false; client.autofillCallbackAuthenticate(authenticationId, intent, fillInIntent); } } @@ -1721,6 +1857,7 @@ public final class AutofillManager { pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled); pw.print(pfx); pw.print("hasService: "); pw.println(mService != null); pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null); + pw.print(pfx); pw.print("onInvisibleCalled "); pw.println(mOnInvisibleCalled); pw.print(pfx); pw.print("last autofilled data: "); pw.println(mLastAutofilledData); pw.print(pfx); pw.print("tracked views: "); if (mTrackedViews == null) { @@ -1891,15 +2028,13 @@ public final class AutofillManager { * @param id the id of the view/virtual view whose visibility changed. * @param isVisible visible if the view is visible in the view hierarchy. */ - void notifyViewVisibilityChanged(@NonNull AutofillId id, boolean isVisible) { - AutofillClient client = getClient(); - + void notifyViewVisibilityChangedLocked(@NonNull AutofillId id, boolean isVisible) { if (sDebug) { Log.d(TAG, "notifyViewVisibilityChanged(): id=" + id + " isVisible=" + isVisible); } - if (client != null && client.isVisibleForAutofill()) { + if (isClientVisibleForAutofillLocked()) { if (isVisible) { if (isInSet(mInvisibleTrackedIds, id)) { mInvisibleTrackedIds = removeFromSet(mInvisibleTrackedIds, id); |