blob: 6b514552b227fedbedbb256586c2b4e311088c68 [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;
Jorim Jaggi84afb1a2016-09-28 14:54:04 +020032import static com.android.server.wm.AppTransition.TRANSIT_NONE;
Jorim Jaggibc5425c2016-03-01 13:51:16 +010033import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
34import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Tony Mak853304c2016-04-18 15:17:41 +010035import static com.android.server.wm.WindowManagerService.H.NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED;
Wale Ogunwalec69694a2016-10-18 13:51:15 -070036import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM;
Jorim Jaggibc5425c2016-03-01 13:51:16 +010037
Filip Gruszczynski466f3212015-09-21 17:57:57 -070038import android.content.Context;
Jorim Jaggi85639432016-05-06 17:27:55 -070039import android.content.res.Configuration;
Filip Gruszczynski466f3212015-09-21 17:57:57 -070040import android.graphics.Rect;
Jorim Jaggia6c934e2015-12-21 13:22:31 +010041import android.os.RemoteCallbackList;
Filip Gruszczynski64cdc142015-11-29 21:10:07 -080042import android.os.RemoteException;
Jorim Jaggi936aaeb2016-08-26 19:02:11 -070043import android.util.ArraySet;
Filip Gruszczynski77049052015-11-09 14:01:21 -080044import android.util.Slog;
Jorim Jaggi50981592015-12-29 17:54:12 +010045import android.view.DisplayInfo;
Jorim Jaggia6c934e2015-12-21 13:22:31 +010046import android.view.IDockedStackListener;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -080047import android.view.animation.AnimationUtils;
48import android.view.animation.Interpolator;
Jorim Jaggieb88d832016-04-13 20:17:43 -070049import android.view.animation.PathInterpolator;
Jorim Jaggi3c5d0f12016-05-24 19:04:30 -070050import android.view.inputmethod.InputMethodManagerInternal;
Jorim Jaggi50981592015-12-29 17:54:12 +010051
Jorim Jaggi85639432016-05-06 17:27:55 -070052import com.android.internal.policy.DividerSnapAlgorithm;
53import com.android.internal.policy.DockedDividerUtils;
Jorim Jaggi3c5d0f12016-05-24 19:04:30 -070054import com.android.server.LocalServices;
Jorim Jaggi50981592015-12-29 17:54:12 +010055import com.android.server.wm.DimLayer.DimLayerUser;
Jorim Jaggiff71d202016-04-14 13:12:36 -070056import com.android.server.wm.WindowManagerService.H;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010057
Jorim Jaggi31f71702016-05-04 16:43:04 -070058import java.io.PrintWriter;
Chong Zhangbaba7832016-03-24 10:21:26 -070059
Filip Gruszczynski466f3212015-09-21 17:57:57 -070060/**
Jorim Jaggi61f39a72015-10-29 16:54:18 +010061 * Keeps information about the docked stack divider.
Filip Gruszczynski466f3212015-09-21 17:57:57 -070062 */
Jorim Jaggi50981592015-12-29 17:54:12 +010063public class DockedStackDividerController implements DimLayerUser {
Jorim Jaggi61f39a72015-10-29 16:54:18 +010064
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080065 private static final String TAG = TAG_WITH_CLASS_NAME ? "DockedStackDividerController" : TAG_WM;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010066
Jorim Jaggif97ed922016-02-18 18:57:07 -080067 /**
68 * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip
69 * revealing surface at the earliest.
70 */
71 private static final float CLIP_REVEAL_MEET_EARLIEST = 0.6f;
72
73 /**
74 * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip
75 * revealing surface at the latest.
76 */
77 private static final float CLIP_REVEAL_MEET_LAST = 1f;
78
79 /**
80 * If the app translates at least CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance, we start
81 * meet somewhere between {@link #CLIP_REVEAL_MEET_LAST} and {@link #CLIP_REVEAL_MEET_EARLIEST}.
82 */
83 private static final float CLIP_REVEAL_MEET_FRACTION_MIN = 0.4f;
84
85 /**
86 * If the app translates equals or more than CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance,
87 * we meet at {@link #CLIP_REVEAL_MEET_EARLIEST}.
88 */
89 private static final float CLIP_REVEAL_MEET_FRACTION_MAX = 0.8f;
90
Jorim Jaggieb88d832016-04-13 20:17:43 -070091 private static final Interpolator IME_ADJUST_ENTRY_INTERPOLATOR =
Jorim Jaggiff71d202016-04-14 13:12:36 -070092 new PathInterpolator(0.2f, 0f, 0.1f, 1f);
Jorim Jaggieb88d832016-04-13 20:17:43 -070093
Jorim Jaggi698e7632016-04-13 21:02:22 -070094 private static final long IME_ADJUST_ANIM_DURATION = 280;
Jorim Jaggieb88d832016-04-13 20:17:43 -070095
Jorim Jaggiff71d202016-04-14 13:12:36 -070096 private static final long IME_ADJUST_DRAWN_TIMEOUT = 200;
97
Chong Zhang198afac2016-04-15 12:03:11 -070098 private static final int DIVIDER_WIDTH_INACTIVE_DP = 4;
99
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800100 private final WindowManagerService mService;
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700101 private final DisplayContent mDisplayContent;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700102 private int mDividerWindowWidth;
Chong Zhang198afac2016-04-15 12:03:11 -0700103 private int mDividerWindowWidthInactive;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700104 private int mDividerInsets;
Matthew Nge15352e2016-12-20 15:36:29 -0800105 private int mTaskHeightInMinimizedMode;
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100106 private boolean mResizing;
107 private WindowState mWindow;
108 private final Rect mTmpRect = new Rect();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800109 private final Rect mTmpRect2 = new Rect();
Jorim Jaggi85639432016-05-06 17:27:55 -0700110 private final Rect mTmpRect3 = new Rect();
Filip Gruszczynski77049052015-11-09 14:01:21 -0800111 private final Rect mLastRect = new Rect();
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800112 private boolean mLastVisibility = false;
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100113 private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners
114 = new RemoteCallbackList<>();
Jorim Jaggi50981592015-12-29 17:54:12 +0100115 private final DimLayer mDimLayer;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700116
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800117 private boolean mMinimizedDock;
Chong Zhangbaba7832016-03-24 10:21:26 -0700118 private boolean mAnimatingForMinimizedDockedStack;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800119 private boolean mAnimationStarted;
120 private long mAnimationStartTime;
121 private float mAnimationStart;
122 private float mAnimationTarget;
Jorim Jaggi8fe7e0a2016-02-12 19:43:39 -0800123 private long mAnimationDuration;
Jorim Jaggiff71d202016-04-14 13:12:36 -0700124 private boolean mAnimationStartDelayed;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800125 private final Interpolator mMinimizedDockInterpolator;
Jorim Jaggif97ed922016-02-18 18:57:07 -0800126 private float mMaximizeMeetFraction;
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100127 private final Rect mTouchRegion = new Rect();
Chong Zhangbaba7832016-03-24 10:21:26 -0700128 private boolean mAnimatingForIme;
129 private boolean mAdjustedForIme;
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700130 private int mImeHeight;
Jorim Jaggiff71d202016-04-14 13:12:36 -0700131 private WindowState mDelayedImeWin;
Chong Zhangf347ab52016-04-18 21:02:01 -0700132 private boolean mAdjustedForDivider;
133 private float mDividerAnimationStart;
134 private float mDividerAnimationTarget;
Wale Ogunwale10124582016-09-15 20:25:50 -0700135 float mLastAnimationProgress;
136 float mLastDividerProgress;
Jorim Jaggi85639432016-05-06 17:27:55 -0700137 private final DividerSnapAlgorithm[] mSnapAlgorithmForRotation = new DividerSnapAlgorithm[4];
Jorim Jaggi3c5d0f12016-05-24 19:04:30 -0700138 private boolean mImeHideRequested;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800139
140 DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
141 mService = service;
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700142 mDisplayContent = displayContent;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800143 final Context context = service.mContext;
Jorim Jaggibc5425c2016-03-01 13:51:16 +0100144 mDimLayer = new DimLayer(displayContent.mService, this, displayContent.getDisplayId(),
145 "DockedStackDim");
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800146 mMinimizedDockInterpolator = AnimationUtils.loadInterpolator(
147 context, android.R.interpolator.fast_out_slow_in);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700148 loadDimens();
149 }
150
Jorim Jaggi85639432016-05-06 17:27:55 -0700151 int getSmallestWidthDpForBounds(Rect bounds) {
152 final DisplayInfo di = mDisplayContent.getDisplayInfo();
153
Jorim Jaggi85639432016-05-06 17:27:55 -0700154 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);
Winson Chungbdc646f2017-02-13 12:12:22 -0800182 mService.intersectDisplayInsetBounds(mTmpRect2, mTmpRect3, mTmpRect);
Jorim Jaggi85639432016-05-06 17:27:55 -0700183 minWidth = Math.min(mTmpRect.width(), minWidth);
184 }
185 return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
186 }
187
Matthew Nge15352e2016-12-20 15:36:29 -0800188 void getHomeStackBoundsInDockedMode(Rect outBounds) {
189 final DisplayInfo di = mDisplayContent.getDisplayInfo();
190 mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
191 mTmpRect);
192 int dividerSize = mDividerWindowWidth - 2 * mDividerInsets;
193 Configuration configuration = mDisplayContent.getConfiguration();
Matthew Nga9e173d2017-05-17 15:03:18 -0700194 // The offset in the left (landscape)/top (portrait) is calculated with the minimized
195 // offset value with the divider size and any system insets in that direction.
Matthew Nge15352e2016-12-20 15:36:29 -0800196 if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
197 outBounds.set(0, mTaskHeightInMinimizedMode + dividerSize + mTmpRect.top,
198 di.logicalWidth, di.logicalHeight);
199 } else {
Matthew Nga9e173d2017-05-17 15:03:18 -0700200 // In landscape append the left position with the statusbar height to match the
201 // minimized size height in portrait mode.
202 outBounds.set(mTaskHeightInMinimizedMode + dividerSize + mTmpRect.left + mTmpRect.top,
203 0, di.logicalWidth, di.logicalHeight);
Matthew Nge15352e2016-12-20 15:36:29 -0800204 }
205 }
206
207 boolean isHomeStackResizable() {
208 final TaskStack homeStack = mDisplayContent.getHomeStack();
209 if (homeStack == null) {
210 return false;
211 }
212 final Task homeTask = homeStack.findHomeTask();
213 return homeTask != null && homeTask.isResizeable();
214 }
215
Jorim Jaggi85639432016-05-06 17:27:55 -0700216 private void initSnapAlgorithmForRotations() {
Andrii Kulian441e4492016-09-29 15:25:00 -0700217 final Configuration baseConfig = mDisplayContent.getConfiguration();
Jorim Jaggi85639432016-05-06 17:27:55 -0700218
219 // Initialize the snap algorithms for all 4 screen orientations.
220 final Configuration config = new Configuration();
221 for (int rotation = 0; rotation < 4; rotation++) {
222 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
223 final int dw = rotated
224 ? mDisplayContent.mBaseDisplayHeight
225 : mDisplayContent.mBaseDisplayWidth;
226 final int dh = rotated
227 ? mDisplayContent.mBaseDisplayWidth
228 : mDisplayContent.mBaseDisplayHeight;
229 mService.mPolicy.getStableInsetsLw(rotation, dw, dh, mTmpRect);
Andrii Kulianb10330d2016-09-16 13:51:46 -0700230 config.unset();
Jorim Jaggi85639432016-05-06 17:27:55 -0700231 config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
Bryce Lee7566d762017-03-30 09:34:15 -0700232
233 final int displayId = mDisplayContent.getDisplayId();
234 final int appWidth = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation,
235 baseConfig.uiMode, displayId);
236 final int appHeight = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation,
237 baseConfig.uiMode, displayId);
238 mService.mPolicy.getNonDecorInsetsLw(rotation, dw, dh, mTmpRect);
239 final int leftInset = mTmpRect.left;
240 final int topInset = mTmpRect.top;
241
242 config.setAppBounds(leftInset /*left*/, topInset /*top*/, leftInset + appWidth /*right*/,
243 topInset + appHeight /*bottom*/);
244
Jorim Jaggi85639432016-05-06 17:27:55 -0700245 config.screenWidthDp = (int)
Andrii Kuliandb8e1062016-11-15 18:30:27 -0800246 (mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, baseConfig.uiMode,
Bryce Lee7566d762017-03-30 09:34:15 -0700247 displayId) / mDisplayContent.getDisplayMetrics().density);
Jorim Jaggi85639432016-05-06 17:27:55 -0700248 config.screenHeightDp = (int)
Andrii Kuliandb8e1062016-11-15 18:30:27 -0800249 (mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, baseConfig.uiMode,
Bryce Lee7566d762017-03-30 09:34:15 -0700250 displayId) / mDisplayContent.getDisplayMetrics().density);
Jorim Jaggi85639432016-05-06 17:27:55 -0700251 final Context rotationContext = mService.mContext.createConfigurationContext(config);
252 mSnapAlgorithmForRotation[rotation] = new DividerSnapAlgorithm(
253 rotationContext.getResources(), dw, dh, getContentWidth(),
254 config.orientation == ORIENTATION_PORTRAIT, mTmpRect);
255 }
256 }
257
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700258 private void loadDimens() {
259 final Context context = mService.mContext;
260 mDividerWindowWidth = context.getResources().getDimensionPixelSize(
261 com.android.internal.R.dimen.docked_stack_divider_thickness);
262 mDividerInsets = context.getResources().getDimensionPixelSize(
263 com.android.internal.R.dimen.docked_stack_divider_insets);
Chong Zhang198afac2016-04-15 12:03:11 -0700264 mDividerWindowWidthInactive = WindowManagerService.dipToPixel(
265 DIVIDER_WIDTH_INACTIVE_DP, mDisplayContent.getDisplayMetrics());
Matthew Nge15352e2016-12-20 15:36:29 -0800266 mTaskHeightInMinimizedMode = context.getResources().getDimensionPixelSize(
267 com.android.internal.R.dimen.task_height_of_minimized_mode);
Jorim Jaggi85639432016-05-06 17:27:55 -0700268 initSnapAlgorithmForRotations();
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700269 }
270
271 void onConfigurationChanged() {
272 loadDimens();
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700273 }
274
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100275 boolean isResizing() {
276 return mResizing;
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700277 }
278
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100279 int getContentWidth() {
280 return mDividerWindowWidth - 2 * mDividerInsets;
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700281 }
282
Jorim Jaggi81ba11e2016-02-03 22:04:22 -0800283 int getContentInsets() {
284 return mDividerInsets;
285 }
286
Chong Zhang198afac2016-04-15 12:03:11 -0700287 int getContentWidthInactive() {
288 return mDividerWindowWidthInactive;
289 }
290
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100291 void setResizing(boolean resizing) {
Jorim Jaggic662d8e2016-02-05 16:54:54 -0800292 if (mResizing != resizing) {
293 mResizing = resizing;
294 resetDragResizingChangeReported();
295 }
296 }
297
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100298 void setTouchRegion(Rect touchRegion) {
299 mTouchRegion.set(touchRegion);
300 }
301
302 void getTouchRegion(Rect outRegion) {
303 outRegion.set(mTouchRegion);
304 outRegion.offset(mWindow.getFrameLw().left, mWindow.getFrameLw().top);
305 }
306
Jorim Jaggic662d8e2016-02-05 16:54:54 -0800307 private void resetDragResizingChangeReported() {
Wale Ogunwaled1880962016-11-08 10:31:59 -0800308 mDisplayContent.forAllWindows(WindowState::resetDragResizingChangeReported,
309 true /* traverseTopToBottom */ );
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100310 }
311
312 void setWindow(WindowState window) {
313 mWindow = window;
Filip Gruszczynski85d5cc42015-12-04 09:21:37 -0800314 reevaluateVisibility(false);
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100315 }
316
Filip Gruszczynski85d5cc42015-12-04 09:21:37 -0800317 void reevaluateVisibility(boolean force) {
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800318 if (mWindow == null) {
319 return;
320 }
Jorim Jaggife762342016-10-13 14:33:27 +0200321 TaskStack stack = mDisplayContent.getDockedStackIgnoringVisibility();
Jorim Jaggi7998e482016-02-12 18:47:06 -0800322
323 // If the stack is invisible, we policy force hide it in WindowAnimator.shouldForceHide
324 final boolean visible = stack != null;
Filip Gruszczynski85d5cc42015-12-04 09:21:37 -0800325 if (mLastVisibility == visible && !force) {
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800326 return;
327 }
328 mLastVisibility = visible;
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100329 notifyDockedDividerVisibilityChanged(visible);
Jorim Jaggi50981592015-12-29 17:54:12 +0100330 if (!visible) {
331 setResizeDimLayer(false, INVALID_STACK_ID, 0f);
332 }
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100333 }
334
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700335 private boolean wasVisible() {
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100336 return mLastVisibility;
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100337 }
338
Chong Zhangf347ab52016-04-18 21:02:01 -0700339 void setAdjustedForIme(
340 boolean adjustedForIme, boolean adjustedForDivider,
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700341 boolean animate, WindowState imeWin, int imeHeight) {
342 if (mAdjustedForIme != adjustedForIme || (adjustedForIme && mImeHeight != imeHeight)
343 || mAdjustedForDivider != adjustedForDivider) {
Jorim Jaggi3070e772016-05-17 16:41:32 -0700344 if (animate && !mAnimatingForMinimizedDockedStack) {
Chong Zhangf347ab52016-04-18 21:02:01 -0700345 startImeAdjustAnimation(adjustedForIme, adjustedForDivider, imeWin);
Jorim Jaggiff71d202016-04-14 13:12:36 -0700346 } else {
Jorim Jaggiff71d202016-04-14 13:12:36 -0700347 // Animation might be delayed, so only notify if we don't run an animation.
Chong Zhangf347ab52016-04-18 21:02:01 -0700348 notifyAdjustedForImeChanged(adjustedForIme || adjustedForDivider, 0 /* duration */);
Jorim Jaggieb88d832016-04-13 20:17:43 -0700349 }
Chong Zhangf347ab52016-04-18 21:02:01 -0700350 mAdjustedForIme = adjustedForIme;
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700351 mImeHeight = imeHeight;
Chong Zhangf347ab52016-04-18 21:02:01 -0700352 mAdjustedForDivider = adjustedForDivider;
Chong Zhangbaba7832016-03-24 10:21:26 -0700353 }
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700354 }
355
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700356 int getImeHeightAdjustedFor() {
357 return mImeHeight;
358 }
359
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700360 void positionDockedStackedDivider(Rect frame) {
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700361 TaskStack stack = mDisplayContent.getDockedStackLocked();
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700362 if (stack == null) {
363 // Unfortunately we might end up with still having a divider, even though the underlying
364 // stack was already removed. This is because we are on AM thread and the removal of the
Filip Gruszczynski77049052015-11-09 14:01:21 -0800365 // divider was deferred to WM thread and hasn't happened yet. In that case let's just
366 // keep putting it in the same place it was before the stack was removed to have
367 // continuity and prevent it from jumping to the center. It will get hidden soon.
368 frame.set(mLastRect);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700369 return;
Filip Gruszczynski77049052015-11-09 14:01:21 -0800370 } else {
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800371 stack.getDimBounds(mTmpRect);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700372 }
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100373 int side = stack.getDockSide();
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700374 switch (side) {
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700375 case DOCKED_LEFT:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100376 frame.set(mTmpRect.right - mDividerInsets, frame.top,
377 mTmpRect.right + frame.width() - mDividerInsets, frame.bottom);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700378 break;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700379 case DOCKED_TOP:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100380 frame.set(frame.left, mTmpRect.bottom - mDividerInsets,
381 mTmpRect.right, mTmpRect.bottom + frame.height() - mDividerInsets);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700382 break;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700383 case DOCKED_RIGHT:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100384 frame.set(mTmpRect.left - frame.width() + mDividerInsets, frame.top,
385 mTmpRect.left + mDividerInsets, frame.bottom);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700386 break;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700387 case DOCKED_BOTTOM:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100388 frame.set(frame.left, mTmpRect.top - frame.height() + mDividerInsets,
389 frame.right, mTmpRect.top + mDividerInsets);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700390 break;
391 }
Filip Gruszczynski77049052015-11-09 14:01:21 -0800392 mLastRect.set(frame);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700393 }
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800394
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700395 private void notifyDockedDividerVisibilityChanged(boolean visible) {
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100396 final int size = mDockedStackListeners.beginBroadcast();
397 for (int i = 0; i < size; ++i) {
398 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
399 try {
400 listener.onDividerVisibilityChanged(visible);
401 } catch (RemoteException e) {
402 Slog.e(TAG_WM, "Error delivering divider visibility changed event.", e);
403 }
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800404 }
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100405 mDockedStackListeners.finishBroadcast();
406 }
407
408 void notifyDockedStackExistsChanged(boolean exists) {
Andrii Kulian5406e7a2016-10-21 11:55:23 -0700409 // TODO(multi-display): Perform all actions only for current display.
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100410 final int size = mDockedStackListeners.beginBroadcast();
411 for (int i = 0; i < size; ++i) {
412 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
413 try {
414 listener.onDockedStackExistsChanged(exists);
415 } catch (RemoteException e) {
416 Slog.e(TAG_WM, "Error delivering docked stack exists changed event.", e);
417 }
418 }
419 mDockedStackListeners.finishBroadcast();
Jorim Jaggi3c5d0f12016-05-24 19:04:30 -0700420 if (exists) {
421 InputMethodManagerInternal inputMethodManagerInternal =
422 LocalServices.getService(InputMethodManagerInternal.class);
423 if (inputMethodManagerInternal != null) {
424
425 // Hide the current IME to avoid problems with animations from IME adjustment when
426 // attaching the docked stack.
427 inputMethodManagerInternal.hideCurrentInputMethod();
428 mImeHideRequested = true;
429 }
Matthew Ngbc527a32017-06-19 16:42:31 -0700430 return;
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700431 }
Matthew Ngbc527a32017-06-19 16:42:31 -0700432 setMinimizedDockedStack(false /* minimizedDock */, false /* animate */);
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100433 }
434
Jorim Jaggi3c5d0f12016-05-24 19:04:30 -0700435 /**
436 * Resets the state that IME hide has been requested. See {@link #isImeHideRequested}.
437 */
438 void resetImeHideRequested() {
439 mImeHideRequested = false;
440 }
441
442 /**
443 * The docked stack divider controller makes sure the IME gets hidden when attaching the docked
444 * stack, to avoid animation problems. This flag indicates whether the request to hide the IME
445 * has been sent in an asynchronous manner, and the IME should be treated as hidden already.
446 *
447 * @return whether IME hide request has been sent
448 */
449 boolean isImeHideRequested() {
450 return mImeHideRequested;
451 }
452
Matthew Nge15352e2016-12-20 15:36:29 -0800453 private void notifyDockedStackMinimizedChanged(boolean minimizedDock, boolean animate,
454 boolean isHomeStackResizable) {
455 long animDuration = 0;
456 if (animate) {
457 final TaskStack stack = mDisplayContent.getStackById(DOCKED_STACK_ID);
458 final long transitionDuration = isAnimationMaximizing()
459 ? mService.mAppTransition.getLastClipRevealTransitionDuration()
460 : DEFAULT_APP_TRANSITION_DURATION;
461 mAnimationDuration = (long)
462 (transitionDuration * mService.getTransitionAnimationScaleLocked());
463 mMaximizeMeetFraction = getClipRevealMeetFraction(stack);
464 animDuration = (long) (mAnimationDuration * mMaximizeMeetFraction);
465 }
Tony Mak853304c2016-04-18 15:17:41 +0100466 mService.mH.removeMessages(NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED);
467 mService.mH.obtainMessage(NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED,
468 minimizedDock ? 1 : 0, 0).sendToTarget();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800469 final int size = mDockedStackListeners.beginBroadcast();
470 for (int i = 0; i < size; ++i) {
471 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
472 try {
Matthew Nge15352e2016-12-20 15:36:29 -0800473 listener.onDockedStackMinimizedChanged(minimizedDock, animDuration,
474 isHomeStackResizable);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800475 } catch (RemoteException e) {
476 Slog.e(TAG_WM, "Error delivering minimized dock changed event.", e);
477 }
478 }
479 mDockedStackListeners.finishBroadcast();
480 }
481
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700482 void notifyDockSideChanged(int newDockSide) {
483 final int size = mDockedStackListeners.beginBroadcast();
484 for (int i = 0; i < size; ++i) {
485 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
486 try {
487 listener.onDockSideChanged(newDockSide);
488 } catch (RemoteException e) {
489 Slog.e(TAG_WM, "Error delivering dock side changed event.", e);
490 }
491 }
492 mDockedStackListeners.finishBroadcast();
493 }
494
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700495 private void notifyAdjustedForImeChanged(boolean adjustedForIme, long animDuration) {
Jorim Jaggi698e7632016-04-13 21:02:22 -0700496 final int size = mDockedStackListeners.beginBroadcast();
497 for (int i = 0; i < size; ++i) {
498 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
499 try {
500 listener.onAdjustedForImeChanged(adjustedForIme, animDuration);
501 } catch (RemoteException e) {
502 Slog.e(TAG_WM, "Error delivering adjusted for ime changed event.", e);
503 }
504 }
505 mDockedStackListeners.finishBroadcast();
506 }
507
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100508 void registerDockedStackListener(IDockedStackListener listener) {
509 mDockedStackListeners.register(listener);
510 notifyDockedDividerVisibilityChanged(wasVisible());
Wale Ogunwale1666e312016-12-16 11:27:18 -0800511 notifyDockedStackExistsChanged(mDisplayContent.getDockedStackIgnoringVisibility() != null);
Matthew Nge15352e2016-12-20 15:36:29 -0800512 notifyDockedStackMinimizedChanged(mMinimizedDock, false /* animate */,
513 isHomeStackResizable());
Jorim Jaggi698e7632016-04-13 21:02:22 -0700514 notifyAdjustedForImeChanged(mAdjustedForIme, 0 /* animDuration */);
515
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800516 }
Jorim Jaggi50981592015-12-29 17:54:12 +0100517
518 void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
Robert Carr68e5c9e2016-09-14 10:50:09 -0700519 mService.openSurfaceTransaction();
Wale Ogunwale1666e312016-12-16 11:27:18 -0800520 final TaskStack stack = mDisplayContent.getStackById(targetStackId);
Jorim Jaggibc5425c2016-03-01 13:51:16 +0100521 final TaskStack dockedStack = mDisplayContent.getDockedStackLocked();
522 boolean visibleAndValid = visible && stack != null && dockedStack != null;
Jorim Jaggi7b371dd2016-01-05 15:32:34 +0100523 if (visibleAndValid) {
Jorim Jaggi50981592015-12-29 17:54:12 +0100524 stack.getDimBounds(mTmpRect);
Jorim Jaggi10b89dc2016-01-05 15:40:17 +0100525 if (mTmpRect.height() > 0 && mTmpRect.width() > 0) {
Jorim Jaggi7b371dd2016-01-05 15:32:34 +0100526 mDimLayer.setBounds(mTmpRect);
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700527 mDimLayer.show(getResizeDimLayer(), alpha, 0 /* duration */);
Jorim Jaggi7b371dd2016-01-05 15:32:34 +0100528 } else {
529 visibleAndValid = false;
530 }
531 }
532 if (!visibleAndValid) {
Jorim Jaggi50981592015-12-29 17:54:12 +0100533 mDimLayer.hide();
534 }
Robert Carr68e5c9e2016-09-14 10:50:09 -0700535 mService.closeSurfaceTransaction();
Jorim Jaggi50981592015-12-29 17:54:12 +0100536 }
537
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800538 /**
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700539 * @return The layer used for dimming the apps when dismissing docked/fullscreen stack. Just
540 * above all application surfaces.
541 */
542 private int getResizeDimLayer() {
543 return (mWindow != null) ? mWindow.mLayer - 1 : LAYER_OFFSET_DIM;
544 }
545
546 /**
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800547 * Notifies the docked stack divider controller of a visibility change that happens without
548 * an animation.
549 */
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700550 void notifyAppVisibilityChanged() {
551 checkMinimizeChanged(false /* animate */);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800552 }
553
Jorim Jaggi84afb1a2016-09-28 14:54:04 +0200554 void notifyAppTransitionStarting(ArraySet<AppWindowToken> openingApps, int appTransition) {
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700555 final boolean wasMinimized = mMinimizedDock;
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700556 checkMinimizeChanged(true /* animate */);
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700557
558 // We were minimized, and now we are still minimized, but somebody is trying to launch an
Matthew Ng8e265522017-02-13 11:09:37 -0800559 // app in docked stack, better show recent apps so we actually get unminimized! However do
560 // not do this if keyguard is dismissed such as when the device is unlocking. This catches
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700561 // any case that was missed in ActivityStarter.postStartActivityUncheckedProcessing because
562 // we couldn't retrace the launch of the app in the docked stack to the launch from
563 // homescreen.
Jorim Jaggi84afb1a2016-09-28 14:54:04 +0200564 if (wasMinimized && mMinimizedDock && containsAppInDockedStack(openingApps)
Matthew Ng8e265522017-02-13 11:09:37 -0800565 && appTransition != TRANSIT_NONE &&
566 !AppTransition.isKeyguardGoingAwayTransit(appTransition)) {
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700567 mService.showRecentApps(true /* fromHome */);
568 }
569 }
570
571 /**
572 * @return true if {@param apps} contains an activity in the docked stack, false otherwise.
573 */
574 private boolean containsAppInDockedStack(ArraySet<AppWindowToken> apps) {
575 for (int i = apps.size() - 1; i >= 0; i--) {
576 final AppWindowToken token = apps.valueAt(i);
Bryce Lee6d410262017-02-28 15:30:17 -0800577 if (token.getTask() != null && token.getTask().mStack.mStackId == DOCKED_STACK_ID) {
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700578 return true;
579 }
580 }
581 return false;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800582 }
583
Jorim Jaggi1ae68bf2016-05-09 18:44:34 -0700584 boolean isMinimizedDock() {
585 return mMinimizedDock;
586 }
587
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700588 private void checkMinimizeChanged(boolean animate) {
Jorim Jaggife762342016-10-13 14:33:27 +0200589 if (mDisplayContent.getDockedStackIgnoringVisibility() == null) {
Jorim Jaggi817a5242016-05-06 15:45:00 -0700590 return;
591 }
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700592 final TaskStack homeStack = mDisplayContent.getHomeStack();
593 if (homeStack == null) {
594 return;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800595 }
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700596 final Task homeTask = homeStack.findHomeTask();
597 if (homeTask == null || !isWithinDisplay(homeTask)) {
598 return;
599 }
Matthew Ng8e265522017-02-13 11:09:37 -0800600
601 // Do not minimize when dock is already minimized while keyguard is showing and not
602 // occluded such as unlocking the screen
603 if (mMinimizedDock && mService.mPolicy.isKeyguardShowingAndNotOccluded()) {
604 return;
605 }
Wale Ogunwale1666e312016-12-16 11:27:18 -0800606 final TaskStack fullscreenStack =
607 mDisplayContent.getStackById(FULLSCREEN_WORKSPACE_STACK_ID);
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700608 final boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700609 final boolean homeBehind = (fullscreenStack != null && fullscreenStack.isVisible())
Wale Ogunwale15ead902016-09-02 14:30:11 -0700610 || (homeStack.hasMultipleTaskWithHomeTaskNotTop());
Wale Ogunwale069bbd32017-02-03 07:58:14 -0800611 setMinimizedDockedStack(homeVisible && !homeBehind, animate);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800612 }
613
614 private boolean isWithinDisplay(Task task) {
615 task.mStack.getBounds(mTmpRect);
616 mDisplayContent.getLogicalDisplayRect(mTmpRect2);
617 return mTmpRect.intersect(mTmpRect2);
618 }
619
620 /**
621 * Sets whether the docked stack is currently in a minimized state, i.e. all the tasks in the
622 * docked stack are heavily clipped so you can only see a minimal peek state.
623 *
624 * @param minimizedDock Whether the docked stack is currently minimized.
625 * @param animate Whether to animate the change.
626 */
627 private void setMinimizedDockedStack(boolean minimizedDock, boolean animate) {
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700628 final boolean wasMinimized = mMinimizedDock;
629 mMinimizedDock = minimizedDock;
Jorim Jaggi817a5242016-05-06 15:45:00 -0700630 if (minimizedDock == wasMinimized) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800631 return;
632 }
633
Chong Zhang22eff0a2016-07-01 14:48:11 -0700634 final boolean imeChanged = clearImeAdjustAnimation();
635 boolean minimizedChange = false;
Matthew Nge15352e2016-12-20 15:36:29 -0800636 if (isHomeStackResizable()) {
637 notifyDockedStackMinimizedChanged(minimizedDock, true /* animate */,
638 true /* isHomeStackResizable */);
639 minimizedChange = true;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800640 } else {
Matthew Nge15352e2016-12-20 15:36:29 -0800641 if (minimizedDock) {
642 if (animate) {
643 startAdjustAnimation(0f, 1f);
644 } else {
645 minimizedChange |= setMinimizedDockedStack(true);
646 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800647 } else {
Matthew Nge15352e2016-12-20 15:36:29 -0800648 if (animate) {
649 startAdjustAnimation(1f, 0f);
650 } else {
651 minimizedChange |= setMinimizedDockedStack(false);
652 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800653 }
654 }
Chong Zhang22eff0a2016-07-01 14:48:11 -0700655 if (imeChanged || minimizedChange) {
656 if (imeChanged && !minimizedChange) {
657 Slog.d(TAG, "setMinimizedDockedStack: IME adjust changed due to minimizing,"
658 + " minimizedDock=" + minimizedDock
659 + " minimizedChange=" + minimizedChange);
660 }
661 mService.mWindowPlacerLocked.performSurfacePlacement();
662 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800663 }
664
Chong Zhang22eff0a2016-07-01 14:48:11 -0700665 private boolean clearImeAdjustAnimation() {
Wale Ogunwale10124582016-09-15 20:25:50 -0700666 final boolean changed = mDisplayContent.clearImeAdjustAnimation();
Jorim Jaggieb88d832016-04-13 20:17:43 -0700667 mAnimatingForIme = false;
Chong Zhang22eff0a2016-07-01 14:48:11 -0700668 return changed;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700669 }
670
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800671 private void startAdjustAnimation(float from, float to) {
Chong Zhangbaba7832016-03-24 10:21:26 -0700672 mAnimatingForMinimizedDockedStack = true;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800673 mAnimationStarted = false;
674 mAnimationStart = from;
675 mAnimationTarget = to;
676 }
677
Chong Zhangf347ab52016-04-18 21:02:01 -0700678 private void startImeAdjustAnimation(
679 boolean adjustedForIme, boolean adjustedForDivider, WindowState imeWin) {
Chong Zhangf347ab52016-04-18 21:02:01 -0700680
681 // If we're not in an animation, the starting point depends on whether we're adjusted
682 // or not. If we're already in an animation, we start from where the current animation
683 // left off, so that the motion doesn't look discontinuous.
684 if (!mAnimatingForIme) {
685 mAnimationStart = mAdjustedForIme ? 1 : 0;
686 mDividerAnimationStart = mAdjustedForDivider ? 1 : 0;
687 mLastAnimationProgress = mAnimationStart;
688 mLastDividerProgress = mDividerAnimationStart;
689 } else {
690 mAnimationStart = mLastAnimationProgress;
691 mDividerAnimationStart = mLastDividerProgress;
692 }
Jorim Jaggi3070e772016-05-17 16:41:32 -0700693 mAnimatingForIme = true;
694 mAnimationStarted = false;
Chong Zhangf347ab52016-04-18 21:02:01 -0700695 mAnimationTarget = adjustedForIme ? 1 : 0;
696 mDividerAnimationTarget = adjustedForDivider ? 1 : 0;
Jorim Jaggiff71d202016-04-14 13:12:36 -0700697
Wale Ogunwale10124582016-09-15 20:25:50 -0700698 mDisplayContent.beginImeAdjustAnimation();
Jorim Jaggiff71d202016-04-14 13:12:36 -0700699
700 // We put all tasks into drag resizing mode - wait until all of them have completed the
701 // drag resizing switch.
702 if (!mService.mWaitingForDrawn.isEmpty()) {
703 mService.mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
704 mService.mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT,
705 IME_ADJUST_DRAWN_TIMEOUT);
706 mAnimationStartDelayed = true;
707 if (imeWin != null) {
708
709 // There might be an old window delaying the animation start - clear it.
710 if (mDelayedImeWin != null) {
711 mDelayedImeWin.mWinAnimator.endDelayingAnimationStart();
712 }
713 mDelayedImeWin = imeWin;
714 imeWin.mWinAnimator.startDelayingAnimationStart();
715 }
Jorim Jaggi31883862016-11-04 15:45:30 -0700716
717 // If we are already waiting for something to be drawn, clear out the old one so it
718 // still gets executed.
719 // TODO: Have a real system where we can wait on different windows to be drawn with
720 // different callbacks.
721 if (mService.mWaitingForDrawnCallback != null) {
722 mService.mWaitingForDrawnCallback.run();
723 }
Jorim Jaggiff71d202016-04-14 13:12:36 -0700724 mService.mWaitingForDrawnCallback = () -> {
725 mAnimationStartDelayed = false;
726 if (mDelayedImeWin != null) {
727 mDelayedImeWin.mWinAnimator.endDelayingAnimationStart();
728 }
Chong Zhang22eff0a2016-07-01 14:48:11 -0700729 // If the adjust status changed since this was posted, only notify
730 // the new states and don't animate.
731 long duration = 0;
732 if (mAdjustedForIme == adjustedForIme
733 && mAdjustedForDivider == adjustedForDivider) {
734 duration = IME_ADJUST_ANIM_DURATION;
735 } else {
736 Slog.w(TAG, "IME adjust changed while waiting for drawn:"
737 + " adjustedForIme=" + adjustedForIme
738 + " adjustedForDivider=" + adjustedForDivider
739 + " mAdjustedForIme=" + mAdjustedForIme
740 + " mAdjustedForDivider=" + mAdjustedForDivider);
741 }
Chong Zhangf347ab52016-04-18 21:02:01 -0700742 notifyAdjustedForImeChanged(
Chong Zhang22eff0a2016-07-01 14:48:11 -0700743 mAdjustedForIme || mAdjustedForDivider, duration);
Jorim Jaggiff71d202016-04-14 13:12:36 -0700744 };
745 } else {
Chong Zhangf347ab52016-04-18 21:02:01 -0700746 notifyAdjustedForImeChanged(
747 adjustedForIme || adjustedForDivider, IME_ADJUST_ANIM_DURATION);
Jorim Jaggiff71d202016-04-14 13:12:36 -0700748 }
Jorim Jaggieb88d832016-04-13 20:17:43 -0700749 }
750
Chong Zhang22eff0a2016-07-01 14:48:11 -0700751 private boolean setMinimizedDockedStack(boolean minimized) {
Jorim Jaggife762342016-10-13 14:33:27 +0200752 final TaskStack stack = mDisplayContent.getDockedStackIgnoringVisibility();
Matthew Nge15352e2016-12-20 15:36:29 -0800753 notifyDockedStackMinimizedChanged(minimized, false /* animate */, isHomeStackResizable());
Chong Zhang22eff0a2016-07-01 14:48:11 -0700754 return stack != null && stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800755 }
756
Jorim Jaggi8fe7e0a2016-02-12 19:43:39 -0800757 private boolean isAnimationMaximizing() {
758 return mAnimationTarget == 0f;
759 }
760
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800761 public boolean animate(long now) {
Wale Ogunwale20ec11b2016-04-22 12:11:51 -0700762 if (mWindow == null) {
763 return false;
764 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700765 if (mAnimatingForMinimizedDockedStack) {
766 return animateForMinimizedDockedStack(now);
767 } else if (mAnimatingForIme) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700768 return animateForIme(now);
Chong Zhangbaba7832016-03-24 10:21:26 -0700769 } else {
Wale Ogunwale20ec11b2016-04-22 12:11:51 -0700770 if (mDimLayer != null && mDimLayer.isDimming()) {
Wale Ogunwalec69694a2016-10-18 13:51:15 -0700771 mDimLayer.setLayer(getResizeDimLayer());
Chong Zhang1402c2e2016-04-21 15:17:47 -0700772 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800773 return false;
774 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700775 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800776
Jorim Jaggieb88d832016-04-13 20:17:43 -0700777 private boolean animateForIme(long now) {
Jorim Jaggiff71d202016-04-14 13:12:36 -0700778 if (!mAnimationStarted || mAnimationStartDelayed) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700779 mAnimationStarted = true;
780 mAnimationStartTime = now;
781 mAnimationDuration = (long)
Jorim Jaggi698e7632016-04-13 21:02:22 -0700782 (IME_ADJUST_ANIM_DURATION * mService.getWindowAnimationScaleLocked());
Jorim Jaggieb88d832016-04-13 20:17:43 -0700783 }
784 float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
785 t = (mAnimationTarget == 1f ? IME_ADJUST_ENTRY_INTERPOLATOR : TOUCH_RESPONSE_INTERPOLATOR)
786 .getInterpolation(t);
Wale Ogunwale10124582016-09-15 20:25:50 -0700787 final boolean updated =
788 mDisplayContent.animateForIme(t, mAnimationTarget, mDividerAnimationTarget);
Jorim Jaggieb88d832016-04-13 20:17:43 -0700789 if (updated) {
790 mService.mWindowPlacerLocked.performSurfacePlacement();
791 }
792 if (t >= 1.0f) {
Chong Zhangf347ab52016-04-18 21:02:01 -0700793 mLastAnimationProgress = mAnimationTarget;
794 mLastDividerProgress = mDividerAnimationTarget;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700795 mAnimatingForIme = false;
796 return false;
797 } else {
798 return true;
799 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700800 }
801
802 private boolean animateForMinimizedDockedStack(long now) {
Wale Ogunwale1666e312016-12-16 11:27:18 -0800803 final TaskStack stack = mDisplayContent.getStackById(DOCKED_STACK_ID);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800804 if (!mAnimationStarted) {
805 mAnimationStarted = true;
806 mAnimationStartTime = now;
Matthew Nge15352e2016-12-20 15:36:29 -0800807 notifyDockedStackMinimizedChanged(mMinimizedDock, true /* animate */,
808 isHomeStackResizable() /* isHomeStackResizable */);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800809 }
Jorim Jaggi8fe7e0a2016-02-12 19:43:39 -0800810 float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
811 t = (isAnimationMaximizing() ? TOUCH_RESPONSE_INTERPOLATOR : mMinimizedDockInterpolator)
812 .getInterpolation(t);
Chong Zhang741c0ba2016-05-27 12:52:11 -0700813 if (stack != null) {
814 if (stack.setAdjustedForMinimizedDock(getMinimizeAmount(stack, t))) {
815 mService.mWindowPlacerLocked.performSurfacePlacement();
816 }
817 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800818 if (t >= 1.0f) {
Chong Zhangbaba7832016-03-24 10:21:26 -0700819 mAnimatingForMinimizedDockedStack = false;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800820 return false;
821 } else {
822 return true;
823 }
824 }
825
Wale Ogunwale10124582016-09-15 20:25:50 -0700826 float getInterpolatedAnimationValue(float t) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700827 return t * mAnimationTarget + (1 - t) * mAnimationStart;
828 }
829
Wale Ogunwale10124582016-09-15 20:25:50 -0700830 float getInterpolatedDividerValue(float t) {
Chong Zhangf347ab52016-04-18 21:02:01 -0700831 return t * mDividerAnimationTarget + (1 - t) * mDividerAnimationStart;
832 }
833
Jorim Jaggif97ed922016-02-18 18:57:07 -0800834 /**
835 * Gets the amount how much to minimize a stack depending on the interpolated fraction t.
836 */
837 private float getMinimizeAmount(TaskStack stack, float t) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700838 final float naturalAmount = getInterpolatedAnimationValue(t);
Jorim Jaggif97ed922016-02-18 18:57:07 -0800839 if (isAnimationMaximizing()) {
840 return adjustMaximizeAmount(stack, t, naturalAmount);
841 } else {
842 return naturalAmount;
843 }
844 }
845
846 /**
847 * When maximizing the stack during a clip reveal transition, this adjusts the minimize amount
848 * during the transition such that the edge of the clip reveal rect is met earlier in the
849 * transition so we don't create a visible "hole", but only if both the clip reveal and the
850 * docked stack divider start from about the same portion on the screen.
851 */
852 private float adjustMaximizeAmount(TaskStack stack, float t, float naturalAmount) {
853 if (mMaximizeMeetFraction == 1f) {
854 return naturalAmount;
855 }
856 final int minimizeDistance = stack.getMinimizeDistance();
857 float startPrime = mService.mAppTransition.getLastClipRevealMaxTranslation()
858 / (float) minimizeDistance;
859 final float amountPrime = t * mAnimationTarget + (1 - t) * startPrime;
860 final float t2 = Math.min(t / mMaximizeMeetFraction, 1);
861 return amountPrime * t2 + naturalAmount * (1 - t2);
862 }
863
864 /**
865 * Retrieves the animation fraction at which the docked stack has to meet the clip reveal
866 * edge. See {@link #adjustMaximizeAmount}.
867 */
868 private float getClipRevealMeetFraction(TaskStack stack) {
869 if (!isAnimationMaximizing() || stack == null ||
870 !mService.mAppTransition.hadClipRevealAnimation()) {
871 return 1f;
872 }
873 final int minimizeDistance = stack.getMinimizeDistance();
874 final float fraction = Math.abs(mService.mAppTransition.getLastClipRevealMaxTranslation())
875 / (float) minimizeDistance;
876 final float t = Math.max(0, Math.min(1, (fraction - CLIP_REVEAL_MEET_FRACTION_MIN)
877 / (CLIP_REVEAL_MEET_FRACTION_MAX - CLIP_REVEAL_MEET_FRACTION_MIN)));
878 return CLIP_REVEAL_MEET_EARLIEST
879 + (1 - t) * (CLIP_REVEAL_MEET_LAST - CLIP_REVEAL_MEET_EARLIEST);
880 }
881
Jorim Jaggi50981592015-12-29 17:54:12 +0100882 @Override
Wale Ogunwale29bfbb82016-05-12 15:13:52 -0700883 public boolean dimFullscreen() {
Jorim Jaggi50981592015-12-29 17:54:12 +0100884 return false;
885 }
886
887 @Override
888 public DisplayInfo getDisplayInfo() {
889 return mDisplayContent.getDisplayInfo();
890 }
891
892 @Override
Wale Ogunwalef0a60a92017-01-19 09:44:40 -0800893 public boolean isAttachedToDisplay() {
894 return mDisplayContent != null;
895 }
896
897 @Override
Jorim Jaggi50981592015-12-29 17:54:12 +0100898 public void getDimBounds(Rect outBounds) {
899 // This dim layer user doesn't need this.
900 }
901
902 @Override
903 public String toShortString() {
904 return TAG;
905 }
Robert Carre63e01a2016-04-18 20:27:34 -0700906
907 WindowState getWindow() {
908 return mWindow;
909 }
Jorim Jaggi31f71702016-05-04 16:43:04 -0700910
911 void dump(String prefix, PrintWriter pw) {
912 pw.println(prefix + "DockedStackDividerController");
913 pw.println(prefix + " mLastVisibility=" + mLastVisibility);
914 pw.println(prefix + " mMinimizedDock=" + mMinimizedDock);
915 pw.println(prefix + " mAdjustedForIme=" + mAdjustedForIme);
916 pw.println(prefix + " mAdjustedForDivider=" + mAdjustedForDivider);
917 if (mDimLayer.isDimming()) {
918 pw.println(prefix + " Dim layer is dimming: ");
919 mDimLayer.printTo(prefix + " ", pw);
920 }
921 }
Robert Carre63e01a2016-04-18 20:27:34 -0700922}