Merge "Pause webkit painting when UI tile painting queue is full"
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index dcddd47..3f5b45e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2654,7 +2654,7 @@
         checkThread();
         mContentWidth = 0;
         mContentHeight = 0;
-        setBaseLayer(0, null, false, false, false);
+        setBaseLayer(0, null, false, false);
         mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
     }
 
@@ -4521,6 +4521,8 @@
 
         if (canvas.isHardwareAccelerated()) {
             mZoomManager.setHardwareAccelerated();
+        } else {
+            mWebViewCore.resumeWebKitDraw();
         }
 
         int saveCount = canvas.save();
@@ -4763,11 +4765,19 @@
     }
 
     void setBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator,
-            boolean isPictureAfterFirstLayout, boolean registerPageSwapCallback) {
+            boolean isPictureAfterFirstLayout) {
         if (mNativeClass == 0)
             return;
-        nativeSetBaseLayer(mNativeClass, layer, invalRegion, showVisualIndicator,
-                isPictureAfterFirstLayout, registerPageSwapCallback);
+        boolean queueFull;
+        queueFull = nativeSetBaseLayer(mNativeClass, layer, invalRegion,
+                                       showVisualIndicator, isPictureAfterFirstLayout);
+
+        if (layer == 0 || isPictureAfterFirstLayout) {
+            mWebViewCore.resumeWebKitDraw();
+        } else if (queueFull) {
+            mWebViewCore.pauseWebKitDraw();
+        }
+
         if (mHTML5VideoViewProxy != null) {
             mHTML5VideoViewProxy.setBaseLayer(layer);
         }
@@ -9049,6 +9059,7 @@
     /** @hide Called by JNI when pages are swapped (only occurs with hardware
      * acceleration) */
     protected void pageSwapCallback(boolean notifyAnimationStarted) {
+        mWebViewCore.resumeWebKitDraw();
         if (inEditingMode()) {
             didUpdateWebTextViewDimensions(ANYWHERE);
         }
@@ -9071,13 +9082,9 @@
         boolean isPictureAfterFirstLayout = viewState != null;
 
         if (updateBaseLayer) {
-            // Request a callback on pageSwap (to reposition the webtextview)
-            boolean registerPageSwapCallback =
-                !mZoomManager.isFixedLengthAnimationInProgress() && inEditingMode();
-
             setBaseLayer(draw.mBaseLayer, draw.mInvalRegion,
                     getSettings().getShowVisualIndicator(),
-                    isPictureAfterFirstLayout, registerPageSwapCallback);
+                    isPictureAfterFirstLayout);
         }
         final Point viewSize = draw.mViewSize;
         // We update the layout (i.e. request a layout from the
@@ -9755,11 +9762,6 @@
         }
     }
 
-    /** @hide call pageSwapCallback upon next page swap */
-    protected void registerPageSwapCallback() {
-        nativeRegisterPageSwapCallback(mNativeClass);
-    }
-
     /** @hide discard all textures from tiles */
     protected void discardAllTextures() {
         nativeDiscardAllTextures();
@@ -9922,10 +9924,9 @@
     private native void     nativeSetFindIsEmpty();
     private native void     nativeSetFindIsUp(boolean isUp);
     private native void     nativeSetHeightCanMeasure(boolean measure);
-    private native void     nativeSetBaseLayer(int nativeInstance,
+    private native boolean  nativeSetBaseLayer(int nativeInstance,
             int layer, Region invalRegion,
-            boolean showVisualIndicator, boolean isPictureAfterFirstLayout,
-            boolean registerPageSwapCallback);
+            boolean showVisualIndicator, boolean isPictureAfterFirstLayout);
     private native int      nativeGetBaseLayer();
     private native void     nativeShowCursorTimed();
     private native void     nativeReplaceBaseContent(int content);
@@ -9937,7 +9938,6 @@
     private native void     nativeStopGL();
     private native Rect     nativeSubtractLayers(Rect content);
     private native int      nativeTextGeneration();
-    private native void     nativeRegisterPageSwapCallback(int nativeInstance);
     private native void     nativeDiscardAllTextures();
     private native void     nativeTileProfilingStart();
     private native float    nativeTileProfilingStop();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 8582dbc..ebf3e21 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2169,7 +2169,36 @@
                 .obtainMessage(WebView.INVAL_RECT_MSG_ID));
     }
 
