blob: 369073c6564dc48c69aafc54c38b26dbbf8b6cc8 [file] [log] [blame]
Winson73bc1592016-10-18 18:47:43 -07001/*
2 * Copyright (C) 2016 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.pip.phone;
18
Arthur Hungd52d1192019-08-30 16:06:59 +080019import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
20import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
21
Sudheer Shankadc589ac2016-11-10 15:30:17 -080022import android.app.ActivityManager;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070023import android.app.ActivityTaskManager;
Winson73bc1592016-10-18 18:47:43 -070024import android.app.IActivityManager;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070025import android.app.IActivityTaskManager;
Winson Chung3535df22017-01-17 18:43:39 -080026import android.content.ComponentName;
Winson73bc1592016-10-18 18:47:43 -070027import android.content.Context;
Winson Chunga29eb982016-12-14 12:01:27 -080028import android.content.pm.ParceledListSlice;
Winson Chung0c5a5922017-05-22 17:41:06 -070029import android.content.res.Configuration;
Winson Chung2a82fe52017-02-02 14:43:34 -080030import android.graphics.Rect;
Winson Chunga29eb982016-12-14 12:01:27 -080031import android.os.Handler;
32import android.os.RemoteException;
33import android.util.Log;
Winson Chung85d3c8a2017-09-15 15:41:00 -070034import android.util.Pair;
Hongwei Wang43a752b2019-09-17 20:20:30 +000035import android.view.DisplayInfo;
Winson Chunga29eb982016-12-14 12:01:27 -080036import android.view.IPinnedStackController;
Gus Prevasab336792018-11-14 13:52:20 -050037
Winson Chung67f5c8b2018-09-24 12:09:19 -070038import com.android.systemui.Dependency;
39import com.android.systemui.UiOffloadThread;
Winson Chung29a78652017-02-09 18:35:26 -080040import com.android.systemui.pip.BasePipManager;
Hongwei Wang43a752b2019-09-17 20:20:30 +000041import com.android.systemui.pip.PipBoundsHandler;
Winson Chungaa357452017-10-31 11:35:30 -070042import com.android.systemui.shared.system.ActivityManagerWrapper;
Winson Chungcbb15a92018-01-25 17:46:16 +000043import com.android.systemui.shared.system.InputConsumerController;
Hongwei Wang43a752b2019-09-17 20:20:30 +000044import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
Winson Chung67f5c8b2018-09-24 12:09:19 -070045import com.android.systemui.shared.system.TaskStackChangeListener;
46import com.android.systemui.shared.system.WindowManagerWrapper;
Gus Prevasab336792018-11-14 13:52:20 -050047
Winson Chung29a78652017-02-09 18:35:26 -080048import java.io.PrintWriter;
49
Winson73bc1592016-10-18 18:47:43 -070050/**
51 * Manages the picture-in-picture (PIP) UI and states for Phones.
52 */
Winson Chung29a78652017-02-09 18:35:26 -080053public class PipManager implements BasePipManager {
Winson73bc1592016-10-18 18:47:43 -070054 private static final String TAG = "PipManager";
55
56 private static PipManager sPipController;
57
58 private Context mContext;
59 private IActivityManager mActivityManager;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070060 private IActivityTaskManager mActivityTaskManager;
Winson Chunga29eb982016-12-14 12:01:27 -080061 private Handler mHandler = new Handler();
62
Hongwei Wang43a752b2019-09-17 20:20:30 +000063 private final PinnedStackListener mPinnedStackListener = new PipManagerPinnedStackListener();
64 private final DisplayInfo mTmpDisplayInfo = new DisplayInfo();
65 private final Rect mTmpInsetBounds = new Rect();
66 private final Rect mTmpNormalBounds = new Rect();
Winson73bc1592016-10-18 18:47:43 -070067
Hongwei Wang43a752b2019-09-17 20:20:30 +000068 private PipBoundsHandler mPipBoundsHandler;
Winson Chungd2d90972017-02-28 11:40:41 -080069 private InputConsumerController mInputConsumerController;
Winson Chung15504af2016-11-02 18:11:36 -070070 private PipMenuActivityController mMenuController;
Winson Chung97a60d92017-01-18 16:01:53 -080071 private PipMediaController mMediaController;
Winson73bc1592016-10-18 18:47:43 -070072 private PipTouchHandler mTouchHandler;
Winson Chung95bccdc2018-01-03 11:45:47 -080073 private PipAppOpsListener mAppOpsListener;
Winson73bc1592016-10-18 18:47:43 -070074
Winson Chunga29eb982016-12-14 12:01:27 -080075 /**
Winson Chung929d4f72017-01-13 10:21:33 -080076 * Handler for system task stack changes.
77 */
Winson Chung67f5c8b2018-09-24 12:09:19 -070078 TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
Winson Chung929d4f72017-01-13 10:21:33 -080079 @Override
Wale Ogunwale89be5762017-10-04 13:27:49 -070080 public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
Winson Chung929d4f72017-01-13 10:21:33 -080081 mTouchHandler.onActivityPinned();
Winson Chung97a60d92017-01-18 16:01:53 -080082 mMediaController.onActivityPinned();
Winson Chungd2d90972017-02-28 11:40:41 -080083 mMenuController.onActivityPinned();
Winson Chung95bccdc2018-01-03 11:45:47 -080084 mAppOpsListener.onActivityPinned(packageName);
Winson Chungac52f282017-03-30 14:44:52 -070085
Winson Chung67f5c8b2018-09-24 12:09:19 -070086 Dependency.get(UiOffloadThread.class).submit(() -> {
87 WindowManagerWrapper.getInstance().setPipVisibility(true);
88 });
Winson Chungc81c0ce2017-03-17 12:27:30 -070089 }
90
91 @Override
92 public void onActivityUnpinned() {
Winson Chung85d3c8a2017-09-15 15:41:00 -070093 final Pair<ComponentName, Integer> topPipActivityInfo = PipUtils.getTopPinnedActivity(
94 mContext, mActivityManager);
95 final ComponentName topActivity = topPipActivityInfo.first;
Winson Chung85d3c8a2017-09-15 15:41:00 -070096 mMenuController.onActivityUnpinned();
97 mTouchHandler.onActivityUnpinned(topActivity);
Winson Chung95bccdc2018-01-03 11:45:47 -080098 mAppOpsListener.onActivityUnpinned();
Winson Chungac52f282017-03-30 14:44:52 -070099
Winson Chung67f5c8b2018-09-24 12:09:19 -0700100 Dependency.get(UiOffloadThread.class).submit(() -> {
101 WindowManagerWrapper.getInstance().setPipVisibility(topActivity != null);
102 });
Winson Chung929d4f72017-01-13 10:21:33 -0800103 }
104
105 @Override
Winson Chung85d39982017-02-24 15:21:25 -0800106 public void onPinnedStackAnimationStarted() {
107 // Disable touches while the animation is running
108 mTouchHandler.setTouchEnabled(false);
109 }
110
111 @Override
Winson Chung929d4f72017-01-13 10:21:33 -0800112 public void onPinnedStackAnimationEnded() {
Winson Chung85d39982017-02-24 15:21:25 -0800113 // Re-enable touches after the animation completes
114 mTouchHandler.setTouchEnabled(true);
Winson Chungac52f282017-03-30 14:44:52 -0700115 mTouchHandler.onPinnedStackAnimationEnded();
Winson Chung34488242017-04-26 15:53:51 -0700116 mMenuController.onPinnedStackAnimationEnded();
Winson Chung929d4f72017-01-13 10:21:33 -0800117 }
118
119 @Override
Winson Chunge6385a22017-05-02 18:15:16 -0700120 public void onPinnedActivityRestartAttempt(boolean clearedTask) {
Winson Chunge6385a22017-05-02 18:15:16 -0700121 mTouchHandler.getMotionHelper().expandPip(clearedTask /* skipAnimation */);
Winson Chung929d4f72017-01-13 10:21:33 -0800122 }
123 };
124
125 /**
Winson Chunga29eb982016-12-14 12:01:27 -0800126 * Handler for messages from the PIP controller.
127 */
Hongwei Wang43a752b2019-09-17 20:20:30 +0000128 private class PipManagerPinnedStackListener extends PinnedStackListener {
Winson Chunga29eb982016-12-14 12:01:27 -0800129 @Override
130 public void onListenerRegistered(IPinnedStackController controller) {
131 mHandler.post(() -> {
Hongwei Wang43a752b2019-09-17 20:20:30 +0000132 mPipBoundsHandler.setPinnedStackController(controller);
Winson Chunga29eb982016-12-14 12:01:27 -0800133 mTouchHandler.setPinnedStackController(controller);
134 });
135 }
136
137 @Override
Winson Chung2a82fe52017-02-02 14:43:34 -0800138 public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
Winson Chunga29eb982016-12-14 12:01:27 -0800139 mHandler.post(() -> {
Hongwei Wang43a752b2019-09-17 20:20:30 +0000140 mPipBoundsHandler.onImeVisibilityChanged(imeVisible, imeHeight);
Winson Chung2a82fe52017-02-02 14:43:34 -0800141 mTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight);
Winson Chunga29eb982016-12-14 12:01:27 -0800142 });
143 }
144
145 @Override
146 public void onMinimizedStateChanged(boolean isMinimized) {
147 mHandler.post(() -> {
Hongwei Wang43a752b2019-09-17 20:20:30 +0000148 mPipBoundsHandler.onMinimizedStateChanged(isMinimized);
Winson Chung2a82fe52017-02-02 14:43:34 -0800149 mTouchHandler.setMinimizedState(isMinimized, true /* fromController */);
Winson Chunga29eb982016-12-14 12:01:27 -0800150 });
151 }
152
153 @Override
Hongwei Wang43a752b2019-09-17 20:20:30 +0000154 public void onMovementBoundsChanged(Rect animatingBounds, boolean fromImeAdjustment,
155 boolean fromShelfAdjustment) {
Hongwei Wang9b751802019-09-11 12:13:21 -0700156 mHandler.post(() -> updateMovementBounds(animatingBounds, fromImeAdjustment,
157 fromShelfAdjustment));
Winson Chung2a82fe52017-02-02 14:43:34 -0800158 }
159
160 @Override
161 public void onActionsChanged(ParceledListSlice actions) {
Hongwei Wang43a752b2019-09-17 20:20:30 +0000162 mHandler.post(() -> mMenuController.setAppActions(actions));
163 }
164
165 @Override
166 public void onSaveReentrySnapFraction(ComponentName componentName, Rect bounds) {
167 mHandler.post(() -> mPipBoundsHandler.onSaveReentrySnapFraction(componentName, bounds));
168 }
169
170 @Override
171 public void onResetReentrySnapFraction(ComponentName componentName) {
172 mHandler.post(() -> mPipBoundsHandler.onResetReentrySnapFraction(componentName));
173 }
174
175 @Override
176 public void onDisplayInfoChanged(DisplayInfo displayInfo) {
177 mHandler.post(() -> mPipBoundsHandler.onDisplayInfoChanged(displayInfo));
178 }
179
180 @Override
181 public void onConfigurationChanged() {
182 mHandler.post(() -> mPipBoundsHandler.onConfigurationChanged());
183 }
184
185 @Override
186 public void onAspectRatioChanged(float aspectRatio) {
187 mHandler.post(() -> mPipBoundsHandler.onAspectRatioChanged(aspectRatio));
188 }
189
190 @Override
191 public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect bounds) {
Winson Chung2a82fe52017-02-02 14:43:34 -0800192 mHandler.post(() -> {
Hongwei Wang43a752b2019-09-17 20:20:30 +0000193 mPipBoundsHandler.onPrepareAnimation(sourceRectHint, aspectRatio, bounds);
Winson Chunga29eb982016-12-14 12:01:27 -0800194 });
195 }
196 }
197
Winson73bc1592016-10-18 18:47:43 -0700198 private PipManager() {}
199
200 /**
201 * Initializes {@link PipManager}.
202 */
203 public void initialize(Context context) {
204 mContext = context;
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800205 mActivityManager = ActivityManager.getService();
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700206 mActivityTaskManager = ActivityTaskManager.getService();
Winson73bc1592016-10-18 18:47:43 -0700207
Winson Chunga29eb982016-12-14 12:01:27 -0800208 try {
Joshua Tsujia19515f2019-02-13 18:02:29 -0500209 WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener);
Winson Chunga29eb982016-12-14 12:01:27 -0800210 } catch (RemoteException e) {
211 Log.e(TAG, "Failed to register pinned stack listener", e);
212 }
Winson Chung2cf6ad82017-11-09 17:36:59 -0800213 ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
Winson Chunga29eb982016-12-14 12:01:27 -0800214
Hongwei Wang43a752b2019-09-17 20:20:30 +0000215 mPipBoundsHandler = new PipBoundsHandler(context);
Winson Chungcbb15a92018-01-25 17:46:16 +0000216 mInputConsumerController = InputConsumerController.getPipInputConsumer();
Winson Chung97a60d92017-01-18 16:01:53 -0800217 mMediaController = new PipMediaController(context, mActivityManager);
Winson Chungd2d90972017-02-28 11:40:41 -0800218 mMenuController = new PipMenuActivityController(context, mActivityManager, mMediaController,
219 mInputConsumerController);
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700220 mTouchHandler = new PipTouchHandler(context, mActivityManager, mActivityTaskManager,
Hongwei Wang43a752b2019-09-17 20:20:30 +0000221 mMenuController, mInputConsumerController, mPipBoundsHandler);
Winson Chung95bccdc2018-01-03 11:45:47 -0800222 mAppOpsListener = new PipAppOpsListener(context, mActivityManager,
223 mTouchHandler.getMotionHelper());
Arthur Hungd52d1192019-08-30 16:06:59 +0800224
225 // If SystemUI restart, and it already existed a pinned stack,
226 // register the pip input consumer to ensure touch can send to it.
227 try {
228 ActivityManager.StackInfo stackInfo = mActivityTaskManager.getStackInfo(
229 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
230 if (stackInfo != null) {
231 mInputConsumerController.registerInputConsumer();
232 }
233 } catch (RemoteException e) {
234 e.printStackTrace();
235 }
Winson73bc1592016-10-18 18:47:43 -0700236 }
237
238 /**
239 * Updates the PIP per configuration changed.
240 */
Winson Chung0c5a5922017-05-22 17:41:06 -0700241 public void onConfigurationChanged(Configuration newConfig) {
Winson Chung303c6b72016-10-24 17:12:49 -0700242 mTouchHandler.onConfigurationChanged();
243 }
Winson73bc1592016-10-18 18:47:43 -0700244
245 /**
Winson Chungb5026902017-05-03 12:45:13 -0700246 * Expands the PIP.
247 */
Winson Chung2dbcf092018-10-24 13:00:41 -0700248 @Override
249 public void expandPip() {
Winson Chungb5026902017-05-03 12:45:13 -0700250 mTouchHandler.getMotionHelper().expandPip(false /* skipAnimation */);
251 }
252
253 /**
Winson Chung2dbcf092018-10-24 13:00:41 -0700254 * Hides the PIP menu.
255 */
256 @Override
257 public void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {
258 mMenuController.hideMenu(onStartCallback, onEndCallback);
259 }
260
261 /**
Winson Chungac52f282017-03-30 14:44:52 -0700262 * Sent from KEYCODE_WINDOW handler in PhoneWindowManager, to request the menu to be shown.
263 */
264 public void showPictureInPictureMenu() {
265 mTouchHandler.showPictureInPictureMenu();
266 }
267
268 /**
Hongwei Wang9b751802019-09-11 12:13:21 -0700269 * Sets both shelf visibility and its height.
270 */
271 @Override
272 public void setShelfHeight(boolean visible, int height) {
273 mHandler.post(() -> {
274 final boolean changed = mPipBoundsHandler.setShelfHeight(visible, height);
275 if (changed) {
276 mTouchHandler.onShelfVisibilityChanged(visible, height);
277 updateMovementBounds(mPipBoundsHandler.getLastDestinationBounds(),
278 false /* fromImeAdjustment */, true /* fromShelfAdjustment */);
279 }
280 });
281 }
282
283 private void updateMovementBounds(Rect animatingBounds, boolean fromImeAdjustment,
284 boolean fromShelfAdjustment) {
285 // Populate inset / normal bounds and DisplayInfo from mPipBoundsHandler first.
286 mPipBoundsHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds,
287 animatingBounds, mTmpDisplayInfo);
288 mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds,
289 animatingBounds, fromImeAdjustment, fromShelfAdjustment,
290 mTmpDisplayInfo.rotation);
291 }
292
293 /**
Winson73bc1592016-10-18 18:47:43 -0700294 * Gets an instance of {@link PipManager}.
295 */
296 public static PipManager getInstance() {
297 if (sPipController == null) {
298 sPipController = new PipManager();
299 }
300 return sPipController;
301 }
Winson Chung29a78652017-02-09 18:35:26 -0800302
303 public void dump(PrintWriter pw) {
304 final String innerPrefix = " ";
305 pw.println(TAG);
Winson Chungd2d90972017-02-28 11:40:41 -0800306 mInputConsumerController.dump(pw, innerPrefix);
Winson Chung29a78652017-02-09 18:35:26 -0800307 mMenuController.dump(pw, innerPrefix);
308 mTouchHandler.dump(pw, innerPrefix);
Hongwei Wang43a752b2019-09-17 20:20:30 +0000309 mPipBoundsHandler.dump(pw, innerPrefix);
Winson Chung29a78652017-02-09 18:35:26 -0800310 }
Winson73bc1592016-10-18 18:47:43 -0700311}