blob: f8996aae9a207761d6b0bab4a572a6875023ed4c [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
Wale Ogunwale68278562017-09-23 17:13:55 -070019import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
20import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Winson Chunga29eb982016-12-14 12:01:27 -080021import static android.view.Display.DEFAULT_DISPLAY;
22
Sudheer Shankadc589ac2016-11-10 15:30:17 -080023import android.app.ActivityManager;
Winson Chungb5026902017-05-03 12:45:13 -070024import android.app.ActivityManager.StackInfo;
Winson73bc1592016-10-18 18:47:43 -070025import android.app.IActivityManager;
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;
Winson73bc1592016-10-18 18:47:43 -070037import android.view.IWindowManager;
38import android.view.WindowManagerGlobal;
39
Winson Chung29a78652017-02-09 18:35:26 -080040import com.android.systemui.pip.BasePipManager;
Winson Chungb5026902017-05-03 12:45:13 -070041import com.android.systemui.recents.events.EventBus;
42import com.android.systemui.recents.events.component.ExpandPipEvent;
Winson Chung929d4f72017-01-13 10:21:33 -080043import com.android.systemui.recents.misc.SystemServicesProxy;
44import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
Winson Chungac52f282017-03-30 14:44:52 -070045import com.android.systemui.statusbar.CommandQueue;
Winson Chung929d4f72017-01-13 10:21:33 -080046
Winson Chung29a78652017-02-09 18:35:26 -080047import java.io.PrintWriter;
48
Winson73bc1592016-10-18 18:47:43 -070049/**
50 * Manages the picture-in-picture (PIP) UI and states for Phones.
51 */
Winson Chung29a78652017-02-09 18:35:26 -080052public class PipManager implements BasePipManager {
Winson73bc1592016-10-18 18:47:43 -070053 private static final String TAG = "PipManager";
54
55 private static PipManager sPipController;
56
57 private Context mContext;
58 private IActivityManager mActivityManager;
59 private IWindowManager mWindowManager;
Winson Chunga29eb982016-12-14 12:01:27 -080060 private Handler mHandler = new Handler();
61
62 private final PinnedStackListener mPinnedStackListener = new PinnedStackListener();
Winson73bc1592016-10-18 18:47:43 -070063
Winson Chungd2d90972017-02-28 11:40:41 -080064 private InputConsumerController mInputConsumerController;
Winson Chung15504af2016-11-02 18:11:36 -070065 private PipMenuActivityController mMenuController;
Winson Chung97a60d92017-01-18 16:01:53 -080066 private PipMediaController mMediaController;
Winson Chungc81c0ce2017-03-17 12:27:30 -070067 private PipNotificationController mNotificationController;
Winson73bc1592016-10-18 18:47:43 -070068 private PipTouchHandler mTouchHandler;
69
Winson Chunga29eb982016-12-14 12:01:27 -080070 /**
Winson Chung929d4f72017-01-13 10:21:33 -080071 * Handler for system task stack changes.
72 */
73 TaskStackListener mTaskStackListener = new TaskStackListener() {
74 @Override
Wale Ogunwale89be5762017-10-04 13:27:49 -070075 public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
Winson Chung929d4f72017-01-13 10:21:33 -080076 mTouchHandler.onActivityPinned();
Winson Chung97a60d92017-01-18 16:01:53 -080077 mMediaController.onActivityPinned();
Winson Chungd2d90972017-02-28 11:40:41 -080078 mMenuController.onActivityPinned();
Winson Chung85d3c8a2017-09-15 15:41:00 -070079 mNotificationController.onActivityPinned(packageName, userId,
Winson Chung6b991b62017-05-11 11:30:36 -070080 true /* deferUntilAnimationEnds */);
Winson Chungac52f282017-03-30 14:44:52 -070081
82 SystemServicesProxy.getInstance(mContext).setPipVisibility(true);
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;
90 final int userId = topActivity != null ? topPipActivityInfo.second : 0;
91 mMenuController.onActivityUnpinned();
92 mTouchHandler.onActivityUnpinned(topActivity);
93 mNotificationController.onActivityUnpinned(topActivity, userId);
Winson Chungac52f282017-03-30 14:44:52 -070094
Winson Chung85d3c8a2017-09-15 15:41:00 -070095 SystemServicesProxy.getInstance(mContext).setPipVisibility(topActivity != null);
Winson Chung929d4f72017-01-13 10:21:33 -080096 }
97
98 @Override
Winson Chung85d39982017-02-24 15:21:25 -080099 public void onPinnedStackAnimationStarted() {
100 // Disable touches while the animation is running
101 mTouchHandler.setTouchEnabled(false);
102 }
103
104 @Override
Winson Chung929d4f72017-01-13 10:21:33 -0800105 public void onPinnedStackAnimationEnded() {
Winson Chung85d39982017-02-24 15:21:25 -0800106 // Re-enable touches after the animation completes
107 mTouchHandler.setTouchEnabled(true);
Winson Chungac52f282017-03-30 14:44:52 -0700108 mTouchHandler.onPinnedStackAnimationEnded();
Winson Chung34488242017-04-26 15:53:51 -0700109 mMenuController.onPinnedStackAnimationEnded();
Winson Chung6b991b62017-05-11 11:30:36 -0700110 mNotificationController.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
139 public void onMinimizedStateChanged(boolean isMinimized) {
140 mHandler.post(() -> {
Winson Chung2a82fe52017-02-02 14:43:34 -0800141 mTouchHandler.setMinimizedState(isMinimized, true /* fromController */);
Winson Chunga29eb982016-12-14 12:01:27 -0800142 });
143 }
144
145 @Override
Winson Chung2a82fe52017-02-02 14:43:34 -0800146 public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
Winson Chungef4dc812017-04-11 13:31:44 -0700147 Rect animatingBounds, boolean fromImeAdjustement, int displayRotation) {
Winson Chunga29eb982016-12-14 12:01:27 -0800148 mHandler.post(() -> {
Winson Chungbaa7b722017-03-03 21:33:44 -0800149 mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, animatingBounds,
Winson Chungef4dc812017-04-11 13:31:44 -0700150 fromImeAdjustement, displayRotation);
Winson Chung2a82fe52017-02-02 14:43:34 -0800151 });
152 }
153
154 @Override
155 public void onActionsChanged(ParceledListSlice actions) {
156 mHandler.post(() -> {
157 mMenuController.setAppActions(actions);
Winson Chunga29eb982016-12-14 12:01:27 -0800158 });
159 }
160 }
161
Winson73bc1592016-10-18 18:47:43 -0700162 private PipManager() {}
163
164 /**
165 * Initializes {@link PipManager}.
166 */
167 public void initialize(Context context) {
168 mContext = context;
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800169 mActivityManager = ActivityManager.getService();
Winson73bc1592016-10-18 18:47:43 -0700170 mWindowManager = WindowManagerGlobal.getWindowManagerService();
171
Winson Chunga29eb982016-12-14 12:01:27 -0800172 try {
173 mWindowManager.registerPinnedStackListener(DEFAULT_DISPLAY, mPinnedStackListener);
174 } catch (RemoteException e) {
175 Log.e(TAG, "Failed to register pinned stack listener", e);
176 }
Winson Chung929d4f72017-01-13 10:21:33 -0800177 SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
Winson Chunga29eb982016-12-14 12:01:27 -0800178
Winson Chungd2d90972017-02-28 11:40:41 -0800179 mInputConsumerController = new InputConsumerController(mWindowManager);
Winson Chung97a60d92017-01-18 16:01:53 -0800180 mMediaController = new PipMediaController(context, mActivityManager);
Winson Chungd2d90972017-02-28 11:40:41 -0800181 mMenuController = new PipMenuActivityController(context, mActivityManager, mMediaController,
182 mInputConsumerController);
183 mTouchHandler = new PipTouchHandler(context, mActivityManager, mMenuController,
184 mInputConsumerController);
Winson Chung664758c2017-03-28 21:03:52 -0700185 mNotificationController = new PipNotificationController(context, mActivityManager,
186 mTouchHandler.getMotionHelper());
Winson Chungb5026902017-05-03 12:45:13 -0700187 EventBus.getDefault().register(this);
Winson73bc1592016-10-18 18:47:43 -0700188 }
189
190 /**
191 * Updates the PIP per configuration changed.
192 */
Winson Chung0c5a5922017-05-22 17:41:06 -0700193 public void onConfigurationChanged(Configuration newConfig) {
Winson Chung303c6b72016-10-24 17:12:49 -0700194 mTouchHandler.onConfigurationChanged();
195 }
Winson73bc1592016-10-18 18:47:43 -0700196
197 /**
Winson Chungb5026902017-05-03 12:45:13 -0700198 * Expands the PIP.
199 */
200 public final void onBusEvent(ExpandPipEvent event) {
201 if (event.clearThumbnailWindows) {
202 try {
Wale Ogunwale68278562017-09-23 17:13:55 -0700203 StackInfo stackInfo = mActivityManager.getStackInfo(
204 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
Winson Chungb5026902017-05-03 12:45:13 -0700205 if (stackInfo != null && stackInfo.taskIds != null) {
206 SystemServicesProxy ssp = SystemServicesProxy.getInstance(mContext);
207 for (int taskId : stackInfo.taskIds) {
208 ssp.cancelThumbnailTransition(taskId);
209 }
210 }
211 } catch (RemoteException e) {
212 // Do nothing
213 }
214 }
215 mTouchHandler.getMotionHelper().expandPip(false /* skipAnimation */);
216 }
217
218 /**
Winson Chungac52f282017-03-30 14:44:52 -0700219 * Sent from KEYCODE_WINDOW handler in PhoneWindowManager, to request the menu to be shown.
220 */
221 public void showPictureInPictureMenu() {
222 mTouchHandler.showPictureInPictureMenu();
223 }
224
225 /**
Winson73bc1592016-10-18 18:47:43 -0700226 * Gets an instance of {@link PipManager}.
227 */
228 public static PipManager getInstance() {
229 if (sPipController == null) {
230 sPipController = new PipManager();
231 }
232 return sPipController;
233 }
Winson Chung29a78652017-02-09 18:35:26 -0800234
235 public void dump(PrintWriter pw) {
236 final String innerPrefix = " ";
237 pw.println(TAG);
Winson Chungd2d90972017-02-28 11:40:41 -0800238 mInputConsumerController.dump(pw, innerPrefix);
Winson Chung29a78652017-02-09 18:35:26 -0800239 mMenuController.dump(pw, innerPrefix);
240 mTouchHandler.dump(pw, innerPrefix);
241 }
Winson73bc1592016-10-18 18:47:43 -0700242}