summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2012-04-27 14:16:30 -0700
committerDianne Hackborn <hackbod@google.com>2012-04-27 15:21:44 -0700
commit12d3a94397c33fdb773a1eaaaa13cab80bf0c571 (patch)
tree607f0f7677f8597227883ced5d97f27b0cf39c52 /core/java/android
parent11dea2945124b166f167d4b5a23a059f33c04fa1 (diff)
When a window is first shown only draw once while animating.
On some hardware allocating a new graphics buffer is quite expensive, which blocks updates to the UI. This can cause glitches when performing window animations. To reduce these glitches, the view hierarchy will now only allow itself to be drawn once if its window is being shown while the window manager is animating, not resuming draws until it is told that the animation is done. Change-Id: Ie15192f6fddbd0931b022a72c76ddd55ca266d84
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/view/IWindow.aidl11
-rw-r--r--core/java/android/view/ViewRootImpl.java51
-rw-r--r--core/java/android/view/WindowManagerImpl.java5
3 files changed, 59 insertions, 8 deletions
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 497bc90b8ed6..d73723a049d1 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -70,11 +70,18 @@ oneway interface IWindow {
/**
* Drag/drop events
*/
- void dispatchDragEvent(in DragEvent event);
+ void dispatchDragEvent(in DragEvent event);
/**
* System chrome visibility changes
*/
- void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
+ void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
int localValue, int localChanges);
+
+ /**
+ * If the window manager returned RELAYOUT_RES_ANIMATING
+ * from relayout(), this method will be called when the animation
+ * is done.
+ */
+ void doneAnimating();
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 59f0917e1916..ef9649a4ecb2 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -229,6 +229,7 @@ public final class ViewRootImpl implements ViewParent,
boolean mNewSurfaceNeeded;
boolean mHasHadWindowFocus;
boolean mLastWasImTarget;
+ boolean mWindowsAnimating;
int mLastSystemUiVisibility;
// Pool of queued input events.
@@ -1768,6 +1769,8 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ boolean skipDraw = false;
+
if (mFirst) {
// handle first focus request
if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: mView.hasFocus()="
@@ -1784,6 +1787,14 @@ public final class ViewRootImpl implements ViewParent,
+ mRealFocusedView);
}
}
+ if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_ANIMATING) != 0) {
+ // The first time we relayout the window, if the system is
+ // doing window animations, we want to hold of on any future
+ // draws until the animation is done.
+ mWindowsAnimating = true;
+ }
+ } else if (mWindowsAnimating) {
+ skipDraw = true;
}
mFirst = false;
@@ -1815,14 +1826,16 @@ public final class ViewRootImpl implements ViewParent,
viewVisibility != View.VISIBLE;
if (!cancelDraw && !newSurface) {
- if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
- for (int i = 0; i < mPendingTransitions.size(); ++i) {
- mPendingTransitions.get(i).startChangingAnimations();
+ if (!skipDraw || mReportNextDraw) {
+ if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
+ for (int i = 0; i < mPendingTransitions.size(); ++i) {
+ mPendingTransitions.get(i).startChangingAnimations();
+ }
+ mPendingTransitions.clear();
}
- mPendingTransitions.clear();
+
+ performDraw();
}
-
- performDraw();
} else {
// End any pending transitions on this non-visible window
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
@@ -2680,6 +2693,7 @@ public final class ViewRootImpl implements ViewParent,
private final static int MSG_DISPATCH_SCREEN_STATE = 20;
private final static int MSG_INVALIDATE_DISPLAY_LIST = 21;
private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 22;
+ private final static int MSG_DISPATCH_DONE_ANIMATING = 23;
final class ViewRootHandler extends Handler {
@Override
@@ -2729,6 +2743,8 @@ public final class ViewRootImpl implements ViewParent,
return "MSG_INVALIDATE_DISPLAY_LIST";
case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST:
return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
+ case MSG_DISPATCH_DONE_ANIMATING:
+ return "MSG_DISPATCH_DONE_ANIMATING";
}
return super.getMessageName(message);
}
@@ -2941,6 +2957,9 @@ public final class ViewRootImpl implements ViewParent,
case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST: {
setAccessibilityFocusedHost(null);
} break;
+ case MSG_DISPATCH_DONE_ANIMATING: {
+ handleDispatchDoneAnimating();
+ } break;
}
}
}
@@ -3756,6 +3775,15 @@ public final class ViewRootImpl implements ViewParent,
mView.dispatchSystemUiVisibilityChanged(args.globalVisibility);
}
+ public void handleDispatchDoneAnimating() {
+ if (mWindowsAnimating) {
+ mWindowsAnimating = false;
+ if (!mDirty.isEmpty() || mIsAnimating) {
+ scheduleTraversals();
+ }
+ }
+ }
+
public void getLastTouchPoint(Point outLocation) {
outLocation.x = (int) mLastTouchPoint.x;
outLocation.y = (int) mLastTouchPoint.y;
@@ -4476,6 +4504,10 @@ public final class ViewRootImpl implements ViewParent,
mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_SYSTEM_UI_VISIBILITY, args));
}
+ public void dispatchDoneAnimating() {
+ mHandler.sendEmptyMessage(MSG_DISPATCH_DONE_ANIMATING);
+ }
+
public void dispatchCheckFocus() {
if (!mHandler.hasMessages(MSG_CHECK_FOCUS)) {
// This will result in a call to checkFocus() below.
@@ -4783,6 +4815,13 @@ public final class ViewRootImpl implements ViewParent,
localValue, localChanges);
}
}
+
+ public void doneAnimating() {
+ final ViewRootImpl viewAncestor = mViewAncestor.get();
+ if (viewAncestor != null) {
+ viewAncestor.dispatchDoneAnimating();
+ }
+ }
}
/**
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index a0f104103b71..56e8b3056c5c 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -73,6 +73,11 @@ public class WindowManagerImpl implements WindowManager {
* The window manager has changed the surface from the last call.
*/
public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
+ /**
+ * The window manager is currently animating. It will call
+ * IWindow.doneAnimating() when done.
+ */
+ public static final int RELAYOUT_RES_ANIMATING = 0x8;
/**
* Flag for relayout: the client will be later giving