summaryrefslogtreecommitdiff
path: root/core/java
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2012-04-23 18:22:09 -0700
committerRomain Guy <romainguy@google.com>2012-04-23 20:29:31 -0700
commitba6be8a62dcdb3ffd210cd36b9af4e3a658eac47 (patch)
tree04f9b4d5589333970c91e51af6280a5859b78460 /core/java
parent88fffb7a34313d5e94b3974d444d07bd6a4879a4 (diff)
Prevent WebView from crashing when detached from the window
Bug #6365056 WebView enqueues a functor in the hardware renderer to handle animations and this functor is called at a later time by the hardware renderer. However, the functor was not removed from the queue when WebView was removed from the window. This could cause the hardware renderer to attempt to execute an invalid functor and lead to a crash. Change-Id: I9d38e80f3fdc5e29d4d0cdfa1e893c251a954508
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/os/Handler.java16
-rw-r--r--core/java/android/os/MessageQueue.java17
-rw-r--r--core/java/android/view/GLES20Canvas.java14
-rw-r--r--core/java/android/view/HardwareCanvas.java22
-rw-r--r--core/java/android/view/HardwareRenderer.java45
-rw-r--r--core/java/android/view/ViewRootImpl.java17
-rw-r--r--core/java/android/webkit/WebViewClassic.java9
7 files changed, 131 insertions, 9 deletions
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index 610b3550402a..0d562e491215 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -550,6 +550,16 @@ public class Handler {
return mQueue.hasMessages(this, what, object);
}
+ /**
+ * Check if there are any pending posts of messages with callback r in
+ * the message queue.
+ *
+ * @hide
+ */
+ public final boolean hasCallbacks(Runnable r) {
+ return mQueue.hasMessages(this, r, null);
+ }
+
// if we can get rid of this method, the handler need not remember its loop
// we could instead export a getMessageQueue() method...
public final Looper getLooper() {
@@ -588,20 +598,20 @@ public class Handler {
}
}
- private final Message getPostMessage(Runnable r) {
+ private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
- private final Message getPostMessage(Runnable r, Object token) {
+ private static Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain();
m.obj = token;
m.callback = r;
return m;
}
- private final void handleCallback(Message message) {
+ private static void handleCallback(Message message) {
message.callback.run();
}
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index 64027ef7fc81..5ad60ec0e7ee 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -347,6 +347,23 @@ public class MessageQueue {
}
}
+ final boolean hasMessages(Handler h, Runnable r, Object object) {
+ if (h == null) {
+ return false;
+ }
+
+ synchronized (this) {
+ Message p = mMessages;
+ while (p != null) {
+ if (p.target == h && p.callback == r && (object == null || p.obj == object)) {
+ return true;
+ }
+ p = p.next;
+ }
+ return false;
+ }
+ }
+
final void removeMessages(Handler h, int what, Object object) {
if (h == null) {
return;
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 7736f57bd249..0bb5f9fcdefd 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -266,6 +266,20 @@ class GLES20Canvas extends HardwareCanvas {
private static native int nInvokeFunctors(int renderer, Rect dirty);
+ @Override
+ public void detachFunctor(int functor) {
+ nDetachFunctor(mRenderer, functor);
+ }
+
+ private static native void nDetachFunctor(int renderer, int functor);
+
+ @Override
+ public void attachFunctor(int functor) {
+ nAttachFunctor(mRenderer, functor);
+ }
+
+ private static native void nAttachFunctor(int renderer, int functor);
+
///////////////////////////////////////////////////////////////////////////
// Memory
///////////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 2f4cd361c8a6..ee2dd5928f2c 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -107,4 +107,26 @@ public abstract class HardwareCanvas extends Canvas {
public int invokeFunctors(Rect dirty) {
return DisplayList.STATUS_DONE;
}
+
+ /**
+ * Detaches the specified functor from the current functor execution queue.
+ *
+ * @param functor The native functor to remove from the execution queue.
+ *
+ * @see #invokeFunctors(android.graphics.Rect)
+ * @see #callDrawGLFunction(int)
+ * @see #detachFunctor(int)
+ */
+ abstract void detachFunctor(int functor);
+
+ /**
+ * Attaches the specified functor to the current functor execution queue.
+ *
+ * @param functor The native functor to add to the execution queue.
+ *
+ * @see #invokeFunctors(android.graphics.Rect)
+ * @see #callDrawGLFunction(int)
+ * @see #detachFunctor(int)
+ */
+ abstract void attachFunctor(int functor);
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 1ec754a1dde1..b9295c368493 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -437,6 +437,27 @@ public abstract class HardwareRenderer {
abstract void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture);
/**
+ * Detaches the specified functor from the current functor execution queue.
+ *
+ * @param functor The native functor to remove from the execution queue.
+ *
+ * @see HardwareCanvas#callDrawGLFunction(int)
+ * @see #attachFunctor(android.view.View.AttachInfo, int)
+ */
+ abstract void detachFunctor(int functor);
+
+ /**
+ * Schedules the specified functor in the functors execution queue.
+ *
+ * @param attachInfo AttachInfo tied to this renderer.
+ * @param functor The native functor to insert in the execution queue.
+ *
+ * @see HardwareCanvas#callDrawGLFunction(int)
+ * @see #detachFunctor(int)
+ */
+ abstract void attachFunctor(View.AttachInfo attachInfo, int functor);
+
+ /**
* Initializes the hardware renderer for the specified surface and setup the
* renderer for drawing, if needed. This is invoked when the ViewAncestor has
* potentially lost the hardware renderer. The hardware renderer should be
@@ -1202,13 +1223,33 @@ public abstract class HardwareRenderer {
}
if ((status & DisplayList.STATUS_INVOKE) != 0) {
- attachInfo.mHandler.removeCallbacks(mFunctorsRunnable);
- mFunctorsRunnable.attachInfo = attachInfo;
+ scheduleFunctors(attachInfo);
+ }
+ }
+
+ private void scheduleFunctors(View.AttachInfo attachInfo) {
+ mFunctorsRunnable.attachInfo = attachInfo;
+ if (!attachInfo.mHandler.hasCallbacks(mFunctorsRunnable)) {
// delay the functor callback by a few ms so it isn't polled constantly
attachInfo.mHandler.postDelayed(mFunctorsRunnable, FUNCTOR_PROCESS_DELAY);
}
}
+ @Override
+ void detachFunctor(int functor) {
+ if (mCanvas != null) {
+ mCanvas.detachFunctor(functor);
+ }
+ }
+
+ @Override
+ void attachFunctor(View.AttachInfo attachInfo, int functor) {
+ if (mCanvas != null) {
+ mCanvas.attachFunctor(functor);
+ scheduleFunctors(attachInfo);
+ }
+ }
+
/**
* Ensures the current EGL context is the one we expect.
*
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e3681df4244d..59f0917e1916 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -59,7 +59,6 @@ import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.util.TypedValue;
-import android.view.KeyCharacterMap.FallbackAction;
import android.view.View.AttachInfo;
import android.view.View.MeasureSpec;
import android.view.accessibility.AccessibilityEvent;
@@ -669,6 +668,18 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ public void attachFunctor(int functor) {
+ if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
+ mAttachInfo.mHardwareRenderer.attachFunctor(mAttachInfo, functor);
+ }
+ }
+
+ public void detachFunctor(int functor) {
+ if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
+ mAttachInfo.mHardwareRenderer.detachFunctor(functor);
+ }
+ }
+
private void enableHardwareAcceleration(Context context, WindowManager.LayoutParams attrs) {
mAttachInfo.mHardwareAccelerated = false;
mAttachInfo.mHardwareAccelerationRequested = false;
@@ -4489,8 +4500,8 @@ public final class ViewRootImpl implements ViewParent,
mHandler.postDelayed(mSendWindowContentChangedAccessibilityEvent,
ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
} else {
- View newSource = getCommonPredecessor(oldSource, source);
- mSendWindowContentChangedAccessibilityEvent.mSource = newSource;
+ mSendWindowContentChangedAccessibilityEvent.mSource =
+ getCommonPredecessor(oldSource, source);
}
}
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 3bd9960a6359..1aa0a52ca700 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -2469,7 +2469,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
/**
* Loads the view data from the input stream. See
- * {@link #saveViewState(OutputStream)} for more information.
+ * {@link #saveViewState(java.io.OutputStream, ValueCallback)} for more information.
* @param stream The {@link InputStream} to load from
*/
public void loadViewState(InputStream stream) {
@@ -5630,6 +5630,13 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
removeAccessibilityApisFromJavaScript();
updateHwAccelerated();
+
+ if (mWebView.isHardwareAccelerated()) {
+ int drawGLFunction = nativeGetDrawGLFunction(mNativeClass);
+ if (drawGLFunction != 0) {
+ mWebView.getViewRootImpl().detachFunctor(drawGLFunction);
+ }
+ }
}
@Override