summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/View.java8
-rw-r--r--core/java/android/view/ViewRootImpl.java3
-rw-r--r--core/java/android/view/ViewTreeObserver.java29
-rw-r--r--tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java2
4 files changed, 36 insertions, 6 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fecb9e6aec43..79bdc004ae67 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -19102,7 +19102,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return mAttachInfo.mTreeObserver;
}
if (mFloatingTreeObserver == null) {
- mFloatingTreeObserver = new ViewTreeObserver();
+ mFloatingTreeObserver = new ViewTreeObserver(mContext);
}
return mFloatingTreeObserver;
}
@@ -23051,7 +23051,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* The view tree observer used to dispatch global events like
* layout, pre-draw, touch mode change, etc.
*/
- final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
+ final ViewTreeObserver mTreeObserver;
/**
* A Canvas used by the view hierarchy to perform bitmap caching.
@@ -23173,7 +23173,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @param handler the events handler the view must use
*/
AttachInfo(IWindowSession session, IWindow window, Display display,
- ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
+ ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
+ Context context) {
mSession = session;
mWindow = window;
mWindowToken = window.asBinder();
@@ -23181,6 +23182,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mViewRootImpl = viewRootImpl;
mHandler = handler;
mRootCallbacks = effectPlayer;
+ mTreeObserver = new ViewTreeObserver(context);
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ece0e1b9d01b..3bbf75e8e856 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -429,7 +429,8 @@ public final class ViewRootImpl implements ViewParent,
mPreviousTransparentRegion = new Region();
mFirst = true; // true for the first time the view is added
mAdded = false;
- mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
+ mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
+ context);
mAccessibilityManager = AccessibilityManager.getInstance(context);
mAccessibilityInteractionConnectionManager =
new AccessibilityInteractionConnectionManager();
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index 521fd3117329..7dd2fc23642d 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -16,8 +16,11 @@
package android.view;
+import android.content.Context;
import android.graphics.Rect;
import android.graphics.Region;
+import android.os.Build;
+import android.util.Log;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -49,7 +52,9 @@ public final class ViewTreeObserver {
private CopyOnWriteArray<OnWindowShownListener> mOnWindowShownListeners;
// These listeners cannot be mutated during dispatch
+ private boolean mInDispatchOnDraw;
private ArrayList<OnDrawListener> mOnDrawListeners;
+ private static boolean sIllegalOnDrawModificationIsFatal;
/** Remains false until #dispatchOnWindowShown() is called. If a listener registers after
* that the listener will be immediately called. */
@@ -327,7 +332,9 @@ public final class ViewTreeObserver {
/**
* Creates a new ViewTreeObserver. This constructor should not be called
*/
- ViewTreeObserver() {
+ ViewTreeObserver(Context context) {
+ sIllegalOnDrawModificationIsFatal =
+ context.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.N_MR1;
}
/**
@@ -657,6 +664,15 @@ public final class ViewTreeObserver {
mOnDrawListeners = new ArrayList<OnDrawListener>();
}
+ if (mInDispatchOnDraw) {
+ IllegalStateException ex = new IllegalStateException(
+ "Cannot call addOnDrawListener inside of onDraw");
+ if (sIllegalOnDrawModificationIsFatal) {
+ throw ex;
+ } else {
+ Log.e("ViewTreeObserver", ex.getMessage(), ex);
+ }
+ }
mOnDrawListeners.add(listener);
}
@@ -676,6 +692,15 @@ public final class ViewTreeObserver {
if (mOnDrawListeners == null) {
return;
}
+ if (mInDispatchOnDraw) {
+ IllegalStateException ex = new IllegalStateException(
+ "Cannot call removeOnDrawListener inside of onDraw");
+ if (sIllegalOnDrawModificationIsFatal) {
+ throw ex;
+ } else {
+ Log.e("ViewTreeObserver", ex.getMessage(), ex);
+ }
+ }
mOnDrawListeners.remove(victim);
}
@@ -976,11 +1001,13 @@ public final class ViewTreeObserver {
*/
public final void dispatchOnDraw() {
if (mOnDrawListeners != null) {
+ mInDispatchOnDraw = true;
final ArrayList<OnDrawListener> listeners = mOnDrawListeners;
int numListeners = listeners.size();
for (int i = 0; i < numListeners; ++i) {
listeners.get(i).onDraw();
}
+ mInDispatchOnDraw = false;
}
}
diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
index 94f3f546d0c3..85584d3ed2cc 100644
--- a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
@@ -34,7 +34,7 @@ public class AttachInfo_Accessor {
Display display = wm.getDefaultDisplay();
ViewRootImpl root = new ViewRootImpl(context, display);
AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
- display, root, new Handler(), null);
+ display, root, new Handler(), null, context);
info.mHasWindowFocus = true;
info.mWindowVisibility = View.VISIBLE;
info.mInTouchMode = false; // this is so that we can display selections.