blob: e3b791e72e59c2e1e4cf6eac7a044059a341414f [file] [log] [blame]
Winson Chung7048fea2014-03-18 12:21:24 -07001/*
2 * Copyright (C) 2014 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.recents;
18
Jorim Jaggicdb06ca2016-01-25 19:15:12 -080019import android.app.ActivityManager;
Sid Soundararajan4bdb6872016-03-18 13:42:10 -070020import android.app.UiModeManager;
Winson190fe3bf2015-10-20 14:57:24 -070021import android.content.ComponentName;
Winsone6309aa2016-01-08 11:19:21 -080022import android.content.ContentResolver;
Winson Chung7048fea2014-03-18 12:21:24 -070023import android.content.Context;
24import android.content.Intent;
Winson190fe3bf2015-10-20 14:57:24 -070025import android.content.ServiceConnection;
Jorim Jaggi29379ec2016-04-11 23:43:42 -070026import android.content.pm.ActivityInfo;
Winson Chung7048fea2014-03-18 12:21:24 -070027import android.content.res.Configuration;
Muyuan Lia2129992016-03-03 18:30:39 -080028import android.graphics.Point;
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -080029import android.graphics.Rect;
Muyuan Lia2129992016-03-03 18:30:39 -080030import android.hardware.display.DisplayManager;
Winson4727ab92015-11-02 14:35:34 -080031import android.os.Build;
Jim Millera237a312014-11-06 18:05:59 -080032import android.os.Handler;
Winson190fe3bf2015-10-20 14:57:24 -070033import android.os.IBinder;
34import android.os.RemoteException;
Winson4727ab92015-11-02 14:35:34 -080035import android.os.SystemProperties;
Winson Chung7048fea2014-03-18 12:21:24 -070036import android.os.UserHandle;
Winsone9243562015-11-10 16:07:13 -080037import android.provider.Settings;
Winsona00a7852016-02-16 11:05:28 -080038import android.util.EventLog;
Winson190fe3bf2015-10-20 14:57:24 -070039import android.util.Log;
Jorim Jaggid61f2272014-12-19 20:35:35 +010040import android.view.Display;
Jorim Jaggiaa6c5742016-03-01 14:10:14 +010041import android.widget.Toast;
Winsonc0d70582016-01-29 10:24:39 -080042
Jorim Jaggi29379ec2016-04-11 23:43:42 -070043import com.android.internal.logging.MetricsLogger;
Tamas Berghammercbd3f0c2016-06-22 15:21:38 +010044import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Winsona00a7852016-02-16 11:05:28 -080045import com.android.systemui.EventLogConstants;
46import com.android.systemui.EventLogTags;
Jorim Jaggiaa6c5742016-03-01 14:10:14 +010047import com.android.systemui.R;
Winson Chung9214eff2014-06-12 13:59:25 -070048import com.android.systemui.RecentsComponent;
Jorim Jaggid61f2272014-12-19 20:35:35 +010049import com.android.systemui.SystemUI;
Winson190fe3bf2015-10-20 14:57:24 -070050import com.android.systemui.recents.events.EventBus;
Winson003eda62016-03-11 14:56:00 -080051import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
Jorim Jaggi899327f2016-02-25 20:44:18 -050052import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
Jorim Jaggicdb06ca2016-01-25 19:15:12 -080053import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
Winson190fe3bf2015-10-20 14:57:24 -070054import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
55import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
Winson675c5d82016-08-23 17:12:22 -070056import com.android.systemui.recents.events.component.ShowUserToastEvent;
Jorim Jaggi11cc01d2016-01-22 19:39:23 -080057import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
Winson Chungffa2ec62014-07-03 15:54:42 -070058import com.android.systemui.recents.misc.SystemServicesProxy;
Winsone7f138c2015-10-22 16:15:21 -070059import com.android.systemui.recents.model.RecentsTaskLoader;
Sid Soundararajan4bdb6872016-03-18 13:42:10 -070060import com.android.systemui.recents.tv.RecentsTvImpl;
Jorim Jaggidb21bbd2016-04-18 15:32:07 -070061import com.android.systemui.stackdivider.Divider;
Winson Chung7048fea2014-03-18 12:21:24 -070062
Winson Chungffa2ec62014-07-03 15:54:42 -070063import java.util.ArrayList;
Winson Chung7048fea2014-03-18 12:21:24 -070064
Winson Chung740c3ac2014-11-12 16:14:38 -080065
Winson190fe3bf2015-10-20 14:57:24 -070066/**
67 * An implementation of the SystemUI recents component, which supports both system and secondary
68 * users.
69 */
Jorim Jaggid61f2272014-12-19 20:35:35 +010070public class Recents extends SystemUI
Winson190fe3bf2015-10-20 14:57:24 -070071 implements RecentsComponent {
72
73 private final static String TAG = "Recents";
74 private final static boolean DEBUG = false;
Winson Chung7048fea2014-03-18 12:21:24 -070075
Winsone6c90732015-09-24 16:06:29 -070076 public final static int EVENT_BUS_PRIORITY = 1;
Winson190fe3bf2015-10-20 14:57:24 -070077 public final static int BIND_TO_SYSTEM_USER_RETRY_DELAY = 5000;
Jorim Jaggidb21bbd2016-04-18 15:32:07 -070078 public final static int RECENTS_GROW_TARGET_INVALID = -1;
Winsone6c90732015-09-24 16:06:29 -070079
Winson4727ab92015-11-02 14:35:34 -080080 // Purely for experimentation
81 private final static String RECENTS_OVERRIDE_SYSPROP_KEY = "persist.recents_override_pkg";
82 private final static String ACTION_SHOW_RECENTS = "com.android.systemui.recents.ACTION_SHOW";
83 private final static String ACTION_HIDE_RECENTS = "com.android.systemui.recents.ACTION_HIDE";
84 private final static String ACTION_TOGGLE_RECENTS = "com.android.systemui.recents.ACTION_TOGGLE";
85
Jorim Jaggi29379ec2016-04-11 23:43:42 -070086 private static final String COUNTER_WINDOW_SUPPORTED = "window_enter_supported";
87 private static final String COUNTER_WINDOW_UNSUPPORTED = "window_enter_unsupported";
88 private static final String COUNTER_WINDOW_INCOMPATIBLE = "window_enter_incompatible";
89
Winsone7f138c2015-10-22 16:15:21 -070090 private static SystemServicesProxy sSystemServicesProxy;
Winsonc742f972015-11-12 11:32:21 -080091 private static RecentsDebugFlags sDebugFlags;
Winsone7f138c2015-10-22 16:15:21 -070092 private static RecentsTaskLoader sTaskLoader;
Winson53ec42c2015-10-28 15:55:35 -070093 private static RecentsConfiguration sConfiguration;
Winsone7f138c2015-10-22 16:15:21 -070094
Winson4727ab92015-11-02 14:35:34 -080095 // For experiments only, allows another package to handle recents if it is defined in the system
96 // properties. This is limited to show/toggle/hide, and does not tie into the ActivityManager,
97 // and does not reside in the home stack.
98 private String mOverrideRecentsPackageName;
99
Winson Chung501d59d2016-10-05 17:49:09 +0000100 private Handler mHandler;
Winson190fe3bf2015-10-20 14:57:24 -0700101 private RecentsImpl mImpl;
Jorim Jaggidd98d412015-11-18 15:57:38 -0800102 private int mDraggingInRecentsCurrentUser;
Winson Chung2002cf52014-12-08 17:26:44 -0800103
Winson190fe3bf2015-10-20 14:57:24 -0700104 // Only For system user, this is the callbacks instance we return to each secondary user
Winsona00a7852016-02-16 11:05:28 -0800105 private RecentsSystemUser mSystemToUserCallbacks;
Winson Chungcdcd4872014-08-05 18:00:13 -0700106
Winson190fe3bf2015-10-20 14:57:24 -0700107 // Only for secondary users, this is the callbacks instance provided by the system user to make
108 // calls back
Winsona00a7852016-02-16 11:05:28 -0800109 private IRecentsSystemUserCallbacks mUserToSystemCallbacks;
Winson Chungb44c24f2014-04-09 15:17:43 -0700110
Winson190fe3bf2015-10-20 14:57:24 -0700111 // The set of runnables to run after binding to the system user's service.
112 private final ArrayList<Runnable> mOnConnectRunnables = new ArrayList<>();
Winson Chung7048fea2014-03-18 12:21:24 -0700113
Winson190fe3bf2015-10-20 14:57:24 -0700114 // Only for secondary users, this is the death handler for the binder from the system user
Winsona00a7852016-02-16 11:05:28 -0800115 private final IBinder.DeathRecipient mUserToSystemCallbacksDeathRcpt = new IBinder.DeathRecipient() {
Winson Chung740c3ac2014-11-12 16:14:38 -0800116 @Override
Winson190fe3bf2015-10-20 14:57:24 -0700117 public void binderDied() {
Winsona00a7852016-02-16 11:05:28 -0800118 mUserToSystemCallbacks = null;
119 EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
120 EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_UNBOUND,
121 sSystemServicesProxy.getProcessUser());
Winson Chung2002cf52014-12-08 17:26:44 -0800122
Winson190fe3bf2015-10-20 14:57:24 -0700123 // Retry after a fixed duration
124 mHandler.postDelayed(new Runnable() {
125 @Override
126 public void run() {
127 registerWithSystemUser();
Winson Chung0eae5572014-12-11 11:04:19 -0800128 }
Winson190fe3bf2015-10-20 14:57:24 -0700129 }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
Winson Chung740c3ac2014-11-12 16:14:38 -0800130 }
Winson190fe3bf2015-10-20 14:57:24 -0700131 };
Winson Chung740c3ac2014-11-12 16:14:38 -0800132
Winson190fe3bf2015-10-20 14:57:24 -0700133 // Only for secondary users, this is the service connection we use to connect to the system user
Winsona00a7852016-02-16 11:05:28 -0800134 private final ServiceConnection mUserToSystemServiceConnection = new ServiceConnection() {
Winson Chung2002cf52014-12-08 17:26:44 -0800135 @Override
Winson190fe3bf2015-10-20 14:57:24 -0700136 public void onServiceConnected(ComponentName name, IBinder service) {
137 if (service != null) {
Winsona00a7852016-02-16 11:05:28 -0800138 mUserToSystemCallbacks = IRecentsSystemUserCallbacks.Stub.asInterface(
Winson190fe3bf2015-10-20 14:57:24 -0700139 service);
Winsona00a7852016-02-16 11:05:28 -0800140 EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
141 EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_BOUND,
142 sSystemServicesProxy.getProcessUser());
Winson190fe3bf2015-10-20 14:57:24 -0700143
144 // Listen for system user's death, so that we can reconnect later
145 try {
Winsona00a7852016-02-16 11:05:28 -0800146 service.linkToDeath(mUserToSystemCallbacksDeathRcpt, 0);
Winson190fe3bf2015-10-20 14:57:24 -0700147 } catch (RemoteException e) {
148 Log.e(TAG, "Lost connection to (System) SystemUI", e);
149 }
150
151 // Run each of the queued runnables
152 runAndFlushOnConnectRunnables();
Winson Chung2002cf52014-12-08 17:26:44 -0800153 }
Winson190fe3bf2015-10-20 14:57:24 -0700154
155 // Unbind ourselves now that we've registered our callbacks. The
156 // binder to the system user are still valid at this point.
157 mContext.unbindService(this);
Winson Chung2002cf52014-12-08 17:26:44 -0800158 }
Winson Chung2002cf52014-12-08 17:26:44 -0800159
Winson190fe3bf2015-10-20 14:57:24 -0700160 @Override
161 public void onServiceDisconnected(ComponentName name) {
162 // Do nothing
163 }
164 };
Winson Chung740c3ac2014-11-12 16:14:38 -0800165
Jorim Jaggid61f2272014-12-19 20:35:35 +0100166 /**
Winson190fe3bf2015-10-20 14:57:24 -0700167 * Returns the callbacks interface that non-system users can call.
Jorim Jaggid61f2272014-12-19 20:35:35 +0100168 */
Winson190fe3bf2015-10-20 14:57:24 -0700169 public IBinder getSystemUserCallbacks() {
Winsona00a7852016-02-16 11:05:28 -0800170 return mSystemToUserCallbacks;
Winson Chung7048fea2014-03-18 12:21:24 -0700171 }
172
Winsone7f138c2015-10-22 16:15:21 -0700173 public static RecentsTaskLoader getTaskLoader() {
174 return sTaskLoader;
175 }
176
177 public static SystemServicesProxy getSystemServices() {
178 return sSystemServicesProxy;
179 }
180
Winson53ec42c2015-10-28 15:55:35 -0700181 public static RecentsConfiguration getConfiguration() {
182 return sConfiguration;
183 }
184
Winsonc742f972015-11-12 11:32:21 -0800185 public static RecentsDebugFlags getDebugFlags() {
186 return sDebugFlags;
187 }
188
Jorim Jaggid61f2272014-12-19 20:35:35 +0100189 @Override
190 public void start() {
Winsonc742f972015-11-12 11:32:21 -0800191 sDebugFlags = new RecentsDebugFlags(mContext);
Jaewan Kim938a50b2016-03-14 17:35:43 +0900192 sSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
Winsone7f138c2015-10-22 16:15:21 -0700193 sTaskLoader = new RecentsTaskLoader(mContext);
Winson53ec42c2015-10-28 15:55:35 -0700194 sConfiguration = new RecentsConfiguration(mContext);
Winson Chung501d59d2016-10-05 17:49:09 +0000195 mHandler = new Handler();
Sid Soundararajan4bdb6872016-03-18 13:42:10 -0700196 UiModeManager uiModeManager = (UiModeManager) mContext.
197 getSystemService(Context.UI_MODE_SERVICE);
198 if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
199 mImpl = new RecentsTvImpl(mContext);
200 } else {
201 mImpl = new RecentsImpl(mContext);
202 }
Jorim Jaggid61f2272014-12-19 20:35:35 +0100203
Winson4727ab92015-11-02 14:35:34 -0800204 // Check if there is a recents override package
205 if ("userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE)) {
206 String cnStr = SystemProperties.get(RECENTS_OVERRIDE_SYSPROP_KEY);
207 if (!cnStr.isEmpty()) {
208 mOverrideRecentsPackageName = cnStr;
209 }
210 }
211
Winson190fe3bf2015-10-20 14:57:24 -0700212 // Register with the event bus
213 EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
Winsonc742f972015-11-12 11:32:21 -0800214 EventBus.getDefault().register(sSystemServicesProxy, EVENT_BUS_PRIORITY);
Winsone7f138c2015-10-22 16:15:21 -0700215 EventBus.getDefault().register(sTaskLoader, EVENT_BUS_PRIORITY);
Jorim Jaggid61f2272014-12-19 20:35:35 +0100216
Winson190fe3bf2015-10-20 14:57:24 -0700217 // Due to the fact that RecentsActivity is per-user, we need to establish and interface for
218 // the system user's Recents component to pass events (like show/hide/toggleRecents) to the
219 // secondary user, and vice versa (like visibility change, screen pinning).
Winsone7f138c2015-10-22 16:15:21 -0700220 final int processUser = sSystemServicesProxy.getProcessUser();
221 if (sSystemServicesProxy.isSystemUser(processUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700222 // For the system user, initialize an instance of the interface that we can pass to the
223 // secondary user
Winsona00a7852016-02-16 11:05:28 -0800224 mSystemToUserCallbacks = new RecentsSystemUser(mContext, mImpl);
Winson190fe3bf2015-10-20 14:57:24 -0700225 } else {
226 // For the secondary user, bind to the primary user's service to get a persistent
227 // interface to register its implementation and to later update its state
228 registerWithSystemUser();
Jorim Jaggid61f2272014-12-19 20:35:35 +0100229 }
Jorim Jaggid61f2272014-12-19 20:35:35 +0100230 putComponent(Recents.class, this);
Winson Chung5abdceb2014-06-05 10:58:05 -0700231 }
232
Jorim Jaggid61f2272014-12-19 20:35:35 +0100233 @Override
Winson Chung8bf05af2014-09-29 13:42:49 -0700234 public void onBootCompleted() {
Winson190fe3bf2015-10-20 14:57:24 -0700235 mImpl.onBootCompleted();
Winson Chung8bf05af2014-09-29 13:42:49 -0700236 }
237
Winson190fe3bf2015-10-20 14:57:24 -0700238 /**
239 * Shows the Recents.
240 */
Jorim Jaggid61f2272014-12-19 20:35:35 +0100241 @Override
Jorim Jaggidb21bbd2016-04-18 15:32:07 -0700242 public void showRecents(boolean triggeredFromAltTab, boolean fromHome) {
Winsone9243562015-11-10 16:07:13 -0800243 // Ensure the device has been provisioned before allowing the user to interact with
244 // recents
Winsone6309aa2016-01-08 11:19:21 -0800245 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800246 return;
247 }
248
Winson4727ab92015-11-02 14:35:34 -0800249 if (proxyToOverridePackage(ACTION_SHOW_RECENTS)) {
250 return;
251 }
252
Jorim Jaggidb21bbd2016-04-18 15:32:07 -0700253 int recentsGrowTarget = getComponent(Divider.class).getView().growsRecents();
254
Winsone7f138c2015-10-22 16:15:21 -0700255 int currentUser = sSystemServicesProxy.getCurrentUser();
256 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Jorim Jaggi435b2e42015-11-24 15:09:30 -0800257 mImpl.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
Jorim Jaggidb21bbd2016-04-18 15:32:07 -0700258 true /* animate */, false /* reloadTasks */, fromHome, recentsGrowTarget);
Winson Chung2002cf52014-12-08 17:26:44 -0800259 } else {
Winsona00a7852016-02-16 11:05:28 -0800260 if (mSystemToUserCallbacks != null) {
Winson190fe3bf2015-10-20 14:57:24 -0700261 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800262 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Winson190fe3bf2015-10-20 14:57:24 -0700263 if (callbacks != null) {
264 try {
Jorim Jaggibb42a462015-11-20 16:27:16 -0800265 callbacks.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
Jorim Jaggidb21bbd2016-04-18 15:32:07 -0700266 true /* animate */, false /* reloadTasks */, fromHome,
267 recentsGrowTarget);
Winson190fe3bf2015-10-20 14:57:24 -0700268 } catch (RemoteException e) {
269 Log.e(TAG, "Callback failed", e);
270 }
271 } else {
272 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
273 }
274 }
Winson Chung2002cf52014-12-08 17:26:44 -0800275 }
276 }
Jorim Jaggid61f2272014-12-19 20:35:35 +0100277
Winson190fe3bf2015-10-20 14:57:24 -0700278 /**
279 * Hides the Recents.
280 */
Jorim Jaggid61f2272014-12-19 20:35:35 +0100281 @Override
282 public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
Winsone9243562015-11-10 16:07:13 -0800283 // Ensure the device has been provisioned before allowing the user to interact with
284 // recents
Winsone6309aa2016-01-08 11:19:21 -0800285 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800286 return;
287 }
288
Winson4727ab92015-11-02 14:35:34 -0800289 if (proxyToOverridePackage(ACTION_HIDE_RECENTS)) {
290 return;
291 }
292
Winsone7f138c2015-10-22 16:15:21 -0700293 int currentUser = sSystemServicesProxy.getCurrentUser();
294 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700295 mImpl.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
Winson Chung2002cf52014-12-08 17:26:44 -0800296 } else {
Winsona00a7852016-02-16 11:05:28 -0800297 if (mSystemToUserCallbacks != null) {
Winson190fe3bf2015-10-20 14:57:24 -0700298 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800299 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Winson190fe3bf2015-10-20 14:57:24 -0700300 if (callbacks != null) {
301 try {
302 callbacks.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
303 } catch (RemoteException e) {
304 Log.e(TAG, "Callback failed", e);
305 }
306 } else {
307 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
308 }
309 }
Winson Chung2002cf52014-12-08 17:26:44 -0800310 }
311 }
Jorim Jaggid61f2272014-12-19 20:35:35 +0100312
Winson190fe3bf2015-10-20 14:57:24 -0700313 /**
314 * Toggles the Recents activity.
315 */
Jorim Jaggid61f2272014-12-19 20:35:35 +0100316 @Override
Jorim Jaggidb21bbd2016-04-18 15:32:07 -0700317 public void toggleRecents(Display display) {
Winsone9243562015-11-10 16:07:13 -0800318 // Ensure the device has been provisioned before allowing the user to interact with
319 // recents
Winsone6309aa2016-01-08 11:19:21 -0800320 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800321 return;
322 }
323
Winson4727ab92015-11-02 14:35:34 -0800324 if (proxyToOverridePackage(ACTION_TOGGLE_RECENTS)) {
325 return;
326 }
327
Jorim Jaggidb21bbd2016-04-18 15:32:07 -0700328 int growTarget = getComponent(Divider.class).getView().growsRecents();
329
Winsone7f138c2015-10-22 16:15:21 -0700330 int currentUser = sSystemServicesProxy.getCurrentUser();
331 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Jorim Jaggidb21bbd2016-04-18 15:32:07 -0700332 mImpl.toggleRecents(growTarget);
Winson Chung2002cf52014-12-08 17:26:44 -0800333 } else {
Winsona00a7852016-02-16 11:05:28 -0800334 if (mSystemToUserCallbacks != null) {
Winson190fe3bf2015-10-20 14:57:24 -0700335 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800336 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Winson190fe3bf2015-10-20 14:57:24 -0700337 if (callbacks != null) {
338 try {
Jorim Jaggidb21bbd2016-04-18 15:32:07 -0700339 callbacks.toggleRecents(growTarget);
Winson190fe3bf2015-10-20 14:57:24 -0700340 } catch (RemoteException e) {
341 Log.e(TAG, "Callback failed", e);
342 }
343 } else {
344 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
345 }
346 }
Winson Chung2002cf52014-12-08 17:26:44 -0800347 }
348 }
Jorim Jaggid61f2272014-12-19 20:35:35 +0100349
Winson190fe3bf2015-10-20 14:57:24 -0700350 /**
351 * Preloads info for the Recents activity.
352 */
Jorim Jaggid61f2272014-12-19 20:35:35 +0100353 @Override
354 public void preloadRecents() {
Winsone9243562015-11-10 16:07:13 -0800355 // Ensure the device has been provisioned before allowing the user to interact with
356 // recents
Winsone6309aa2016-01-08 11:19:21 -0800357 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800358 return;
359 }
360
Winsone7f138c2015-10-22 16:15:21 -0700361 int currentUser = sSystemServicesProxy.getCurrentUser();
362 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700363 mImpl.preloadRecents();
Winson Chung2002cf52014-12-08 17:26:44 -0800364 } else {
Winsona00a7852016-02-16 11:05:28 -0800365 if (mSystemToUserCallbacks != null) {
Winson190fe3bf2015-10-20 14:57:24 -0700366 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800367 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Winson190fe3bf2015-10-20 14:57:24 -0700368 if (callbacks != null) {
369 try {
370 callbacks.preloadRecents();
371 } catch (RemoteException e) {
372 Log.e(TAG, "Callback failed", e);
373 }
374 } else {
375 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
376 }
Winson Chunga278cae2015-06-09 13:51:13 -0700377 }
Winson Chunge1e20e12015-06-02 14:11:49 -0700378 }
Winson Chung7048fea2014-03-18 12:21:24 -0700379 }
380
Jorim Jaggid61f2272014-12-19 20:35:35 +0100381 @Override
382 public void cancelPreloadingRecents() {
Winsone9243562015-11-10 16:07:13 -0800383 // Ensure the device has been provisioned before allowing the user to interact with
384 // recents
Winsone6309aa2016-01-08 11:19:21 -0800385 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800386 return;
387 }
388
Winsone7f138c2015-10-22 16:15:21 -0700389 int currentUser = sSystemServicesProxy.getCurrentUser();
390 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700391 mImpl.cancelPreloadingRecents();
Winson Chungb1f74992014-08-08 12:53:09 -0700392 } else {
Winsona00a7852016-02-16 11:05:28 -0800393 if (mSystemToUserCallbacks != null) {
Winson190fe3bf2015-10-20 14:57:24 -0700394 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800395 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Winson190fe3bf2015-10-20 14:57:24 -0700396 if (callbacks != null) {
397 try {
398 callbacks.cancelPreloadingRecents();
399 } catch (RemoteException e) {
400 Log.e(TAG, "Callback failed", e);
401 }
402 } else {
403 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
404 }
405 }
Winson Chungb1f74992014-08-08 12:53:09 -0700406 }
407 }
408
Jorim Jaggid61f2272014-12-19 20:35:35 +0100409 @Override
Jorim Jaggi29379ec2016-04-11 23:43:42 -0700410 public boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds,
411 int metricsDockAction) {
Winsone6309aa2016-01-08 11:19:21 -0800412 // Ensure the device has been provisioned before allowing the user to interact with
413 // recents
414 if (!isUserSetup()) {
415 return false;
Jorim Jaggidd98d412015-11-18 15:57:38 -0800416 }
Winsone6309aa2016-01-08 11:19:21 -0800417
Muyuan Lia2129992016-03-03 18:30:39 -0800418 Point realSize = new Point();
419 if (initialBounds == null) {
420 mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
421 .getRealSize(realSize);
422 initialBounds = new Rect(0, 0, realSize.x, realSize.y);
423 }
424
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800425 int currentUser = sSystemServicesProxy.getCurrentUser();
426 SystemServicesProxy ssp = Recents.getSystemServices();
Winsond46b7272016-04-20 11:54:27 -0700427 ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800428 boolean screenPinningActive = ssp.isScreenPinningActive();
Winsond46b7272016-04-20 11:54:27 -0700429 boolean isRunningTaskInHomeStack = runningTask != null &&
430 SystemServicesProxy.isHomeStack(runningTask.stackId);
431 if (runningTask != null && !isRunningTaskInHomeStack && !screenPinningActive) {
432 logDockAttempt(mContext, runningTask.topActivity, runningTask.resizeMode);
433 if (runningTask.isDockable) {
Jorim Jaggi29379ec2016-04-11 23:43:42 -0700434 if (metricsDockAction != -1) {
435 MetricsLogger.action(mContext, metricsDockAction,
Winsond46b7272016-04-20 11:54:27 -0700436 runningTask.topActivity.flattenToShortString());
Jorim Jaggi29379ec2016-04-11 23:43:42 -0700437 }
Jorim Jaggiaa6c5742016-03-01 14:10:14 +0100438 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Winsond46b7272016-04-20 11:54:27 -0700439 mImpl.dockTopTask(runningTask.id, dragMode, stackCreateMode, initialBounds);
Jorim Jaggiaa6c5742016-03-01 14:10:14 +0100440 } else {
441 if (mSystemToUserCallbacks != null) {
442 IRecentsNonSystemUserCallbacks callbacks =
443 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
444 if (callbacks != null) {
445 try {
Winsond46b7272016-04-20 11:54:27 -0700446 callbacks.dockTopTask(runningTask.id, dragMode, stackCreateMode,
Jorim Jaggiaa6c5742016-03-01 14:10:14 +0100447 initialBounds);
448 } catch (RemoteException e) {
449 Log.e(TAG, "Callback failed", e);
450 }
451 } else {
452 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800453 }
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800454 }
455 }
Jorim Jaggiaa6c5742016-03-01 14:10:14 +0100456 mDraggingInRecentsCurrentUser = currentUser;
457 return true;
458 } else {
Winson675c5d82016-08-23 17:12:22 -0700459 EventBus.getDefault().send(new ShowUserToastEvent(
460 R.string.recents_incompatible_app_message, Toast.LENGTH_SHORT));
Jorim Jaggiaa6c5742016-03-01 14:10:14 +0100461 return false;
Winsone6309aa2016-01-08 11:19:21 -0800462 }
Jorim Jaggiaa6c5742016-03-01 14:10:14 +0100463 } else {
464 return false;
Winsone6309aa2016-01-08 11:19:21 -0800465 }
Jorim Jaggidd98d412015-11-18 15:57:38 -0800466 }
467
Jorim Jaggi29379ec2016-04-11 23:43:42 -0700468 public static void logDockAttempt(Context ctx, ComponentName activity, int resizeMode) {
469 if (resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE) {
470 MetricsLogger.action(ctx, MetricsEvent.ACTION_WINDOW_DOCK_UNRESIZABLE,
471 activity.flattenToShortString());
472 }
473 MetricsLogger.count(ctx, getMetricsCounterForResizeMode(resizeMode), 1);
474 }
475
476 private static String getMetricsCounterForResizeMode(int resizeMode) {
477 switch (resizeMode) {
478 case ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE:
479 return COUNTER_WINDOW_UNSUPPORTED;
480 case ActivityInfo.RESIZE_MODE_RESIZEABLE:
481 case ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE:
482 return COUNTER_WINDOW_SUPPORTED;
483 default:
484 return COUNTER_WINDOW_INCOMPATIBLE;
485 }
486 }
487
Jorim Jaggidd98d412015-11-18 15:57:38 -0800488 @Override
489 public void onDraggingInRecents(float distanceFromTop) {
490 if (sSystemServicesProxy.isSystemUser(mDraggingInRecentsCurrentUser)) {
491 mImpl.onDraggingInRecents(distanceFromTop);
492 } else {
Winsona00a7852016-02-16 11:05:28 -0800493 if (mSystemToUserCallbacks != null) {
Jorim Jaggidd98d412015-11-18 15:57:38 -0800494 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800495 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(
Jorim Jaggidd98d412015-11-18 15:57:38 -0800496 mDraggingInRecentsCurrentUser);
497 if (callbacks != null) {
498 try {
499 callbacks.onDraggingInRecents(distanceFromTop);
500 } catch (RemoteException e) {
501 Log.e(TAG, "Callback failed", e);
502 }
503 } else {
504 Log.e(TAG, "No SystemUI callbacks found for user: "
505 + mDraggingInRecentsCurrentUser);
506 }
507 }
508 }
509 }
510
511 @Override
512 public void onDraggingInRecentsEnded(float velocity) {
513 if (sSystemServicesProxy.isSystemUser(mDraggingInRecentsCurrentUser)) {
514 mImpl.onDraggingInRecentsEnded(velocity);
515 } else {
Winsona00a7852016-02-16 11:05:28 -0800516 if (mSystemToUserCallbacks != null) {
Jorim Jaggidd98d412015-11-18 15:57:38 -0800517 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800518 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(
Jorim Jaggidd98d412015-11-18 15:57:38 -0800519 mDraggingInRecentsCurrentUser);
520 if (callbacks != null) {
521 try {
522 callbacks.onDraggingInRecentsEnded(velocity);
523 } catch (RemoteException e) {
524 Log.e(TAG, "Callback failed", e);
525 }
526 } else {
527 Log.e(TAG, "No SystemUI callbacks found for user: "
528 + mDraggingInRecentsCurrentUser);
529 }
530 }
531 }
Jorim Jaggi75b25972015-10-21 14:51:10 +0200532 }
533
534 @Override
Jorim Jaggid61f2272014-12-19 20:35:35 +0100535 public void showNextAffiliatedTask() {
Winsone9243562015-11-10 16:07:13 -0800536 // Ensure the device has been provisioned before allowing the user to interact with
537 // recents
Winsone6309aa2016-01-08 11:19:21 -0800538 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800539 return;
540 }
541
Winson190fe3bf2015-10-20 14:57:24 -0700542 mImpl.showNextAffiliatedTask();
Winson Chungb1f74992014-08-08 12:53:09 -0700543 }
544
Jorim Jaggid61f2272014-12-19 20:35:35 +0100545 @Override
546 public void showPrevAffiliatedTask() {
Winsone9243562015-11-10 16:07:13 -0800547 // Ensure the device has been provisioned before allowing the user to interact with
548 // recents
Winsone6309aa2016-01-08 11:19:21 -0800549 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800550 return;
551 }
552
Winson190fe3bf2015-10-20 14:57:24 -0700553 mImpl.showPrevAffiliatedTask();
Winson Chungb1f74992014-08-08 12:53:09 -0700554 }
555
Winson190fe3bf2015-10-20 14:57:24 -0700556 /**
557 * Updates on configuration change.
558 */
Winson Chung7048fea2014-03-18 12:21:24 -0700559 public void onConfigurationChanged(Configuration newConfig) {
Winsone7f138c2015-10-22 16:15:21 -0700560 int currentUser = sSystemServicesProxy.getCurrentUser();
561 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700562 mImpl.onConfigurationChanged();
Winson Chung2002cf52014-12-08 17:26:44 -0800563 } else {
Winsona00a7852016-02-16 11:05:28 -0800564 if (mSystemToUserCallbacks != null) {
Winson190fe3bf2015-10-20 14:57:24 -0700565 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800566 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Winson190fe3bf2015-10-20 14:57:24 -0700567 if (callbacks != null) {
568 try {
569 callbacks.onConfigurationChanged();
570 } catch (RemoteException e) {
571 Log.e(TAG, "Callback failed", e);
Winson Chungb0a28ea2014-10-28 15:21:35 -0700572 }
Winson190fe3bf2015-10-20 14:57:24 -0700573 } else {
574 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
Winson Chungb0a28ea2014-10-28 15:21:35 -0700575 }
Winson190fe3bf2015-10-20 14:57:24 -0700576 }
Winson Chungb0a28ea2014-10-28 15:21:35 -0700577 }
578 }
Winson190fe3bf2015-10-20 14:57:24 -0700579
580 /**
581 * Handle Recents activity visibility changed.
582 */
583 public final void onBusEvent(final RecentsVisibilityChangedEvent event) {
Winson88737542016-02-17 13:27:33 -0800584 SystemServicesProxy ssp = Recents.getSystemServices();
585 int processUser = ssp.getProcessUser();
586 if (ssp.isSystemUser(processUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700587 mImpl.onVisibilityChanged(event.applicationContext, event.visible);
588 } else {
589 postToSystemUser(new Runnable() {
590 @Override
591 public void run() {
592 try {
Winsona00a7852016-02-16 11:05:28 -0800593 mUserToSystemCallbacks.updateRecentsVisibility(event.visible);
Winson190fe3bf2015-10-20 14:57:24 -0700594 } catch (RemoteException e) {
595 Log.e(TAG, "Callback failed", e);
596 }
597 }
598 });
599 }
600 }
601
602 /**
603 * Handle screen pinning request.
604 */
605 public final void onBusEvent(final ScreenPinningRequestEvent event) {
Winson83c1b072015-11-09 10:48:04 -0800606 int processUser = sSystemServicesProxy.getProcessUser();
607 if (sSystemServicesProxy.isSystemUser(processUser)) {
Andrii Kulian0f051f52016-04-14 00:41:51 -0700608 mImpl.onStartScreenPinning(event.applicationContext, event.taskId);
Winson190fe3bf2015-10-20 14:57:24 -0700609 } else {
610 postToSystemUser(new Runnable() {
611 @Override
612 public void run() {
613 try {
Andrii Kulian0f051f52016-04-14 00:41:51 -0700614 mUserToSystemCallbacks.startScreenPinning(event.taskId);
Winson190fe3bf2015-10-20 14:57:24 -0700615 } catch (RemoteException e) {
616 Log.e(TAG, "Callback failed", e);
617 }
618 }
619 });
620 }
621 }
622
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800623 public final void onBusEvent(final RecentsDrawnEvent event) {
624 int processUser = sSystemServicesProxy.getProcessUser();
625 if (!sSystemServicesProxy.isSystemUser(processUser)) {
626 postToSystemUser(new Runnable() {
627 @Override
628 public void run() {
629 try {
Winsona00a7852016-02-16 11:05:28 -0800630 mUserToSystemCallbacks.sendRecentsDrawnEvent();
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800631 } catch (RemoteException e) {
632 Log.e(TAG, "Callback failed", e);
633 }
634 }
635 });
636 }
637 }
638
Jorim Jaggi899327f2016-02-25 20:44:18 -0500639 public final void onBusEvent(final DockedTopTaskEvent event) {
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800640 int processUser = sSystemServicesProxy.getProcessUser();
641 if (!sSystemServicesProxy.isSystemUser(processUser)) {
642 postToSystemUser(new Runnable() {
643 @Override
644 public void run() {
645 try {
Jorim Jaggi899327f2016-02-25 20:44:18 -0500646 mUserToSystemCallbacks.sendDockingTopTaskEvent(event.dragMode,
647 event.initialRect);
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800648 } catch (RemoteException e) {
649 Log.e(TAG, "Callback failed", e);
650 }
651 }
652 });
653 }
654 }
655
656 public final void onBusEvent(final RecentsActivityStartingEvent event) {
657 int processUser = sSystemServicesProxy.getProcessUser();
658 if (!sSystemServicesProxy.isSystemUser(processUser)) {
659 postToSystemUser(new Runnable() {
660 @Override
661 public void run() {
662 try {
Winsona00a7852016-02-16 11:05:28 -0800663 mUserToSystemCallbacks.sendLaunchRecentsEvent();
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800664 } catch (RemoteException e) {
665 Log.e(TAG, "Callback failed", e);
666 }
667 }
668 });
669 }
670 }
671
Winson003eda62016-03-11 14:56:00 -0800672 public final void onBusEvent(ConfigurationChangedEvent event) {
673 // Update the configuration for the Recents component when the activity configuration
674 // changes as well
675 mImpl.onConfigurationChanged();
676 }
677
Winson675c5d82016-08-23 17:12:22 -0700678 public final void onBusEvent(ShowUserToastEvent event) {
679 int currentUser = sSystemServicesProxy.getCurrentUser();
680 if (sSystemServicesProxy.isSystemUser(currentUser)) {
681 mImpl.onShowCurrentUserToast(event.msgResId, event.msgLength);
682 } else {
683 if (mSystemToUserCallbacks != null) {
684 IRecentsNonSystemUserCallbacks callbacks =
685 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
686 if (callbacks != null) {
687 try {
688 callbacks.showCurrentUserToast(event.msgResId, event.msgLength);
689 } catch (RemoteException e) {
690 Log.e(TAG, "Callback failed", e);
691 }
692 } else {
693 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
694 }
695 }
696 }
697 }
698
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800699 /**
Winson190fe3bf2015-10-20 14:57:24 -0700700 * Attempts to register with the system user.
701 */
702 private void registerWithSystemUser() {
Winsone7f138c2015-10-22 16:15:21 -0700703 final int processUser = sSystemServicesProxy.getProcessUser();
Winson190fe3bf2015-10-20 14:57:24 -0700704 postToSystemUser(new Runnable() {
705 @Override
706 public void run() {
707 try {
Winsona00a7852016-02-16 11:05:28 -0800708 mUserToSystemCallbacks.registerNonSystemUserCallbacks(
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800709 new RecentsImplProxy(mImpl), processUser);
Winson190fe3bf2015-10-20 14:57:24 -0700710 } catch (RemoteException e) {
711 Log.e(TAG, "Failed to register", e);
712 }
713 }
714 });
715 }
716
717 /**
718 * Runs the runnable in the system user's Recents context, connecting to the service if
719 * necessary.
720 */
721 private void postToSystemUser(final Runnable onConnectRunnable) {
722 mOnConnectRunnables.add(onConnectRunnable);
Winsona00a7852016-02-16 11:05:28 -0800723 if (mUserToSystemCallbacks == null) {
Winson190fe3bf2015-10-20 14:57:24 -0700724 Intent systemUserServiceIntent = new Intent();
725 systemUserServiceIntent.setClass(mContext, RecentsSystemUserService.class);
726 boolean bound = mContext.bindServiceAsUser(systemUserServiceIntent,
Winsona00a7852016-02-16 11:05:28 -0800727 mUserToSystemServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
728 EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
729 EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_BIND_SERVICE,
730 sSystemServicesProxy.getProcessUser());
Winson190fe3bf2015-10-20 14:57:24 -0700731 if (!bound) {
732 // Retry after a fixed duration
733 mHandler.postDelayed(new Runnable() {
734 @Override
735 public void run() {
736 registerWithSystemUser();
737 }
738 }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
739 }
740 } else {
741 runAndFlushOnConnectRunnables();
742 }
743 }
744
745 /**
746 * Runs all the queued runnables after a service connection is made.
747 */
748 private void runAndFlushOnConnectRunnables() {
749 for (Runnable r : mOnConnectRunnables) {
750 r.run();
751 }
752 mOnConnectRunnables.clear();
753 }
Winson4727ab92015-11-02 14:35:34 -0800754
755 /**
Winsone6309aa2016-01-08 11:19:21 -0800756 * @return whether this device is provisioned and the current user is set up.
Winsone9243562015-11-10 16:07:13 -0800757 */
Winsone6309aa2016-01-08 11:19:21 -0800758 private boolean isUserSetup() {
759 ContentResolver cr = mContext.getContentResolver();
760 return (Settings.Global.getInt(cr, Settings.Global.DEVICE_PROVISIONED, 0) != 0) &&
761 (Settings.Secure.getInt(cr, Settings.Secure.USER_SETUP_COMPLETE, 0) != 0);
Winsone9243562015-11-10 16:07:13 -0800762 }
763
764 /**
Winson4727ab92015-11-02 14:35:34 -0800765 * Attempts to proxy the following action to the override recents package.
766 * @return whether the proxying was successful
767 */
768 private boolean proxyToOverridePackage(String action) {
769 if (mOverrideRecentsPackageName != null) {
770 Intent intent = new Intent(action);
771 intent.setPackage(mOverrideRecentsPackageName);
772 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
773 mContext.sendBroadcast(intent);
774 return true;
775 }
776 return false;
777 }
Winson Chung7048fea2014-03-18 12:21:24 -0700778}