summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2018-11-27 19:30:48 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2018-11-27 19:30:48 +0000
commit2bad68cd1a4ee4cc9b4617507fa7884bfafec053 (patch)
tree2a1f0ab6bad6c86cfdb08f8f8bc8be45c9dbd601
parentfa2b85579e4b75c31e411207b6dca026421d1489 (diff)
parentbd5f58d845313796dcc0564fc659d3c7e12ad948 (diff)
Merge "Fixed when IntelligenceManager.notifyAppeared()/disappeared() is called."
-rw-r--r--core/java/android/view/View.java133
-rw-r--r--core/java/android/widget/TextView.java3
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;