blob: f59b2a4e25dee0b571f6db0f57131de1327b6ed5 [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
Winson Chunga29eb982016-12-14 12:01:27 -080019import static android.view.Display.DEFAULT_DISPLAY;
20
Sudheer Shankadc589ac2016-11-10 15:30:17 -080021import android.app.ActivityManager;
Winson73bc1592016-10-18 18:47:43 -070022import android.app.IActivityManager;
Winson Chung3535df22017-01-17 18:43:39 -080023import android.content.ComponentName;
Winson73bc1592016-10-18 18:47:43 -070024import android.content.Context;
Winson Chunga29eb982016-12-14 12:01:27 -080025import android.content.pm.ParceledListSlice;
Winson Chung2a82fe52017-02-02 14:43:34 -080026import android.graphics.Rect;
Winson Chunga29eb982016-12-14 12:01:27 -080027import android.os.Handler;
28import android.os.RemoteException;
29import android.util.Log;
30import android.view.IPinnedStackController;
31import android.view.IPinnedStackListener;
Winson73bc1592016-10-18 18:47:43 -070032import android.view.IWindowManager;
33import android.view.WindowManagerGlobal;
34
Winson Chung929d4f72017-01-13 10:21:33 -080035import com.android.systemui.recents.misc.SystemServicesProxy;
36import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
37
Winson73bc1592016-10-18 18:47:43 -070038/**
39 * Manages the picture-in-picture (PIP) UI and states for Phones.
40 */
41public class PipManager {
42 private static final String TAG = "PipManager";
43
44 private static PipManager sPipController;
45
46 private Context mContext;
47 private IActivityManager mActivityManager;
48 private IWindowManager mWindowManager;
Winson Chunga29eb982016-12-14 12:01:27 -080049 private Handler mHandler = new Handler();
50
51 private final PinnedStackListener mPinnedStackListener = new PinnedStackListener();
Winson73bc1592016-10-18 18:47:43 -070052
Winson Chung15504af2016-11-02 18:11:36 -070053 private PipMenuActivityController mMenuController;
Winson Chung97a60d92017-01-18 16:01:53 -080054 private PipMediaController mMediaController;
Winson73bc1592016-10-18 18:47:43 -070055 private PipTouchHandler mTouchHandler;
56
Winson Chunga29eb982016-12-14 12:01:27 -080057 /**
Winson Chung929d4f72017-01-13 10:21:33 -080058 * Handler for system task stack changes.
59 */
60 TaskStackListener mTaskStackListener = new TaskStackListener() {
61 @Override
62 public void onActivityPinned() {
Winson Chung3535df22017-01-17 18:43:39 -080063 if (!checkCurrentUserId(false /* debug */)) {
64 return;
65 }
Winson Chung929d4f72017-01-13 10:21:33 -080066 mTouchHandler.onActivityPinned();
Winson Chung97a60d92017-01-18 16:01:53 -080067 mMediaController.onActivityPinned();
Winson Chung929d4f72017-01-13 10:21:33 -080068 }
69
70 @Override
71 public void onPinnedStackAnimationEnded() {
72 // TODO(winsonc): Disable touch interaction with the PiP until the animation ends
73 }
74
75 @Override
Winson Chung3535df22017-01-17 18:43:39 -080076 public void onPinnedActivityRestartAttempt(ComponentName sourceComponent) {
77 if (!checkCurrentUserId(false /* debug */)) {
78 return;
79 }
80
81 // Expand the activity back to fullscreen only if it was attempted to be restarted from
82 // another package than the top activity in the stack
83 boolean expandPipToFullscreen = true;
84 if (sourceComponent != null) {
Winson Chung734c9c02017-01-23 19:08:37 -080085 ComponentName topActivity = PipUtils.getTopPinnedActivity(mContext,
86 mActivityManager);
87 if (topActivity != null && topActivity.getPackageName().equals(
88 sourceComponent.getPackageName())) {
89 expandPipToFullscreen = false;
90 }
Winson Chung3535df22017-01-17 18:43:39 -080091 }
92 if (expandPipToFullscreen) {
Winson Chung2a82fe52017-02-02 14:43:34 -080093 mTouchHandler.getMotionHelper().expandPip();
Winson Chung3535df22017-01-17 18:43:39 -080094 } else {
95 Log.w(TAG, "Can not expand PiP to fullscreen via intent from the same package.");
96 }
Winson Chung929d4f72017-01-13 10:21:33 -080097 }
98 };
99
100 /**
Winson Chunga29eb982016-12-14 12:01:27 -0800101 * Handler for messages from the PIP controller.
102 */
103 private class PinnedStackListener extends IPinnedStackListener.Stub {
104
105 @Override
106 public void onListenerRegistered(IPinnedStackController controller) {
107 mHandler.post(() -> {
108 mTouchHandler.setPinnedStackController(controller);
109 });
110 }
111
112 @Override
Winson Chung2a82fe52017-02-02 14:43:34 -0800113 public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
Winson Chunga29eb982016-12-14 12:01:27 -0800114 mHandler.post(() -> {
Winson Chung2a82fe52017-02-02 14:43:34 -0800115 mTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight);
Winson Chunga29eb982016-12-14 12:01:27 -0800116 });
117 }
118
119 @Override
120 public void onMinimizedStateChanged(boolean isMinimized) {
121 mHandler.post(() -> {
Winson Chung2a82fe52017-02-02 14:43:34 -0800122 mTouchHandler.setMinimizedState(isMinimized, true /* fromController */);
Winson Chunga29eb982016-12-14 12:01:27 -0800123 });
124 }
125
126 @Override
Winson Chung2a82fe52017-02-02 14:43:34 -0800127 public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
128 boolean fromImeAdjustement) {
Winson Chunga29eb982016-12-14 12:01:27 -0800129 mHandler.post(() -> {
Winson Chung2a82fe52017-02-02 14:43:34 -0800130 mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, fromImeAdjustement);
131 });
132 }
133
134 @Override
135 public void onActionsChanged(ParceledListSlice actions) {
136 mHandler.post(() -> {
137 mMenuController.setAppActions(actions);
Winson Chunga29eb982016-12-14 12:01:27 -0800138 });
139 }
140 }
141
Winson73bc1592016-10-18 18:47:43 -0700142 private PipManager() {}
143
144 /**
145 * Initializes {@link PipManager}.
146 */
147 public void initialize(Context context) {
148 mContext = context;
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800149 mActivityManager = ActivityManager.getService();
Winson73bc1592016-10-18 18:47:43 -0700150 mWindowManager = WindowManagerGlobal.getWindowManagerService();
151
Winson Chunga29eb982016-12-14 12:01:27 -0800152 try {
153 mWindowManager.registerPinnedStackListener(DEFAULT_DISPLAY, mPinnedStackListener);
154 } catch (RemoteException e) {
155 Log.e(TAG, "Failed to register pinned stack listener", e);
156 }
Winson Chung929d4f72017-01-13 10:21:33 -0800157 SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
Winson Chunga29eb982016-12-14 12:01:27 -0800158
Winson Chung97a60d92017-01-18 16:01:53 -0800159 mMediaController = new PipMediaController(context, mActivityManager);
160 mMenuController = new PipMenuActivityController(context, mActivityManager, mWindowManager,
161 mMediaController);
Winson Chung15504af2016-11-02 18:11:36 -0700162 mTouchHandler = new PipTouchHandler(context, mMenuController, mActivityManager,
163 mWindowManager);
Winson73bc1592016-10-18 18:47:43 -0700164 }
165
166 /**
167 * Updates the PIP per configuration changed.
168 */
Winson Chung303c6b72016-10-24 17:12:49 -0700169 public void onConfigurationChanged() {
170 mTouchHandler.onConfigurationChanged();
171 }
Winson73bc1592016-10-18 18:47:43 -0700172
173 /**
174 * Gets an instance of {@link PipManager}.
175 */
176 public static PipManager getInstance() {
177 if (sPipController == null) {
178 sPipController = new PipManager();
179 }
180 return sPipController;
181 }
182}