blob: db33c79be773cc31ad305cdf21aadb53a6703fd5 [file] [log] [blame]
Jorim Jaggi1fcbab62015-11-04 16:39:50 +01001/*
2 * Copyright (C) 2015 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.systemui.stackdivider;
18
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010019import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
Evan Rosky05ec8862020-02-28 19:37:04 -080020import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
21import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000022import static android.view.Display.DEFAULT_DISPLAY;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010023
Evan Rosky8d1c24e2020-04-23 09:21:16 -070024import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
25
Evan Rosky95729202020-02-21 10:16:08 -080026import android.animation.Animator;
27import android.animation.AnimatorListenerAdapter;
28import android.animation.ValueAnimator;
Evan Rosky8d1c24e2020-04-23 09:21:16 -070029import android.app.ActivityManager;
Evan Roskyb8540a02020-03-25 16:30:24 -070030import android.app.ActivityTaskManager;
Dave Mankoffa5d8a392019-10-10 12:21:09 -040031import android.content.Context;
Winson Chung67f5c8b2018-09-24 12:09:19 -070032import android.content.res.Configuration;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000033import android.graphics.Rect;
34import android.os.Handler;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000035import android.provider.Settings;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000036import android.util.Slog;
Winson Chung67f5c8b2018-09-24 12:09:19 -070037import android.view.LayoutInflater;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000038import android.view.SurfaceControl;
Winson Chung67f5c8b2018-09-24 12:09:19 -070039import android.view.View;
Evan Rosky8d1c24e2020-04-23 09:21:16 -070040import android.window.TaskOrganizer;
41import android.window.WindowContainerToken;
Wale Ogunwale57946582020-03-21 14:29:07 -070042import android.window.WindowContainerTransaction;
Wale Ogunwale568f9f412020-03-21 22:27:35 -070043import android.window.WindowOrganizer;
Gus Prevasab336792018-11-14 13:52:20 -050044
Evan Rosky95729202020-02-21 10:16:08 -080045import androidx.annotation.Nullable;
46
Evan Roskyaf9f27c2020-02-18 18:58:35 +000047import com.android.internal.policy.DividerSnapAlgorithm;
Winson Chung67f5c8b2018-09-24 12:09:19 -070048import com.android.systemui.R;
49import com.android.systemui.SystemUI;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000050import com.android.systemui.TransactionPool;
Winson Chung67f5c8b2018-09-24 12:09:19 -070051import com.android.systemui.recents.Recents;
Evan Rosky8d1c24e2020-04-23 09:21:16 -070052import com.android.systemui.shared.system.ActivityManagerWrapper;
53import com.android.systemui.shared.system.TaskStackChangeListener;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000054import com.android.systemui.statusbar.policy.KeyguardStateController;
55import com.android.systemui.wm.DisplayChangeController;
56import com.android.systemui.wm.DisplayController;
57import com.android.systemui.wm.DisplayImeController;
58import com.android.systemui.wm.DisplayLayout;
59import com.android.systemui.wm.SystemWindows;
Gus Prevasab336792018-11-14 13:52:20 -050060
Jorim Jaggi31f71702016-05-04 16:43:04 -070061import java.io.FileDescriptor;
62import java.io.PrintWriter;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000063import java.lang.ref.WeakReference;
64import java.util.ArrayList;
Dave Mankoff6c64d1f2019-11-07 17:27:50 -050065import java.util.Optional;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000066import java.util.function.Consumer;
67
68import javax.inject.Singleton;
Dave Mankoff6c64d1f2019-11-07 17:27:50 -050069
70import dagger.Lazy;
Jorim Jaggi31f71702016-05-04 16:43:04 -070071
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010072/**
73 * Controls the docked stack divider.
74 */
Evan Roskyaf9f27c2020-02-18 18:58:35 +000075@Singleton
76public class Divider extends SystemUI implements DividerView.DividerCallbacks,
77 DisplayController.OnDisplaysChangedListener {
Winson Chung67f5c8b2018-09-24 12:09:19 -070078 private static final String TAG = "Divider";
Evan Roskyaf9f27c2020-02-18 18:58:35 +000079
Evan Roskyfdc71c42020-03-13 18:23:08 -070080 static final boolean DEBUG = false;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000081
82 static final int DEFAULT_APP_TRANSITION_DURATION = 336;
Evan Rosky95729202020-02-21 10:16:08 -080083 static final float ADJUSTED_NONFOCUS_DIM = 0.3f;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000084
Dave Mankoff6c64d1f2019-11-07 17:27:50 -050085 private final Optional<Lazy<Recents>> mRecentsOptionalLazy;
Winson Chung67f5c8b2018-09-24 12:09:19 -070086
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010087 private DividerWindowManager mWindowManager;
Jorim Jaggidd98d412015-11-18 15:57:38 -080088 private DividerView mView;
Jorim Jaggia6c05d52016-05-27 00:31:21 -070089 private final DividerState mDividerState = new DividerState();
Filip Gruszczynski64cdc142015-11-29 21:10:07 -080090 private boolean mVisible = false;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -080091 private boolean mMinimized = false;
Jorim Jaggi698e7632016-04-13 21:02:22 -070092 private boolean mAdjustedForIme = false;
Matthew Nge15352e2016-12-20 15:36:29 -080093 private boolean mHomeStackResizable = false;
Jorim Jaggi2adba072016-03-03 13:43:39 +010094 private ForcedResizableInfoActivityController mForcedResizableController;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000095 private SystemWindows mSystemWindows;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000096 private DisplayController mDisplayController;
97 private DisplayImeController mImeController;
98 final TransactionPool mTransactionPool;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010099
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000100 // Keeps track of real-time split geometry including snap positions and ime adjustments
101 private SplitDisplayLayout mSplitLayout;
102
103 // Transient: this contains the layout calculated for a new rotation requested by WM. This is
104 // kept around so that we can wait for a matching configuration change and then use the exact
105 // layout that we sent back to WM.
106 private SplitDisplayLayout mRotateSplitLayout;
107
108 private Handler mHandler;
109 private KeyguardStateController mKeyguardStateController;
110
111 private final ArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners =
112 new ArrayList<>();
113
114 private SplitScreenTaskOrganizer mSplits = new SplitScreenTaskOrganizer(this);
115
116 private DisplayChangeController.OnDisplayChangingListener mRotationController =
117 (display, fromRotation, toRotation, t) -> {
Evan Roskyb8540a02020-03-25 16:30:24 -0700118 if (!mSplits.isSplitScreenSupported()) {
119 return;
120 }
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000121 DisplayLayout displayLayout =
122 new DisplayLayout(mDisplayController.getDisplayLayout(display));
123 SplitDisplayLayout sdl = new SplitDisplayLayout(mContext, displayLayout, mSplits);
124 sdl.rotateTo(toRotation);
125 mRotateSplitLayout = sdl;
126 int position = mMinimized ? mView.mSnapTargetBeforeMinimized.position
127 : mView.getCurrentPosition();
128 DividerSnapAlgorithm snap = sdl.getSnapAlgorithm();
129 final DividerSnapAlgorithm.SnapTarget target =
130 snap.calculateNonDismissingSnapTarget(position);
131 sdl.resizeSplits(target.position, t);
132
133 if (inSplitMode()) {
134 WindowManagerProxy.applyHomeTasksMinimized(sdl, mSplits.mSecondary.token, t);
135 }
136 };
137
Evan Roskyfe31c042020-03-06 19:35:48 -0800138 private class DividerImeController implements DisplayImeController.ImePositionProcessor {
139 /**
140 * These are the y positions of the top of the IME surface when it is hidden and when it is
141 * shown respectively. These are NOT necessarily the top of the visible IME itself.
142 */
143 private int mHiddenTop = 0;
144 private int mShownTop = 0;
Evan Rosky95729202020-02-21 10:16:08 -0800145
Evan Roskyfe31c042020-03-06 19:35:48 -0800146 // The following are target states (what we are curretly animating towards).
147 /**
148 * {@code true} if, at the end of the animation, the split task positions should be
149 * adjusted by height of the IME. This happens when the secondary split is the IME target.
150 */
151 private boolean mTargetAdjusted = false;
152 /**
153 * {@code true} if, at the end of the animation, the IME should be shown/visible
154 * regardless of what has focus.
155 */
156 private boolean mTargetShown = false;
Evan Roskye5fb45a2020-03-09 10:51:27 -0700157 private float mTargetPrimaryDim = 0.f;
158 private float mTargetSecondaryDim = 0.f;
Evan Rosky95729202020-02-21 10:16:08 -0800159
Evan Roskyfe31c042020-03-06 19:35:48 -0800160 // The following are the current (most recent) states set during animation
161 /** {@code true} if the secondary split has IME focus. */
162 private boolean mSecondaryHasFocus = false;
163 /** The dimming currently applied to the primary/secondary splits. */
164 private float mLastPrimaryDim = 0.f;
165 private float mLastSecondaryDim = 0.f;
166 /** The most recent y position of the top of the IME surface */
167 private int mLastAdjustTop = -1;
Evan Rosky95729202020-02-21 10:16:08 -0800168
Evan Roskyfe31c042020-03-06 19:35:48 -0800169 // The following are states reached last time an animation fully completed.
170 /** {@code true} if the IME was shown/visible by the last-completed animation. */
171 private boolean mImeWasShown = false;
172 /** {@code true} if the split positions were adjusted by the last-completed animation. */
173 private boolean mAdjusted = false;
Evan Rosky95729202020-02-21 10:16:08 -0800174
Evan Roskyfe31c042020-03-06 19:35:48 -0800175 /**
176 * When some aspect of split-screen needs to animate independent from the IME,
177 * this will be non-null and control split animation.
178 */
179 @Nullable
180 private ValueAnimator mAnimation = null;
Evan Rosky95729202020-02-21 10:16:08 -0800181
Evan Roskyc0eec052020-03-06 18:54:55 -0800182 private boolean mPaused = true;
183 private boolean mPausedTargetAdjusted = false;
184
Evan Roskyfe31c042020-03-06 19:35:48 -0800185 private boolean getSecondaryHasFocus(int displayId) {
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700186 WindowContainerToken imeSplit = TaskOrganizer.getImeTarget(displayId);
187 return imeSplit != null
188 && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder());
Evan Roskyfe31c042020-03-06 19:35:48 -0800189 }
Wale Ogunwale91ac7d72020-03-10 13:46:27 +0000190
Evan Roskyc0eec052020-03-06 18:54:55 -0800191 private void updateDimTargets() {
192 final boolean splitIsVisible = !mView.isHidden();
193 mTargetPrimaryDim = (mSecondaryHasFocus && mTargetShown && splitIsVisible)
194 ? ADJUSTED_NONFOCUS_DIM : 0.f;
195 mTargetSecondaryDim = (!mSecondaryHasFocus && mTargetShown && splitIsVisible)
196 ? ADJUSTED_NONFOCUS_DIM : 0.f;
197 }
198
Evan Roskyfe31c042020-03-06 19:35:48 -0800199 @Override
200 public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
201 boolean imeShouldShow, SurfaceControl.Transaction t) {
Evan Roskye5fb45a2020-03-09 10:51:27 -0700202 if (!inSplitMode()) {
203 return;
204 }
205 final boolean splitIsVisible = !mView.isHidden();
Evan Roskyfe31c042020-03-06 19:35:48 -0800206 mSecondaryHasFocus = getSecondaryHasFocus(displayId);
Evan Roskyc0eec052020-03-06 18:54:55 -0800207 final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
Evan Roskyfe31c042020-03-06 19:35:48 -0800208 && !mSplitLayout.mDisplayLayout.isLandscape();
209 mHiddenTop = hiddenTop;
210 mShownTop = shownTop;
211 mTargetShown = imeShouldShow;
212 if (mLastAdjustTop < 0) {
213 mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop;
Tony Huangd1cb4402020-04-27 11:36:00 +0800214 } else if (mLastAdjustTop != (imeShouldShow ? mShownTop : mHiddenTop)) {
Evan Roskyfdc71c42020-03-13 18:23:08 -0700215 if (mTargetAdjusted != targetAdjusted && targetAdjusted == mAdjusted) {
Tony Huangd1cb4402020-04-27 11:36:00 +0800216 // Check for an "interruption" of an existing animation. In this case, we
217 // need to fake-flip the last-known state direction so that the animation
218 // completes in the other direction.
219 mAdjusted = mTargetAdjusted;
220 } else if (targetAdjusted && mTargetAdjusted && mAdjusted) {
221 // Already fully adjusted for IME, but IME height has changed; so, force-start
222 // an async animation to the new IME height.
223 mAdjusted = false;
Evan Roskyfdc71c42020-03-13 18:23:08 -0700224 }
Evan Roskyfe31c042020-03-06 19:35:48 -0800225 }
Evan Roskyc0eec052020-03-06 18:54:55 -0800226 if (mPaused) {
227 mPausedTargetAdjusted = targetAdjusted;
Evan Roskyfdc71c42020-03-13 18:23:08 -0700228 if (DEBUG) Slog.d(TAG, " ime starting but paused " + dumpState());
Evan Roskyc0eec052020-03-06 18:54:55 -0800229 return;
230 }
231 mTargetAdjusted = targetAdjusted;
232 updateDimTargets();
Evan Roskyfdc71c42020-03-13 18:23:08 -0700233 if (DEBUG) Slog.d(TAG, " ime starting. vis:" + splitIsVisible + " " + dumpState());
Evan Roskyfe31c042020-03-06 19:35:48 -0800234 if (mAnimation != null || (mImeWasShown && imeShouldShow
235 && mTargetAdjusted != mAdjusted)) {
236 // We need to animate adjustment independently of the IME position, so
237 // start our own animation to drive adjustment. This happens when a
238 // different split's editor has gained focus while the IME is still visible.
239 startAsyncAnimation();
240 }
Evan Roskye5fb45a2020-03-09 10:51:27 -0700241 if (splitIsVisible) {
242 // If split is hidden, we don't want to trigger any relayouts that would cause the
243 // divider to show again.
244 updateImeAdjustState();
245 }
Evan Roskyfe31c042020-03-06 19:35:48 -0800246 }
247
248 private void updateImeAdjustState() {
249 // Reposition the server's secondary split position so that it evaluates
250 // insets properly.
251 WindowContainerTransaction wct = new WindowContainerTransaction();
252 if (mTargetAdjusted) {
253 mSplitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop);
254 wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mAdjustedSecondary);
255 // "Freeze" the configuration size so that the app doesn't get a config
256 // or relaunch. This is required because normally nav-bar contributes
257 // to configuration bounds (via nondecorframe).
258 Rect adjustAppBounds = new Rect(mSplits.mSecondary.configuration
259 .windowConfiguration.getAppBounds());
260 adjustAppBounds.offset(0, mSplitLayout.mAdjustedSecondary.top
261 - mSplitLayout.mSecondary.top);
262 wct.setAppBounds(mSplits.mSecondary.token, adjustAppBounds);
263 wct.setScreenSizeDp(mSplits.mSecondary.token,
264 mSplits.mSecondary.configuration.screenWidthDp,
265 mSplits.mSecondary.configuration.screenHeightDp);
Evan Roskye067ddf2020-04-24 18:28:25 -0700266
267 wct.setBounds(mSplits.mPrimary.token, mSplitLayout.mAdjustedPrimary);
268 adjustAppBounds = new Rect(mSplits.mPrimary.configuration
269 .windowConfiguration.getAppBounds());
270 adjustAppBounds.offset(0, mSplitLayout.mAdjustedPrimary.top
271 - mSplitLayout.mPrimary.top);
272 wct.setAppBounds(mSplits.mPrimary.token, adjustAppBounds);
273 wct.setScreenSizeDp(mSplits.mPrimary.token,
274 mSplits.mPrimary.configuration.screenWidthDp,
275 mSplits.mPrimary.configuration.screenHeightDp);
Evan Roskyfe31c042020-03-06 19:35:48 -0800276 } else {
277 wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mSecondary);
278 wct.setAppBounds(mSplits.mSecondary.token, null);
279 wct.setScreenSizeDp(mSplits.mSecondary.token,
280 SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
Evan Roskye067ddf2020-04-24 18:28:25 -0700281 wct.setBounds(mSplits.mPrimary.token, mSplitLayout.mPrimary);
282 wct.setAppBounds(mSplits.mPrimary.token, null);
283 wct.setScreenSizeDp(mSplits.mPrimary.token,
284 SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
Evan Roskyfe31c042020-03-06 19:35:48 -0800285 }
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700286
287 WindowOrganizer.applyTransaction(wct);
Evan Roskyfe31c042020-03-06 19:35:48 -0800288
289 // Update all the adjusted-for-ime states
Evan Roskyf64f5da2020-03-16 13:47:48 -0700290 if (!mPaused) {
291 mView.setAdjustedForIme(mTargetShown, mTargetShown
292 ? DisplayImeController.ANIMATION_DURATION_SHOW_MS
293 : DisplayImeController.ANIMATION_DURATION_HIDE_MS);
294 }
295 setAdjustedForIme(mTargetShown && !mPaused);
Evan Roskyfe31c042020-03-06 19:35:48 -0800296 }
297
298 @Override
299 public void onImePositionChanged(int displayId, int imeTop,
300 SurfaceControl.Transaction t) {
Evan Roskyc0eec052020-03-06 18:54:55 -0800301 if (mAnimation != null || !inSplitMode() || mPaused) {
Evan Roskyfe31c042020-03-06 19:35:48 -0800302 // Not synchronized with IME anymore, so return.
303 return;
304 }
305 final float fraction = ((float) imeTop - mHiddenTop) / (mShownTop - mHiddenTop);
306 final float progress = mTargetShown ? fraction : 1.f - fraction;
307 onProgress(progress, t);
308 }
309
310 @Override
311 public void onImeEndPositioning(int displayId, boolean cancelled,
312 SurfaceControl.Transaction t) {
Evan Roskyc0eec052020-03-06 18:54:55 -0800313 if (mAnimation != null || !inSplitMode() || mPaused) {
Evan Roskyfe31c042020-03-06 19:35:48 -0800314 // Not synchronized with IME anymore, so return.
315 return;
316 }
317 onEnd(cancelled, t);
318 }
319
320 private void onProgress(float progress, SurfaceControl.Transaction t) {
Evan Roskyc0eec052020-03-06 18:54:55 -0800321 if (mTargetAdjusted != mAdjusted && !mPaused) {
Evan Roskyfe31c042020-03-06 19:35:48 -0800322 final float fraction = mTargetAdjusted ? progress : 1.f - progress;
323 mLastAdjustTop = (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop);
324 mSplitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop);
325 mView.resizeSplitSurfaces(t, mSplitLayout.mAdjustedPrimary,
326 mSplitLayout.mAdjustedSecondary);
327 }
328 final float invProg = 1.f - progress;
Evan Roskyfe31c042020-03-06 19:35:48 -0800329 mView.setResizeDimLayer(t, true /* primary */,
Evan Roskye5fb45a2020-03-09 10:51:27 -0700330 mLastPrimaryDim * invProg + progress * mTargetPrimaryDim);
Evan Roskyfe31c042020-03-06 19:35:48 -0800331 mView.setResizeDimLayer(t, false /* primary */,
Evan Roskye5fb45a2020-03-09 10:51:27 -0700332 mLastSecondaryDim * invProg + progress * mTargetSecondaryDim);
Evan Roskyfe31c042020-03-06 19:35:48 -0800333 }
334
335 private void onEnd(boolean cancelled, SurfaceControl.Transaction t) {
336 if (!cancelled) {
337 onProgress(1.f, t);
338 mAdjusted = mTargetAdjusted;
339 mImeWasShown = mTargetShown;
340 mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop;
Evan Roskye5fb45a2020-03-09 10:51:27 -0700341 mLastPrimaryDim = mTargetPrimaryDim;
342 mLastSecondaryDim = mTargetSecondaryDim;
Evan Roskyfe31c042020-03-06 19:35:48 -0800343 }
344 }
345
346 private void startAsyncAnimation() {
347 if (mAnimation != null) {
348 mAnimation.cancel();
349 }
350 mAnimation = ValueAnimator.ofFloat(0.f, 1.f);
351 mAnimation.setDuration(DisplayImeController.ANIMATION_DURATION_SHOW_MS);
352 if (mTargetAdjusted != mAdjusted) {
353 final float fraction =
354 ((float) mLastAdjustTop - mHiddenTop) / (mShownTop - mHiddenTop);
355 final float progress = mTargetAdjusted ? fraction : 1.f - fraction;
356 mAnimation.setCurrentFraction(progress);
357 }
358
359 mAnimation.addUpdateListener(animation -> {
360 SurfaceControl.Transaction t = mTransactionPool.acquire();
361 float value = (float) animation.getAnimatedValue();
362 onProgress(value, t);
363 t.apply();
364 mTransactionPool.release(t);
365 });
366 mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR);
367 mAnimation.addListener(new AnimatorListenerAdapter() {
368 private boolean mCancel = false;
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000369 @Override
Evan Roskyfe31c042020-03-06 19:35:48 -0800370 public void onAnimationCancel(Animator animation) {
371 mCancel = true;
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000372 }
Wale Ogunwale91ac7d72020-03-10 13:46:27 +0000373 @Override
Evan Roskyfe31c042020-03-06 19:35:48 -0800374 public void onAnimationEnd(Animator animation) {
375 SurfaceControl.Transaction t = mTransactionPool.acquire();
376 onEnd(mCancel, t);
377 t.apply();
378 mTransactionPool.release(t);
379 mAnimation = null;
Wale Ogunwale91ac7d72020-03-10 13:46:27 +0000380 }
Evan Roskyfe31c042020-03-06 19:35:48 -0800381 });
382 mAnimation.start();
383 }
Evan Roskyc0eec052020-03-06 18:54:55 -0800384
Evan Roskyfdc71c42020-03-13 18:23:08 -0700385 private String dumpState() {
386 return "top:" + mHiddenTop + "->" + mShownTop
387 + " adj:" + mAdjusted + "->" + mTargetAdjusted + "(" + mLastAdjustTop + ")"
388 + " shw:" + mImeWasShown + "->" + mTargetShown
389 + " dims:" + mLastPrimaryDim + "," + mLastSecondaryDim
390 + "->" + mTargetPrimaryDim + "," + mTargetSecondaryDim
391 + " shf:" + mSecondaryHasFocus + " desync:" + (mAnimation != null)
392 + " paus:" + mPaused + "[" + mPausedTargetAdjusted + "]";
393 }
394
Evan Roskyc0eec052020-03-06 18:54:55 -0800395 /** Completely aborts/resets adjustment state */
396 public void pause(int displayId) {
Evan Roskyfdc71c42020-03-13 18:23:08 -0700397 if (DEBUG) Slog.d(TAG, "ime pause posting " + dumpState());
Evan Roskyc0eec052020-03-06 18:54:55 -0800398 mHandler.post(() -> {
Evan Roskyfdc71c42020-03-13 18:23:08 -0700399 if (DEBUG) Slog.d(TAG, "ime pause run posted " + dumpState());
400 if (mPaused) {
401 return;
402 }
Evan Roskyc0eec052020-03-06 18:54:55 -0800403 mPaused = true;
404 mPausedTargetAdjusted = mTargetAdjusted;
405 mTargetAdjusted = false;
406 mTargetPrimaryDim = mTargetSecondaryDim = 0.f;
407 updateImeAdjustState();
408 startAsyncAnimation();
Evan Roskyf64f5da2020-03-16 13:47:48 -0700409 if (mAnimation != null) {
410 mAnimation.end();
411 }
Evan Roskyc0eec052020-03-06 18:54:55 -0800412 });
413 }
414
415 public void resume(int displayId) {
Evan Roskyfdc71c42020-03-13 18:23:08 -0700416 if (DEBUG) Slog.d(TAG, "ime resume posting " + dumpState());
Evan Roskyc0eec052020-03-06 18:54:55 -0800417 mHandler.post(() -> {
Evan Roskyfdc71c42020-03-13 18:23:08 -0700418 if (DEBUG) Slog.d(TAG, "ime resume run posted " + dumpState());
419 if (!mPaused) {
420 return;
421 }
Evan Roskyc0eec052020-03-06 18:54:55 -0800422 mPaused = false;
423 mTargetAdjusted = mPausedTargetAdjusted;
424 updateDimTargets();
Evan Roskyfdc71c42020-03-13 18:23:08 -0700425 if ((mTargetAdjusted != mAdjusted) && !mMinimized && mView != null) {
Evan Roskyc0eec052020-03-06 18:54:55 -0800426 // End unminimize animations since they conflict with adjustment animations.
427 mView.finishAnimations();
428 }
429 updateImeAdjustState();
430 startAsyncAnimation();
431 });
432 }
Evan Roskyfe31c042020-03-06 19:35:48 -0800433 }
434 private final DividerImeController mImePositionProcessor = new DividerImeController();
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000435
Evan Rosky8d1c24e2020-04-23 09:21:16 -0700436 private TaskStackChangeListener mActivityRestartListener = new TaskStackChangeListener() {
437 @Override
438 public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
439 boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
440 if (!wasVisible || task.configuration.windowConfiguration.getWindowingMode()
441 != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY || !mSplits.isSplitScreenSupported()) {
442 return;
443 }
444
445 if (isMinimized()) {
446 onUndockingTask();
447 }
448 }
449 };
450
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000451 public Divider(Context context, Optional<Lazy<Recents>> recentsOptionalLazy,
452 DisplayController displayController, SystemWindows systemWindows,
453 DisplayImeController imeController, Handler handler,
454 KeyguardStateController keyguardStateController, TransactionPool transactionPool) {
Dave Mankoffa5d8a392019-10-10 12:21:09 -0400455 super(context);
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000456 mDisplayController = displayController;
457 mSystemWindows = systemWindows;
458 mImeController = imeController;
459 mHandler = handler;
460 mKeyguardStateController = keyguardStateController;
Dave Mankoff6c64d1f2019-11-07 17:27:50 -0500461 mRecentsOptionalLazy = recentsOptionalLazy;
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000462 mForcedResizableController = new ForcedResizableInfoActivityController(context, this);
463 mTransactionPool = transactionPool;
Dave Mankoffa5d8a392019-10-10 12:21:09 -0400464 }
465
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100466 @Override
467 public void start() {
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000468 mWindowManager = new DividerWindowManager(mSystemWindows);
469 mDisplayController.addDisplayWindowListener(this);
470 // Hide the divider when keyguard is showing. Even though keyguard/statusbar is above
471 // everything, it is actually transparent except for notifications, so we still need to
472 // hide any surfaces that are below it.
473 // TODO(b/148906453): Figure out keyguard dismiss animation for divider view.
474 mKeyguardStateController.addCallback(new KeyguardStateController.Callback() {
475 @Override
476 public void onUnlockedChanged() {
477
478 }
479
480 @Override
481 public void onKeyguardShowingChanged() {
482 if (!inSplitMode() || mView == null) {
483 return;
484 }
485 mView.setHidden(mKeyguardStateController.isShowing());
486 }
487
488 @Override
489 public void onKeyguardFadingAwayChanged() {
490
491 }
492 });
493 // Don't initialize the divider or anything until we get the default display.
Evan Roskybed2d1b2019-11-05 10:26:24 -0800494 }
495
496 @Override
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000497 public void onDisplayAdded(int displayId) {
498 if (displayId != DEFAULT_DISPLAY) {
499 return;
500 }
501 mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
502 mDisplayController.getDisplayLayout(displayId), mSplits);
503 mImeController.addPositionProcessor(mImePositionProcessor);
504 mDisplayController.addDisplayChangingController(mRotationController);
Evan Roskyb8540a02020-03-25 16:30:24 -0700505 if (!ActivityTaskManager.supportsSplitScreenMultiWindow(mContext)) {
506 removeDivider();
507 return;
508 }
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000509 try {
chaviwda7b3c22020-04-24 11:25:08 -0700510 mSplits.init();
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000511 // Set starting tile bounds based on middle target
512 final WindowContainerTransaction tct = new WindowContainerTransaction();
513 int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
514 mSplitLayout.resizeSplits(midPos, tct);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700515 WindowOrganizer.applyTransaction(tct);
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000516 } catch (Exception e) {
517 Slog.e(TAG, "Failed to register docked stack listener", e);
Evan Roskyb8540a02020-03-25 16:30:24 -0700518 removeDivider();
519 return;
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000520 }
Evan Rosky8d1c24e2020-04-23 09:21:16 -0700521 ActivityManagerWrapper.getInstance().registerTaskStackListener(mActivityRestartListener);
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000522 }
523
524 @Override
525 public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
Evan Roskyb8540a02020-03-25 16:30:24 -0700526 if (displayId != DEFAULT_DISPLAY || !mSplits.isSplitScreenSupported()) {
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000527 return;
528 }
529 mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
530 mDisplayController.getDisplayLayout(displayId), mSplits);
531 if (mRotateSplitLayout == null) {
532 int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
533 final WindowContainerTransaction tct = new WindowContainerTransaction();
534 mSplitLayout.resizeSplits(midPos, tct);
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700535 WindowOrganizer.applyTransaction(tct);
536 } else if (mSplitLayout.mDisplayLayout.rotation()
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000537 == mRotateSplitLayout.mDisplayLayout.rotation()) {
538 mSplitLayout.mPrimary = new Rect(mRotateSplitLayout.mPrimary);
539 mSplitLayout.mSecondary = new Rect(mRotateSplitLayout.mSecondary);
540 mRotateSplitLayout = null;
541 }
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100542 update(newConfig);
543 }
544
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000545 Handler getHandler() {
546 return mHandler;
547 }
548
Jorim Jaggidd98d412015-11-18 15:57:38 -0800549 public DividerView getView() {
550 return mView;
551 }
552
Matthew Ng8d372882016-12-20 11:06:49 -0800553 public boolean isMinimized() {
554 return mMinimized;
555 }
556
Matthew Ngfb692ac2017-02-02 14:02:56 -0800557 public boolean isHomeStackResizable() {
558 return mHomeStackResizable;
559 }
560
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000561 /** {@code true} if this is visible */
562 public boolean inSplitMode() {
563 return mView != null && mView.getVisibility() == View.VISIBLE;
564 }
565
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100566 private void addDivider(Configuration configuration) {
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000567 Context dctx = mDisplayController.getDisplayContext(mContext.getDisplayId());
Jorim Jaggidd98d412015-11-18 15:57:38 -0800568 mView = (DividerView)
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000569 LayoutInflater.from(dctx).inflate(R.layout.docked_stack_divider, null);
570 DisplayLayout displayLayout = mDisplayController.getDisplayLayout(mContext.getDisplayId());
571 mView.injectDependencies(mWindowManager, mDividerState, this, mSplits, mSplitLayout);
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800572 mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
Matthew Nge15352e2016-12-20 15:36:29 -0800573 mView.setMinimizedDockStack(mMinimized, mHomeStackResizable);
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000574 final int size = dctx.getResources().getDimensionPixelSize(
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700575 com.android.internal.R.dimen.docked_stack_divider_thickness);
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100576 final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000577 final int width = landscape ? size : displayLayout.width();
578 final int height = landscape ? displayLayout.height() : size;
579 mWindowManager.add(mView, width, height, mContext.getDisplayId());
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100580 }
581
582 private void removeDivider() {
Wale Ogunwale15ba1512017-06-06 08:31:17 -0700583 if (mView != null) {
584 mView.onDividerRemoved();
585 }
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100586 mWindowManager.remove();
587 }
588
589 private void update(Configuration configuration) {
Tony Huangdf3cfc12020-04-29 15:47:53 +0800590 final boolean isDividerHidden = mView != null && mView.isHidden();
591
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100592 removeDivider();
593 addDivider(configuration);
Tony Huangdf3cfc12020-04-29 15:47:53 +0800594
Vishnu Nair4880a302020-05-08 11:05:58 -0700595 if (mMinimized) {
596 mView.setMinimizedDockStack(true, mHomeStackResizable);
597 updateTouchable();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800598 }
Vishnu Nair4880a302020-05-08 11:05:58 -0700599 mView.setHidden(isDividerHidden);
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100600 }
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800601
chaviwda7b3c22020-04-24 11:25:08 -0700602 void onTaskVanished() {
603 mHandler.post(this::removeDivider);
604 }
605
606 void onTasksReady() {
607 mHandler.post(() -> update(mDisplayController.getDisplayContext(
608 mContext.getDisplayId()).getResources().getConfiguration()));
609 }
610
Vishnu Nair4880a302020-05-08 11:05:58 -0700611 private void updateVisibility(final boolean visible) {
Evan Roskyfdc71c42020-03-13 18:23:08 -0700612 if (DEBUG) Slog.d(TAG, "Updating visibility " + mVisible + "->" + visible);
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000613 if (mVisible != visible) {
614 mVisible = visible;
615 mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
Jorim Jaggief92d6f2016-03-25 22:07:16 -0700616
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000617 if (visible) {
618 mView.enterSplitMode(mHomeStackResizable);
619 // Update state because animations won't finish.
620 mView.setMinimizedDockStack(mMinimized, mHomeStackResizable);
621 } else {
622 mView.exitSplitMode();
623 // un-minimize so that next entry triggers minimize anim.
624 mView.setMinimizedDockStack(false /* minimized */, mHomeStackResizable);
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800625 }
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000626 // Notify existence listeners
627 synchronized (mDockedStackExistsListeners) {
628 mDockedStackExistsListeners.removeIf(wf -> {
629 Consumer<Boolean> l = wf.get();
630 if (l != null) l.accept(visible);
631 return l == null;
632 });
633 }
634 }
635 }
636
Louis Chang98578b72020-04-28 15:22:39 +0800637 void onSplitDismissed() {
638 mMinimized = false;
639 updateVisibility(false /* visible */);
Vishnu Nair4880a302020-05-08 11:05:58 -0700640 removeDivider();
Louis Chang98578b72020-04-28 15:22:39 +0800641 }
642
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000643 /** Switch to minimized state if appropriate */
644 public void setMinimized(final boolean minimized) {
Evan Roskyfdc71c42020-03-13 18:23:08 -0700645 if (DEBUG) Slog.d(TAG, "posting ext setMinimized " + minimized + " vis:" + mVisible);
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000646 mHandler.post(() -> {
Evan Roskyfdc71c42020-03-13 18:23:08 -0700647 if (DEBUG) Slog.d(TAG, "run posted ext setMinimized " + minimized + " vis:" + mVisible);
648 if (!mVisible) {
649 return;
650 }
Evan Roskyfe31c042020-03-06 19:35:48 -0800651 setHomeMinimized(minimized, mHomeStackResizable);
Wale Ogunwale91ac7d72020-03-10 13:46:27 +0000652 });
Evan Rosky877739b2020-03-06 19:35:48 -0800653 }
654
Evan Roskyfe31c042020-03-06 19:35:48 -0800655 private void setHomeMinimized(final boolean minimized, boolean homeStackResizable) {
Evan Roskyfdc71c42020-03-13 18:23:08 -0700656 if (DEBUG) {
657 Slog.d(TAG, "setHomeMinimized min:" + mMinimized + "->" + minimized + " hrsz:"
658 + mHomeStackResizable + "->" + homeStackResizable + " split:" + inSplitMode());
659 }
Evan Roskyfe31c042020-03-06 19:35:48 -0800660 WindowContainerTransaction wct = new WindowContainerTransaction();
Evan Roskyf64f5da2020-03-16 13:47:48 -0700661 final boolean minimizedChanged = mMinimized != minimized;
Evan Roskyfe31c042020-03-06 19:35:48 -0800662 // Update minimized state
Evan Roskyf64f5da2020-03-16 13:47:48 -0700663 if (minimizedChanged) {
Evan Roskyfe31c042020-03-06 19:35:48 -0800664 mMinimized = minimized;
665 }
666 // Always set this because we could be entering split when mMinimized is already true
667 wct.setFocusable(mSplits.mPrimary.token, !mMinimized);
668
669 // Update home-stack resizability
Evan Roskyf64f5da2020-03-16 13:47:48 -0700670 final boolean homeResizableChanged = mHomeStackResizable != homeStackResizable;
671 if (homeResizableChanged) {
Evan Roskyfe31c042020-03-06 19:35:48 -0800672 mHomeStackResizable = homeStackResizable;
673 if (inSplitMode()) {
674 WindowManagerProxy.applyHomeTasksMinimized(
675 mSplitLayout, mSplits.mSecondary.token, wct);
676 }
677 }
678
679 // Sync state to DividerView if it exists.
680 if (mView != null) {
Evan Roskyc0eec052020-03-06 18:54:55 -0800681 final int displayId = mView.getDisplay() != null
682 ? mView.getDisplay().getDisplayId() : DEFAULT_DISPLAY;
683 // pause ime here (before updateMinimizedDockedStack)
684 if (mMinimized) {
685 mImePositionProcessor.pause(displayId);
686 }
Evan Roskyf64f5da2020-03-16 13:47:48 -0700687 if (minimizedChanged || homeResizableChanged) {
688 // This conflicts with IME adjustment, so only call it when things change.
689 mView.setMinimizedDockStack(minimized, getAnimDuration(), homeStackResizable);
690 }
Evan Roskyc0eec052020-03-06 18:54:55 -0800691 if (!mMinimized) {
692 // afterwards so it can end any animations started in view
693 mImePositionProcessor.resume(displayId);
694 }
Evan Roskyfe31c042020-03-06 19:35:48 -0800695 }
696 updateTouchable();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700697 WindowOrganizer.applyTransaction(wct);
Evan Roskyfe31c042020-03-06 19:35:48 -0800698 }
699
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000700 void setAdjustedForIme(boolean adjustedForIme) {
701 if (mAdjustedForIme == adjustedForIme) {
702 return;
703 }
704 mAdjustedForIme = adjustedForIme;
705 updateTouchable();
Jorim Jaggi2adba072016-03-03 13:43:39 +0100706 }
707
Jorim Jaggi698e7632016-04-13 21:02:22 -0700708 private void updateTouchable() {
Matthew Nge15352e2016-12-20 15:36:29 -0800709 mWindowManager.setTouchable((mHomeStackResizable || !mMinimized) && !mAdjustedForIme);
Jorim Jaggi698e7632016-04-13 21:02:22 -0700710 }
711
Winson Chung60fa6472017-06-12 15:30:14 -0700712 /**
Winson Chung67f5c8b2018-09-24 12:09:19 -0700713 * Workaround for b/62528361, at the time recents has drawn, it may happen before a
Winson Chung60fa6472017-06-12 15:30:14 -0700714 * configuration change to the Divider, and internally, the event will be posted to the
715 * subscriber, or DividerView, which has been removed and prevented from resizing. Instead,
716 * register the event handler here and proxy the event to the current DividerView.
717 */
Winson Chung67f5c8b2018-09-24 12:09:19 -0700718 public void onRecentsDrawn() {
Winson Chung60fa6472017-06-12 15:30:14 -0700719 if (mView != null) {
720 mView.onRecentsDrawn();
721 }
722 }
723
Winson Chung67f5c8b2018-09-24 12:09:19 -0700724 public void onUndockingTask() {
725 if (mView != null) {
726 mView.onUndockingTask();
727 }
728 }
729
730 public void onDockedFirstAnimationFrame() {
731 if (mView != null) {
732 mView.onDockedFirstAnimationFrame();
733 }
734 }
735
736 public void onDockedTopTask() {
737 if (mView != null) {
738 mView.onDockedTopTask();
739 }
740 }
741
742 public void onAppTransitionFinished() {
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000743 if (mView == null) {
744 return;
745 }
Winson Chung67f5c8b2018-09-24 12:09:19 -0700746 mForcedResizableController.onAppTransitionFinished();
747 }
748
749 @Override
750 public void onDraggingStart() {
751 mForcedResizableController.onDraggingStart();
752 }
753
754 @Override
755 public void onDraggingEnd() {
756 mForcedResizableController.onDraggingEnd();
757 }
758
759 @Override
760 public void growRecents() {
Dave Mankoff6c64d1f2019-11-07 17:27:50 -0500761 mRecentsOptionalLazy.ifPresent(recentsLazy -> recentsLazy.get().growRecents());
Winson Chung67f5c8b2018-09-24 12:09:19 -0700762 }
763
Jorim Jaggi31f71702016-05-04 16:43:04 -0700764 @Override
765 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
766 pw.print(" mVisible="); pw.println(mVisible);
767 pw.print(" mMinimized="); pw.println(mMinimized);
768 pw.print(" mAdjustedForIme="); pw.println(mAdjustedForIme);
769 }
770
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000771 long getAnimDuration() {
772 float transitionScale = Settings.Global.getFloat(mContext.getContentResolver(),
773 Settings.Global.TRANSITION_ANIMATION_SCALE,
774 mContext.getResources().getFloat(
775 com.android.internal.R.dimen
776 .config_appTransitionAnimationDurationScaleDefault));
777 final long transitionDuration = DEFAULT_APP_TRANSITION_DURATION;
778 return (long) (transitionDuration * transitionScale);
779 }
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100780
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000781 /** Register a listener that gets called whenever the existence of the divider changes */
782 public void registerInSplitScreenListener(Consumer<Boolean> listener) {
783 listener.accept(inSplitMode());
784 synchronized (mDockedStackExistsListeners) {
785 mDockedStackExistsListeners.add(new WeakReference<>(listener));
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800786 }
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000787 }
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100788
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000789 void startEnterSplit() {
Vishnu Nair4880a302020-05-08 11:05:58 -0700790 update(mDisplayController.getDisplayContext(
791 mContext.getDisplayId()).getResources().getConfiguration());
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000792 // Set resizable directly here because applyEnterSplit already resizes home stack.
793 mHomeStackResizable = WindowManagerProxy.applyEnterSplit(mSplits, mSplitLayout);
794 }
795
796 void ensureMinimizedSplit() {
Evan Roskyfe31c042020-03-06 19:35:48 -0800797 setHomeMinimized(true /* minimized */, mSplits.mSecondary.isResizable());
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000798 if (!inSplitMode()) {
799 // Wasn't in split-mode yet, so enter now.
800 if (DEBUG) {
Evan Roskyfdc71c42020-03-13 18:23:08 -0700801 Slog.d(TAG, " entering split mode with minimized=true");
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000802 }
803 updateVisibility(true /* visible */);
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100804 }
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000805 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800806
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000807 void ensureNormalSplit() {
Evan Roskyfe31c042020-03-06 19:35:48 -0800808 setHomeMinimized(false /* minimized */, mHomeStackResizable);
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000809 if (!inSplitMode()) {
810 // Wasn't in split-mode, so enter now.
811 if (DEBUG) {
Evan Roskyfdc71c42020-03-13 18:23:08 -0700812 Slog.d(TAG, " enter split mode unminimized ");
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000813 }
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000814 updateVisibility(true /* visible */);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800815 }
Filip Gruszczynski64cdc142015-11-29 21:10:07 -0800816 }
Evan Rosky2af969c2020-05-08 16:26:31 +0000817
818 /** @return the container token for the secondary split root task. */
819 public WindowContainerToken getSecondaryRoot() {
820 if (mSplits == null || mSplits.mSecondary == null) {
821 return null;
822 }
823 return mSplits.mSecondary.token;
824 }
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100825}