blob: 989e8f23693a6278274c2fecd626e99f46770dda [file] [log] [blame]
Winson Chung55893332017-02-17 17:13:10 -08001/*
2 * Copyright (C) 2017 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
19import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
Winson Chung9c844412017-04-27 17:36:41 -070020
Winson Chung8bca9e42017-04-16 15:59:43 -070021import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
22import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
23import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
24import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState;
Winson Chung55893332017-02-17 17:13:10 -080025
26import android.app.RemoteAction;
27import android.graphics.Rect;
28
29import com.android.server.UiThread;
30
31import java.util.List;
32
33/**
34 * Controller for the pinned stack container. See {@link StackWindowController}.
35 */
36public class PinnedStackWindowController extends StackWindowController {
37
Winson Chunga71febe2017-05-22 11:14:22 -070038 private Rect mTmpFromBounds = new Rect();
39 private Rect mTmpToBounds = new Rect();
Winson Chung55893332017-02-17 17:13:10 -080040
Winson Chung3a682872017-04-10 14:38:05 -070041 public PinnedStackWindowController(int stackId, PinnedStackWindowListener listener,
42 int displayId, boolean onTop, Rect outBounds) {
Winson Chung55893332017-02-17 17:13:10 -080043 super(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
44 }
45
46 /**
Winson Chunga71febe2017-05-22 11:14:22 -070047 * @return the {@param currentStackBounds} transformed to the give {@param aspectRatio}. If
48 * {@param currentStackBounds} is null, then the {@param aspectRatio} is applied to the
49 * default bounds.
Winson Chung9c844412017-04-27 17:36:41 -070050 */
Winson Chunga71febe2017-05-22 11:14:22 -070051 public Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) {
Winson Chung9c844412017-04-27 17:36:41 -070052 synchronized (mWindowMap) {
53 if (!mService.mSupportsPictureInPicture || mContainer == null) {
54 return null;
55 }
56
Winson Chung9c844412017-04-27 17:36:41 -070057 final DisplayContent displayContent = mContainer.getDisplayContent();
58 if (displayContent == null) {
59 return null;
60 }
61
62 final PinnedStackController pinnedStackController =
63 displayContent.getPinnedStackController();
Winson Chunga71febe2017-05-22 11:14:22 -070064 if (stackBounds == null) {
65 // Calculate the aspect ratio bounds from the default bounds
Winson Chung9c844412017-04-27 17:36:41 -070066 stackBounds = pinnedStackController.getDefaultBounds();
67 }
68
69 if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) {
Winson Chunga71febe2017-05-22 11:14:22 -070070 return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio,
71 true /* useCurrentMinEdgeSize */);
Winson Chung9c844412017-04-27 17:36:41 -070072 } else {
73 return stackBounds;
74 }
75 }
76 }
77
78 /**
Winson Chung55893332017-02-17 17:13:10 -080079 * Animates the pinned stack.
80 */
Winson Chung8bca9e42017-04-16 15:59:43 -070081 public void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds,
Winson Chunge7ba6862017-05-24 12:13:33 -070082 int animationDuration, boolean fromFullscreen) {
Winson Chung55893332017-02-17 17:13:10 -080083 synchronized (mWindowMap) {
84 if (mContainer == null) {
85 throw new IllegalArgumentException("Pinned stack container not found :(");
86 }
87
Winson Chung8bca9e42017-04-16 15:59:43 -070088 // Get the from-bounds
89 final Rect fromBounds = new Rect();
90 mContainer.getBounds(fromBounds);
Winson Chung55893332017-02-17 17:13:10 -080091
Winson Chung8bca9e42017-04-16 15:59:43 -070092 // Get non-null fullscreen to-bounds for animating if the bounds are null
93 @SchedulePipModeChangedState int schedulePipModeChangedState =
94 NO_PIP_MODE_CHANGED_CALLBACKS;
95 final boolean toFullscreen = toBounds == null;
96 if (toFullscreen) {
Winson Chunge7ba6862017-05-24 12:13:33 -070097 if (fromFullscreen) {
Winson Chung8bca9e42017-04-16 15:59:43 -070098 throw new IllegalArgumentException("Should not defer scheduling PiP mode"
99 + " change on animation to fullscreen.");
100 }
101 schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_START;
102
Winson Chunga71febe2017-05-22 11:14:22 -0700103 mService.getStackBounds(FULLSCREEN_WORKSPACE_STACK_ID, mTmpToBounds);
104 if (!mTmpToBounds.isEmpty()) {
Winson Chung8bca9e42017-04-16 15:59:43 -0700105 // If there is a fullscreen bounds, use that
Winson Chunga71febe2017-05-22 11:14:22 -0700106 toBounds = new Rect(mTmpToBounds);
Winson Chung8bca9e42017-04-16 15:59:43 -0700107 } else {
108 // Otherwise, use the display bounds
109 toBounds = new Rect();
110 mContainer.getDisplayContent().getLogicalDisplayRect(toBounds);
111 }
Winson Chunge7ba6862017-05-24 12:13:33 -0700112 } else if (fromFullscreen) {
Winson Chung8bca9e42017-04-16 15:59:43 -0700113 schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
Winson Chung55893332017-02-17 17:13:10 -0800114 }
115
Winson Chung8bca9e42017-04-16 15:59:43 -0700116 mContainer.setAnimationFinalBounds(sourceHintBounds, toBounds, toFullscreen);
117
118 final Rect finalToBounds = toBounds;
119 final @SchedulePipModeChangedState int finalSchedulePipModeChangedState =
120 schedulePipModeChangedState;
Winson Chunge7ba6862017-05-24 12:13:33 -0700121 mService.mBoundsAnimationController.getHandler().post(() -> {
Winson Chungbb250542017-03-20 20:06:46 -0700122 if (mContainer == null) {
123 return;
124 }
Winson Chung8bca9e42017-04-16 15:59:43 -0700125 mService.mBoundsAnimationController.animateBounds(mContainer, fromBounds,
126 finalToBounds, animationDuration, finalSchedulePipModeChangedState,
Winson Chunge7ba6862017-05-24 12:13:33 -0700127 fromFullscreen, toFullscreen);
Winson Chung55893332017-02-17 17:13:10 -0800128 });
129 }
130 }
131
132 /**
133 * Sets the current picture-in-picture aspect ratio.
134 */
135 public void setPictureInPictureAspectRatio(float aspectRatio) {
136 synchronized (mWindowMap) {
137 if (!mService.mSupportsPictureInPicture || mContainer == null) {
138 return;
139 }
140
Winson Chung55893332017-02-17 17:13:10 -0800141 final PinnedStackController pinnedStackController =
142 mContainer.getDisplayContent().getPinnedStackController();
Winson Chungc95ff842017-03-21 10:20:20 -0700143
144 if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) != 0) {
Winson Chunga71febe2017-05-22 11:14:22 -0700145 mContainer.getAnimationOrCurrentBounds(mTmpFromBounds);
146 mTmpToBounds.set(mTmpFromBounds);
147 getPictureInPictureBounds(aspectRatio, mTmpToBounds);
148 if (!mTmpToBounds.equals(mTmpFromBounds)) {
149 animateResizePinnedStack(mTmpToBounds, null /* sourceHintBounds */,
Winson Chunge7ba6862017-05-24 12:13:33 -0700150 -1 /* duration */, false /* fromFullscreen */);
Winson Chung08f81892017-03-02 15:40:51 -0800151 }
Winson Chungc95ff842017-03-21 10:20:20 -0700152 pinnedStackController.setAspectRatio(
153 pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
154 ? aspectRatio : -1f);
155 }
Winson Chung55893332017-02-17 17:13:10 -0800156 }
157 }
158
159 /**
160 * Sets the current picture-in-picture actions.
161 */
162 public void setPictureInPictureActions(List<RemoteAction> actions) {
163 synchronized (mWindowMap) {
164 if (!mService.mSupportsPictureInPicture || mContainer == null) {
165 return;
166 }
167
168 mContainer.getDisplayContent().getPinnedStackController().setActions(actions);
169 }
170 }
171
172 /**
Winson Chung8bca9e42017-04-16 15:59:43 -0700173 * @return whether the multi-window mode change should be deferred as a part of a transition
174 * from fullscreen to non-fullscreen bounds.
Winson Chung02e71932017-03-10 10:08:17 -0800175 */
Winson Chung8bca9e42017-04-16 15:59:43 -0700176 public boolean deferScheduleMultiWindowModeChanged() {
177 synchronized(mWindowMap) {
178 return mContainer.deferScheduleMultiWindowModeChanged();
179 }
Winson Chung19953ca2017-04-11 11:19:23 -0700180 }
181
Winson Chung02e71932017-03-10 10:08:17 -0800182 /**
Winson Chung8bca9e42017-04-16 15:59:43 -0700183 * @return whether the bounds are currently animating to fullscreen.
Winson Chung55893332017-02-17 17:13:10 -0800184 */
Winson Chung8bca9e42017-04-16 15:59:43 -0700185 public boolean isAnimatingBoundsToFullscreen() {
186 synchronized (mWindowMap) {
187 return mContainer.isAnimatingBoundsToFullscreen();
Winson Chung55893332017-02-17 17:13:10 -0800188 }
Winson Chung8bca9e42017-04-16 15:59:43 -0700189 }
190
191 /**
192 * @return whether the stack can be resized from the bounds animation.
193 */
194 public boolean pinnedStackResizeDisallowed() {
195 synchronized (mWindowMap) {
196 return mContainer.pinnedStackResizeDisallowed();
197 }
Winson Chung55893332017-02-17 17:13:10 -0800198 }
Winson Chung3a682872017-04-10 14:38:05 -0700199
200 /**
201 * The following calls are made from WM to AM.
202 */
203
204 /** Calls directly into activity manager so window manager lock shouldn't held. */
205 public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
206 if (mListener != null) {
207 PinnedStackWindowListener listener = (PinnedStackWindowListener) mListener;
208 listener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
209 }
210 }
Winson Chung55893332017-02-17 17:13:10 -0800211}