blob: f5ae3514d7807ea50a0aff98a5a9e85c2cc617e7 [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;
Winson190fe3bf2015-10-20 14:57:24 -070020import android.content.ComponentName;
Winsone6309aa2016-01-08 11:19:21 -080021import android.content.ContentResolver;
Winson Chung7048fea2014-03-18 12:21:24 -070022import android.content.Context;
23import android.content.Intent;
Winson190fe3bf2015-10-20 14:57:24 -070024import android.content.ServiceConnection;
Winson Chung7048fea2014-03-18 12:21:24 -070025import android.content.res.Configuration;
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -080026import android.graphics.Rect;
Winson4727ab92015-11-02 14:35:34 -080027import android.os.Build;
Jim Millera237a312014-11-06 18:05:59 -080028import android.os.Handler;
Winson190fe3bf2015-10-20 14:57:24 -070029import android.os.IBinder;
30import android.os.RemoteException;
Winson4727ab92015-11-02 14:35:34 -080031import android.os.SystemProperties;
Winson Chung7048fea2014-03-18 12:21:24 -070032import android.os.UserHandle;
Winsone9243562015-11-10 16:07:13 -080033import android.provider.Settings;
Winsona00a7852016-02-16 11:05:28 -080034import android.util.EventLog;
Winson190fe3bf2015-10-20 14:57:24 -070035import android.util.Log;
Jorim Jaggid61f2272014-12-19 20:35:35 +010036import android.view.Display;
Winson Chung7048fea2014-03-18 12:21:24 -070037import android.view.View;
Winsonc0d70582016-01-29 10:24:39 -080038
Winsona00a7852016-02-16 11:05:28 -080039import com.android.systemui.EventLogConstants;
40import com.android.systemui.EventLogTags;
Winson Chung9214eff2014-06-12 13:59:25 -070041import com.android.systemui.RecentsComponent;
Jorim Jaggid61f2272014-12-19 20:35:35 +010042import com.android.systemui.SystemUI;
Winson190fe3bf2015-10-20 14:57:24 -070043import com.android.systemui.recents.events.EventBus;
Jorim Jaggicdb06ca2016-01-25 19:15:12 -080044import com.android.systemui.recents.events.activity.DockingTopTaskEvent;
45import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
Winson190fe3bf2015-10-20 14:57:24 -070046import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
47import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
Jorim Jaggi11cc01d2016-01-22 19:39:23 -080048import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
Winson Chungffa2ec62014-07-03 15:54:42 -070049import com.android.systemui.recents.misc.SystemServicesProxy;
Winsone7f138c2015-10-22 16:15:21 -070050import com.android.systemui.recents.model.RecentsTaskLoader;
Winson Chung7048fea2014-03-18 12:21:24 -070051
Winson Chungffa2ec62014-07-03 15:54:42 -070052import java.util.ArrayList;
Winson Chung7048fea2014-03-18 12:21:24 -070053
Winson Chung740c3ac2014-11-12 16:14:38 -080054
Winson190fe3bf2015-10-20 14:57:24 -070055/**
56 * An implementation of the SystemUI recents component, which supports both system and secondary
57 * users.
58 */
Jorim Jaggid61f2272014-12-19 20:35:35 +010059public class Recents extends SystemUI
Winson190fe3bf2015-10-20 14:57:24 -070060 implements RecentsComponent {
61
62 private final static String TAG = "Recents";
63 private final static boolean DEBUG = false;
Winson Chung7048fea2014-03-18 12:21:24 -070064
Winsone6c90732015-09-24 16:06:29 -070065 public final static int EVENT_BUS_PRIORITY = 1;
Winson190fe3bf2015-10-20 14:57:24 -070066 public final static int BIND_TO_SYSTEM_USER_RETRY_DELAY = 5000;
Winsone6c90732015-09-24 16:06:29 -070067
Winson4727ab92015-11-02 14:35:34 -080068 // Purely for experimentation
69 private final static String RECENTS_OVERRIDE_SYSPROP_KEY = "persist.recents_override_pkg";
70 private final static String ACTION_SHOW_RECENTS = "com.android.systemui.recents.ACTION_SHOW";
71 private final static String ACTION_HIDE_RECENTS = "com.android.systemui.recents.ACTION_HIDE";
72 private final static String ACTION_TOGGLE_RECENTS = "com.android.systemui.recents.ACTION_TOGGLE";
73
Winsone7f138c2015-10-22 16:15:21 -070074 private static SystemServicesProxy sSystemServicesProxy;
Winsonc742f972015-11-12 11:32:21 -080075 private static RecentsDebugFlags sDebugFlags;
Winsone7f138c2015-10-22 16:15:21 -070076 private static RecentsTaskLoader sTaskLoader;
Winson53ec42c2015-10-28 15:55:35 -070077 private static RecentsConfiguration sConfiguration;
Winsone7f138c2015-10-22 16:15:21 -070078
Winson4727ab92015-11-02 14:35:34 -080079 // For experiments only, allows another package to handle recents if it is defined in the system
80 // properties. This is limited to show/toggle/hide, and does not tie into the ActivityManager,
81 // and does not reside in the home stack.
82 private String mOverrideRecentsPackageName;
83
Winson190fe3bf2015-10-20 14:57:24 -070084 private Handler mHandler;
85 private RecentsImpl mImpl;
Jorim Jaggidd98d412015-11-18 15:57:38 -080086 private int mDraggingInRecentsCurrentUser;
Winson Chung2002cf52014-12-08 17:26:44 -080087
Winson190fe3bf2015-10-20 14:57:24 -070088 // Only For system user, this is the callbacks instance we return to each secondary user
Winsona00a7852016-02-16 11:05:28 -080089 private RecentsSystemUser mSystemToUserCallbacks;
Winson Chungcdcd4872014-08-05 18:00:13 -070090
Winson190fe3bf2015-10-20 14:57:24 -070091 // Only for secondary users, this is the callbacks instance provided by the system user to make
92 // calls back
Winsona00a7852016-02-16 11:05:28 -080093 private IRecentsSystemUserCallbacks mUserToSystemCallbacks;
Winson Chungb44c24f2014-04-09 15:17:43 -070094
Winson190fe3bf2015-10-20 14:57:24 -070095 // The set of runnables to run after binding to the system user's service.
96 private final ArrayList<Runnable> mOnConnectRunnables = new ArrayList<>();
Winson Chung7048fea2014-03-18 12:21:24 -070097
Winson190fe3bf2015-10-20 14:57:24 -070098 // Only for secondary users, this is the death handler for the binder from the system user
Winsona00a7852016-02-16 11:05:28 -080099 private final IBinder.DeathRecipient mUserToSystemCallbacksDeathRcpt = new IBinder.DeathRecipient() {
Winson Chung740c3ac2014-11-12 16:14:38 -0800100 @Override
Winson190fe3bf2015-10-20 14:57:24 -0700101 public void binderDied() {
Winsona00a7852016-02-16 11:05:28 -0800102 mUserToSystemCallbacks = null;
103 EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
104 EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_UNBOUND,
105 sSystemServicesProxy.getProcessUser());
Winson Chung2002cf52014-12-08 17:26:44 -0800106
Winson190fe3bf2015-10-20 14:57:24 -0700107 // Retry after a fixed duration
108 mHandler.postDelayed(new Runnable() {
109 @Override
110 public void run() {
111 registerWithSystemUser();
Winson Chung0eae5572014-12-11 11:04:19 -0800112 }
Winson190fe3bf2015-10-20 14:57:24 -0700113 }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
Winson Chung740c3ac2014-11-12 16:14:38 -0800114 }
Winson190fe3bf2015-10-20 14:57:24 -0700115 };
Winson Chung740c3ac2014-11-12 16:14:38 -0800116
Winson190fe3bf2015-10-20 14:57:24 -0700117 // Only for secondary users, this is the service connection we use to connect to the system user
Winsona00a7852016-02-16 11:05:28 -0800118 private final ServiceConnection mUserToSystemServiceConnection = new ServiceConnection() {
Winson Chung2002cf52014-12-08 17:26:44 -0800119 @Override
Winson190fe3bf2015-10-20 14:57:24 -0700120 public void onServiceConnected(ComponentName name, IBinder service) {
121 if (service != null) {
Winsona00a7852016-02-16 11:05:28 -0800122 mUserToSystemCallbacks = IRecentsSystemUserCallbacks.Stub.asInterface(
Winson190fe3bf2015-10-20 14:57:24 -0700123 service);
Winsona00a7852016-02-16 11:05:28 -0800124 EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
125 EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_BOUND,
126 sSystemServicesProxy.getProcessUser());
Winson190fe3bf2015-10-20 14:57:24 -0700127
128 // Listen for system user's death, so that we can reconnect later
129 try {
Winsona00a7852016-02-16 11:05:28 -0800130 service.linkToDeath(mUserToSystemCallbacksDeathRcpt, 0);
Winson190fe3bf2015-10-20 14:57:24 -0700131 } catch (RemoteException e) {
132 Log.e(TAG, "Lost connection to (System) SystemUI", e);
133 }
134
135 // Run each of the queued runnables
136 runAndFlushOnConnectRunnables();
Winson Chung2002cf52014-12-08 17:26:44 -0800137 }
Winson190fe3bf2015-10-20 14:57:24 -0700138
139 // Unbind ourselves now that we've registered our callbacks. The
140 // binder to the system user are still valid at this point.
141 mContext.unbindService(this);
Winson Chung2002cf52014-12-08 17:26:44 -0800142 }
Winson Chung2002cf52014-12-08 17:26:44 -0800143
Winson190fe3bf2015-10-20 14:57:24 -0700144 @Override
145 public void onServiceDisconnected(ComponentName name) {
146 // Do nothing
147 }
148 };
Winson Chung740c3ac2014-11-12 16:14:38 -0800149
Jorim Jaggid61f2272014-12-19 20:35:35 +0100150 /**
Winson190fe3bf2015-10-20 14:57:24 -0700151 * Returns the callbacks interface that non-system users can call.
Jorim Jaggid61f2272014-12-19 20:35:35 +0100152 */
Winson190fe3bf2015-10-20 14:57:24 -0700153 public IBinder getSystemUserCallbacks() {
Winsona00a7852016-02-16 11:05:28 -0800154 return mSystemToUserCallbacks;
Winson Chung7048fea2014-03-18 12:21:24 -0700155 }
156
Winsone7f138c2015-10-22 16:15:21 -0700157 public static RecentsTaskLoader getTaskLoader() {
158 return sTaskLoader;
159 }
160
161 public static SystemServicesProxy getSystemServices() {
162 return sSystemServicesProxy;
163 }
164
Winson53ec42c2015-10-28 15:55:35 -0700165 public static RecentsConfiguration getConfiguration() {
166 return sConfiguration;
167 }
168
Winsonc742f972015-11-12 11:32:21 -0800169 public static RecentsDebugFlags getDebugFlags() {
170 return sDebugFlags;
171 }
172
Jorim Jaggid61f2272014-12-19 20:35:35 +0100173 @Override
174 public void start() {
Winsonc742f972015-11-12 11:32:21 -0800175 sDebugFlags = new RecentsDebugFlags(mContext);
Winsone7f138c2015-10-22 16:15:21 -0700176 sSystemServicesProxy = new SystemServicesProxy(mContext);
177 sTaskLoader = new RecentsTaskLoader(mContext);
Winson53ec42c2015-10-28 15:55:35 -0700178 sConfiguration = new RecentsConfiguration(mContext);
Jorim Jaggid61f2272014-12-19 20:35:35 +0100179 mHandler = new Handler();
Winson190fe3bf2015-10-20 14:57:24 -0700180 mImpl = new RecentsImpl(mContext);
Jorim Jaggid61f2272014-12-19 20:35:35 +0100181
Winson4727ab92015-11-02 14:35:34 -0800182 // Check if there is a recents override package
183 if ("userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE)) {
184 String cnStr = SystemProperties.get(RECENTS_OVERRIDE_SYSPROP_KEY);
185 if (!cnStr.isEmpty()) {
186 mOverrideRecentsPackageName = cnStr;
187 }
188 }
189
Winson190fe3bf2015-10-20 14:57:24 -0700190 // Register with the event bus
191 EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
Winsonc742f972015-11-12 11:32:21 -0800192 EventBus.getDefault().register(sSystemServicesProxy, EVENT_BUS_PRIORITY);
Winsone7f138c2015-10-22 16:15:21 -0700193 EventBus.getDefault().register(sTaskLoader, EVENT_BUS_PRIORITY);
Jorim Jaggid61f2272014-12-19 20:35:35 +0100194
Winson190fe3bf2015-10-20 14:57:24 -0700195 // Due to the fact that RecentsActivity is per-user, we need to establish and interface for
196 // the system user's Recents component to pass events (like show/hide/toggleRecents) to the
197 // secondary user, and vice versa (like visibility change, screen pinning).
Winsone7f138c2015-10-22 16:15:21 -0700198 final int processUser = sSystemServicesProxy.getProcessUser();
199 if (sSystemServicesProxy.isSystemUser(processUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700200 // For the system user, initialize an instance of the interface that we can pass to the
201 // secondary user
Winsona00a7852016-02-16 11:05:28 -0800202 mSystemToUserCallbacks = new RecentsSystemUser(mContext, mImpl);
Winson190fe3bf2015-10-20 14:57:24 -0700203 } else {
204 // For the secondary user, bind to the primary user's service to get a persistent
205 // interface to register its implementation and to later update its state
206 registerWithSystemUser();
Jorim Jaggid61f2272014-12-19 20:35:35 +0100207 }
Jorim Jaggid61f2272014-12-19 20:35:35 +0100208 putComponent(Recents.class, this);
Winson Chung5abdceb2014-06-05 10:58:05 -0700209 }
210
Jorim Jaggid61f2272014-12-19 20:35:35 +0100211 @Override
Winson Chung8bf05af2014-09-29 13:42:49 -0700212 public void onBootCompleted() {
Winson190fe3bf2015-10-20 14:57:24 -0700213 mImpl.onBootCompleted();
Winson Chung8bf05af2014-09-29 13:42:49 -0700214 }
215
Winson190fe3bf2015-10-20 14:57:24 -0700216 /**
217 * Shows the Recents.
218 */
Jorim Jaggid61f2272014-12-19 20:35:35 +0100219 @Override
220 public void showRecents(boolean triggeredFromAltTab, View statusBarView) {
Winsone9243562015-11-10 16:07:13 -0800221 // Ensure the device has been provisioned before allowing the user to interact with
222 // recents
Winsone6309aa2016-01-08 11:19:21 -0800223 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800224 return;
225 }
226
Winson4727ab92015-11-02 14:35:34 -0800227 if (proxyToOverridePackage(ACTION_SHOW_RECENTS)) {
228 return;
229 }
230
Winsone7f138c2015-10-22 16:15:21 -0700231 int currentUser = sSystemServicesProxy.getCurrentUser();
232 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Jorim Jaggi435b2e42015-11-24 15:09:30 -0800233 mImpl.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
234 true /* animate */, false /* reloadTasks */);
Winson Chung2002cf52014-12-08 17:26:44 -0800235 } else {
Winsona00a7852016-02-16 11:05:28 -0800236 if (mSystemToUserCallbacks != null) {
Winson190fe3bf2015-10-20 14:57:24 -0700237 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800238 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Winson190fe3bf2015-10-20 14:57:24 -0700239 if (callbacks != null) {
240 try {
Jorim Jaggibb42a462015-11-20 16:27:16 -0800241 callbacks.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
Jorim Jaggi435b2e42015-11-24 15:09:30 -0800242 true /* animate */, false /* reloadTasks */);
Winson190fe3bf2015-10-20 14:57:24 -0700243 } catch (RemoteException e) {
244 Log.e(TAG, "Callback failed", e);
245 }
246 } else {
247 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
248 }
249 }
Winson Chung2002cf52014-12-08 17:26:44 -0800250 }
251 }
Jorim Jaggid61f2272014-12-19 20:35:35 +0100252
Winson190fe3bf2015-10-20 14:57:24 -0700253 /**
254 * Hides the Recents.
255 */
Jorim Jaggid61f2272014-12-19 20:35:35 +0100256 @Override
257 public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
Winsone9243562015-11-10 16:07:13 -0800258 // Ensure the device has been provisioned before allowing the user to interact with
259 // recents
Winsone6309aa2016-01-08 11:19:21 -0800260 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800261 return;
262 }
263
Winson4727ab92015-11-02 14:35:34 -0800264 if (proxyToOverridePackage(ACTION_HIDE_RECENTS)) {
265 return;
266 }
267
Winsone7f138c2015-10-22 16:15:21 -0700268 int currentUser = sSystemServicesProxy.getCurrentUser();
269 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700270 mImpl.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
Winson Chung2002cf52014-12-08 17:26:44 -0800271 } else {
Winsona00a7852016-02-16 11:05:28 -0800272 if (mSystemToUserCallbacks != null) {
Winson190fe3bf2015-10-20 14:57:24 -0700273 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800274 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Winson190fe3bf2015-10-20 14:57:24 -0700275 if (callbacks != null) {
276 try {
277 callbacks.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
278 } catch (RemoteException e) {
279 Log.e(TAG, "Callback failed", e);
280 }
281 } else {
282 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
283 }
284 }
Winson Chung2002cf52014-12-08 17:26:44 -0800285 }
286 }
Jorim Jaggid61f2272014-12-19 20:35:35 +0100287
Winson190fe3bf2015-10-20 14:57:24 -0700288 /**
289 * Toggles the Recents activity.
290 */
Jorim Jaggid61f2272014-12-19 20:35:35 +0100291 @Override
292 public void toggleRecents(Display display, int layoutDirection, View statusBarView) {
Winsone9243562015-11-10 16:07:13 -0800293 // Ensure the device has been provisioned before allowing the user to interact with
294 // recents
Winsone6309aa2016-01-08 11:19:21 -0800295 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800296 return;
297 }
298
Winson4727ab92015-11-02 14:35:34 -0800299 if (proxyToOverridePackage(ACTION_TOGGLE_RECENTS)) {
300 return;
301 }
302
Winsone7f138c2015-10-22 16:15:21 -0700303 int currentUser = sSystemServicesProxy.getCurrentUser();
304 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700305 mImpl.toggleRecents();
Winson Chung2002cf52014-12-08 17:26:44 -0800306 } else {
Winsona00a7852016-02-16 11:05:28 -0800307 if (mSystemToUserCallbacks != null) {
Winson190fe3bf2015-10-20 14:57:24 -0700308 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800309 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Winson190fe3bf2015-10-20 14:57:24 -0700310 if (callbacks != null) {
311 try {
312 callbacks.toggleRecents();
313 } catch (RemoteException e) {
314 Log.e(TAG, "Callback failed", e);
315 }
316 } else {
317 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
318 }
319 }
Winson Chung2002cf52014-12-08 17:26:44 -0800320 }
321 }
Jorim Jaggid61f2272014-12-19 20:35:35 +0100322
Winson190fe3bf2015-10-20 14:57:24 -0700323 /**
324 * Preloads info for the Recents activity.
325 */
Jorim Jaggid61f2272014-12-19 20:35:35 +0100326 @Override
327 public void preloadRecents() {
Winsone9243562015-11-10 16:07:13 -0800328 // Ensure the device has been provisioned before allowing the user to interact with
329 // recents
Winsone6309aa2016-01-08 11:19:21 -0800330 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800331 return;
332 }
333
Winsone7f138c2015-10-22 16:15:21 -0700334 int currentUser = sSystemServicesProxy.getCurrentUser();
335 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700336 mImpl.preloadRecents();
Winson Chung2002cf52014-12-08 17:26:44 -0800337 } else {
Winsona00a7852016-02-16 11:05:28 -0800338 if (mSystemToUserCallbacks != null) {
Winson190fe3bf2015-10-20 14:57:24 -0700339 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800340 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Winson190fe3bf2015-10-20 14:57:24 -0700341 if (callbacks != null) {
342 try {
343 callbacks.preloadRecents();
344 } catch (RemoteException e) {
345 Log.e(TAG, "Callback failed", e);
346 }
347 } else {
348 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
349 }
Winson Chunga278cae2015-06-09 13:51:13 -0700350 }
Winson Chunge1e20e12015-06-02 14:11:49 -0700351 }
Winson Chung7048fea2014-03-18 12:21:24 -0700352 }
353
Jorim Jaggid61f2272014-12-19 20:35:35 +0100354 @Override
355 public void cancelPreloadingRecents() {
Winsone9243562015-11-10 16:07:13 -0800356 // Ensure the device has been provisioned before allowing the user to interact with
357 // recents
Winsone6309aa2016-01-08 11:19:21 -0800358 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800359 return;
360 }
361
Winsone7f138c2015-10-22 16:15:21 -0700362 int currentUser = sSystemServicesProxy.getCurrentUser();
363 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700364 mImpl.cancelPreloadingRecents();
Winson Chungb1f74992014-08-08 12:53:09 -0700365 } else {
Winsona00a7852016-02-16 11:05:28 -0800366 if (mSystemToUserCallbacks != null) {
Winson190fe3bf2015-10-20 14:57:24 -0700367 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800368 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Winson190fe3bf2015-10-20 14:57:24 -0700369 if (callbacks != null) {
370 try {
371 callbacks.cancelPreloadingRecents();
372 } catch (RemoteException e) {
373 Log.e(TAG, "Callback failed", e);
374 }
375 } else {
376 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
377 }
378 }
Winson Chungb1f74992014-08-08 12:53:09 -0700379 }
380 }
381
Jorim Jaggid61f2272014-12-19 20:35:35 +0100382 @Override
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800383 public boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds) {
Winsone6309aa2016-01-08 11:19:21 -0800384 // Ensure the device has been provisioned before allowing the user to interact with
385 // recents
386 if (!isUserSetup()) {
387 return false;
Jorim Jaggidd98d412015-11-18 15:57:38 -0800388 }
Winsone6309aa2016-01-08 11:19:21 -0800389
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800390 int currentUser = sSystemServicesProxy.getCurrentUser();
391 SystemServicesProxy ssp = Recents.getSystemServices();
392 ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
393 boolean screenPinningActive = ssp.isScreenPinningActive();
394 boolean isTopTaskHome = topTask != null && SystemServicesProxy.isHomeStack(topTask.stackId);
395 if (topTask != null && !isTopTaskHome && !screenPinningActive) {
396 if (sSystemServicesProxy.isSystemUser(currentUser)) {
397 mImpl.dockTopTask(topTask.id, dragMode, stackCreateMode, initialBounds);
398 } else {
Winsona00a7852016-02-16 11:05:28 -0800399 if (mSystemToUserCallbacks != null) {
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800400 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800401 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800402 if (callbacks != null) {
403 try {
404 callbacks.dockTopTask(topTask.id, dragMode, stackCreateMode,
405 initialBounds);
406 } catch (RemoteException e) {
407 Log.e(TAG, "Callback failed", e);
408 }
409 } else {
410 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
411 }
412 }
Winsone6309aa2016-01-08 11:19:21 -0800413 }
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800414 mDraggingInRecentsCurrentUser = currentUser;
Winsone6309aa2016-01-08 11:19:21 -0800415 return true;
416 }
417 return false;
Jorim Jaggidd98d412015-11-18 15:57:38 -0800418 }
419
420 @Override
421 public void onDraggingInRecents(float distanceFromTop) {
422 if (sSystemServicesProxy.isSystemUser(mDraggingInRecentsCurrentUser)) {
423 mImpl.onDraggingInRecents(distanceFromTop);
424 } else {
Winsona00a7852016-02-16 11:05:28 -0800425 if (mSystemToUserCallbacks != null) {
Jorim Jaggidd98d412015-11-18 15:57:38 -0800426 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800427 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(
Jorim Jaggidd98d412015-11-18 15:57:38 -0800428 mDraggingInRecentsCurrentUser);
429 if (callbacks != null) {
430 try {
431 callbacks.onDraggingInRecents(distanceFromTop);
432 } catch (RemoteException e) {
433 Log.e(TAG, "Callback failed", e);
434 }
435 } else {
436 Log.e(TAG, "No SystemUI callbacks found for user: "
437 + mDraggingInRecentsCurrentUser);
438 }
439 }
440 }
441 }
442
443 @Override
444 public void onDraggingInRecentsEnded(float velocity) {
445 if (sSystemServicesProxy.isSystemUser(mDraggingInRecentsCurrentUser)) {
446 mImpl.onDraggingInRecentsEnded(velocity);
447 } else {
Winsona00a7852016-02-16 11:05:28 -0800448 if (mSystemToUserCallbacks != null) {
Jorim Jaggidd98d412015-11-18 15:57:38 -0800449 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800450 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(
Jorim Jaggidd98d412015-11-18 15:57:38 -0800451 mDraggingInRecentsCurrentUser);
452 if (callbacks != null) {
453 try {
454 callbacks.onDraggingInRecentsEnded(velocity);
455 } catch (RemoteException e) {
456 Log.e(TAG, "Callback failed", e);
457 }
458 } else {
459 Log.e(TAG, "No SystemUI callbacks found for user: "
460 + mDraggingInRecentsCurrentUser);
461 }
462 }
463 }
Jorim Jaggi75b25972015-10-21 14:51:10 +0200464 }
465
466 @Override
Jorim Jaggid61f2272014-12-19 20:35:35 +0100467 public void showNextAffiliatedTask() {
Winsone9243562015-11-10 16:07:13 -0800468 // Ensure the device has been provisioned before allowing the user to interact with
469 // recents
Winsone6309aa2016-01-08 11:19:21 -0800470 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800471 return;
472 }
473
Winson190fe3bf2015-10-20 14:57:24 -0700474 mImpl.showNextAffiliatedTask();
Winson Chungb1f74992014-08-08 12:53:09 -0700475 }
476
Jorim Jaggid61f2272014-12-19 20:35:35 +0100477 @Override
478 public void showPrevAffiliatedTask() {
Winsone9243562015-11-10 16:07:13 -0800479 // Ensure the device has been provisioned before allowing the user to interact with
480 // recents
Winsone6309aa2016-01-08 11:19:21 -0800481 if (!isUserSetup()) {
Winsone9243562015-11-10 16:07:13 -0800482 return;
483 }
484
Winson190fe3bf2015-10-20 14:57:24 -0700485 mImpl.showPrevAffiliatedTask();
Winson Chungb1f74992014-08-08 12:53:09 -0700486 }
487
Winson190fe3bf2015-10-20 14:57:24 -0700488 /**
489 * Updates on configuration change.
490 */
Winson Chung7048fea2014-03-18 12:21:24 -0700491 public void onConfigurationChanged(Configuration newConfig) {
Winsone7f138c2015-10-22 16:15:21 -0700492 int currentUser = sSystemServicesProxy.getCurrentUser();
493 if (sSystemServicesProxy.isSystemUser(currentUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700494 mImpl.onConfigurationChanged();
Winson Chung2002cf52014-12-08 17:26:44 -0800495 } else {
Winsona00a7852016-02-16 11:05:28 -0800496 if (mSystemToUserCallbacks != null) {
Winson190fe3bf2015-10-20 14:57:24 -0700497 IRecentsNonSystemUserCallbacks callbacks =
Winsona00a7852016-02-16 11:05:28 -0800498 mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
Winson190fe3bf2015-10-20 14:57:24 -0700499 if (callbacks != null) {
500 try {
501 callbacks.onConfigurationChanged();
502 } catch (RemoteException e) {
503 Log.e(TAG, "Callback failed", e);
Winson Chungb0a28ea2014-10-28 15:21:35 -0700504 }
Winson190fe3bf2015-10-20 14:57:24 -0700505 } else {
506 Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
Winson Chungb0a28ea2014-10-28 15:21:35 -0700507 }
Winson190fe3bf2015-10-20 14:57:24 -0700508 }
Winson Chungb0a28ea2014-10-28 15:21:35 -0700509 }
510 }
Winson190fe3bf2015-10-20 14:57:24 -0700511
512 /**
513 * Handle Recents activity visibility changed.
514 */
515 public final void onBusEvent(final RecentsVisibilityChangedEvent event) {
516 int processUser = event.systemServicesProxy.getProcessUser();
517 if (event.systemServicesProxy.isSystemUser(processUser)) {
518 mImpl.onVisibilityChanged(event.applicationContext, event.visible);
519 } else {
520 postToSystemUser(new Runnable() {
521 @Override
522 public void run() {
523 try {
Winsona00a7852016-02-16 11:05:28 -0800524 mUserToSystemCallbacks.updateRecentsVisibility(event.visible);
Winson190fe3bf2015-10-20 14:57:24 -0700525 } catch (RemoteException e) {
526 Log.e(TAG, "Callback failed", e);
527 }
528 }
529 });
530 }
531 }
532
533 /**
534 * Handle screen pinning request.
535 */
536 public final void onBusEvent(final ScreenPinningRequestEvent event) {
Winson83c1b072015-11-09 10:48:04 -0800537 int processUser = sSystemServicesProxy.getProcessUser();
538 if (sSystemServicesProxy.isSystemUser(processUser)) {
Winson190fe3bf2015-10-20 14:57:24 -0700539 mImpl.onStartScreenPinning(event.applicationContext);
540 } else {
541 postToSystemUser(new Runnable() {
542 @Override
543 public void run() {
544 try {
Winsona00a7852016-02-16 11:05:28 -0800545 mUserToSystemCallbacks.startScreenPinning();
Winson190fe3bf2015-10-20 14:57:24 -0700546 } catch (RemoteException e) {
547 Log.e(TAG, "Callback failed", e);
548 }
549 }
550 });
551 }
552 }
553
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800554 public final void onBusEvent(final RecentsDrawnEvent event) {
555 int processUser = sSystemServicesProxy.getProcessUser();
556 if (!sSystemServicesProxy.isSystemUser(processUser)) {
557 postToSystemUser(new Runnable() {
558 @Override
559 public void run() {
560 try {
Winsona00a7852016-02-16 11:05:28 -0800561 mUserToSystemCallbacks.sendRecentsDrawnEvent();
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800562 } catch (RemoteException e) {
563 Log.e(TAG, "Callback failed", e);
564 }
565 }
566 });
567 }
568 }
569
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800570 public final void onBusEvent(final DockingTopTaskEvent event) {
571 int processUser = sSystemServicesProxy.getProcessUser();
572 if (!sSystemServicesProxy.isSystemUser(processUser)) {
573 postToSystemUser(new Runnable() {
574 @Override
575 public void run() {
576 try {
Winsona00a7852016-02-16 11:05:28 -0800577 mUserToSystemCallbacks.sendDockingTopTaskEvent(event.dragMode);
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800578 } catch (RemoteException e) {
579 Log.e(TAG, "Callback failed", e);
580 }
581 }
582 });
583 }
584 }
585
586 public final void onBusEvent(final RecentsActivityStartingEvent event) {
587 int processUser = sSystemServicesProxy.getProcessUser();
588 if (!sSystemServicesProxy.isSystemUser(processUser)) {
589 postToSystemUser(new Runnable() {
590 @Override
591 public void run() {
592 try {
Winsona00a7852016-02-16 11:05:28 -0800593 mUserToSystemCallbacks.sendLaunchRecentsEvent();
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800594 } catch (RemoteException e) {
595 Log.e(TAG, "Callback failed", e);
596 }
597 }
598 });
599 }
600 }
601
Jorim Jaggi11cc01d2016-01-22 19:39:23 -0800602 /**
Winson190fe3bf2015-10-20 14:57:24 -0700603 * Attempts to register with the system user.
604 */
605 private void registerWithSystemUser() {
Winsone7f138c2015-10-22 16:15:21 -0700606 final int processUser = sSystemServicesProxy.getProcessUser();
Winson190fe3bf2015-10-20 14:57:24 -0700607 postToSystemUser(new Runnable() {
608 @Override
609 public void run() {
610 try {
Winsona00a7852016-02-16 11:05:28 -0800611 mUserToSystemCallbacks.registerNonSystemUserCallbacks(
Jorim Jaggicdb06ca2016-01-25 19:15:12 -0800612 new RecentsImplProxy(mImpl), processUser);
Winson190fe3bf2015-10-20 14:57:24 -0700613 } catch (RemoteException e) {
614 Log.e(TAG, "Failed to register", e);
615 }
616 }
617 });
618 }
619
620 /**
621 * Runs the runnable in the system user's Recents context, connecting to the service if
622 * necessary.
623 */
624 private void postToSystemUser(final Runnable onConnectRunnable) {
625 mOnConnectRunnables.add(onConnectRunnable);
Winsona00a7852016-02-16 11:05:28 -0800626 if (mUserToSystemCallbacks == null) {
Winson190fe3bf2015-10-20 14:57:24 -0700627 Intent systemUserServiceIntent = new Intent();
628 systemUserServiceIntent.setClass(mContext, RecentsSystemUserService.class);
629 boolean bound = mContext.bindServiceAsUser(systemUserServiceIntent,
Winsona00a7852016-02-16 11:05:28 -0800630 mUserToSystemServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
631 EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
632 EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_BIND_SERVICE,
633 sSystemServicesProxy.getProcessUser());
Winson190fe3bf2015-10-20 14:57:24 -0700634 if (!bound) {
635 // Retry after a fixed duration
636 mHandler.postDelayed(new Runnable() {
637 @Override
638 public void run() {
639 registerWithSystemUser();
640 }
641 }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
642 }
643 } else {
644 runAndFlushOnConnectRunnables();
645 }
646 }
647
648 /**
649 * Runs all the queued runnables after a service connection is made.
650 */
651 private void runAndFlushOnConnectRunnables() {
652 for (Runnable r : mOnConnectRunnables) {
653 r.run();
654 }
655 mOnConnectRunnables.clear();
656 }
Winson4727ab92015-11-02 14:35:34 -0800657
658 /**
Winsone6309aa2016-01-08 11:19:21 -0800659 * @return whether this device is provisioned and the current user is set up.
Winsone9243562015-11-10 16:07:13 -0800660 */
Winsone6309aa2016-01-08 11:19:21 -0800661 private boolean isUserSetup() {
662 ContentResolver cr = mContext.getContentResolver();
663 return (Settings.Global.getInt(cr, Settings.Global.DEVICE_PROVISIONED, 0) != 0) &&
664 (Settings.Secure.getInt(cr, Settings.Secure.USER_SETUP_COMPLETE, 0) != 0);
Winsone9243562015-11-10 16:07:13 -0800665 }
666
667 /**
Winson4727ab92015-11-02 14:35:34 -0800668 * Attempts to proxy the following action to the override recents package.
669 * @return whether the proxying was successful
670 */
671 private boolean proxyToOverridePackage(String action) {
672 if (mOverrideRecentsPackageName != null) {
673 Intent intent = new Intent(action);
674 intent.setPackage(mOverrideRecentsPackageName);
675 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
676 mContext.sendBroadcast(intent);
677 return true;
678 }
679 return false;
680 }
Winson Chung7048fea2014-03-18 12:21:24 -0700681}