Skip to content

Commit 79c6346

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "When a window is first shown only draw once while animating." into jb-dev
2 parents a36b7ab + 12d3a94 commit 79c6346

File tree

6 files changed

+90
-10
lines changed

6 files changed

+90
-10
lines changed

core/java/android/view/IWindow.aidl

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,18 @@ oneway interface IWindow {
7070
/**
7171
* Drag/drop events
7272
*/
73-
void dispatchDragEvent(in DragEvent event);
73+
void dispatchDragEvent(in DragEvent event);
7474

7575
/**
7676
* System chrome visibility changes
7777
*/
78-
void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
78+
void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
7979
int localValue, int localChanges);
80+
81+
/**
82+
* If the window manager returned RELAYOUT_RES_ANIMATING
83+
* from relayout(), this method will be called when the animation
84+
* is done.
85+
*/
86+
void doneAnimating();
8087
}

core/java/android/view/ViewRootImpl.java

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ public final class ViewRootImpl implements ViewParent,
229229
boolean mNewSurfaceNeeded;
230230
boolean mHasHadWindowFocus;
231231
boolean mLastWasImTarget;
232+
boolean mWindowsAnimating;
232233
int mLastSystemUiVisibility;
233234

234235
// Pool of queued input events.
@@ -1766,6 +1767,8 @@ private void performTraversals() {
17661767
}
17671768
}
17681769

1770+
boolean skipDraw = false;
1771+
17691772
if (mFirst) {
17701773
// handle first focus request
17711774
if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: mView.hasFocus()="
@@ -1782,6 +1785,14 @@ private void performTraversals() {
17821785
+ mRealFocusedView);
17831786
}
17841787
}
1788+
if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_ANIMATING) != 0) {
1789+
// The first time we relayout the window, if the system is
1790+
// doing window animations, we want to hold of on any future
1791+
// draws until the animation is done.
1792+
mWindowsAnimating = true;
1793+
}
1794+
} else if (mWindowsAnimating) {
1795+
skipDraw = true;
17851796
}
17861797

17871798
mFirst = false;
@@ -1813,14 +1824,16 @@ private void performTraversals() {
18131824
viewVisibility != View.VISIBLE;
18141825

18151826
if (!cancelDraw && !newSurface) {
1816-
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
1817-
for (int i = 0; i < mPendingTransitions.size(); ++i) {
1818-
mPendingTransitions.get(i).startChangingAnimations();
1827+
if (!skipDraw || mReportNextDraw) {
1828+
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
1829+
for (int i = 0; i < mPendingTransitions.size(); ++i) {
1830+
mPendingTransitions.get(i).startChangingAnimations();
1831+
}
1832+
mPendingTransitions.clear();
18191833
}
1820-
mPendingTransitions.clear();
1834+
1835+
performDraw();
18211836
}
1822-
1823-
performDraw();
18241837
} else {
18251838
// End any pending transitions on this non-visible window
18261839
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
@@ -2677,6 +2690,7 @@ private static void forceLayout(View view) {
26772690
private final static int MSG_DISPATCH_SCREEN_STATE = 20;
26782691
private final static int MSG_INVALIDATE_DISPLAY_LIST = 21;
26792692
private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 22;
2693+
private final static int MSG_DISPATCH_DONE_ANIMATING = 23;
26802694

26812695
final class ViewRootHandler extends Handler {
26822696
@Override
@@ -2726,6 +2740,8 @@ public String getMessageName(Message message) {
27262740
return "MSG_INVALIDATE_DISPLAY_LIST";
27272741
case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST:
27282742
return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
2743+
case MSG_DISPATCH_DONE_ANIMATING:
2744+
return "MSG_DISPATCH_DONE_ANIMATING";
27292745
}
27302746
return super.getMessageName(message);
27312747
}
@@ -2938,6 +2954,9 @@ public void handleMessage(Message msg) {
29382954
case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST: {
29392955
setAccessibilityFocusedHost(null);
29402956
} break;
2957+
case MSG_DISPATCH_DONE_ANIMATING: {
2958+
handleDispatchDoneAnimating();
2959+
} break;
29412960
}
29422961
}
29432962
}
@@ -3753,6 +3772,15 @@ public void handleDispatchSystemUiVisibilityChanged(SystemUiVisibilityInfo args)
37533772
mView.dispatchSystemUiVisibilityChanged(args.globalVisibility);
37543773
}
37553774

3775+
public void handleDispatchDoneAnimating() {
3776+
if (mWindowsAnimating) {
3777+
mWindowsAnimating = false;
3778+
if (!mDirty.isEmpty() || mIsAnimating) {
3779+
scheduleTraversals();
3780+
}
3781+
}
3782+
}
3783+
37563784
public void getLastTouchPoint(Point outLocation) {
37573785
outLocation.x = (int) mLastTouchPoint.x;
37583786
outLocation.y = (int) mLastTouchPoint.y;
@@ -4465,6 +4493,10 @@ public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
44654493
mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_SYSTEM_UI_VISIBILITY, args));
44664494
}
44674495

