diff options
6 files changed, 90 insertions, 10 deletions
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 497bc90b..d73723a 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 59f0917..ef9649a 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 a0f1041..56e8b30 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 diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 15d11d8..a649ee1 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -87,4 +87,7 @@ public class BaseIWindow extends IWindow.Stub { } } } + + public void doneAnimating() { + } } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index b270cee..276bc5b 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -424,6 +424,12 @@ public class WindowManagerService extends IWindowManager.Stub = new ArrayList<Pair<WindowState, IRemoteCallback>>(); /** + * Windows that have called relayout() while we were running animations, + * so we need to tell when the animation is done. + */ + final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>(); + + /** * Used when rebuilding window list to keep track of windows that have * been removed. */ @@ -2647,6 +2653,7 @@ public class WindowManagerService extends IWindowManager.Stub boolean inTouchMode; boolean configChanged; boolean surfaceChanged = false; + boolean animating; // if they don't have this permission, mask out the status bar bits int systemUiVisibility = 0; @@ -2946,7 +2953,11 @@ public class WindowManagerService extends IWindowManager.Stub TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange); inTouchMode = mInTouchMode; - + animating = mAnimator.mAnimating; + if (animating && !mRelayoutWhileAnimating.contains(win)) { + mRelayoutWhileAnimating.add(win); + } + mInputMonitor.updateInputWindowsLw(true /*force*/); } @@ -2958,7 +2969,8 @@ public class WindowManagerService extends IWindowManager.Stub return (inTouchMode ? WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE : 0) | (displayed ? WindowManagerImpl.RELAYOUT_RES_FIRST_TIME : 0) - | (surfaceChanged ? WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED : 0); + | (surfaceChanged ? WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED : 0) + | (animating ? WindowManagerImpl.RELAYOUT_RES_ANIMATING : 0); } public void performDeferredDestroyWindow(Session session, IWindow client) { @@ -8579,6 +8591,16 @@ public class WindowManagerService extends IWindowManager.Stub mToBottomApps.clear(); } + if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) { + for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) { + try { + mRelayoutWhileAnimating.get(j).mClient.doneAnimating(); + } catch (RemoteException e) { + } + } + mRelayoutWhileAnimating.clear(); + } + if (wallpaperDestroyed) { mLayoutNeeded |= adjustWallpaperWindowsLocked() != 0; } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java index 7c683c9..434ae9d 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java @@ -91,6 +91,10 @@ public final class BridgeWindow implements IWindow { } @Override + public void doneAnimating() { + } + + @Override public IBinder asBinder() { // pass for now. return null; |