diff options
| author | 2018-11-27 19:30:48 +0000 | |
|---|---|---|
| committer | 2018-11-27 19:30:48 +0000 | |
| commit | 2bad68cd1a4ee4cc9b4617507fa7884bfafec053 (patch) | |
| tree | 2a1f0ab6bad6c86cfdb08f8f8bc8be45c9dbd601 | |
| parent | fa2b85579e4b75c31e411207b6dca026421d1489 (diff) | |
| parent | bd5f58d845313796dcc0564fc659d3c7e12ad948 (diff) | |
Merge "Fixed when IntelligenceManager.notifyAppeared()/disappeared() is called."
| -rw-r--r-- | core/java/android/view/View.java | 133 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 3 |
2 files changed, 59 insertions, 77 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index cb454ff8af37..0eaef5aa3c53 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3373,9 +3373,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * |-------|-------|-------|-------| * 1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK - * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT - * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED - * 1 PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE + * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED + * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED * |-------|-------|-------|-------| */ @@ -3396,28 +3395,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods * should be called. * - * The idea is to call notifyNodeAdded() after the view is layout and visible, then call - * notifyNodeRemoved() when it's gone (without known when it was removed from the parent). - * - * TODO(b/111276913): the current algortighm could probably be optimized and some of them - * removed + * The idea is to call notifyAppeared() after the view is layout and visible, then call + * notifyDisappeared() when it's gone (without known when it was removed from the parent). */ - private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT = 0x10; - private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED = 0x20; - private static final int PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE = 0x40; + private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED = 0x10; + private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED = 0x20; /* End of masks for mPrivateFlags4 */ - private static final int CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED = 1; - private static final int CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED = 0; - - @IntDef(flag = true, prefix = { "CONTENT_CAPTURE_NOTIFICATION_TYPE_" }, value = { - CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED, - CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED - }) - @Retention(RetentionPolicy.SOURCE) - private @interface ContentCaptureNotificationType {} - /** @hide */ protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0; /** @hide */ @@ -8933,63 +8918,61 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Helper used to notify the {@link IntelligenceManager} when the view is removed or * added, based on whether it's laid out and visible, and without knowing if the parent removed * it from the view hierarchy. + * + * <p>This method is called from many places (visibility changed, view laid out, view attached + * or detached to/from window, etc...) and hence must contain the logic to call the manager, as + * described below: + * + * <ol> + * <li>It should only be called when content capture is enabled for the view. + * <li>It must call viewAppeared() before viewDisappeared() + * <li>viewAppearead() can only be called when the view is visible and laidout + * <li>It should not call the same event twice. + * </ol> */ - // TODO(b/111276913): make sure the current algorithm covers all cases. For example, it should - // probably be called every time notifyEnterOrExitForAutoFillIfNeeded() is called as well. - private void notifyNodeAddedOrRemovedForContentCaptureIfNeeded( - @ContentCaptureNotificationType int type) { - if (type != CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED - && type != CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED) { - // Sanity check so it does not screw up the flags - Log.wtf(CONTENT_CAPTURE_LOG_TAG, "notifyNodeAddedOrRemovedForContentCaptureIfNeeded(): " - + "invalid type " + type + " for " + this); - return; - } - - if (!isImportantForContentCapture()) return; + private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) { final IntelligenceManager im = mContext.getSystemService(IntelligenceManager.class); if (im == null || !im.isContentCaptureEnabled()) return; - // Make sure event is notified just once, and reset the - // PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE flag - boolean ignoreNotification = false; - if (type == CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED) { - if ((mPrivateFlags4 & PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE) - == CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED) { - ignoreNotification = true; - } else { - mPrivateFlags4 |= PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE; - } - } else { - if ((mPrivateFlags4 & PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE) - == CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED) { - ignoreNotification = true; - } else { - mPrivateFlags4 &= ~PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE; - } - } - if (ignoreNotification) { - if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) { - // TODO(b/111276913): remove this log statement if the algorithm is not improved - // (right now it's called too many times when the activity is stopped and/or views - // disappear - Log.v(CONTENT_CAPTURE_LOG_TAG, "notifyNodeAddedOrRemovedForContentCaptureIfNeeded(" - + type + "): ignoring repeated notification on " + this); - } - return; - } + // NOTE: isImportantForContentCapture() is more expensive than im.isContentCaptureEnabled() + if (!isImportantForContentCapture()) return; - if (type == CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED) { + if (appeared) { + if (!isLaidOut() || !isVisibleToUser() + || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0) { + if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) { + Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid=" + + isLaidOut() + ", visible=" + isVisibleToUser() + + ": alreadyNotifiedAppeared=" + + ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)); + } + return; + } + // All good: notify the manager... final ViewStructure structure = im.newViewStructure(this); onProvideContentCaptureStructure(structure, /* flags= */ 0); im.notifyViewAppeared(structure); - mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED; + // ...and set the flags + mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED; + mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED; } else { - if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED) == 0) { - return; // skip initial notification + if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) == 0 + || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0) { + if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) { + Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'disappeared' on " + this + + ": notifiedAppeared=" + + ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0) + + ", alreadyNotifiedDisappeared=" + ((mPrivateFlags4 + & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0)); + } + return; } + // All good: notify the manager... im.notifyViewDisappeared(getAutofillId()); + // ...and set the flags + mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED; + mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED; } } @@ -12896,6 +12879,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public void dispatchStartTemporaryDetach() { mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH; notifyEnterOrExitForAutoFillIfNeeded(false); + notifyAppearedOrDisappearedForContentCaptureIfNeeded(false); onStartTemporaryDetach(); } @@ -12922,6 +12906,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, notifyFocusChangeToInputMethodManager(true /* hasFocus */); } notifyEnterOrExitForAutoFillIfNeeded(true); + notifyAppearedOrDisappearedForContentCaptureIfNeeded(true); } /** @@ -13503,9 +13488,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED); } } - notifyNodeAddedOrRemovedForContentCaptureIfNeeded(isVisible - ? CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED - : CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED); + + notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible); } /** @@ -19076,6 +19060,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, needGlobalAttributesUpdate(false); notifyEnterOrExitForAutoFillIfNeeded(true); + notifyAppearedOrDisappearedForContentCaptureIfNeeded(true); } @UnsupportedAppUsage @@ -19125,8 +19110,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } notifyEnterOrExitForAutoFillIfNeeded(false); - notifyNodeAddedOrRemovedForContentCaptureIfNeeded( - CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED); + notifyAppearedOrDisappearedForContentCaptureIfNeeded(false); } /** @@ -21432,12 +21416,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, notifyEnterOrExitForAutoFillIfNeeded(true); } - if ((mViewFlags & VISIBILITY_MASK) == VISIBLE - && (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT) == 0) { - notifyNodeAddedOrRemovedForContentCaptureIfNeeded( - CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED); - mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT; - } + notifyAppearedOrDisappearedForContentCaptureIfNeeded(true); } private boolean hasParentWantsFocus() { diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 35be7669a4d8..4ed9924f0d51 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -10942,6 +10942,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) { if (mLayout == null) { + if (viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) { + Log.w(LOG_TAG, "onProvideContentCaptureStructure(): calling assumeLayout()"); + } assumeLayout(); } Layout layout = mLayout; |