+    private Boolean m_skipDrawFlag = false;
+    private boolean m_drawWasSkipped = false;
+
+    void pauseWebKitDraw() {
+        synchronized (m_skipDrawFlag) {
+            if (!m_skipDrawFlag) {
+                m_skipDrawFlag = true;
+            }
+        }
+    }
+
+    void resumeWebKitDraw() {
+        synchronized (m_skipDrawFlag) {
+            if (m_skipDrawFlag && m_drawWasSkipped) {
+                // a draw was dropped, send a retry
+                m_drawWasSkipped = false;
+                mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
+            }
+            m_skipDrawFlag = false;
+        }
+    }
+
     private void webkitDraw() {
+        synchronized (m_skipDrawFlag) {
+            if (m_skipDrawFlag) {
+                m_drawWasSkipped = true;
+                return;
+            }
+        }
+
         mDrawIsScheduled = false;
         DrawData draw = new DrawData();
         if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw start");
@@ -2178,7 +2207,7 @@
         if (draw.mBaseLayer == 0) {
             if (mWebView != null && !mWebView.isPaused()) {
                 if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort, resending draw message");
-                mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW));
+                mEventHub.sendMessageDelayed(Message.obtain(null, EventHub.WEBKIT_DRAW), 10);
             } else {
                 if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort, webview paused");
             }
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
index a706f78..a38ac25 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
@@ -40,8 +40,11 @@
     private long mContentInvalMillis;
     private static final int LOAD_STALL_MILLIS = 2000; // nr of millis after load,
                                                        // before test is forced
-    private double mLoadTime;
-    private double mAnimationTime;
+
+    // ignore anim end events until this many millis after load
+    private static final long ANIM_SAFETY_THRESHOLD = 200;
+    private long mLoadTime;
+    private long mAnimationTime;
 
     public ProfiledWebView(Context context) {
         super(context);
@@ -131,7 +134,6 @@
                     // invalidate all content, and kick off redraw
                     Log.d("ProfiledWebView",
                             "kicking off test with callback registration, and tile discard...");
-                    registerPageSwapCallback();
                     discardAllTextures();
                     invalidate();
                     mIsScrolling = true;
@@ -150,10 +152,11 @@
      */
     @Override
     protected void pageSwapCallback(boolean startAnim) {
+        super.pageSwapCallback(startAnim);
+
         if (!mIsTesting && mIsScrolling) {
             // kick off testing
             mContentInvalMillis = System.currentTimeMillis() - mContentInvalMillis;
-            super.pageSwapCallback(startAnim);
             Log.d("ProfiledWebView", "REDRAW TOOK " + mContentInvalMillis + "millis");
             mIsTesting = true;
             invalidate(); // ensure a redraw so that auto-scrolling can occur
@@ -166,14 +169,14 @@
         String updatesString = settings.getProperty("tree_updates");
         int updates = (updatesString == null) ? -1 : Integer.parseInt(updatesString);
 
-        double animationTime;
-        if (mAnimationTime == 0) {
+        long animationTime;
+        if (mAnimationTime == 0 || mAnimationTime - mLoadTime < ANIM_SAFETY_THRESHOLD) {
             animationTime = System.currentTimeMillis() - mLoadTime;
         } else {
             animationTime = mAnimationTime - mLoadTime;
         }
 
-        return updates * 1000 / animationTime;
+        return updates * 1000.0 / animationTime;
     }
 
     public void setDoubleBuffering(boolean useDoubleBuffering) {