blob: 1b31d07cf31ebda7ac208407062fd8d60fcb0a88 [file] [log] [blame]
Filip Gruszczynski466f3212015-09-21 17:57:57 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Jorim Jaggibc5425c2016-03-01 13:51:16 +010019import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
Jorim Jaggid3ec5072016-04-28 15:57:47 -070020import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
Jorim Jaggibc5425c2016-03-01 13:51:16 +010021import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
Jorim Jaggi85639432016-05-06 17:27:55 -070022import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
23import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
24import static android.view.Surface.ROTATION_270;
25import static android.view.Surface.ROTATION_90;
Jorim Jaggibc5425c2016-03-01 13:51:16 +010026import static android.view.WindowManager.DOCKED_BOTTOM;
27import static android.view.WindowManager.DOCKED_LEFT;
28import static android.view.WindowManager.DOCKED_RIGHT;
29import static android.view.WindowManager.DOCKED_TOP;
30import static com.android.server.wm.AppTransition.DEFAULT_APP_TRANSITION_DURATION;
31import static com.android.server.wm.AppTransition.TOUCH_RESPONSE_INTERPOLATOR;
32import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
33import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Tony Mak853304c2016-04-18 15:17:41 +010034import static com.android.server.wm.WindowManagerService.H.NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED;
Jorim Jaggibc5425c2016-03-01 13:51:16 +010035
Filip Gruszczynski466f3212015-09-21 17:57:57 -070036import android.content.Context;
Jorim Jaggi85639432016-05-06 17:27:55 -070037import android.content.res.Configuration;
Filip Gruszczynski466f3212015-09-21 17:57:57 -070038import android.graphics.Rect;
Jorim Jaggia6c934e2015-12-21 13:22:31 +010039import android.os.RemoteCallbackList;
Filip Gruszczynski64cdc142015-11-29 21:10:07 -080040import android.os.RemoteException;
Filip Gruszczynski77049052015-11-09 14:01:21 -080041import android.util.Slog;
Jorim Jaggi50981592015-12-29 17:54:12 +010042import android.view.DisplayInfo;
Jorim Jaggia6c934e2015-12-21 13:22:31 +010043import android.view.IDockedStackListener;
Jorim Jaggi50981592015-12-29 17:54:12 +010044import android.view.SurfaceControl;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -080045import android.view.animation.AnimationUtils;
46import android.view.animation.Interpolator;
Jorim Jaggieb88d832016-04-13 20:17:43 -070047import android.view.animation.PathInterpolator;
Jorim Jaggi50981592015-12-29 17:54:12 +010048
Jorim Jaggi85639432016-05-06 17:27:55 -070049import com.android.internal.policy.DividerSnapAlgorithm;
50import com.android.internal.policy.DockedDividerUtils;
Jorim Jaggi50981592015-12-29 17:54:12 +010051import com.android.server.wm.DimLayer.DimLayerUser;
Jorim Jaggiff71d202016-04-14 13:12:36 -070052import com.android.server.wm.WindowManagerService.H;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010053
Jorim Jaggi31f71702016-05-04 16:43:04 -070054import java.io.PrintWriter;
Chong Zhangbaba7832016-03-24 10:21:26 -070055import java.util.ArrayList;
56
Filip Gruszczynski466f3212015-09-21 17:57:57 -070057/**
Jorim Jaggi61f39a72015-10-29 16:54:18 +010058 * Keeps information about the docked stack divider.
Filip Gruszczynski466f3212015-09-21 17:57:57 -070059 */
Jorim Jaggi50981592015-12-29 17:54:12 +010060public class DockedStackDividerController implements DimLayerUser {
Jorim Jaggi61f39a72015-10-29 16:54:18 +010061
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080062 private static final String TAG = TAG_WITH_CLASS_NAME ? "DockedStackDividerController" : TAG_WM;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010063
Jorim Jaggif97ed922016-02-18 18:57:07 -080064 /**
65 * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip
66 * revealing surface at the earliest.
67 */
68 private static final float CLIP_REVEAL_MEET_EARLIEST = 0.6f;
69
70 /**
71 * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip
72 * revealing surface at the latest.
73 */
74 private static final float CLIP_REVEAL_MEET_LAST = 1f;
75
76 /**
77 * If the app translates at least CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance, we start
78 * meet somewhere between {@link #CLIP_REVEAL_MEET_LAST} and {@link #CLIP_REVEAL_MEET_EARLIEST}.
79 */
80 private static final float CLIP_REVEAL_MEET_FRACTION_MIN = 0.4f;
81
82 /**
83 * If the app translates equals or more than CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance,
84 * we meet at {@link #CLIP_REVEAL_MEET_EARLIEST}.
85 */
86 private static final float CLIP_REVEAL_MEET_FRACTION_MAX = 0.8f;
87
Jorim Jaggieb88d832016-04-13 20:17:43 -070088 private static final Interpolator IME_ADJUST_ENTRY_INTERPOLATOR =
Jorim Jaggiff71d202016-04-14 13:12:36 -070089 new PathInterpolator(0.2f, 0f, 0.1f, 1f);
Jorim Jaggieb88d832016-04-13 20:17:43 -070090
Jorim Jaggi698e7632016-04-13 21:02:22 -070091 private static final long IME_ADJUST_ANIM_DURATION = 280;
Jorim Jaggieb88d832016-04-13 20:17:43 -070092
Jorim Jaggiff71d202016-04-14 13:12:36 -070093 private static final long IME_ADJUST_DRAWN_TIMEOUT = 200;
94
Chong Zhang198afac2016-04-15 12:03:11 -070095 private static final int DIVIDER_WIDTH_INACTIVE_DP = 4;
96
Jorim Jaggi42625d1b2016-02-11 20:11:07 -080097 private final WindowManagerService mService;
Filip Gruszczynski466f3212015-09-21 17:57:57 -070098 private final DisplayContent mDisplayContent;
Jorim Jaggi11c62e12016-04-05 20:41:21 -070099 private int mDividerWindowWidth;
Chong Zhang198afac2016-04-15 12:03:11 -0700100 private int mDividerWindowWidthInactive;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700101 private int mDividerInsets;
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100102 private boolean mResizing;
103 private WindowState mWindow;
104 private final Rect mTmpRect = new Rect();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800105 private final Rect mTmpRect2 = new Rect();
Jorim Jaggi85639432016-05-06 17:27:55 -0700106 private final Rect mTmpRect3 = new Rect();
Filip Gruszczynski77049052015-11-09 14:01:21 -0800107 private final Rect mLastRect = new Rect();
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800108 private boolean mLastVisibility = false;
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100109 private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners
110 = new RemoteCallbackList<>();
Jorim Jaggi50981592015-12-29 17:54:12 +0100111 private final DimLayer mDimLayer;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700112
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800113 private boolean mMinimizedDock;
Chong Zhangbaba7832016-03-24 10:21:26 -0700114 private boolean mAnimatingForMinimizedDockedStack;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800115 private boolean mAnimationStarted;
116 private long mAnimationStartTime;
117 private float mAnimationStart;
118 private float mAnimationTarget;
Jorim Jaggi8fe7e0a2016-02-12 19:43:39 -0800119 private long mAnimationDuration;
Jorim Jaggiff71d202016-04-14 13:12:36 -0700120 private boolean mAnimationStartDelayed;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800121 private final Interpolator mMinimizedDockInterpolator;
Jorim Jaggif97ed922016-02-18 18:57:07 -0800122 private float mMaximizeMeetFraction;
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100123 private final Rect mTouchRegion = new Rect();
Chong Zhangbaba7832016-03-24 10:21:26 -0700124 private boolean mAnimatingForIme;
125 private boolean mAdjustedForIme;
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700126 private int mImeHeight;
Jorim Jaggiff71d202016-04-14 13:12:36 -0700127 private WindowState mDelayedImeWin;
Chong Zhangf347ab52016-04-18 21:02:01 -0700128 private boolean mAdjustedForDivider;
129 private float mDividerAnimationStart;
130 private float mDividerAnimationTarget;
131 private float mLastAnimationProgress;
132 private float mLastDividerProgress;
Jorim Jaggi85639432016-05-06 17:27:55 -0700133 private final DividerSnapAlgorithm[] mSnapAlgorithmForRotation = new DividerSnapAlgorithm[4];
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800134
135 DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
136 mService = service;
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700137 mDisplayContent = displayContent;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800138 final Context context = service.mContext;
Jorim Jaggibc5425c2016-03-01 13:51:16 +0100139 mDimLayer = new DimLayer(displayContent.mService, this, displayContent.getDisplayId(),
140 "DockedStackDim");
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800141 mMinimizedDockInterpolator = AnimationUtils.loadInterpolator(
142 context, android.R.interpolator.fast_out_slow_in);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700143 loadDimens();
144 }
145
Jorim Jaggi85639432016-05-06 17:27:55 -0700146 int getSmallestWidthDpForBounds(Rect bounds) {
147 final DisplayInfo di = mDisplayContent.getDisplayInfo();
148
149 // If the bounds are fullscreen, return the value of the fullscreen configuration
150 if (bounds == null || (bounds.left == 0 && bounds.top == 0
151 && bounds.right == di.logicalWidth && bounds.bottom == di.logicalHeight)) {
152 return mService.mCurConfiguration.smallestScreenWidthDp;
153 }
154 final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth;
155 final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight;
156 int minWidth = Integer.MAX_VALUE;
157
158 // Go through all screen orientations and find the orientation in which the task has the
159 // smallest width.
160 for (int rotation = 0; rotation < 4; rotation++) {
161 mTmpRect.set(bounds);
162 mDisplayContent.rotateBounds(di.rotation, rotation, mTmpRect);
163 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
164 mTmpRect2.set(0, 0,
165 rotated ? baseDisplayHeight : baseDisplayWidth,
166 rotated ? baseDisplayWidth : baseDisplayHeight);
167 final int orientation = mTmpRect2.width() <= mTmpRect2.height()
168 ? ORIENTATION_PORTRAIT
169 : ORIENTATION_LANDSCAPE;
170 final int dockSide = TaskStack.getDockSideUnchecked(mTmpRect, mTmpRect2, orientation);
171 final int position = DockedDividerUtils.calculatePositionForBounds(mTmpRect, dockSide,
172 getContentWidth());
173
174 // Since we only care about feasible states, snap to the closest snap target, like it
175 // would happen when actually rotating the screen.
176 final int snappedPosition = mSnapAlgorithmForRotation[rotation]
177 .calculateNonDismissingSnapTarget(position).position;
178 DockedDividerUtils.calculateBoundsForPosition(snappedPosition, dockSide, mTmpRect,
179 mTmpRect2.width(), mTmpRect2.height(), getContentWidth());
180 mService.mPolicy.getStableInsetsLw(rotation, mTmpRect2.width(), mTmpRect2.height(),
181 mTmpRect3);
182 mService.subtractInsets(mTmpRect2, mTmpRect3, mTmpRect);
183 minWidth = Math.min(mTmpRect.width(), minWidth);
184 }
185 return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
186 }
187
188 private void initSnapAlgorithmForRotations() {
189 final Configuration baseConfig = mService.mCurConfiguration;
190
191 // Initialize the snap algorithms for all 4 screen orientations.
192 final Configuration config = new Configuration();
193 for (int rotation = 0; rotation < 4; rotation++) {
194 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
195 final int dw = rotated
196 ? mDisplayContent.mBaseDisplayHeight
197 : mDisplayContent.mBaseDisplayWidth;
198 final int dh = rotated
199 ? mDisplayContent.mBaseDisplayWidth
200 : mDisplayContent.mBaseDisplayHeight;
201 mService.mPolicy.getStableInsetsLw(rotation, dw, dh, mTmpRect);
202 config.setToDefaults();
203 config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
204 config.screenWidthDp = (int)
205 (mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, baseConfig.uiMode) /
206 mDisplayContent.getDisplayMetrics().density);
207 config.screenHeightDp = (int)
208 (mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, baseConfig.uiMode) /
209 mDisplayContent.getDisplayMetrics().density);
210 final Context rotationContext = mService.mContext.createConfigurationContext(config);
211 mSnapAlgorithmForRotation[rotation] = new DividerSnapAlgorithm(
212 rotationContext.getResources(), dw, dh, getContentWidth(),
213 config.orientation == ORIENTATION_PORTRAIT, mTmpRect);
214 }
215 }
216
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700217 private void loadDimens() {
218 final Context context = mService.mContext;
219 mDividerWindowWidth = context.getResources().getDimensionPixelSize(
220 com.android.internal.R.dimen.docked_stack_divider_thickness);
221 mDividerInsets = context.getResources().getDimensionPixelSize(
222 com.android.internal.R.dimen.docked_stack_divider_insets);
Chong Zhang198afac2016-04-15 12:03:11 -0700223 mDividerWindowWidthInactive = WindowManagerService.dipToPixel(
224 DIVIDER_WIDTH_INACTIVE_DP, mDisplayContent.getDisplayMetrics());
Jorim Jaggi85639432016-05-06 17:27:55 -0700225 initSnapAlgorithmForRotations();
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700226 }
227
228 void onConfigurationChanged() {
229 loadDimens();
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700230 }
231
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100232 boolean isResizing() {
233 return mResizing;
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700234 }
235
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100236 int getContentWidth() {
237 return mDividerWindowWidth - 2 * mDividerInsets;
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700238 }
239
Jorim Jaggi81ba11e2016-02-03 22:04:22 -0800240 int getContentInsets() {
241 return mDividerInsets;
242 }
243
Chong Zhang198afac2016-04-15 12:03:11 -0700244 int getContentWidthInactive() {
245 return mDividerWindowWidthInactive;
246 }
247
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100248 void setResizing(boolean resizing) {
Jorim Jaggic662d8e2016-02-05 16:54:54 -0800249 if (mResizing != resizing) {
250 mResizing = resizing;
251 resetDragResizingChangeReported();
252 }
253 }
254
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100255 void setTouchRegion(Rect touchRegion) {
256 mTouchRegion.set(touchRegion);
257 }
258
259 void getTouchRegion(Rect outRegion) {
260 outRegion.set(mTouchRegion);
261 outRegion.offset(mWindow.getFrameLw().left, mWindow.getFrameLw().top);
262 }
263
Jorim Jaggic662d8e2016-02-05 16:54:54 -0800264 private void resetDragResizingChangeReported() {
265 final WindowList windowList = mDisplayContent.getWindowList();
266 for (int i = windowList.size() - 1; i >= 0; i--) {
267 windowList.get(i).resetDragResizingChangeReported();
268 }
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100269 }
270
271 void setWindow(WindowState window) {
272 mWindow = window;
Filip Gruszczynski85d5cc42015-12-04 09:21:37 -0800273 reevaluateVisibility(false);
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100274 }
275
Filip Gruszczynski85d5cc42015-12-04 09:21:37 -0800276 void reevaluateVisibility(boolean force) {
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800277 if (mWindow == null) {
278 return;
279 }
Jorim Jaggie48f4282015-11-06 17:32:44 +0100280 TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID);
Jorim Jaggi7998e482016-02-12 18:47:06 -0800281
282 // If the stack is invisible, we policy force hide it in WindowAnimator.shouldForceHide
283 final boolean visible = stack != null;
Filip Gruszczynski85d5cc42015-12-04 09:21:37 -0800284 if (mLastVisibility == visible && !force) {
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800285 return;
286 }
287 mLastVisibility = visible;
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100288 notifyDockedDividerVisibilityChanged(visible);
Jorim Jaggi50981592015-12-29 17:54:12 +0100289 if (!visible) {
290 setResizeDimLayer(false, INVALID_STACK_ID, 0f);
291 }
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100292 }
293
294 boolean wasVisible() {
295 return mLastVisibility;
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100296 }
297
Chong Zhangf347ab52016-04-18 21:02:01 -0700298 void setAdjustedForIme(
299 boolean adjustedForIme, boolean adjustedForDivider,
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700300 boolean animate, WindowState imeWin, int imeHeight) {
301 if (mAdjustedForIme != adjustedForIme || (adjustedForIme && mImeHeight != imeHeight)
302 || mAdjustedForDivider != adjustedForDivider) {
Jorim Jaggi3070e772016-05-17 16:41:32 -0700303 if (animate && !mAnimatingForMinimizedDockedStack) {
Chong Zhangf347ab52016-04-18 21:02:01 -0700304 startImeAdjustAnimation(adjustedForIme, adjustedForDivider, imeWin);
Jorim Jaggiff71d202016-04-14 13:12:36 -0700305 } else {
Jorim Jaggiff71d202016-04-14 13:12:36 -0700306 // Animation might be delayed, so only notify if we don't run an animation.
Chong Zhangf347ab52016-04-18 21:02:01 -0700307 notifyAdjustedForImeChanged(adjustedForIme || adjustedForDivider, 0 /* duration */);
Jorim Jaggieb88d832016-04-13 20:17:43 -0700308 }
Chong Zhangf347ab52016-04-18 21:02:01 -0700309 mAdjustedForIme = adjustedForIme;
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700310 mImeHeight = imeHeight;
Chong Zhangf347ab52016-04-18 21:02:01 -0700311 mAdjustedForDivider = adjustedForDivider;
Chong Zhangbaba7832016-03-24 10:21:26 -0700312 }
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700313 }
314
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700315 int getImeHeightAdjustedFor() {
316 return mImeHeight;
317 }
318
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700319 void positionDockedStackedDivider(Rect frame) {
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700320 TaskStack stack = mDisplayContent.getDockedStackLocked();
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700321 if (stack == null) {
322 // Unfortunately we might end up with still having a divider, even though the underlying
323 // stack was already removed. This is because we are on AM thread and the removal of the
Filip Gruszczynski77049052015-11-09 14:01:21 -0800324 // divider was deferred to WM thread and hasn't happened yet. In that case let's just
325 // keep putting it in the same place it was before the stack was removed to have
326 // continuity and prevent it from jumping to the center. It will get hidden soon.
327 frame.set(mLastRect);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700328 return;
Filip Gruszczynski77049052015-11-09 14:01:21 -0800329 } else {
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800330 stack.getDimBounds(mTmpRect);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700331 }
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100332 int side = stack.getDockSide();
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700333 switch (side) {
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700334 case DOCKED_LEFT:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100335 frame.set(mTmpRect.right - mDividerInsets, frame.top,
336 mTmpRect.right + frame.width() - mDividerInsets, frame.bottom);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700337 break;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700338 case DOCKED_TOP:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100339 frame.set(frame.left, mTmpRect.bottom - mDividerInsets,
340 mTmpRect.right, mTmpRect.bottom + frame.height() - mDividerInsets);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700341 break;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700342 case DOCKED_RIGHT:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100343 frame.set(mTmpRect.left - frame.width() + mDividerInsets, frame.top,
344 mTmpRect.left + mDividerInsets, frame.bottom);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700345 break;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700346 case DOCKED_BOTTOM:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100347 frame.set(frame.left, mTmpRect.top - frame.height() + mDividerInsets,
348 frame.right, mTmpRect.top + mDividerInsets);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700349 break;
350 }
Filip Gruszczynski77049052015-11-09 14:01:21 -0800351 mLastRect.set(frame);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700352 }
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800353
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100354 void notifyDockedDividerVisibilityChanged(boolean visible) {
355 final int size = mDockedStackListeners.beginBroadcast();
356 for (int i = 0; i < size; ++i) {
357 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
358 try {
359 listener.onDividerVisibilityChanged(visible);
360 } catch (RemoteException e) {
361 Slog.e(TAG_WM, "Error delivering divider visibility changed event.", e);
362 }
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800363 }
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100364 mDockedStackListeners.finishBroadcast();
365 }
366
367 void notifyDockedStackExistsChanged(boolean exists) {
368 final int size = mDockedStackListeners.beginBroadcast();
369 for (int i = 0; i < size; ++i) {
370 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
371 try {
372 listener.onDockedStackExistsChanged(exists);
373 } catch (RemoteException e) {
374 Slog.e(TAG_WM, "Error delivering docked stack exists changed event.", e);
375 }
376 }
377 mDockedStackListeners.finishBroadcast();
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700378 if (!exists) {
379 setMinimizedDockedStack(false);
380 }
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100381 }
382
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800383 void notifyDockedStackMinimizedChanged(boolean minimizedDock, long animDuration) {
Tony Mak853304c2016-04-18 15:17:41 +0100384 mService.mH.removeMessages(NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED);
385 mService.mH.obtainMessage(NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED,
386 minimizedDock ? 1 : 0, 0).sendToTarget();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800387 final int size = mDockedStackListeners.beginBroadcast();
388 for (int i = 0; i < size; ++i) {
389 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
390 try {
391 listener.onDockedStackMinimizedChanged(minimizedDock, animDuration);
392 } catch (RemoteException e) {
393 Slog.e(TAG_WM, "Error delivering minimized dock changed event.", e);
394 }
395 }
396 mDockedStackListeners.finishBroadcast();
397 }
398
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700399 void notifyDockSideChanged(int newDockSide) {
400 final int size = mDockedStackListeners.beginBroadcast();
401 for (int i = 0; i < size; ++i) {
402 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
403 try {
404 listener.onDockSideChanged(newDockSide);
405 } catch (RemoteException e) {
406 Slog.e(TAG_WM, "Error delivering dock side changed event.", e);
407 }
408 }
409 mDockedStackListeners.finishBroadcast();
410 }
411
Jorim Jaggi698e7632016-04-13 21:02:22 -0700412 void notifyAdjustedForImeChanged(boolean adjustedForIme, long animDuration) {
413 final int size = mDockedStackListeners.beginBroadcast();
414 for (int i = 0; i < size; ++i) {
415 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
416 try {
417 listener.onAdjustedForImeChanged(adjustedForIme, animDuration);
418 } catch (RemoteException e) {
419 Slog.e(TAG_WM, "Error delivering adjusted for ime changed event.", e);
420 }
421 }
422 mDockedStackListeners.finishBroadcast();
423 }
424
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100425 void registerDockedStackListener(IDockedStackListener listener) {
426 mDockedStackListeners.register(listener);
427 notifyDockedDividerVisibilityChanged(wasVisible());
428 notifyDockedStackExistsChanged(
429 mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID) != null);
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700430 notifyDockedStackMinimizedChanged(mMinimizedDock, 0 /* animDuration */);
Jorim Jaggi698e7632016-04-13 21:02:22 -0700431 notifyAdjustedForImeChanged(mAdjustedForIme, 0 /* animDuration */);
432
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800433 }
Jorim Jaggi50981592015-12-29 17:54:12 +0100434
435 void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
436 SurfaceControl.openTransaction();
Jorim Jaggibc5425c2016-03-01 13:51:16 +0100437 final TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(targetStackId);
438 final TaskStack dockedStack = mDisplayContent.getDockedStackLocked();
439 boolean visibleAndValid = visible && stack != null && dockedStack != null;
Jorim Jaggi7b371dd2016-01-05 15:32:34 +0100440 if (visibleAndValid) {
Jorim Jaggi50981592015-12-29 17:54:12 +0100441 stack.getDimBounds(mTmpRect);
Jorim Jaggi10b89dc2016-01-05 15:40:17 +0100442 if (mTmpRect.height() > 0 && mTmpRect.width() > 0) {
Jorim Jaggi7b371dd2016-01-05 15:32:34 +0100443 mDimLayer.setBounds(mTmpRect);
Chong Zhang1402c2e2016-04-21 15:17:47 -0700444 mDimLayer.show(mService.mLayersController.getResizeDimLayer(),
Jorim Jaggi7b371dd2016-01-05 15:32:34 +0100445 alpha, 0 /* duration */);
446 } else {
447 visibleAndValid = false;
448 }
449 }
450 if (!visibleAndValid) {
Jorim Jaggi50981592015-12-29 17:54:12 +0100451 mDimLayer.hide();
452 }
453 SurfaceControl.closeTransaction();
454 }
455
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800456 /**
457 * Notifies the docked stack divider controller of a visibility change that happens without
458 * an animation.
459 */
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700460 void notifyAppVisibilityChanged() {
461 checkMinimizeChanged(false /* animate */);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800462 }
463
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700464 void notifyAppTransitionStarting() {
465 checkMinimizeChanged(true /* animate */);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800466 }
467
Jorim Jaggi1ae68bf2016-05-09 18:44:34 -0700468 boolean isMinimizedDock() {
469 return mMinimizedDock;
470 }
471
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700472 private void checkMinimizeChanged(boolean animate) {
Jorim Jaggi817a5242016-05-06 15:45:00 -0700473 if (mDisplayContent.getDockedStackVisibleForUserLocked() == null) {
474 return;
475 }
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700476 final TaskStack homeStack = mDisplayContent.getHomeStack();
477 if (homeStack == null) {
478 return;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800479 }
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700480 final Task homeTask = homeStack.findHomeTask();
481 if (homeTask == null || !isWithinDisplay(homeTask)) {
482 return;
483 }
484 final TaskStack fullscreenStack
485 = mService.mStackIdToStack.get(FULLSCREEN_WORKSPACE_STACK_ID);
486 final ArrayList<Task> homeStackTasks = homeStack.getTasks();
487 final Task topHomeStackTask = homeStackTasks.get(homeStackTasks.size() - 1);
488 final boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
489 final boolean homeBehind = (fullscreenStack != null && fullscreenStack.isVisibleLocked())
490 || (homeStackTasks.size() > 1 && topHomeStackTask != homeTask);
491 setMinimizedDockedStack(homeVisible && !homeBehind, animate);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800492 }
493
494 private boolean isWithinDisplay(Task task) {
495 task.mStack.getBounds(mTmpRect);
496 mDisplayContent.getLogicalDisplayRect(mTmpRect2);
497 return mTmpRect.intersect(mTmpRect2);
498 }
499
500 /**
501 * Sets whether the docked stack is currently in a minimized state, i.e. all the tasks in the
502 * docked stack are heavily clipped so you can only see a minimal peek state.
503 *
504 * @param minimizedDock Whether the docked stack is currently minimized.
505 * @param animate Whether to animate the change.
506 */
507 private void setMinimizedDockedStack(boolean minimizedDock, boolean animate) {
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700508 final boolean wasMinimized = mMinimizedDock;
509 mMinimizedDock = minimizedDock;
Jorim Jaggi817a5242016-05-06 15:45:00 -0700510 if (minimizedDock == wasMinimized) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800511 return;
512 }
513
Jorim Jaggieb88d832016-04-13 20:17:43 -0700514 clearImeAdjustAnimation();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800515 if (minimizedDock) {
516 if (animate) {
517 startAdjustAnimation(0f, 1f);
518 } else {
519 setMinimizedDockedStack(true);
520 }
521 } else {
522 if (animate) {
523 startAdjustAnimation(1f, 0f);
524 } else {
525 setMinimizedDockedStack(false);
526 }
527 }
528 }
529
Jorim Jaggieb88d832016-04-13 20:17:43 -0700530 private void clearImeAdjustAnimation() {
531 final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
532 for (int i = stacks.size() - 1; i >= 0; --i) {
533 final TaskStack stack = stacks.get(i);
534 if (stack != null && stack.isAdjustedForIme()) {
535 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
536 }
537 }
538 mAnimatingForIme = false;
539 }
540
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800541 private void startAdjustAnimation(float from, float to) {
Chong Zhangbaba7832016-03-24 10:21:26 -0700542 mAnimatingForMinimizedDockedStack = true;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800543 mAnimationStarted = false;
544 mAnimationStart = from;
545 mAnimationTarget = to;
546 }
547
Chong Zhangf347ab52016-04-18 21:02:01 -0700548 private void startImeAdjustAnimation(
549 boolean adjustedForIme, boolean adjustedForDivider, WindowState imeWin) {
Chong Zhangf347ab52016-04-18 21:02:01 -0700550
551 // If we're not in an animation, the starting point depends on whether we're adjusted
552 // or not. If we're already in an animation, we start from where the current animation
553 // left off, so that the motion doesn't look discontinuous.
554 if (!mAnimatingForIme) {
555 mAnimationStart = mAdjustedForIme ? 1 : 0;
556 mDividerAnimationStart = mAdjustedForDivider ? 1 : 0;
557 mLastAnimationProgress = mAnimationStart;
558 mLastDividerProgress = mDividerAnimationStart;
559 } else {
560 mAnimationStart = mLastAnimationProgress;
561 mDividerAnimationStart = mLastDividerProgress;
562 }
Jorim Jaggi3070e772016-05-17 16:41:32 -0700563 mAnimatingForIme = true;
564 mAnimationStarted = false;
Chong Zhangf347ab52016-04-18 21:02:01 -0700565 mAnimationTarget = adjustedForIme ? 1 : 0;
566 mDividerAnimationTarget = adjustedForDivider ? 1 : 0;
Jorim Jaggiff71d202016-04-14 13:12:36 -0700567
568 final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
569 for (int i = stacks.size() - 1; i >= 0; --i) {
570 final TaskStack stack = stacks.get(i);
571 if (stack.isVisibleLocked() && stack.isAdjustedForIme()) {
572 stack.beginImeAdjustAnimation();
573 }
574 }
575
576 // We put all tasks into drag resizing mode - wait until all of them have completed the
577 // drag resizing switch.
578 if (!mService.mWaitingForDrawn.isEmpty()) {
579 mService.mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
580 mService.mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT,
581 IME_ADJUST_DRAWN_TIMEOUT);
582 mAnimationStartDelayed = true;
583 if (imeWin != null) {
584
585 // There might be an old window delaying the animation start - clear it.
586 if (mDelayedImeWin != null) {
587 mDelayedImeWin.mWinAnimator.endDelayingAnimationStart();
588 }
589 mDelayedImeWin = imeWin;
590 imeWin.mWinAnimator.startDelayingAnimationStart();
591 }
592 mService.mWaitingForDrawnCallback = () -> {
593 mAnimationStartDelayed = false;
594 if (mDelayedImeWin != null) {
595 mDelayedImeWin.mWinAnimator.endDelayingAnimationStart();
596 }
Chong Zhangf347ab52016-04-18 21:02:01 -0700597 notifyAdjustedForImeChanged(
598 adjustedForIme || adjustedForDivider, IME_ADJUST_ANIM_DURATION);
Jorim Jaggiff71d202016-04-14 13:12:36 -0700599 };
600 } else {
Chong Zhangf347ab52016-04-18 21:02:01 -0700601 notifyAdjustedForImeChanged(
602 adjustedForIme || adjustedForDivider, IME_ADJUST_ANIM_DURATION);
Jorim Jaggiff71d202016-04-14 13:12:36 -0700603 }
Jorim Jaggieb88d832016-04-13 20:17:43 -0700604 }
605
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800606 private void setMinimizedDockedStack(boolean minimized) {
607 final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked();
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700608 notifyDockedStackMinimizedChanged(minimized, 0);
Chong Zhangf0b76b02016-05-13 18:04:23 -0700609 setMinimizeAmount(stack, minimized ? 1f : 0f);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800610 }
611
Jorim Jaggi8fe7e0a2016-02-12 19:43:39 -0800612 private boolean isAnimationMaximizing() {
613 return mAnimationTarget == 0f;
614 }
615
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800616 public boolean animate(long now) {
Wale Ogunwale20ec11b2016-04-22 12:11:51 -0700617 if (mWindow == null) {
618 return false;
619 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700620 if (mAnimatingForMinimizedDockedStack) {
621 return animateForMinimizedDockedStack(now);
622 } else if (mAnimatingForIme) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700623 return animateForIme(now);
Chong Zhangbaba7832016-03-24 10:21:26 -0700624 } else {
Wale Ogunwale20ec11b2016-04-22 12:11:51 -0700625 if (mDimLayer != null && mDimLayer.isDimming()) {
Chong Zhang1402c2e2016-04-21 15:17:47 -0700626 mDimLayer.setLayer(mService.mLayersController.getResizeDimLayer());
627 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800628 return false;
629 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700630 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800631
Jorim Jaggieb88d832016-04-13 20:17:43 -0700632 private boolean animateForIme(long now) {
Jorim Jaggiff71d202016-04-14 13:12:36 -0700633 if (!mAnimationStarted || mAnimationStartDelayed) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700634 mAnimationStarted = true;
635 mAnimationStartTime = now;
636 mAnimationDuration = (long)
Jorim Jaggi698e7632016-04-13 21:02:22 -0700637 (IME_ADJUST_ANIM_DURATION * mService.getWindowAnimationScaleLocked());
Jorim Jaggieb88d832016-04-13 20:17:43 -0700638 }
639 float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
640 t = (mAnimationTarget == 1f ? IME_ADJUST_ENTRY_INTERPOLATOR : TOUCH_RESPONSE_INTERPOLATOR)
641 .getInterpolation(t);
Chong Zhangbaba7832016-03-24 10:21:26 -0700642 final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
Jorim Jaggieb88d832016-04-13 20:17:43 -0700643 boolean updated = false;
Chong Zhangbaba7832016-03-24 10:21:26 -0700644 for (int i = stacks.size() - 1; i >= 0; --i) {
645 final TaskStack stack = stacks.get(i);
646 if (stack != null && stack.isAdjustedForIme()) {
Chong Zhangf347ab52016-04-18 21:02:01 -0700647 if (t >= 1f && mAnimationTarget == 0f && mDividerAnimationTarget == 0f) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700648 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
649 updated = true;
650 } else {
Chong Zhangf347ab52016-04-18 21:02:01 -0700651 mLastAnimationProgress = getInterpolatedAnimationValue(t);
652 mLastDividerProgress = getInterpolatedDividerValue(t);
653 updated |= stack.updateAdjustForIme(
654 mLastAnimationProgress,
655 mLastDividerProgress,
Jorim Jaggiff71d202016-04-14 13:12:36 -0700656 false /* force */);
657 }
658 if (t >= 1f) {
659 stack.endImeAdjustAnimation();
Chong Zhangbaba7832016-03-24 10:21:26 -0700660 }
661 }
662 }
Jorim Jaggieb88d832016-04-13 20:17:43 -0700663 if (updated) {
664 mService.mWindowPlacerLocked.performSurfacePlacement();
665 }
666 if (t >= 1.0f) {
Chong Zhangf347ab52016-04-18 21:02:01 -0700667 mLastAnimationProgress = mAnimationTarget;
668 mLastDividerProgress = mDividerAnimationTarget;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700669 mAnimatingForIme = false;
670 return false;
671 } else {
672 return true;
673 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700674 }
675
676 private boolean animateForMinimizedDockedStack(long now) {
Jorim Jaggiaf558e12016-04-27 22:56:56 -0700677 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800678 if (!mAnimationStarted) {
679 mAnimationStarted = true;
680 mAnimationStartTime = now;
Jorim Jaggi8fe7e0a2016-02-12 19:43:39 -0800681 final long transitionDuration = isAnimationMaximizing()
682 ? mService.mAppTransition.getLastClipRevealTransitionDuration()
683 : DEFAULT_APP_TRANSITION_DURATION;
684 mAnimationDuration = (long)
685 (transitionDuration * mService.getTransitionAnimationScaleLocked());
Jorim Jaggif97ed922016-02-18 18:57:07 -0800686 mMaximizeMeetFraction = getClipRevealMeetFraction(stack);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800687 notifyDockedStackMinimizedChanged(mMinimizedDock,
Jorim Jaggif97ed922016-02-18 18:57:07 -0800688 (long) (mAnimationDuration * mMaximizeMeetFraction));
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800689 }
Jorim Jaggi8fe7e0a2016-02-12 19:43:39 -0800690 float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
691 t = (isAnimationMaximizing() ? TOUCH_RESPONSE_INTERPOLATOR : mMinimizedDockInterpolator)
692 .getInterpolation(t);
Chong Zhangf0b76b02016-05-13 18:04:23 -0700693 setMinimizeAmount(stack, getMinimizeAmount(stack, t));
694
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800695 if (t >= 1.0f) {
Chong Zhangbaba7832016-03-24 10:21:26 -0700696 mAnimatingForMinimizedDockedStack = false;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800697 return false;
698 } else {
699 return true;
700 }
701 }
702
Chong Zhangf0b76b02016-05-13 18:04:23 -0700703 void setMinimizeAmount(TaskStack dockedStack, float minimizeAmount) {
704 final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
705
706 // If the docked stack is not visible, clear the complementary stack on all stacks.
707 if (dockedStack == null) {
708 for (int i = stacks.size() - 1; i >= 0; --i) {
709 final TaskStack stack = stacks.get(i);
710 stack.resetAdjustedForComplementDock();
711 }
712 return;
713 }
714
715 // Otherwise if the docked stack minimize amount has changed, update the adjusted bounds
716 // on the other stack that's currently visible, so that the stack's getDimBounds()
717 // occupies what's left by the docked stack. This is needed so that stuff like wallpaper
718 // gets cropped properly to the area left by the dock.
719 if (dockedStack.setAdjustedForMinimizedDock(minimizeAmount)) {
720 final boolean adjusted =
721 dockedStack.isVisibleForUserLocked() && minimizeAmount != 0.0f;
722 dockedStack.getDimBounds(mTmpRect2);
723 int dockSide = dockedStack.getDockSide();
724 for (int i = stacks.size() - 1; i >= 0; --i) {
725 final TaskStack stack = stacks.get(i);
726 if (stack == dockedStack) {
727 continue;
728 }
729 if (stack.isVisibleLocked() && adjusted) {
730 stack.setAdjustedForComplementDock(mTmpRect2, dockSide);
731 } else {
732 stack.resetAdjustedForComplementDock();
733 }
734 }
735 mService.mWindowPlacerLocked.performSurfacePlacement();
736 }
737 }
738
Jorim Jaggieb88d832016-04-13 20:17:43 -0700739 private float getInterpolatedAnimationValue(float t) {
740 return t * mAnimationTarget + (1 - t) * mAnimationStart;
741 }
742
Chong Zhangf347ab52016-04-18 21:02:01 -0700743 private float getInterpolatedDividerValue(float t) {
744 return t * mDividerAnimationTarget + (1 - t) * mDividerAnimationStart;
745 }
746
Jorim Jaggif97ed922016-02-18 18:57:07 -0800747 /**
748 * Gets the amount how much to minimize a stack depending on the interpolated fraction t.
749 */
750 private float getMinimizeAmount(TaskStack stack, float t) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700751 final float naturalAmount = getInterpolatedAnimationValue(t);
Jorim Jaggif97ed922016-02-18 18:57:07 -0800752 if (isAnimationMaximizing()) {
753 return adjustMaximizeAmount(stack, t, naturalAmount);
754 } else {
755 return naturalAmount;
756 }
757 }
758
759 /**
760 * When maximizing the stack during a clip reveal transition, this adjusts the minimize amount
761 * during the transition such that the edge of the clip reveal rect is met earlier in the
762 * transition so we don't create a visible "hole", but only if both the clip reveal and the
763 * docked stack divider start from about the same portion on the screen.
764 */
765 private float adjustMaximizeAmount(TaskStack stack, float t, float naturalAmount) {
766 if (mMaximizeMeetFraction == 1f) {
767 return naturalAmount;
768 }
769 final int minimizeDistance = stack.getMinimizeDistance();
770 float startPrime = mService.mAppTransition.getLastClipRevealMaxTranslation()
771 / (float) minimizeDistance;
772 final float amountPrime = t * mAnimationTarget + (1 - t) * startPrime;
773 final float t2 = Math.min(t / mMaximizeMeetFraction, 1);
774 return amountPrime * t2 + naturalAmount * (1 - t2);
775 }
776
777 /**
778 * Retrieves the animation fraction at which the docked stack has to meet the clip reveal
779 * edge. See {@link #adjustMaximizeAmount}.
780 */
781 private float getClipRevealMeetFraction(TaskStack stack) {
782 if (!isAnimationMaximizing() || stack == null ||
783 !mService.mAppTransition.hadClipRevealAnimation()) {
784 return 1f;
785 }
786 final int minimizeDistance = stack.getMinimizeDistance();
787 final float fraction = Math.abs(mService.mAppTransition.getLastClipRevealMaxTranslation())
788 / (float) minimizeDistance;
789 final float t = Math.max(0, Math.min(1, (fraction - CLIP_REVEAL_MEET_FRACTION_MIN)
790 / (CLIP_REVEAL_MEET_FRACTION_MAX - CLIP_REVEAL_MEET_FRACTION_MIN)));
791 return CLIP_REVEAL_MEET_EARLIEST
792 + (1 - t) * (CLIP_REVEAL_MEET_LAST - CLIP_REVEAL_MEET_EARLIEST);
793 }
794
Jorim Jaggi50981592015-12-29 17:54:12 +0100795 @Override
Wale Ogunwale29bfbb82016-05-12 15:13:52 -0700796 public boolean dimFullscreen() {
Jorim Jaggi50981592015-12-29 17:54:12 +0100797 return false;
798 }
799
800 @Override
801 public DisplayInfo getDisplayInfo() {
802 return mDisplayContent.getDisplayInfo();
803 }
804
805 @Override
806 public void getDimBounds(Rect outBounds) {
807 // This dim layer user doesn't need this.
808 }
809
810 @Override
811 public String toShortString() {
812 return TAG;
813 }
Robert Carre63e01a2016-04-18 20:27:34 -0700814
815 WindowState getWindow() {
816 return mWindow;
817 }
Jorim Jaggi31f71702016-05-04 16:43:04 -0700818
819 void dump(String prefix, PrintWriter pw) {
820 pw.println(prefix + "DockedStackDividerController");
821 pw.println(prefix + " mLastVisibility=" + mLastVisibility);
822 pw.println(prefix + " mMinimizedDock=" + mMinimizedDock);
823 pw.println(prefix + " mAdjustedForIme=" + mAdjustedForIme);
824 pw.println(prefix + " mAdjustedForDivider=" + mAdjustedForDivider);
825 if (mDimLayer.isDimming()) {
826 pw.println(prefix + " Dim layer is dimming: ");
827 mDimLayer.printTo(prefix + " ", pw);
828 }
829 }
Robert Carre63e01a2016-04-18 20:27:34 -0700830}