blob: 6f0a43a20e8ac9b59377ed51db043c4d774b1a18 [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;
Jorim Jaggibc5425c2016-03-01 13:51:16 +010036
Filip Gruszczynski466f3212015-09-21 17:57:57 -070037import android.content.Context;
Jorim Jaggi85639432016-05-06 17:27:55 -070038import android.content.res.Configuration;
Filip Gruszczynski466f3212015-09-21 17:57:57 -070039import android.graphics.Rect;
Jorim Jaggia6c934e2015-12-21 13:22:31 +010040import android.os.RemoteCallbackList;
Filip Gruszczynski64cdc142015-11-29 21:10:07 -080041import android.os.RemoteException;
Jorim Jaggi936aaeb2016-08-26 19:02:11 -070042import android.util.ArraySet;
Filip Gruszczynski77049052015-11-09 14:01:21 -080043import android.util.Slog;
Jorim Jaggi50981592015-12-29 17:54:12 +010044import android.view.DisplayInfo;
Jorim Jaggia6c934e2015-12-21 13:22:31 +010045import android.view.IDockedStackListener;
Jorim Jaggi50981592015-12-29 17:54:12 +010046import android.view.SurfaceControl;
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 -070059import java.util.ArrayList;
60
Filip Gruszczynski466f3212015-09-21 17:57:57 -070061/**
Jorim Jaggi61f39a72015-10-29 16:54:18 +010062 * Keeps information about the docked stack divider.
Filip Gruszczynski466f3212015-09-21 17:57:57 -070063 */
Jorim Jaggi50981592015-12-29 17:54:12 +010064public class DockedStackDividerController implements DimLayerUser {
Jorim Jaggi61f39a72015-10-29 16:54:18 +010065
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080066 private static final String TAG = TAG_WITH_CLASS_NAME ? "DockedStackDividerController" : TAG_WM;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010067
Jorim Jaggif97ed922016-02-18 18:57:07 -080068 /**
69 * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip
70 * revealing surface at the earliest.
71 */
72 private static final float CLIP_REVEAL_MEET_EARLIEST = 0.6f;
73
74 /**
75 * The fraction during the maximize/clip reveal animation the divider meets the edge of the clip
76 * revealing surface at the latest.
77 */
78 private static final float CLIP_REVEAL_MEET_LAST = 1f;
79
80 /**
81 * If the app translates at least CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance, we start
82 * meet somewhere between {@link #CLIP_REVEAL_MEET_LAST} and {@link #CLIP_REVEAL_MEET_EARLIEST}.
83 */
84 private static final float CLIP_REVEAL_MEET_FRACTION_MIN = 0.4f;
85
86 /**
87 * If the app translates equals or more than CLIP_REVEAL_MEET_FRACTION_MIN * minimize distance,
88 * we meet at {@link #CLIP_REVEAL_MEET_EARLIEST}.
89 */
90 private static final float CLIP_REVEAL_MEET_FRACTION_MAX = 0.8f;
91
Jorim Jaggieb88d832016-04-13 20:17:43 -070092 private static final Interpolator IME_ADJUST_ENTRY_INTERPOLATOR =
Jorim Jaggiff71d202016-04-14 13:12:36 -070093 new PathInterpolator(0.2f, 0f, 0.1f, 1f);
Jorim Jaggieb88d832016-04-13 20:17:43 -070094
Jorim Jaggi698e7632016-04-13 21:02:22 -070095 private static final long IME_ADJUST_ANIM_DURATION = 280;
Jorim Jaggieb88d832016-04-13 20:17:43 -070096
Jorim Jaggiff71d202016-04-14 13:12:36 -070097 private static final long IME_ADJUST_DRAWN_TIMEOUT = 200;
98
Chong Zhang198afac2016-04-15 12:03:11 -070099 private static final int DIVIDER_WIDTH_INACTIVE_DP = 4;
100
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800101 private final WindowManagerService mService;
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700102 private final DisplayContent mDisplayContent;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700103 private int mDividerWindowWidth;
Chong Zhang198afac2016-04-15 12:03:11 -0700104 private int mDividerWindowWidthInactive;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700105 private int mDividerInsets;
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;
135 private float mLastAnimationProgress;
136 private 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
154 // If the bounds are fullscreen, return the value of the fullscreen configuration
155 if (bounds == null || (bounds.left == 0 && bounds.top == 0
156 && bounds.right == di.logicalWidth && bounds.bottom == di.logicalHeight)) {
157 return mService.mCurConfiguration.smallestScreenWidthDp;
158 }
159 final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth;
160 final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight;
161 int minWidth = Integer.MAX_VALUE;
162
163 // Go through all screen orientations and find the orientation in which the task has the
164 // smallest width.
165 for (int rotation = 0; rotation < 4; rotation++) {
166 mTmpRect.set(bounds);
167 mDisplayContent.rotateBounds(di.rotation, rotation, mTmpRect);
168 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
169 mTmpRect2.set(0, 0,
170 rotated ? baseDisplayHeight : baseDisplayWidth,
171 rotated ? baseDisplayWidth : baseDisplayHeight);
172 final int orientation = mTmpRect2.width() <= mTmpRect2.height()
173 ? ORIENTATION_PORTRAIT
174 : ORIENTATION_LANDSCAPE;
175 final int dockSide = TaskStack.getDockSideUnchecked(mTmpRect, mTmpRect2, orientation);
176 final int position = DockedDividerUtils.calculatePositionForBounds(mTmpRect, dockSide,
177 getContentWidth());
178
179 // Since we only care about feasible states, snap to the closest snap target, like it
180 // would happen when actually rotating the screen.
181 final int snappedPosition = mSnapAlgorithmForRotation[rotation]
182 .calculateNonDismissingSnapTarget(position).position;
183 DockedDividerUtils.calculateBoundsForPosition(snappedPosition, dockSide, mTmpRect,
184 mTmpRect2.width(), mTmpRect2.height(), getContentWidth());
185 mService.mPolicy.getStableInsetsLw(rotation, mTmpRect2.width(), mTmpRect2.height(),
186 mTmpRect3);
187 mService.subtractInsets(mTmpRect2, mTmpRect3, mTmpRect);
188 minWidth = Math.min(mTmpRect.width(), minWidth);
189 }
190 return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
191 }
192
193 private void initSnapAlgorithmForRotations() {
194 final Configuration baseConfig = mService.mCurConfiguration;
195
196 // Initialize the snap algorithms for all 4 screen orientations.
197 final Configuration config = new Configuration();
198 for (int rotation = 0; rotation < 4; rotation++) {
199 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
200 final int dw = rotated
201 ? mDisplayContent.mBaseDisplayHeight
202 : mDisplayContent.mBaseDisplayWidth;
203 final int dh = rotated
204 ? mDisplayContent.mBaseDisplayWidth
205 : mDisplayContent.mBaseDisplayHeight;
206 mService.mPolicy.getStableInsetsLw(rotation, dw, dh, mTmpRect);
207 config.setToDefaults();
208 config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
209 config.screenWidthDp = (int)
210 (mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, baseConfig.uiMode) /
211 mDisplayContent.getDisplayMetrics().density);
212 config.screenHeightDp = (int)
213 (mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, baseConfig.uiMode) /
214 mDisplayContent.getDisplayMetrics().density);
215 final Context rotationContext = mService.mContext.createConfigurationContext(config);
216 mSnapAlgorithmForRotation[rotation] = new DividerSnapAlgorithm(
217 rotationContext.getResources(), dw, dh, getContentWidth(),
218 config.orientation == ORIENTATION_PORTRAIT, mTmpRect);
219 }
220 }
221
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700222 private void loadDimens() {
223 final Context context = mService.mContext;
224 mDividerWindowWidth = context.getResources().getDimensionPixelSize(
225 com.android.internal.R.dimen.docked_stack_divider_thickness);
226 mDividerInsets = context.getResources().getDimensionPixelSize(
227 com.android.internal.R.dimen.docked_stack_divider_insets);
Chong Zhang198afac2016-04-15 12:03:11 -0700228 mDividerWindowWidthInactive = WindowManagerService.dipToPixel(
229 DIVIDER_WIDTH_INACTIVE_DP, mDisplayContent.getDisplayMetrics());
Jorim Jaggi85639432016-05-06 17:27:55 -0700230 initSnapAlgorithmForRotations();
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700231 }
232
233 void onConfigurationChanged() {
234 loadDimens();
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700235 }
236
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100237 boolean isResizing() {
238 return mResizing;
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700239 }
240
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100241 int getContentWidth() {
242 return mDividerWindowWidth - 2 * mDividerInsets;
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700243 }
244
Jorim Jaggi81ba11e2016-02-03 22:04:22 -0800245 int getContentInsets() {
246 return mDividerInsets;
247 }
248
Chong Zhang198afac2016-04-15 12:03:11 -0700249 int getContentWidthInactive() {
250 return mDividerWindowWidthInactive;
251 }
252
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100253 void setResizing(boolean resizing) {
Jorim Jaggic662d8e2016-02-05 16:54:54 -0800254 if (mResizing != resizing) {
255 mResizing = resizing;
256 resetDragResizingChangeReported();
257 }
258 }
259
Jorim Jaggid47e7e12016-03-01 09:57:38 +0100260 void setTouchRegion(Rect touchRegion) {
261 mTouchRegion.set(touchRegion);
262 }
263
264 void getTouchRegion(Rect outRegion) {
265 outRegion.set(mTouchRegion);
266 outRegion.offset(mWindow.getFrameLw().left, mWindow.getFrameLw().top);
267 }
268
Jorim Jaggic662d8e2016-02-05 16:54:54 -0800269 private void resetDragResizingChangeReported() {
270 final WindowList windowList = mDisplayContent.getWindowList();
271 for (int i = windowList.size() - 1; i >= 0; i--) {
272 windowList.get(i).resetDragResizingChangeReported();
273 }
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100274 }
275
276 void setWindow(WindowState window) {
277 mWindow = window;
Filip Gruszczynski85d5cc42015-12-04 09:21:37 -0800278 reevaluateVisibility(false);
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100279 }
280
Filip Gruszczynski85d5cc42015-12-04 09:21:37 -0800281 void reevaluateVisibility(boolean force) {
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800282 if (mWindow == null) {
283 return;
284 }
Jorim Jaggie48f4282015-11-06 17:32:44 +0100285 TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID);
Jorim Jaggi7998e482016-02-12 18:47:06 -0800286
287 // If the stack is invisible, we policy force hide it in WindowAnimator.shouldForceHide
288 final boolean visible = stack != null;
Filip Gruszczynski85d5cc42015-12-04 09:21:37 -0800289 if (mLastVisibility == visible && !force) {
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800290 return;
291 }
292 mLastVisibility = visible;
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100293 notifyDockedDividerVisibilityChanged(visible);
Jorim Jaggi50981592015-12-29 17:54:12 +0100294 if (!visible) {
295 setResizeDimLayer(false, INVALID_STACK_ID, 0f);
296 }
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100297 }
298
299 boolean wasVisible() {
300 return mLastVisibility;
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100301 }
302
Chong Zhangf347ab52016-04-18 21:02:01 -0700303 void setAdjustedForIme(
304 boolean adjustedForIme, boolean adjustedForDivider,
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700305 boolean animate, WindowState imeWin, int imeHeight) {
306 if (mAdjustedForIme != adjustedForIme || (adjustedForIme && mImeHeight != imeHeight)
307 || mAdjustedForDivider != adjustedForDivider) {
Jorim Jaggi3070e772016-05-17 16:41:32 -0700308 if (animate && !mAnimatingForMinimizedDockedStack) {
Chong Zhangf347ab52016-04-18 21:02:01 -0700309 startImeAdjustAnimation(adjustedForIme, adjustedForDivider, imeWin);
Jorim Jaggiff71d202016-04-14 13:12:36 -0700310 } else {
Jorim Jaggiff71d202016-04-14 13:12:36 -0700311 // Animation might be delayed, so only notify if we don't run an animation.
Chong Zhangf347ab52016-04-18 21:02:01 -0700312 notifyAdjustedForImeChanged(adjustedForIme || adjustedForDivider, 0 /* duration */);
Jorim Jaggieb88d832016-04-13 20:17:43 -0700313 }
Chong Zhangf347ab52016-04-18 21:02:01 -0700314 mAdjustedForIme = adjustedForIme;
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700315 mImeHeight = imeHeight;
Chong Zhangf347ab52016-04-18 21:02:01 -0700316 mAdjustedForDivider = adjustedForDivider;
Chong Zhangbaba7832016-03-24 10:21:26 -0700317 }
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700318 }
319
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700320 int getImeHeightAdjustedFor() {
321 return mImeHeight;
322 }
323
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700324 void positionDockedStackedDivider(Rect frame) {
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700325 TaskStack stack = mDisplayContent.getDockedStackLocked();
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700326 if (stack == null) {
327 // Unfortunately we might end up with still having a divider, even though the underlying
328 // stack was already removed. This is because we are on AM thread and the removal of the
Filip Gruszczynski77049052015-11-09 14:01:21 -0800329 // divider was deferred to WM thread and hasn't happened yet. In that case let's just
330 // keep putting it in the same place it was before the stack was removed to have
331 // continuity and prevent it from jumping to the center. It will get hidden soon.
332 frame.set(mLastRect);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700333 return;
Filip Gruszczynski77049052015-11-09 14:01:21 -0800334 } else {
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800335 stack.getDimBounds(mTmpRect);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700336 }
Jorim Jaggi61f39a72015-10-29 16:54:18 +0100337 int side = stack.getDockSide();
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700338 switch (side) {
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700339 case DOCKED_LEFT:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100340 frame.set(mTmpRect.right - mDividerInsets, frame.top,
341 mTmpRect.right + frame.width() - mDividerInsets, frame.bottom);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700342 break;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700343 case DOCKED_TOP:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100344 frame.set(frame.left, mTmpRect.bottom - mDividerInsets,
345 mTmpRect.right, mTmpRect.bottom + frame.height() - mDividerInsets);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700346 break;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700347 case DOCKED_RIGHT:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100348 frame.set(mTmpRect.left - frame.width() + mDividerInsets, frame.top,
349 mTmpRect.left + mDividerInsets, frame.bottom);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700350 break;
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700351 case DOCKED_BOTTOM:
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100352 frame.set(frame.left, mTmpRect.top - frame.height() + mDividerInsets,
353 frame.right, mTmpRect.top + mDividerInsets);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700354 break;
355 }
Filip Gruszczynski77049052015-11-09 14:01:21 -0800356 mLastRect.set(frame);
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700357 }
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800358
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100359 void notifyDockedDividerVisibilityChanged(boolean visible) {
360 final int size = mDockedStackListeners.beginBroadcast();
361 for (int i = 0; i < size; ++i) {
362 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
363 try {
364 listener.onDividerVisibilityChanged(visible);
365 } catch (RemoteException e) {
366 Slog.e(TAG_WM, "Error delivering divider visibility changed event.", e);
367 }
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800368 }
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100369 mDockedStackListeners.finishBroadcast();
370 }
371
372 void notifyDockedStackExistsChanged(boolean exists) {
373 final int size = mDockedStackListeners.beginBroadcast();
374 for (int i = 0; i < size; ++i) {
375 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
376 try {
377 listener.onDockedStackExistsChanged(exists);
378 } catch (RemoteException e) {
379 Slog.e(TAG_WM, "Error delivering docked stack exists changed event.", e);
380 }
381 }
382 mDockedStackListeners.finishBroadcast();
Jorim Jaggi3c5d0f12016-05-24 19:04:30 -0700383 if (exists) {
384 InputMethodManagerInternal inputMethodManagerInternal =
385 LocalServices.getService(InputMethodManagerInternal.class);
386 if (inputMethodManagerInternal != null) {
387
388 // Hide the current IME to avoid problems with animations from IME adjustment when
389 // attaching the docked stack.
390 inputMethodManagerInternal.hideCurrentInputMethod();
391 mImeHideRequested = true;
392 }
Chong Zhang22eff0a2016-07-01 14:48:11 -0700393 } else if (setMinimizedDockedStack(false)) {
394 mService.mWindowPlacerLocked.performSurfacePlacement();
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700395 }
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100396 }
397
Jorim Jaggi3c5d0f12016-05-24 19:04:30 -0700398 /**
399 * Resets the state that IME hide has been requested. See {@link #isImeHideRequested}.
400 */
401 void resetImeHideRequested() {
402 mImeHideRequested = false;
403 }
404
405 /**
406 * The docked stack divider controller makes sure the IME gets hidden when attaching the docked
407 * stack, to avoid animation problems. This flag indicates whether the request to hide the IME
408 * has been sent in an asynchronous manner, and the IME should be treated as hidden already.
409 *
410 * @return whether IME hide request has been sent
411 */
412 boolean isImeHideRequested() {
413 return mImeHideRequested;
414 }
415
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800416 void notifyDockedStackMinimizedChanged(boolean minimizedDock, long animDuration) {
Tony Mak853304c2016-04-18 15:17:41 +0100417 mService.mH.removeMessages(NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED);
418 mService.mH.obtainMessage(NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED,
419 minimizedDock ? 1 : 0, 0).sendToTarget();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800420 final int size = mDockedStackListeners.beginBroadcast();
421 for (int i = 0; i < size; ++i) {
422 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
423 try {
424 listener.onDockedStackMinimizedChanged(minimizedDock, animDuration);
425 } catch (RemoteException e) {
426 Slog.e(TAG_WM, "Error delivering minimized dock changed event.", e);
427 }
428 }
429 mDockedStackListeners.finishBroadcast();
430 }
431
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700432 void notifyDockSideChanged(int newDockSide) {
433 final int size = mDockedStackListeners.beginBroadcast();
434 for (int i = 0; i < size; ++i) {
435 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
436 try {
437 listener.onDockSideChanged(newDockSide);
438 } catch (RemoteException e) {
439 Slog.e(TAG_WM, "Error delivering dock side changed event.", e);
440 }
441 }
442 mDockedStackListeners.finishBroadcast();
443 }
444
Jorim Jaggi698e7632016-04-13 21:02:22 -0700445 void notifyAdjustedForImeChanged(boolean adjustedForIme, long animDuration) {
446 final int size = mDockedStackListeners.beginBroadcast();
447 for (int i = 0; i < size; ++i) {
448 final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
449 try {
450 listener.onAdjustedForImeChanged(adjustedForIme, animDuration);
451 } catch (RemoteException e) {
452 Slog.e(TAG_WM, "Error delivering adjusted for ime changed event.", e);
453 }
454 }
455 mDockedStackListeners.finishBroadcast();
456 }
457
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100458 void registerDockedStackListener(IDockedStackListener listener) {
459 mDockedStackListeners.register(listener);
460 notifyDockedDividerVisibilityChanged(wasVisible());
461 notifyDockedStackExistsChanged(
462 mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID) != null);
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700463 notifyDockedStackMinimizedChanged(mMinimizedDock, 0 /* animDuration */);
Jorim Jaggi698e7632016-04-13 21:02:22 -0700464 notifyAdjustedForImeChanged(mAdjustedForIme, 0 /* animDuration */);
465
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800466 }
Jorim Jaggi50981592015-12-29 17:54:12 +0100467
468 void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
469 SurfaceControl.openTransaction();
Jorim Jaggibc5425c2016-03-01 13:51:16 +0100470 final TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(targetStackId);
471 final TaskStack dockedStack = mDisplayContent.getDockedStackLocked();
472 boolean visibleAndValid = visible && stack != null && dockedStack != null;
Jorim Jaggi7b371dd2016-01-05 15:32:34 +0100473 if (visibleAndValid) {
Jorim Jaggi50981592015-12-29 17:54:12 +0100474 stack.getDimBounds(mTmpRect);
Jorim Jaggi10b89dc2016-01-05 15:40:17 +0100475 if (mTmpRect.height() > 0 && mTmpRect.width() > 0) {
Jorim Jaggi7b371dd2016-01-05 15:32:34 +0100476 mDimLayer.setBounds(mTmpRect);
Chong Zhang1402c2e2016-04-21 15:17:47 -0700477 mDimLayer.show(mService.mLayersController.getResizeDimLayer(),
Jorim Jaggi7b371dd2016-01-05 15:32:34 +0100478 alpha, 0 /* duration */);
479 } else {
480 visibleAndValid = false;
481 }
482 }
483 if (!visibleAndValid) {
Jorim Jaggi50981592015-12-29 17:54:12 +0100484 mDimLayer.hide();
485 }
486 SurfaceControl.closeTransaction();
487 }
488
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800489 /**
490 * Notifies the docked stack divider controller of a visibility change that happens without
491 * an animation.
492 */
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700493 void notifyAppVisibilityChanged() {
494 checkMinimizeChanged(false /* animate */);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800495 }
496
Jorim Jaggi84afb1a2016-09-28 14:54:04 +0200497 void notifyAppTransitionStarting(ArraySet<AppWindowToken> openingApps, int appTransition) {
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700498 final boolean wasMinimized = mMinimizedDock;
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700499 checkMinimizeChanged(true /* animate */);
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700500
501 // We were minimized, and now we are still minimized, but somebody is trying to launch an
502 // app in docked stack, better show recent apps so we actually get unminimized! This catches
503 // any case that was missed in ActivityStarter.postStartActivityUncheckedProcessing because
504 // we couldn't retrace the launch of the app in the docked stack to the launch from
505 // homescreen.
Jorim Jaggi84afb1a2016-09-28 14:54:04 +0200506 if (wasMinimized && mMinimizedDock && containsAppInDockedStack(openingApps)
507 && appTransition != TRANSIT_NONE) {
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700508 mService.showRecentApps(true /* fromHome */);
509 }
510 }
511
512 /**
513 * @return true if {@param apps} contains an activity in the docked stack, false otherwise.
514 */
515 private boolean containsAppInDockedStack(ArraySet<AppWindowToken> apps) {
516 for (int i = apps.size() - 1; i >= 0; i--) {
517 final AppWindowToken token = apps.valueAt(i);
518 if (token.mTask != null && token.mTask.mStack.mStackId == DOCKED_STACK_ID) {
519 return true;
520 }
521 }
522 return false;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800523 }
524
Jorim Jaggi1ae68bf2016-05-09 18:44:34 -0700525 boolean isMinimizedDock() {
526 return mMinimizedDock;
527 }
528
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700529 private void checkMinimizeChanged(boolean animate) {
Jorim Jaggi817a5242016-05-06 15:45:00 -0700530 if (mDisplayContent.getDockedStackVisibleForUserLocked() == null) {
531 return;
532 }
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700533 final TaskStack homeStack = mDisplayContent.getHomeStack();
534 if (homeStack == null) {
535 return;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800536 }
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700537 final Task homeTask = homeStack.findHomeTask();
538 if (homeTask == null || !isWithinDisplay(homeTask)) {
539 return;
540 }
541 final TaskStack fullscreenStack
542 = mService.mStackIdToStack.get(FULLSCREEN_WORKSPACE_STACK_ID);
543 final ArrayList<Task> homeStackTasks = homeStack.getTasks();
544 final Task topHomeStackTask = homeStackTasks.get(homeStackTasks.size() - 1);
545 final boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
546 final boolean homeBehind = (fullscreenStack != null && fullscreenStack.isVisibleLocked())
547 || (homeStackTasks.size() > 1 && topHomeStackTask != homeTask);
548 setMinimizedDockedStack(homeVisible && !homeBehind, animate);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800549 }
550
551 private boolean isWithinDisplay(Task task) {
552 task.mStack.getBounds(mTmpRect);
553 mDisplayContent.getLogicalDisplayRect(mTmpRect2);
554 return mTmpRect.intersect(mTmpRect2);
555 }
556
557 /**
558 * Sets whether the docked stack is currently in a minimized state, i.e. all the tasks in the
559 * docked stack are heavily clipped so you can only see a minimal peek state.
560 *
561 * @param minimizedDock Whether the docked stack is currently minimized.
562 * @param animate Whether to animate the change.
563 */
564 private void setMinimizedDockedStack(boolean minimizedDock, boolean animate) {
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700565 final boolean wasMinimized = mMinimizedDock;
566 mMinimizedDock = minimizedDock;
Jorim Jaggi817a5242016-05-06 15:45:00 -0700567 if (minimizedDock == wasMinimized) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800568 return;
569 }
570
Chong Zhang22eff0a2016-07-01 14:48:11 -0700571 final boolean imeChanged = clearImeAdjustAnimation();
572 boolean minimizedChange = false;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800573 if (minimizedDock) {
574 if (animate) {
575 startAdjustAnimation(0f, 1f);
576 } else {
Chong Zhang22eff0a2016-07-01 14:48:11 -0700577 minimizedChange |= setMinimizedDockedStack(true);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800578 }
579 } else {
580 if (animate) {
581 startAdjustAnimation(1f, 0f);
582 } else {
Chong Zhang22eff0a2016-07-01 14:48:11 -0700583 minimizedChange |= setMinimizedDockedStack(false);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800584 }
585 }
Chong Zhang22eff0a2016-07-01 14:48:11 -0700586 if (imeChanged || minimizedChange) {
587 if (imeChanged && !minimizedChange) {
588 Slog.d(TAG, "setMinimizedDockedStack: IME adjust changed due to minimizing,"
589 + " minimizedDock=" + minimizedDock
590 + " minimizedChange=" + minimizedChange);
591 }
592 mService.mWindowPlacerLocked.performSurfacePlacement();
593 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800594 }
595
Chong Zhang22eff0a2016-07-01 14:48:11 -0700596 private boolean clearImeAdjustAnimation() {
597 boolean changed = false;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700598 final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
599 for (int i = stacks.size() - 1; i >= 0; --i) {
600 final TaskStack stack = stacks.get(i);
601 if (stack != null && stack.isAdjustedForIme()) {
602 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
Chong Zhang22eff0a2016-07-01 14:48:11 -0700603 changed = true;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700604 }
605 }
606 mAnimatingForIme = false;
Chong Zhang22eff0a2016-07-01 14:48:11 -0700607 return changed;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700608 }
609
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800610 private void startAdjustAnimation(float from, float to) {
Chong Zhangbaba7832016-03-24 10:21:26 -0700611 mAnimatingForMinimizedDockedStack = true;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800612 mAnimationStarted = false;
613 mAnimationStart = from;
614 mAnimationTarget = to;
615 }
616
Chong Zhangf347ab52016-04-18 21:02:01 -0700617 private void startImeAdjustAnimation(
618 boolean adjustedForIme, boolean adjustedForDivider, WindowState imeWin) {
Chong Zhangf347ab52016-04-18 21:02:01 -0700619
620 // If we're not in an animation, the starting point depends on whether we're adjusted
621 // or not. If we're already in an animation, we start from where the current animation
622 // left off, so that the motion doesn't look discontinuous.
623 if (!mAnimatingForIme) {
624 mAnimationStart = mAdjustedForIme ? 1 : 0;
625 mDividerAnimationStart = mAdjustedForDivider ? 1 : 0;
626 mLastAnimationProgress = mAnimationStart;
627 mLastDividerProgress = mDividerAnimationStart;
628 } else {
629 mAnimationStart = mLastAnimationProgress;
630 mDividerAnimationStart = mLastDividerProgress;
631 }
Jorim Jaggi3070e772016-05-17 16:41:32 -0700632 mAnimatingForIme = true;
633 mAnimationStarted = false;
Chong Zhangf347ab52016-04-18 21:02:01 -0700634 mAnimationTarget = adjustedForIme ? 1 : 0;
635 mDividerAnimationTarget = adjustedForDivider ? 1 : 0;
Jorim Jaggiff71d202016-04-14 13:12:36 -0700636
637 final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
638 for (int i = stacks.size() - 1; i >= 0; --i) {
639 final TaskStack stack = stacks.get(i);
640 if (stack.isVisibleLocked() && stack.isAdjustedForIme()) {
641 stack.beginImeAdjustAnimation();
642 }
643 }
644
645 // We put all tasks into drag resizing mode - wait until all of them have completed the
646 // drag resizing switch.
647 if (!mService.mWaitingForDrawn.isEmpty()) {
648 mService.mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
649 mService.mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT,
650 IME_ADJUST_DRAWN_TIMEOUT);
651 mAnimationStartDelayed = true;
652 if (imeWin != null) {
653
654 // There might be an old window delaying the animation start - clear it.
655 if (mDelayedImeWin != null) {
656 mDelayedImeWin.mWinAnimator.endDelayingAnimationStart();
657 }
658 mDelayedImeWin = imeWin;
659 imeWin.mWinAnimator.startDelayingAnimationStart();
660 }
661 mService.mWaitingForDrawnCallback = () -> {
662 mAnimationStartDelayed = false;
663 if (mDelayedImeWin != null) {
664 mDelayedImeWin.mWinAnimator.endDelayingAnimationStart();
665 }
Chong Zhang22eff0a2016-07-01 14:48:11 -0700666 // If the adjust status changed since this was posted, only notify
667 // the new states and don't animate.
668 long duration = 0;
669 if (mAdjustedForIme == adjustedForIme
670 && mAdjustedForDivider == adjustedForDivider) {
671 duration = IME_ADJUST_ANIM_DURATION;
672 } else {
673 Slog.w(TAG, "IME adjust changed while waiting for drawn:"
674 + " adjustedForIme=" + adjustedForIme
675 + " adjustedForDivider=" + adjustedForDivider
676 + " mAdjustedForIme=" + mAdjustedForIme
677 + " mAdjustedForDivider=" + mAdjustedForDivider);
678 }
Chong Zhangf347ab52016-04-18 21:02:01 -0700679 notifyAdjustedForImeChanged(
Chong Zhang22eff0a2016-07-01 14:48:11 -0700680 mAdjustedForIme || mAdjustedForDivider, duration);
Jorim Jaggiff71d202016-04-14 13:12:36 -0700681 };
682 } else {
Chong Zhangf347ab52016-04-18 21:02:01 -0700683 notifyAdjustedForImeChanged(
684 adjustedForIme || adjustedForDivider, IME_ADJUST_ANIM_DURATION);
Jorim Jaggiff71d202016-04-14 13:12:36 -0700685 }
Jorim Jaggieb88d832016-04-13 20:17:43 -0700686 }
687
Chong Zhang22eff0a2016-07-01 14:48:11 -0700688 private boolean setMinimizedDockedStack(boolean minimized) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800689 final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked();
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700690 notifyDockedStackMinimizedChanged(minimized, 0);
Chong Zhang22eff0a2016-07-01 14:48:11 -0700691 return stack != null && stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800692 }
693
Jorim Jaggi8fe7e0a2016-02-12 19:43:39 -0800694 private boolean isAnimationMaximizing() {
695 return mAnimationTarget == 0f;
696 }
697
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800698 public boolean animate(long now) {
Wale Ogunwale20ec11b2016-04-22 12:11:51 -0700699 if (mWindow == null) {
700 return false;
701 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700702 if (mAnimatingForMinimizedDockedStack) {
703 return animateForMinimizedDockedStack(now);
704 } else if (mAnimatingForIme) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700705 return animateForIme(now);
Chong Zhangbaba7832016-03-24 10:21:26 -0700706 } else {
Wale Ogunwale20ec11b2016-04-22 12:11:51 -0700707 if (mDimLayer != null && mDimLayer.isDimming()) {
Chong Zhang1402c2e2016-04-21 15:17:47 -0700708 mDimLayer.setLayer(mService.mLayersController.getResizeDimLayer());
709 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800710 return false;
711 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700712 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800713
Jorim Jaggieb88d832016-04-13 20:17:43 -0700714 private boolean animateForIme(long now) {
Jorim Jaggiff71d202016-04-14 13:12:36 -0700715 if (!mAnimationStarted || mAnimationStartDelayed) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700716 mAnimationStarted = true;
717 mAnimationStartTime = now;
718 mAnimationDuration = (long)
Jorim Jaggi698e7632016-04-13 21:02:22 -0700719 (IME_ADJUST_ANIM_DURATION * mService.getWindowAnimationScaleLocked());
Jorim Jaggieb88d832016-04-13 20:17:43 -0700720 }
721 float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
722 t = (mAnimationTarget == 1f ? IME_ADJUST_ENTRY_INTERPOLATOR : TOUCH_RESPONSE_INTERPOLATOR)
723 .getInterpolation(t);
Chong Zhangbaba7832016-03-24 10:21:26 -0700724 final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
Jorim Jaggieb88d832016-04-13 20:17:43 -0700725 boolean updated = false;
Chong Zhangbaba7832016-03-24 10:21:26 -0700726 for (int i = stacks.size() - 1; i >= 0; --i) {
727 final TaskStack stack = stacks.get(i);
728 if (stack != null && stack.isAdjustedForIme()) {
Chong Zhangf347ab52016-04-18 21:02:01 -0700729 if (t >= 1f && mAnimationTarget == 0f && mDividerAnimationTarget == 0f) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700730 stack.resetAdjustedForIme(true /* adjustBoundsNow */);
731 updated = true;
732 } else {
Chong Zhangf347ab52016-04-18 21:02:01 -0700733 mLastAnimationProgress = getInterpolatedAnimationValue(t);
734 mLastDividerProgress = getInterpolatedDividerValue(t);
735 updated |= stack.updateAdjustForIme(
736 mLastAnimationProgress,
737 mLastDividerProgress,
Jorim Jaggiff71d202016-04-14 13:12:36 -0700738 false /* force */);
739 }
740 if (t >= 1f) {
741 stack.endImeAdjustAnimation();
Chong Zhangbaba7832016-03-24 10:21:26 -0700742 }
743 }
744 }
Jorim Jaggieb88d832016-04-13 20:17:43 -0700745 if (updated) {
746 mService.mWindowPlacerLocked.performSurfacePlacement();
747 }
748 if (t >= 1.0f) {
Chong Zhangf347ab52016-04-18 21:02:01 -0700749 mLastAnimationProgress = mAnimationTarget;
750 mLastDividerProgress = mDividerAnimationTarget;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700751 mAnimatingForIme = false;
752 return false;
753 } else {
754 return true;
755 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700756 }
757
758 private boolean animateForMinimizedDockedStack(long now) {
Jorim Jaggiaf558e12016-04-27 22:56:56 -0700759 final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800760 if (!mAnimationStarted) {
761 mAnimationStarted = true;
762 mAnimationStartTime = now;
Jorim Jaggi8fe7e0a2016-02-12 19:43:39 -0800763 final long transitionDuration = isAnimationMaximizing()
764 ? mService.mAppTransition.getLastClipRevealTransitionDuration()
765 : DEFAULT_APP_TRANSITION_DURATION;
766 mAnimationDuration = (long)
767 (transitionDuration * mService.getTransitionAnimationScaleLocked());
Jorim Jaggif97ed922016-02-18 18:57:07 -0800768 mMaximizeMeetFraction = getClipRevealMeetFraction(stack);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800769 notifyDockedStackMinimizedChanged(mMinimizedDock,
Jorim Jaggif97ed922016-02-18 18:57:07 -0800770 (long) (mAnimationDuration * mMaximizeMeetFraction));
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800771 }
Jorim Jaggi8fe7e0a2016-02-12 19:43:39 -0800772 float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
773 t = (isAnimationMaximizing() ? TOUCH_RESPONSE_INTERPOLATOR : mMinimizedDockInterpolator)
774 .getInterpolation(t);
Chong Zhang741c0ba2016-05-27 12:52:11 -0700775 if (stack != null) {
776 if (stack.setAdjustedForMinimizedDock(getMinimizeAmount(stack, t))) {
777 mService.mWindowPlacerLocked.performSurfacePlacement();
778 }
779 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800780 if (t >= 1.0f) {
Chong Zhangbaba7832016-03-24 10:21:26 -0700781 mAnimatingForMinimizedDockedStack = false;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800782 return false;
783 } else {
784 return true;
785 }
786 }
787
Jorim Jaggieb88d832016-04-13 20:17:43 -0700788 private float getInterpolatedAnimationValue(float t) {
789 return t * mAnimationTarget + (1 - t) * mAnimationStart;
790 }
791
Chong Zhangf347ab52016-04-18 21:02:01 -0700792 private float getInterpolatedDividerValue(float t) {
793 return t * mDividerAnimationTarget + (1 - t) * mDividerAnimationStart;
794 }
795
Jorim Jaggif97ed922016-02-18 18:57:07 -0800796 /**
797 * Gets the amount how much to minimize a stack depending on the interpolated fraction t.
798 */
799 private float getMinimizeAmount(TaskStack stack, float t) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700800 final float naturalAmount = getInterpolatedAnimationValue(t);
Jorim Jaggif97ed922016-02-18 18:57:07 -0800801 if (isAnimationMaximizing()) {
802 return adjustMaximizeAmount(stack, t, naturalAmount);
803 } else {
804 return naturalAmount;
805 }
806 }
807
808 /**
809 * When maximizing the stack during a clip reveal transition, this adjusts the minimize amount
810 * during the transition such that the edge of the clip reveal rect is met earlier in the
811 * transition so we don't create a visible "hole", but only if both the clip reveal and the
812 * docked stack divider start from about the same portion on the screen.
813 */
814 private float adjustMaximizeAmount(TaskStack stack, float t, float naturalAmount) {
815 if (mMaximizeMeetFraction == 1f) {
816 return naturalAmount;
817 }
818 final int minimizeDistance = stack.getMinimizeDistance();
819 float startPrime = mService.mAppTransition.getLastClipRevealMaxTranslation()
820 / (float) minimizeDistance;
821 final float amountPrime = t * mAnimationTarget + (1 - t) * startPrime;
822 final float t2 = Math.min(t / mMaximizeMeetFraction, 1);
823 return amountPrime * t2 + naturalAmount * (1 - t2);
824 }
825
826 /**
827 * Retrieves the animation fraction at which the docked stack has to meet the clip reveal
828 * edge. See {@link #adjustMaximizeAmount}.
829 */
830 private float getClipRevealMeetFraction(TaskStack stack) {
831 if (!isAnimationMaximizing() || stack == null ||
832 !mService.mAppTransition.hadClipRevealAnimation()) {
833 return 1f;
834 }
835 final int minimizeDistance = stack.getMinimizeDistance();
836 final float fraction = Math.abs(mService.mAppTransition.getLastClipRevealMaxTranslation())
837 / (float) minimizeDistance;
838 final float t = Math.max(0, Math.min(1, (fraction - CLIP_REVEAL_MEET_FRACTION_MIN)
839 / (CLIP_REVEAL_MEET_FRACTION_MAX - CLIP_REVEAL_MEET_FRACTION_MIN)));
840 return CLIP_REVEAL_MEET_EARLIEST
841 + (1 - t) * (CLIP_REVEAL_MEET_LAST - CLIP_REVEAL_MEET_EARLIEST);
842 }
843
Jorim Jaggi50981592015-12-29 17:54:12 +0100844 @Override
Wale Ogunwale29bfbb82016-05-12 15:13:52 -0700845 public boolean dimFullscreen() {
Jorim Jaggi50981592015-12-29 17:54:12 +0100846 return false;
847 }
848
849 @Override
850 public DisplayInfo getDisplayInfo() {
851 return mDisplayContent.getDisplayInfo();
852 }
853
854 @Override
855 public void getDimBounds(Rect outBounds) {
856 // This dim layer user doesn't need this.
857 }
858
859 @Override
860 public String toShortString() {
861 return TAG;
862 }
Robert Carre63e01a2016-04-18 20:27:34 -0700863
864 WindowState getWindow() {
865 return mWindow;
866 }
Jorim Jaggi31f71702016-05-04 16:43:04 -0700867
868 void dump(String prefix, PrintWriter pw) {
869 pw.println(prefix + "DockedStackDividerController");
870 pw.println(prefix + " mLastVisibility=" + mLastVisibility);
871 pw.println(prefix + " mMinimizedDock=" + mMinimizedDock);
872 pw.println(prefix + " mAdjustedForIme=" + mAdjustedForIme);
873 pw.println(prefix + " mAdjustedForDivider=" + mAdjustedForDivider);
874 if (mDimLayer.isDimming()) {
875 pw.println(prefix + " Dim layer is dimming: ");
876 mDimLayer.printTo(prefix + " ", pw);
877 }
878 }
Robert Carre63e01a2016-04-18 20:27:34 -0700879}