4496+
public void dispatchDoneAnimating() {
4497+
mHandler.sendEmptyMessage(MSG_DISPATCH_DONE_ANIMATING);
4498+
}
4499+
44684500
public void dispatchCheckFocus() {
44694501
if (!mHandler.hasMessages(MSG_CHECK_FOCUS)) {
44704502
// This will result in a call to checkFocus() below.
@@ -4772,6 +4804,13 @@ public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
47724804
localValue, localChanges);
47734805
}
47744806
}
4807+
4808+
public void doneAnimating() {
4809+
final ViewRootImpl viewAncestor = mViewAncestor.get();
4810+
if (viewAncestor != null) {
4811+
viewAncestor.dispatchDoneAnimating();
4812+
}
4813+
}
47754814
}
47764815

47774816
/**

core/java/android/view/WindowManagerImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ public class WindowManagerImpl implements WindowManager {
7373
* The window manager has changed the surface from the last call.
7474
*/
7575
public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4;
76+
/**
77+
* The window manager is currently animating. It will call
78+
* IWindow.doneAnimating() when done.
79+
*/
80+
public static final int RELAYOUT_RES_ANIMATING = 0x8;
7681

7782
/**
7883
* Flag for relayout: the client will be later giving

core/java/com/android/internal/view/BaseIWindow.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,7 @@ public void dispatchWallpaperCommand(String action, int x, int y,
8787
}
8888
}
8989
}
90+
91+
public void doneAnimating() {
92+
}
9093
}

services/java/com/android/server/wm/WindowManagerService.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,12 @@ public void onReceive(Context context, Intent intent) {
423423
ArrayList<Pair<WindowState, IRemoteCallback>> mWaitingForDrawn
424424
= new ArrayList<Pair<WindowState, IRemoteCallback>>();
425425

426+
/**
427+
* Windows that have called relayout() while we were running animations,
428+
* so we need to tell when the animation is done.
429+
*/
430+
final ArrayList<WindowState> mRelayoutWhileAnimating = new ArrayList<WindowState>();
431+
426432
/**
427433
* Used when rebuilding window list to keep track of windows that have
428434
* been removed.
@@ -2647,6 +2653,7 @@ public int relayoutWindow(Session session, IWindow client, int seq,
26472653
boolean inTouchMode;
26482654
boolean configChanged;
26492655
boolean surfaceChanged = false;
2656+
boolean animating;
26502657

26512658
// if they don't have this permission, mask out the status bar bits
26522659
int systemUiVisibility = 0;
@@ -2946,7 +2953,11 @@ public int relayoutWindow(Session session, IWindow client, int seq,
29462953
TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
29472954

29482955
inTouchMode = mInTouchMode;
2949-
2956+
animating = mAnimator.mAnimating;
2957+
if (animating && !mRelayoutWhileAnimating.contains(win)) {
2958+
mRelayoutWhileAnimating.add(win);
2959+
}
2960+
29502961
mInputMonitor.updateInputWindowsLw(true /*force*/);
29512962
}
29522963

@@ -2958,7 +2969,8 @@ public int relayoutWindow(Session session, IWindow client, int seq,
29582969

29592970
return (inTouchMode ? WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE : 0)
29602971
| (displayed ? WindowManagerImpl.RELAYOUT_RES_FIRST_TIME : 0)
2961-
| (surfaceChanged ? WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED : 0);
2972+
| (surfaceChanged ? WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED : 0)
2973+
| (animating ? WindowManagerImpl.RELAYOUT_RES_ANIMATING : 0);
29622974
}
29632975

29642976
public void performDeferredDestroyWindow(Session session, IWindow client) {
@@ -8579,6 +8591,16 @@ private final void performLayoutAndPlaceSurfacesLockedInner(
85798591
mToBottomApps.clear();
85808592
}
85818593

8594+
if (!mAnimator.mAnimating && mRelayoutWhileAnimating.size() > 0) {
8595+
for (int j=mRelayoutWhileAnimating.size()-1; j>=0; j--) {
8596+
try {
8597+
mRelayoutWhileAnimating.get(j).mClient.doneAnimating();
8598+
} catch (RemoteException e) {
8599+
}
8600+
}
8601+
mRelayoutWhileAnimating.clear();
8602+
}
8603+
85828604
if (wallpaperDestroyed) {
85838605
mLayoutNeeded |= adjustWallpaperWindowsLocked() != 0;
85848606
}

tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ public void dispatchSystemUiVisibilityChanged(int seq, int globalUi,
9090
// pass for now.
9191
}
9292

93+
@Override
94+
public void doneAnimating() {
95+
}
96+
9397
@Override
9498
public IBinder asBinder() {
9599
// pass for now.

0 commit comments

Comments
 (0)