blob: 3be3422a36addbcd1e5f03dc58f15d7d1dfc29d8 [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 Hung0ede6e92019-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;
Winson Chunga29eb982016-12-14 12:01:27 -080035import android.view.IPinnedStackController;
36import android.view.IPinnedStackListener;
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;
Winson Chungaa357452017-10-31 11:35:30 -070041import com.android.systemui.shared.system.ActivityManagerWrapper;
Winson Chungcbb15a92018-01-25 17:46:16 +000042import com.android.systemui.shared.system.InputConsumerController;
Winson Chung67f5c8b2018-09-24 12:09:19 -070043import com.android.systemui.shared.system.TaskStackChangeListener;
44import com.android.systemui.shared.system.WindowManagerWrapper;
Gus Prevasab336792018-11-14 13:52:20 -050045
Winson Chung29a78652017-02-09 18:35:26 -080046import java.io.PrintWriter;
47
Winson73bc1592016-10-18 18:47:43 -070048/**
49 * Manages the picture-in-picture (PIP) UI and states for Phones.
50 */
Winson Chung29a78652017-02-09 18:35:26 -080051public class PipManager implements BasePipManager {
Winson73bc1592016-10-18 18:47:43 -070052 private static final String TAG = "PipManager";
53
54 private static PipManager sPipController;
55
56 private Context mContext;
57 private IActivityManager mActivityManager;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070058 private IActivityTaskManager mActivityTaskManager;
Winson Chunga29eb982016-12-14 12:01:27 -080059 private Handler mHandler = new Handler();
60
61 private final PinnedStackListener mPinnedStackListener = new PinnedStackListener();
Winson73bc1592016-10-18 18:47:43 -070062
Winson Chungd2d90972017-02-28 11:40:41 -080063 private InputConsumerController mInputConsumerController;
Winson Chung15504af2016-11-02 18:11:36 -070064 private PipMenuActivityController mMenuController;
Winson Chung97a60d92017-01-18 16:01:53 -080065 private PipMediaController mMediaController;
Winson73bc1592016-10-18 18:47:43 -070066 private PipTouchHandler mTouchHandler;
Winson Chung95bccdc2018-01-03 11:45:47 -080067 private PipAppOpsListener mAppOpsListener;
Winson73bc1592016-10-18 18:47:43 -070068
Winson Chunga29eb982016-12-14 12:01:27 -080069 /**
Winson Chung929d4f72017-01-13 10:21:33 -080070 * Handler for system task stack changes.
71 */
Winson Chung67f5c8b2018-09-24 12:09:19 -070072 TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
Winson Chung929d4f72017-01-13 10:21:33 -080073 @Override
Wale Ogunwale89be5762017-10-04 13:27:49 -070074 public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
Winson Chung929d4f72017-01-13 10:21:33 -080075 mTouchHandler.onActivityPinned();
Winson Chung97a60d92017-01-18 16:01:53 -080076 mMediaController.onActivityPinned();
Winson Chungd2d90972017-02-28 11:40:41 -080077 mMenuController.onActivityPinned();
Winson Chung95bccdc2018-01-03 11:45:47 -080078 mAppOpsListener.onActivityPinned(packageName);
Winson Chungac52f282017-03-30 14:44:52 -070079
Winson Chung67f5c8b2018-09-24 12:09:19 -070080 Dependency.get(UiOffloadThread.class).submit(() -> {
81 WindowManagerWrapper.getInstance().setPipVisibility(true);
82 });
Winson Chungc81c0ce2017-03-17 12:27:30 -070083 }
84
85 @Override
86 public void onActivityUnpinned() {
Winson Chung85d3c8a2017-09-15 15:41:00 -070087 final Pair<ComponentName, Integer> topPipActivityInfo = PipUtils.getTopPinnedActivity(
88 mContext, mActivityManager);
89 final ComponentName topActivity = topPipActivityInfo.first;
Winson Chung85d3c8a2017-09-15 15:41:00 -070090 mMenuController.onActivityUnpinned();
91 mTouchHandler.onActivityUnpinned(topActivity);
Winson Chung95bccdc2018-01-03 11:45:47 -080092 mAppOpsListener.onActivityUnpinned();
Winson Chungac52f282017-03-30 14:44:52 -070093
Winson Chung67f5c8b2018-09-24 12:09:19 -070094 Dependency.get(UiOffloadThread.class).submit(() -> {
95 WindowManagerWrapper.getInstance().setPipVisibility(topActivity != null);
96 });
Winson Chung929d4f72017-01-13 10:21:33 -080097 }
98
99 @Override
Winson Chung85d39982017-02-24 15:21:25 -0800100 public void onPinnedStackAnimationStarted() {
101 // Disable touches while the animation is running
102 mTouchHandler.setTouchEnabled(false);
103 }
104
105 @Override
Winson Chung929d4f72017-01-13 10:21:33 -0800106 public void onPinnedStackAnimationEnded() {
Winson Chung85d39982017-02-24 15:21:25 -0800107 // Re-enable touches after the animation completes
108 mTouchHandler.setTouchEnabled(true);
Winson Chungac52f282017-03-30 14:44:52 -0700109 mTouchHandler.onPinnedStackAnimationEnded();
Winson Chung34488242017-04-26 15:53:51 -0700110 mMenuController.onPinnedStackAnimationEnded();
Winson Chung929d4f72017-01-13 10:21:33 -0800111 }
112
113 @Override
Winson Chunge6385a22017-05-02 18:15:16 -0700114 public void onPinnedActivityRestartAttempt(boolean clearedTask) {
Winson Chunge6385a22017-05-02 18:15:16 -0700115 mTouchHandler.getMotionHelper().expandPip(clearedTask /* skipAnimation */);
Winson Chung929d4f72017-01-13 10:21:33 -0800116 }
117 };
118
119 /**
Winson Chunga29eb982016-12-14 12:01:27 -0800120 * Handler for messages from the PIP controller.
121 */
122 private class PinnedStackListener extends IPinnedStackListener.Stub {
123
124 @Override
125 public void onListenerRegistered(IPinnedStackController controller) {
126 mHandler.post(() -> {
127 mTouchHandler.setPinnedStackController(controller);
128 });
129 }
130
131 @Override
Winson Chung2a82fe52017-02-02 14:43:34 -0800132 public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
Winson Chunga29eb982016-12-14 12:01:27 -0800133 mHandler.post(() -> {
Winson Chung2a82fe52017-02-02 14:43:34 -0800134 mTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight);
Winson Chunga29eb982016-12-14 12:01:27 -0800135 });
136 }
137
138 @Override
Tracy Zhou43513082018-03-08 21:58:36 -0800139 public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
140 mHandler.post(() -> {
141 mTouchHandler.onShelfVisibilityChanged(shelfVisible, shelfHeight);
142 });
143 }
144
145 @Override
Winson Chunga29eb982016-12-14 12:01:27 -0800146 public void onMinimizedStateChanged(boolean isMinimized) {
147 mHandler.post(() -> {
Winson Chung2a82fe52017-02-02 14:43:34 -0800148 mTouchHandler.setMinimizedState(isMinimized, true /* fromController */);
Winson Chunga29eb982016-12-14 12:01:27 -0800149 });
150 }
151
152 @Override
Winson Chung2a82fe52017-02-02 14:43:34 -0800153 public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
Tracy Zhou43513082018-03-08 21:58:36 -0800154 Rect animatingBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment,
155 int displayRotation) {
Winson Chunga29eb982016-12-14 12:01:27 -0800156 mHandler.post(() -> {
Winson Chungbaa7b722017-03-03 21:33:44 -0800157 mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, animatingBounds,
Tracy Zhou43513082018-03-08 21:58:36 -0800158 fromImeAdjustment, fromShelfAdjustment, displayRotation);
Winson Chung2a82fe52017-02-02 14:43:34 -0800159 });
160 }
161
162 @Override
163 public void onActionsChanged(ParceledListSlice actions) {
164 mHandler.post(() -> {
165 mMenuController.setAppActions(actions);
Winson Chunga29eb982016-12-14 12:01:27 -0800166 });
167 }
168 }
169
Winson73bc1592016-10-18 18:47:43 -0700170 private PipManager() {}
171
172 /**
173 * Initializes {@link PipManager}.
174 */
175 public void initialize(Context context) {
176 mContext = context;
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800177 mActivityManager = ActivityManager.getService();
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700178 mActivityTaskManager = ActivityTaskManager.getService();
Winson73bc1592016-10-18 18:47:43 -0700179
Winson Chunga29eb982016-12-14 12:01:27 -0800180 try {
Joshua Tsujia19515f2019-02-13 18:02:29 -0500181 WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener);
Winson Chunga29eb982016-12-14 12:01:27 -0800182 } catch (RemoteException e) {
183 Log.e(TAG, "Failed to register pinned stack listener", e);
184 }
Winson Chung2cf6ad82017-11-09 17:36:59 -0800185 ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
Winson Chunga29eb982016-12-14 12:01:27 -0800186
Winson Chungcbb15a92018-01-25 17:46:16 +0000187 mInputConsumerController = InputConsumerController.getPipInputConsumer();
Winson Chung97a60d92017-01-18 16:01:53 -0800188 mMediaController = new PipMediaController(context, mActivityManager);
Winson Chungd2d90972017-02-28 11:40:41 -0800189 mMenuController = new PipMenuActivityController(context, mActivityManager, mMediaController,
190 mInputConsumerController);
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700191 mTouchHandler = new PipTouchHandler(context, mActivityManager, mActivityTaskManager,
192 mMenuController, mInputConsumerController);
Winson Chung95bccdc2018-01-03 11:45:47 -0800193 mAppOpsListener = new PipAppOpsListener(context, mActivityManager,
194 mTouchHandler.getMotionHelper());
Arthur Hung0ede6e92019-08-30 16:06:59 +0800195
196 // If SystemUI restart, and it already existed a pinned stack,
197 // register the pip input consumer to ensure touch can send to it.
198 try {
199 ActivityManager.StackInfo stackInfo = mActivityTaskManager.getStackInfo(
200 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
201 if (stackInfo != null) {
202 mInputConsumerController.registerInputConsumer();
203 }
204 } catch (RemoteException e) {
205 e.printStackTrace();
206 }
Winson73bc1592016-10-18 18:47:43 -0700207 }
208
209 /**
210 * Updates the PIP per configuration changed.
211 */
Winson Chung0c5a5922017-05-22 17:41:06 -0700212 public void onConfigurationChanged(Configuration newConfig) {
Winson Chung303c6b72016-10-24 17:12:49 -0700213 mTouchHandler.onConfigurationChanged();
214 }
Winson73bc1592016-10-18 18:47:43 -0700215
216 /**
Winson Chungb5026902017-05-03 12:45:13 -0700217 * Expands the PIP.
218 */
Winson Chung2dbcf092018-10-24 13:00:41 -0700219 @Override
220 public void expandPip() {
Winson Chungb5026902017-05-03 12:45:13 -0700221 mTouchHandler.getMotionHelper().expandPip(false /* skipAnimation */);
222 }
223
224 /**
Winson Chung2dbcf092018-10-24 13:00:41 -0700225 * Hides the PIP menu.
226 */
227 @Override
228 public void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {
229 mMenuController.hideMenu(onStartCallback, onEndCallback);
230 }
231
232 /**
Winson Chungac52f282017-03-30 14:44:52 -0700233 * Sent from KEYCODE_WINDOW handler in PhoneWindowManager, to request the menu to be shown.
234 */
235 public void showPictureInPictureMenu() {
236 mTouchHandler.showPictureInPictureMenu();
237 }
238
239 /**
Winson73bc1592016-10-18 18:47:43 -0700240 * Gets an instance of {@link PipManager}.
241 */
242 public static PipManager getInstance() {
243 if (sPipController == null) {
244 sPipController = new PipManager();
245 }
246 return sPipController;
247 }
Winson Chung29a78652017-02-09 18:35:26 -0800248
249 public void dump(PrintWriter pw) {
250 final String innerPrefix = " ";
251 pw.println(TAG);
Winson Chungd2d90972017-02-28 11:40:41 -0800252 mInputConsumerController.dump(pw, innerPrefix);
Winson Chung29a78652017-02-09 18:35:26 -0800253 mMenuController.dump(pw, innerPrefix);
254 mTouchHandler.dump(pw, innerPrefix);
255 }
Winson73bc1592016-10-18 18:47:43 -0700256}