summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chong Zhang <chz@google.com> 2015-10-12 20:47:38 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2015-10-12 20:47:38 +0000
commit34259092854d389f6f85508a1dd53aeebcc6f6cc (patch)
treea87e08e3ee5337e598b1e496a77408b9e29fbdc4
parentc7e19d9f141ad702bc94a7a97aea41e07da57d59 (diff)
parent8dbd9ad68248a921637c4b2b866e86854b5860f6 (diff)
Merge "Fix missing frame or wrong frame position when resize starts"
-rw-r--r--core/java/android/view/ViewRootImpl.java55
-rw-r--r--core/java/android/view/WindowCallbacks.java11
-rw-r--r--core/java/com/android/internal/widget/NonClientDecorView.java53
3 files changed, 103 insertions, 16 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 14e7d6c4e81e..3d10289ac8e9 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -88,6 +88,7 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
import java.util.HashSet;
/**
@@ -238,6 +239,7 @@ public final class ViewRootImpl implements ViewParent,
boolean mNewSurfaceNeeded;
boolean mHasHadWindowFocus;
boolean mLastWasImTarget;
+ CountDownLatch mWindowDrawCountDown;
boolean mIsDrawing;
int mLastSystemUiVisibility;
@@ -436,6 +438,12 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ public void reportDrawFinish() {
+ if (mWindowDrawCountDown != null) {
+ mWindowDrawCountDown.countDown();
+ }
+ }
+
// FIXME for perf testing only
private boolean mProfile = false;
@@ -2419,6 +2427,17 @@ public final class ViewRootImpl implements ViewParent,
if (mReportNextDraw) {
mReportNextDraw = false;
+
+ // if we're using multi-thread renderer, wait for the window frame draws
+ if (mWindowDrawCountDown != null) {
+ try {
+ mWindowDrawCountDown.await();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Window redraw count down interruped!");
+ }
+ mWindowDrawCountDown = null;
+ }
+
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.fence();
}
@@ -2568,13 +2587,13 @@ public final class ViewRootImpl implements ViewParent,
// Stage the content drawn size now. It will be transferred to the renderer
// shortly before the draw commands get send to the renderer.
- synchronized (mWindowCallbacks) {
- for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
- mWindowCallbacks.get(i).onContentDraw(mWindowAttributes.surfaceInsets.left,
- mWindowAttributes.surfaceInsets.top, mWidth, mHeight);
- }
- }
+ final boolean updated = updateContentDrawBounds();
+
mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
+
+ if (updated) {
+ requestDrawWindow();
+ }
} else {
// If we get here with a disabled & requested hardware renderer, something went
// wrong (an invalidate posted right before we destroyed the hardware surface
@@ -6796,6 +6815,30 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ private boolean updateContentDrawBounds() {
+ boolean updated = false;
+ synchronized (mWindowCallbacks) {
+ for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
+ updated |= mWindowCallbacks.get(i).onContentDrawn(
+ mWindowAttributes.surfaceInsets.left,
+ mWindowAttributes.surfaceInsets.top,
+ mWidth, mHeight);
+ }
+ }
+ return updated | (mDragResizing && mReportNextDraw);
+ }
+
+ private void requestDrawWindow() {
+ if (mReportNextDraw) {
+ mWindowDrawCountDown = new CountDownLatch(mWindowCallbacks.size());
+ }
+ synchronized (mWindowCallbacks) {
+ for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
+ mWindowCallbacks.get(i).onRequestDraw(mReportNextDraw);
+ }
+ }
+ }
+
/**
* Class for managing the accessibility interaction connection
* based on the global accessibility state.
diff --git a/core/java/android/view/WindowCallbacks.java b/core/java/android/view/WindowCallbacks.java
index 1aeaec8c6d15..def02365dfed 100644
--- a/core/java/android/view/WindowCallbacks.java
+++ b/core/java/android/view/WindowCallbacks.java
@@ -49,7 +49,14 @@ public interface WindowCallbacks {
void onWindowDragResizeEnd();
/**
- * The content will now be drawn to these bounds.
+ * The content will now be drawn to these bounds. Returns true if
+ * a draw should be requested after the next content draw.
*/
- void onContentDraw(int offsetX, int offsetY, int sizeX, int sizeY);
+ boolean onContentDrawn(int offsetX, int offsetY, int sizeX, int sizeY);
+
+ /**
+ * Called to request the window to draw one frame.
+ * @param reportNextDraw Whether it should report when the requested draw finishes.
+ */
+ void onRequestDraw(boolean reportNextDraw);
}
diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java
index 6557ed159a0b..ed7492aae47b 100644
--- a/core/java/com/android/internal/widget/NonClientDecorView.java
+++ b/core/java/com/android/internal/widget/NonClientDecorView.java
@@ -355,9 +355,22 @@ public class NonClientDecorView extends LinearLayout
}
@Override
- public void onContentDraw(int xOffset, int yOffset, int xSize, int ySize) {
+ public boolean onContentDrawn(int xOffset, int yOffset, int xSize, int ySize) {
+ if (mFrameRendererThread == null) {
+ return false;
+ }
+ return mFrameRendererThread.onContentDrawn(xOffset, yOffset, xSize, ySize);
+ }
+
+ @Override
+ public void onRequestDraw(boolean reportNextDraw) {
if (mFrameRendererThread != null) {
- mFrameRendererThread.onContentDraw(xOffset, yOffset, xSize, ySize);
+ mFrameRendererThread.onRequsetDraw(reportNextDraw);
+ } else if (reportNextDraw) {
+ // If render thread is gone, just report immediately.
+ if (isAttachedToWindow()) {
+ getViewRootImpl().reportDrawFinish();
+ }
}
}
@@ -423,6 +436,9 @@ public class NonClientDecorView extends LinearLayout
private int mLastXOffset;
private int mLastYOffset;
+ // Whether to report when next frame is drawn or not.
+ private boolean mReportNextDraw;
+
ResizeFrameThread(ThreadedRenderer renderer, Rect initialBounds) {
setName("ResizeFrame");
mRenderer = renderer;
@@ -518,12 +534,13 @@ public class NonClientDecorView extends LinearLayout
public void doFrame(long frameTimeNanos) {
synchronized (this) {
if (mRenderer == null) {
+ reportDrawIfNeeded();
// Tell the looper to stop. We are done.
Looper.myLooper().quit();
return;
}
mNewTargetRect.set(mTargetRect);
- if (!mNewTargetRect.equals(mOldTargetRect)) {
+ if (!mNewTargetRect.equals(mOldTargetRect) || mReportNextDraw) {
mOldTargetRect.set(mNewTargetRect);
changeWindowSizeLocked(mNewTargetRect);
}
@@ -538,8 +555,9 @@ public class NonClientDecorView extends LinearLayout
* @param yOffset The y offset where the content is drawn to.
* @param xSize The width size of the content. This should not be 0.
* @param ySize The height of the content.
+ * @return true if a frame should be requested after the content is drawn; false otherwise.
*/
- public void onContentDraw(int xOffset, int yOffset, int xSize, int ySize) {
+ public boolean onContentDrawn(int xOffset, int yOffset, int xSize, int ySize) {
synchronized (this) {
final boolean firstCall = mLastContentWidth == 0;
// The current content buffer is drawn here.
@@ -555,10 +573,15 @@ public class NonClientDecorView extends LinearLayout
mLastYOffset + mLastCaptionHeight + mLastContentHeight);
// If this was the first call and changeWindowSizeLocked got already called prior
// to us, we should re-issue a changeWindowSizeLocked now.
- if (firstCall && (mLastCaptionHeight != 0 || !mShowDecor)) {
- mOldTargetRect.set(0, 0, 0, 0);
- pingRenderLocked();
- }
+ return firstCall && (mLastCaptionHeight != 0 || !mShowDecor);
+ }
+ }
+
+ public void onRequsetDraw(boolean reportNextDraw) {
+ synchronized (this) {
+ mReportNextDraw = reportNextDraw;
+ mOldTargetRect.set(0, 0, 0, 0);
+ pingRenderLocked();
}
}
@@ -617,6 +640,20 @@ public class NonClientDecorView extends LinearLayout
// We need to render both rendered nodes explicitly.
mRenderer.drawRenderNode(mFrameNode);
mRenderer.drawRenderNode(mBackdropNode);
+
+ reportDrawIfNeeded();
+ }
+
+ /**
+ * Notify view root that a frame has been drawn by us, if it has requested so.
+ */
+ private void reportDrawIfNeeded() {
+ if (mReportNextDraw) {
+ if (isAttachedToWindow()) {
+ getViewRootImpl().reportDrawFinish();
+ }
+ mReportNextDraw = false;
+ }
}
/**