Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba6be8a6 authored by Romain Guy's avatar Romain Guy
Browse files

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
parent 88fffb7a
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -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();
    }

+17 −0
Original line number Diff line number Diff line
@@ -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;
+14 −0
Original line number Diff line number Diff line
@@ -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
    ///////////////////////////////////////////////////////////////////////////
+22 −0
Original line number Diff line number Diff line
@@ -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);
}
+43 −2
Original line number Diff line number Diff line
@@ -436,6 +436,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
@@ -1202,13 +1223,33 @@ public abstract class HardwareRenderer {
            }

            if ((status & DisplayList.STATUS_INVOKE) != 0) {
                attachInfo.mHandler.removeCallbacks(mFunctorsRunnable);
                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.
         * 
Loading