17048fea75c06324a748d49f25bc05be908cda9ffWinson Chung/*
27048fea75c06324a748d49f25bc05be908cda9ffWinson Chung * Copyright (C) 2014 The Android Open Source Project
37048fea75c06324a748d49f25bc05be908cda9ffWinson Chung *
47048fea75c06324a748d49f25bc05be908cda9ffWinson Chung * Licensed under the Apache License, Version 2.0 (the "License");
57048fea75c06324a748d49f25bc05be908cda9ffWinson Chung * you may not use this file except in compliance with the License.
67048fea75c06324a748d49f25bc05be908cda9ffWinson Chung * You may obtain a copy of the License at
77048fea75c06324a748d49f25bc05be908cda9ffWinson Chung *
87048fea75c06324a748d49f25bc05be908cda9ffWinson Chung *      http://www.apache.org/licenses/LICENSE-2.0
97048fea75c06324a748d49f25bc05be908cda9ffWinson Chung *
107048fea75c06324a748d49f25bc05be908cda9ffWinson Chung * Unless required by applicable law or agreed to in writing, software
117048fea75c06324a748d49f25bc05be908cda9ffWinson Chung * distributed under the License is distributed on an "AS IS" BASIS,
127048fea75c06324a748d49f25bc05be908cda9ffWinson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137048fea75c06324a748d49f25bc05be908cda9ffWinson Chung * See the License for the specific language governing permissions and
147048fea75c06324a748d49f25bc05be908cda9ffWinson Chung * limitations under the License.
157048fea75c06324a748d49f25bc05be908cda9ffWinson Chung */
167048fea75c06324a748d49f25bc05be908cda9ffWinson Chung
177048fea75c06324a748d49f25bc05be908cda9ffWinson Chungpackage com.android.systemui.recents;
187048fea75c06324a748d49f25bc05be908cda9ffWinson Chung
19764da991def991a3aa7f09ab715ad18062e79cd9Jason Monkimport static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS;
20764da991def991a3aa7f09ab715ad18062e79cd9Jason Monk
21cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggiimport android.app.ActivityManager;
22190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.content.ComponentName;
23e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winsonimport android.content.ContentResolver;
247048fea75c06324a748d49f25bc05be908cda9ffWinson Chungimport android.content.Context;
257048fea75c06324a748d49f25bc05be908cda9ffWinson Chungimport android.content.Intent;
26190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.content.ServiceConnection;
2729379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggiimport android.content.pm.ActivityInfo;
287048fea75c06324a748d49f25bc05be908cda9ffWinson Chungimport android.content.res.Configuration;
29a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Liimport android.graphics.Point;
309ea2f7ba3155a455724f64e2d6a964ad4e99dfa5Jorim Jaggiimport android.graphics.Rect;
31a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Liimport android.hardware.display.DisplayManager;
324727ab9322661eb0c1684d750ce11bdc06312c1cWinsonimport android.os.Build;
33a237a314845d4e606a74a3135f78efa51006cc0fJim Millerimport android.os.Handler;
34190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.os.IBinder;
35190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.os.RemoteException;
364727ab9322661eb0c1684d750ce11bdc06312c1cWinsonimport android.os.SystemProperties;
377048fea75c06324a748d49f25bc05be908cda9ffWinson Chungimport android.os.UserHandle;
38e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winsonimport android.provider.Settings;
39a00a785ec889602b66be3d09814c0babfb610b1cWinsonimport android.util.EventLog;
40190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport android.util.Log;
41d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggiimport android.view.Display;
42aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggiimport android.widget.Toast;
43c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson
4429379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggiimport com.android.internal.logging.MetricsLogger;
45383db5ebcc3a4a615faf249bf4f126f42e80b82eTamas Berghammerimport com.android.internal.logging.nano.MetricsProto.MetricsEvent;
46a00a785ec889602b66be3d09814c0babfb610b1cWinsonimport com.android.systemui.EventLogConstants;
47a00a785ec889602b66be3d09814c0babfb610b1cWinsonimport com.android.systemui.EventLogTags;
48aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggiimport com.android.systemui.R;
499214eff52adf56b7c9532e40b784d52f9f94b6d1Winson Chungimport com.android.systemui.RecentsComponent;
50d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggiimport com.android.systemui.SystemUI;
51190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.events.EventBus;
52003eda6c230a1b1c4e3709466c46660e7602d740Winsonimport com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
53899327f5cbbfb0eae5562b262ccea860c98f6bc4Jorim Jaggiimport com.android.systemui.recents.events.activity.DockedTopTaskEvent;
54cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggiimport com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
55190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
56190fe3bf88388fcb109af64571e3baa0d01f1c37Winsonimport com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
57675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinsonimport com.android.systemui.recents.events.component.ShowUserToastEvent;
5811cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggiimport com.android.systemui.recents.events.ui.RecentsDrawnEvent;
59ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.SystemServicesProxy;
60e7f138c7f0a190c86cec10fb32fa106aacae4093Winsonimport com.android.systemui.recents.model.RecentsTaskLoader;
61db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggiimport com.android.systemui.stackdivider.Divider;
62764da991def991a3aa7f09ab715ad18062e79cd9Jason Monkimport com.android.systemui.statusbar.CommandQueue;
63ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung
64ee69756d542c9e65389e2907c2dc7aa8cca1250dWinson Chungimport java.io.FileDescriptor;
65ee69756d542c9e65389e2907c2dc7aa8cca1250dWinson Chungimport java.io.PrintWriter;
66ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.util.ArrayList;
67906a3a8e8090a3e974a7d859f7151245ed80cfe4Manu Cornetimport java.util.HashSet;
68906a3a8e8090a3e974a7d859f7151245ed80cfe4Manu Cornetimport java.util.Set;
697048fea75c06324a748d49f25bc05be908cda9ffWinson Chung
70190fe3bf88388fcb109af64571e3baa0d01f1c37Winson
712002cf5b463737e7f615f1469cb20d324c283544Winson Chung/**
72190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * An implementation of the SystemUI recents component, which supports both system and secondary
73190fe3bf88388fcb109af64571e3baa0d01f1c37Winson * users.
742002cf5b463737e7f615f1469cb20d324c283544Winson Chung */
75d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggipublic class Recents extends SystemUI
76764da991def991a3aa7f09ab715ad18062e79cd9Jason Monk        implements RecentsComponent, CommandQueue.Callbacks {
777048fea75c06324a748d49f25bc05be908cda9ffWinson Chung
78190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    private final static String TAG = "Recents";
79190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    private final static boolean DEBUG = false;
80e6c9073d81822496c038e70361e25b3f1287c2bcWinson
81190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    public final static int EVENT_BUS_PRIORITY = 1;
82190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    public final static int BIND_TO_SYSTEM_USER_RETRY_DELAY = 5000;
83db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi    public final static int RECENTS_GROW_TARGET_INVALID = -1;
842002cf5b463737e7f615f1469cb20d324c283544Winson Chung
85906a3a8e8090a3e974a7d859f7151245ed80cfe4Manu Cornet    public final static Set<String> RECENTS_ACTIVITIES = new HashSet<>();
86906a3a8e8090a3e974a7d859f7151245ed80cfe4Manu Cornet    static {
87906a3a8e8090a3e974a7d859f7151245ed80cfe4Manu Cornet        RECENTS_ACTIVITIES.add(RecentsImpl.RECENTS_ACTIVITY);
88906a3a8e8090a3e974a7d859f7151245ed80cfe4Manu Cornet    }
89906a3a8e8090a3e974a7d859f7151245ed80cfe4Manu Cornet
904727ab9322661eb0c1684d750ce11bdc06312c1cWinson    // Purely for experimentation
914727ab9322661eb0c1684d750ce11bdc06312c1cWinson    private final static String RECENTS_OVERRIDE_SYSPROP_KEY = "persist.recents_override_pkg";
924727ab9322661eb0c1684d750ce11bdc06312c1cWinson    private final static String ACTION_SHOW_RECENTS = "com.android.systemui.recents.ACTION_SHOW";
934727ab9322661eb0c1684d750ce11bdc06312c1cWinson    private final static String ACTION_HIDE_RECENTS = "com.android.systemui.recents.ACTION_HIDE";
944727ab9322661eb0c1684d750ce11bdc06312c1cWinson    private final static String ACTION_TOGGLE_RECENTS = "com.android.systemui.recents.ACTION_TOGGLE";
954727ab9322661eb0c1684d750ce11bdc06312c1cWinson
9629379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi    private static final String COUNTER_WINDOW_SUPPORTED = "window_enter_supported";
9729379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi    private static final String COUNTER_WINDOW_UNSUPPORTED = "window_enter_unsupported";
9829379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi    private static final String COUNTER_WINDOW_INCOMPATIBLE = "window_enter_incompatible";
9929379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi
100e7f138c7f0a190c86cec10fb32fa106aacae4093Winson    private static SystemServicesProxy sSystemServicesProxy;
101c742f973b1e506732911c156c5869fd377afc5bfWinson    private static RecentsDebugFlags sDebugFlags;
102e7f138c7f0a190c86cec10fb32fa106aacae4093Winson    private static RecentsTaskLoader sTaskLoader;
10353ec42cb17693b2d631746e1e5d31021a3359163Winson    private static RecentsConfiguration sConfiguration;
104e7f138c7f0a190c86cec10fb32fa106aacae4093Winson
1054727ab9322661eb0c1684d750ce11bdc06312c1cWinson    // For experiments only, allows another package to handle recents if it is defined in the system
1064727ab9322661eb0c1684d750ce11bdc06312c1cWinson    // properties.  This is limited to show/toggle/hide, and does not tie into the ActivityManager,
1074727ab9322661eb0c1684d750ce11bdc06312c1cWinson    // and does not reside in the home stack.
1084727ab9322661eb0c1684d750ce11bdc06312c1cWinson    private String mOverrideRecentsPackageName;
1094727ab9322661eb0c1684d750ce11bdc06312c1cWinson
110501d59dcea4e48f4abf00fbe671d17290cb1e66cWinson Chung    private Handler mHandler;
111190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    private RecentsImpl mImpl;
112dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi    private int mDraggingInRecentsCurrentUser;
113cdcd487abad10f728f0542accc42a31d1f7fedacWinson Chung
114190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    // Only For system user, this is the callbacks instance we return to each secondary user
115a00a785ec889602b66be3d09814c0babfb610b1cWinson    private RecentsSystemUser mSystemToUserCallbacks;
116b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung
117190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    // Only for secondary users, this is the callbacks instance provided by the system user to make
118190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    // calls back
119a00a785ec889602b66be3d09814c0babfb610b1cWinson    private IRecentsSystemUserCallbacks mUserToSystemCallbacks;
1207048fea75c06324a748d49f25bc05be908cda9ffWinson Chung
121190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    // The set of runnables to run after binding to the system user's service.
122190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    private final ArrayList<Runnable> mOnConnectRunnables = new ArrayList<>();
1237048fea75c06324a748d49f25bc05be908cda9ffWinson Chung
124190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    // Only for secondary users, this is the death handler for the binder from the system user
125a00a785ec889602b66be3d09814c0babfb610b1cWinson    private final IBinder.DeathRecipient mUserToSystemCallbacksDeathRcpt = new IBinder.DeathRecipient() {
126190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        @Override
127190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        public void binderDied() {
128a00a785ec889602b66be3d09814c0babfb610b1cWinson            mUserToSystemCallbacks = null;
129a00a785ec889602b66be3d09814c0babfb610b1cWinson            EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
130a00a785ec889602b66be3d09814c0babfb610b1cWinson                    EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_UNBOUND,
131a00a785ec889602b66be3d09814c0babfb610b1cWinson                    sSystemServicesProxy.getProcessUser());
1322002cf5b463737e7f615f1469cb20d324c283544Winson Chung
133190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            // Retry after a fixed duration
134190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            mHandler.postDelayed(new Runnable() {
135190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                @Override
136190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                public void run() {
137190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    registerWithSystemUser();
138190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                }
139190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
1402002cf5b463737e7f615f1469cb20d324c283544Winson Chung        }
141190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    };
1422002cf5b463737e7f615f1469cb20d324c283544Winson Chung
143190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    // Only for secondary users, this is the service connection we use to connect to the system user
144a00a785ec889602b66be3d09814c0babfb610b1cWinson    private final ServiceConnection mUserToSystemServiceConnection = new ServiceConnection() {
145740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung        @Override
146190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        public void onServiceConnected(ComponentName name, IBinder service) {
147190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            if (service != null) {
148a00a785ec889602b66be3d09814c0babfb610b1cWinson                mUserToSystemCallbacks = IRecentsSystemUserCallbacks.Stub.asInterface(
149190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        service);
150a00a785ec889602b66be3d09814c0babfb610b1cWinson                EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
151a00a785ec889602b66be3d09814c0babfb610b1cWinson                        EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_BOUND,
152a00a785ec889602b66be3d09814c0babfb610b1cWinson                        sSystemServicesProxy.getProcessUser());
153190fe3bf88388fcb109af64571e3baa0d01f1c37Winson
154190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                // Listen for system user's death, so that we can reconnect later
155190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                try {
156a00a785ec889602b66be3d09814c0babfb610b1cWinson                    service.linkToDeath(mUserToSystemCallbacksDeathRcpt, 0);
157190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                } catch (RemoteException e) {
158190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    Log.e(TAG, "Lost connection to (System) SystemUI", e);
1590eae5573b59ac2d3e484b7977f5fca7df9812c68Winson Chung                }
160190fe3bf88388fcb109af64571e3baa0d01f1c37Winson
161190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                // Run each of the queued runnables
162190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                runAndFlushOnConnectRunnables();
163740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung            }
164190fe3bf88388fcb109af64571e3baa0d01f1c37Winson
165190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            // Unbind ourselves now that we've registered our callbacks.  The
166190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            // binder to the system user are still valid at this point.
167190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            mContext.unbindService(this);
168740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung        }
169740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung
1702002cf5b463737e7f615f1469cb20d324c283544Winson Chung        @Override
171190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        public void onServiceDisconnected(ComponentName name) {
172190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            // Do nothing
1732002cf5b463737e7f615f1469cb20d324c283544Winson Chung        }
174190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    };
175d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi
176d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    /**
177190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     * Returns the callbacks interface that non-system users can call.
178d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi     */
179190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    public IBinder getSystemUserCallbacks() {
180a00a785ec889602b66be3d09814c0babfb610b1cWinson        return mSystemToUserCallbacks;
181d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    }
182d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi
183e7f138c7f0a190c86cec10fb32fa106aacae4093Winson    public static RecentsTaskLoader getTaskLoader() {
184e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        return sTaskLoader;
185e7f138c7f0a190c86cec10fb32fa106aacae4093Winson    }
186e7f138c7f0a190c86cec10fb32fa106aacae4093Winson
1876f9dbcb742ee930151444118dd61c2239efce09dJorim Jaggi
188e7f138c7f0a190c86cec10fb32fa106aacae4093Winson    public static SystemServicesProxy getSystemServices() {
189e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        return sSystemServicesProxy;
190e7f138c7f0a190c86cec10fb32fa106aacae4093Winson    }
191e7f138c7f0a190c86cec10fb32fa106aacae4093Winson
19253ec42cb17693b2d631746e1e5d31021a3359163Winson    public static RecentsConfiguration getConfiguration() {
19353ec42cb17693b2d631746e1e5d31021a3359163Winson        return sConfiguration;
19453ec42cb17693b2d631746e1e5d31021a3359163Winson    }
19553ec42cb17693b2d631746e1e5d31021a3359163Winson
196c742f973b1e506732911c156c5869fd377afc5bfWinson    public static RecentsDebugFlags getDebugFlags() {
197c742f973b1e506732911c156c5869fd377afc5bfWinson        return sDebugFlags;
198c742f973b1e506732911c156c5869fd377afc5bfWinson    }
199c742f973b1e506732911c156c5869fd377afc5bfWinson
200d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    @Override
201d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    public void start() {
202c742f973b1e506732911c156c5869fd377afc5bfWinson        sDebugFlags = new RecentsDebugFlags(mContext);
203938a50b424eb73ee96d34c96b5e2cbd11f733d7aJaewan Kim        sSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
204e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        sTaskLoader = new RecentsTaskLoader(mContext);
20553ec42cb17693b2d631746e1e5d31021a3359163Winson        sConfiguration = new RecentsConfiguration(mContext);
206501d59dcea4e48f4abf00fbe671d17290cb1e66cWinson Chung        mHandler = new Handler();
2070e88d32b96526adc241ce7a0970e8177b4254810Sid Soundararajan        mImpl = new RecentsImpl(mContext);
208190fe3bf88388fcb109af64571e3baa0d01f1c37Winson
2094727ab9322661eb0c1684d750ce11bdc06312c1cWinson        // Check if there is a recents override package
2104727ab9322661eb0c1684d750ce11bdc06312c1cWinson        if ("userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE)) {
2114727ab9322661eb0c1684d750ce11bdc06312c1cWinson            String cnStr = SystemProperties.get(RECENTS_OVERRIDE_SYSPROP_KEY);
2124727ab9322661eb0c1684d750ce11bdc06312c1cWinson            if (!cnStr.isEmpty()) {
2134727ab9322661eb0c1684d750ce11bdc06312c1cWinson                mOverrideRecentsPackageName = cnStr;
2144727ab9322661eb0c1684d750ce11bdc06312c1cWinson            }
2154727ab9322661eb0c1684d750ce11bdc06312c1cWinson        }
2164727ab9322661eb0c1684d750ce11bdc06312c1cWinson
217190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        // Register with the event bus
218190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
219c742f973b1e506732911c156c5869fd377afc5bfWinson        EventBus.getDefault().register(sSystemServicesProxy, EVENT_BUS_PRIORITY);
220e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        EventBus.getDefault().register(sTaskLoader, EVENT_BUS_PRIORITY);
221190fe3bf88388fcb109af64571e3baa0d01f1c37Winson
222190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        // Due to the fact that RecentsActivity is per-user, we need to establish and interface for
223190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        // the system user's Recents component to pass events (like show/hide/toggleRecents) to the
224190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        // secondary user, and vice versa (like visibility change, screen pinning).
225e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        final int processUser = sSystemServicesProxy.getProcessUser();
226e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        if (sSystemServicesProxy.isSystemUser(processUser)) {
227190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            // For the system user, initialize an instance of the interface that we can pass to the
228190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            // secondary user
2290c7592ffacd21c52f2fb30313b56dd9b5e9bf6f4Winson Chung            getComponent(CommandQueue.class).addCallbacks(this);
230a00a785ec889602b66be3d09814c0babfb610b1cWinson            mSystemToUserCallbacks = new RecentsSystemUser(mContext, mImpl);
231190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        } else {
232190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            // For the secondary user, bind to the primary user's service to get a persistent
233190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            // interface to register its implementation and to later update its state
234190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            registerWithSystemUser();
2352002cf5b463737e7f615f1469cb20d324c283544Winson Chung        }
236d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi        putComponent(Recents.class, this);
2375abdceb64b18460197fc6e8b76daecf259080991Winson Chung    }
2385abdceb64b18460197fc6e8b76daecf259080991Winson Chung
239d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    @Override
2408bf05afc26c4b727af25a669914c057877355891Winson Chung    public void onBootCompleted() {
241190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        mImpl.onBootCompleted();
2428bf05afc26c4b727af25a669914c057877355891Winson Chung    }
2438bf05afc26c4b727af25a669914c057877355891Winson Chung
244190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    /**
245190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     * Shows the Recents.
246190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     */
247d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    @Override
248764da991def991a3aa7f09ab715ad18062e79cd9Jason Monk    public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
249e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // Ensure the device has been provisioned before allowing the user to interact with
250e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // recents
251e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        if (!isUserSetup()) {
252e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson            return;
253e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        }
254e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson
2554727ab9322661eb0c1684d750ce11bdc06312c1cWinson        if (proxyToOverridePackage(ACTION_SHOW_RECENTS)) {
2564727ab9322661eb0c1684d750ce11bdc06312c1cWinson            return;
2574727ab9322661eb0c1684d750ce11bdc06312c1cWinson        }
258764da991def991a3aa7f09ab715ad18062e79cd9Jason Monk        try {
259764da991def991a3aa7f09ab715ad18062e79cd9Jason Monk            ActivityManager.getService().closeSystemDialogs(SYSTEM_DIALOG_REASON_RECENT_APPS);
260764da991def991a3aa7f09ab715ad18062e79cd9Jason Monk        } catch (RemoteException e) {
261764da991def991a3aa7f09ab715ad18062e79cd9Jason Monk        }
2624727ab9322661eb0c1684d750ce11bdc06312c1cWinson
263db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi        int recentsGrowTarget = getComponent(Divider.class).getView().growsRecents();
264db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi
265e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        int currentUser = sSystemServicesProxy.getCurrentUser();
266e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        if (sSystemServicesProxy.isSystemUser(currentUser)) {
267435b2e43cb131d0b38ba19f335aec78bb83944b2Jorim Jaggi            mImpl.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
268db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi                    true /* animate */, false /* reloadTasks */, fromHome, recentsGrowTarget);
2692002cf5b463737e7f615f1469cb20d324c283544Winson Chung        } else {
270a00a785ec889602b66be3d09814c0babfb610b1cWinson            if (mSystemToUserCallbacks != null) {
271190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                IRecentsNonSystemUserCallbacks callbacks =
272a00a785ec889602b66be3d09814c0babfb610b1cWinson                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
273190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                if (callbacks != null) {
274190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    try {
275bb42a46631b4cecdd03bd628feeb8270d412ebd3Jorim Jaggi                        callbacks.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
276db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi                                true /* animate */, false /* reloadTasks */, fromHome,
277db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi                                recentsGrowTarget);
278190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    } catch (RemoteException e) {
279190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        Log.e(TAG, "Callback failed", e);
280190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    }
281190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                } else {
282190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
283190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                }
284190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            }
2851e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung        }
2861e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung    }
2871e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung
288190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    /**
289190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     * Hides the Recents.
290190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     */
291d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    @Override
292764da991def991a3aa7f09ab715ad18062e79cd9Jason Monk    public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
293e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // Ensure the device has been provisioned before allowing the user to interact with
294e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // recents
295e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        if (!isUserSetup()) {
296e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson            return;
297e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        }
298e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson
2994727ab9322661eb0c1684d750ce11bdc06312c1cWinson        if (proxyToOverridePackage(ACTION_HIDE_RECENTS)) {
3004727ab9322661eb0c1684d750ce11bdc06312c1cWinson            return;
3014727ab9322661eb0c1684d750ce11bdc06312c1cWinson        }
3024727ab9322661eb0c1684d750ce11bdc06312c1cWinson
303e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        int currentUser = sSystemServicesProxy.getCurrentUser();
304e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        if (sSystemServicesProxy.isSystemUser(currentUser)) {
305190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            mImpl.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
3062002cf5b463737e7f615f1469cb20d324c283544Winson Chung        } else {
307a00a785ec889602b66be3d09814c0babfb610b1cWinson            if (mSystemToUserCallbacks != null) {
308190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                IRecentsNonSystemUserCallbacks callbacks =
309a00a785ec889602b66be3d09814c0babfb610b1cWinson                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
310190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                if (callbacks != null) {
311190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    try {
312190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        callbacks.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
313190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    } catch (RemoteException e) {
314190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        Log.e(TAG, "Callback failed", e);
315190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    }
316190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                } else {
317190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
318190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                }
319190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            }
3201e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung        }
3211e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung    }
3221e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung
323190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    /**
324190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     * Toggles the Recents activity.
325190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     */
326d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    @Override
327ebe1ba19806530eda8ed53b7162a074a5af67be4Winson Chung    public void toggleRecentApps() {
328e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // Ensure the device has been provisioned before allowing the user to interact with
329e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // recents
330e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        if (!isUserSetup()) {
331e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson            return;
332e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        }
333e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson
3344727ab9322661eb0c1684d750ce11bdc06312c1cWinson        if (proxyToOverridePackage(ACTION_TOGGLE_RECENTS)) {
3354727ab9322661eb0c1684d750ce11bdc06312c1cWinson            return;
3364727ab9322661eb0c1684d750ce11bdc06312c1cWinson        }
3374727ab9322661eb0c1684d750ce11bdc06312c1cWinson
338db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi        int growTarget = getComponent(Divider.class).getView().growsRecents();
339db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi
340e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        int currentUser = sSystemServicesProxy.getCurrentUser();
341e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        if (sSystemServicesProxy.isSystemUser(currentUser)) {
342db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi            mImpl.toggleRecents(growTarget);
3432002cf5b463737e7f615f1469cb20d324c283544Winson Chung        } else {
344a00a785ec889602b66be3d09814c0babfb610b1cWinson            if (mSystemToUserCallbacks != null) {
345190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                IRecentsNonSystemUserCallbacks callbacks =
346a00a785ec889602b66be3d09814c0babfb610b1cWinson                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
347190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                if (callbacks != null) {
348190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    try {
349db21bbd2caf05322864f09ec45a0c572cf071123Jorim Jaggi                        callbacks.toggleRecents(growTarget);
350190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    } catch (RemoteException e) {
351190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        Log.e(TAG, "Callback failed", e);
352190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    }
353190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                } else {
354190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
355190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                }
356190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            }
3577048fea75c06324a748d49f25bc05be908cda9ffWinson Chung        }
3587048fea75c06324a748d49f25bc05be908cda9ffWinson Chung    }
3597048fea75c06324a748d49f25bc05be908cda9ffWinson Chung
360190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    /**
361190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     * Preloads info for the Recents activity.
362190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     */
363d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    @Override
364ebe1ba19806530eda8ed53b7162a074a5af67be4Winson Chung    public void preloadRecentApps() {
365e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // Ensure the device has been provisioned before allowing the user to interact with
366e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // recents
367e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        if (!isUserSetup()) {
368e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson            return;
369e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        }
370e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson
371e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        int currentUser = sSystemServicesProxy.getCurrentUser();
372e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        if (sSystemServicesProxy.isSystemUser(currentUser)) {
373190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            mImpl.preloadRecents();
3742002cf5b463737e7f615f1469cb20d324c283544Winson Chung        } else {
375a00a785ec889602b66be3d09814c0babfb610b1cWinson            if (mSystemToUserCallbacks != null) {
376190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                IRecentsNonSystemUserCallbacks callbacks =
377a00a785ec889602b66be3d09814c0babfb610b1cWinson                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
378190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                if (callbacks != null) {
379190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    try {
380190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        callbacks.preloadRecents();
381190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    } catch (RemoteException e) {
382190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        Log.e(TAG, "Callback failed", e);
383190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    }
384190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                } else {
385190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
386190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                }
387a278cae54cf8768a5d7caf54f21ac9f254c11c95Winson Chung            }
388e1e20e11a758ee82753e8052773664823ca74746Winson Chung        }
3897048fea75c06324a748d49f25bc05be908cda9ffWinson Chung    }
3907048fea75c06324a748d49f25bc05be908cda9ffWinson Chung
391d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    @Override
392764da991def991a3aa7f09ab715ad18062e79cd9Jason Monk    public void cancelPreloadRecentApps() {
393e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // Ensure the device has been provisioned before allowing the user to interact with
394e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // recents
395e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        if (!isUserSetup()) {
396e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson            return;
397e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        }
398e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson
399e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        int currentUser = sSystemServicesProxy.getCurrentUser();
400e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        if (sSystemServicesProxy.isSystemUser(currentUser)) {
401190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            mImpl.cancelPreloadingRecents();
402190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        } else {
403a00a785ec889602b66be3d09814c0babfb610b1cWinson            if (mSystemToUserCallbacks != null) {
404190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                IRecentsNonSystemUserCallbacks callbacks =
405a00a785ec889602b66be3d09814c0babfb610b1cWinson                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
406190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                if (callbacks != null) {
407190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    try {
408190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        callbacks.cancelPreloadingRecents();
409190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    } catch (RemoteException e) {
410190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        Log.e(TAG, "Callback failed", e);
411190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    }
412044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung                } else {
413190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
414044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung                }
4153aa9c221c0d092b927628be6a7ba371028cebe79Winson Chung            }
416b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung        }
417b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung    }
418b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung
419d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    @Override
42029379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi    public boolean dockTopTask(int dragMode, int stackCreateMode, Rect initialBounds,
42129379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi            int metricsDockAction) {
422e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        // Ensure the device has been provisioned before allowing the user to interact with
423e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        // recents
424e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        if (!isUserSetup()) {
425e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson            return false;
426dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi        }
427e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson
428a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li        Point realSize = new Point();
429a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li        if (initialBounds == null) {
430a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li            mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
431a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li                    .getRealSize(realSize);
432a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li            initialBounds = new Rect(0, 0, realSize.x, realSize.y);
433a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li        }
434a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li
435cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi        int currentUser = sSystemServicesProxy.getCurrentUser();
436cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi        SystemServicesProxy ssp = Recents.getSystemServices();
437d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson        ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
438cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi        boolean screenPinningActive = ssp.isScreenPinningActive();
439ae1ff4f85ffd12ab8a14c610b1474a012536888fMatthew Ng        boolean isRunningTaskInHomeOrRecentsStack = runningTask != null &&
440ae1ff4f85ffd12ab8a14c610b1474a012536888fMatthew Ng                ActivityManager.StackId.isHomeOrRecentsStack(runningTask.stackId);
441ae1ff4f85ffd12ab8a14c610b1474a012536888fMatthew Ng        if (runningTask != null && !isRunningTaskInHomeOrRecentsStack && !screenPinningActive) {
442d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson            logDockAttempt(mContext, runningTask.topActivity, runningTask.resizeMode);
443d339538a67b7d6bb3d7ad73f31ad20ffc932f891Winson Chung            if (runningTask.supportsSplitScreenMultiWindow) {
44429379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi                if (metricsDockAction != -1) {
44529379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi                    MetricsLogger.action(mContext, metricsDockAction,
446d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson                            runningTask.topActivity.flattenToShortString());
44729379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi                }
448aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                if (sSystemServicesProxy.isSystemUser(currentUser)) {
449d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson                    mImpl.dockTopTask(runningTask.id, dragMode, stackCreateMode, initialBounds);
450aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                } else {
451aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                    if (mSystemToUserCallbacks != null) {
452aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                        IRecentsNonSystemUserCallbacks callbacks =
453aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                                mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
454aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                        if (callbacks != null) {
455aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                            try {
456d46b72788e8811d2e423ea1e5b2ff104ecb7f721Winson                                callbacks.dockTopTask(runningTask.id, dragMode, stackCreateMode,
457aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                                        initialBounds);
458aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                            } catch (RemoteException e) {
459aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                                Log.e(TAG, "Callback failed", e);
460aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                            }
461aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                        } else {
462aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                            Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
463cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                        }
464cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                    }
465cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                }
466aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                mDraggingInRecentsCurrentUser = currentUser;
467aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                return true;
468aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi            } else {
469675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson                EventBus.getDefault().send(new ShowUserToastEvent(
47080f7b015ca02dc568c5df30e09510e87a94ee6b1Winson Chung                        R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT));
471aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi                return false;
472e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson            }
473aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi        } else {
474aa6c574411e8e5fd1244808381e7abd45bf3744fJorim Jaggi            return false;
475e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        }
476dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi    }
477dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi
47829379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi    public static void logDockAttempt(Context ctx, ComponentName activity, int resizeMode) {
47929379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi        if (resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE) {
48029379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi            MetricsLogger.action(ctx, MetricsEvent.ACTION_WINDOW_DOCK_UNRESIZABLE,
48129379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi                    activity.flattenToShortString());
48229379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi        }
48329379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi        MetricsLogger.count(ctx, getMetricsCounterForResizeMode(resizeMode), 1);
48429379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi    }
48529379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi
48629379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi    private static String getMetricsCounterForResizeMode(int resizeMode) {
48729379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi        switch (resizeMode) {
48829379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi            case ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE:
48929379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi                return COUNTER_WINDOW_UNSUPPORTED;
49029379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi            case ActivityInfo.RESIZE_MODE_RESIZEABLE:
49172a73e347352302c72a4ef701bcba91336db22a9Wale Ogunwale            case ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION:
49229379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi                return COUNTER_WINDOW_SUPPORTED;
49329379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi            default:
49429379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi                return COUNTER_WINDOW_INCOMPATIBLE;
49529379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi        }
49629379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi    }
49729379ec859bf7118dec9f3248c63ee369218ad6bJorim Jaggi
498dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi    @Override
499dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi    public void onDraggingInRecents(float distanceFromTop) {
500dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi        if (sSystemServicesProxy.isSystemUser(mDraggingInRecentsCurrentUser)) {
501dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi            mImpl.onDraggingInRecents(distanceFromTop);
502dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi        } else {
503a00a785ec889602b66be3d09814c0babfb610b1cWinson            if (mSystemToUserCallbacks != null) {
504dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                IRecentsNonSystemUserCallbacks callbacks =
505a00a785ec889602b66be3d09814c0babfb610b1cWinson                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(
506dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                                mDraggingInRecentsCurrentUser);
507dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                if (callbacks != null) {
508dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                    try {
509dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                        callbacks.onDraggingInRecents(distanceFromTop);
510dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                    } catch (RemoteException e) {
511dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                        Log.e(TAG, "Callback failed", e);
512dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                    }
513dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                } else {
514dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                    Log.e(TAG, "No SystemUI callbacks found for user: "
515dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                            + mDraggingInRecentsCurrentUser);
516dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                }
517dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi            }
518dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi        }
519dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi    }
520dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi
521dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi    @Override
522dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi    public void onDraggingInRecentsEnded(float velocity) {
523dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi        if (sSystemServicesProxy.isSystemUser(mDraggingInRecentsCurrentUser)) {
524dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi            mImpl.onDraggingInRecentsEnded(velocity);
525dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi        } else {
526a00a785ec889602b66be3d09814c0babfb610b1cWinson            if (mSystemToUserCallbacks != null) {
527dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                IRecentsNonSystemUserCallbacks callbacks =
528a00a785ec889602b66be3d09814c0babfb610b1cWinson                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(
529dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                                mDraggingInRecentsCurrentUser);
530dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                if (callbacks != null) {
531dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                    try {
532dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                        callbacks.onDraggingInRecentsEnded(velocity);
533dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                    } catch (RemoteException e) {
534dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                        Log.e(TAG, "Callback failed", e);
535dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                    }
536dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                } else {
537dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                    Log.e(TAG, "No SystemUI callbacks found for user: "
538dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                            + mDraggingInRecentsCurrentUser);
539dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi                }
540dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi            }
541dd98d41e3a65b3bcb37007ea5b29371cf013f563Jorim Jaggi        }
54275b2597e5826662c1740d6f3b81966a9e6a9e7b4Jorim Jaggi    }
54375b2597e5826662c1740d6f3b81966a9e6a9e7b4Jorim Jaggi
54475b2597e5826662c1740d6f3b81966a9e6a9e7b4Jorim Jaggi    @Override
545d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    public void showNextAffiliatedTask() {
546e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // Ensure the device has been provisioned before allowing the user to interact with
547e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // recents
548e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        if (!isUserSetup()) {
549e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson            return;
550e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        }
551e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson
552190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        mImpl.showNextAffiliatedTask();
553b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung    }
554b1f749906f5c27114d02ea0c3f8ce0dcea08fd3fWinson Chung
555d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    @Override
556d61f2271c40cd7b3b10f39d8ffdaf8c527cb78beJorim Jaggi    public void showPrevAffiliatedTask() {
557e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // Ensure the device has been provisioned before allowing the user to interact with
558e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        // recents
559e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        if (!isUserSetup()) {
560e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson            return;
561e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson        }
562e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson
563190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        mImpl.showPrevAffiliatedTask();
56448a10a56e98b008ac55b9d50aee1ad33b377e367Winson Chung    }
56548a10a56e98b008ac55b9d50aee1ad33b377e367Winson Chung
566ec417e4cc082e1734e7184c51762d21a430c0b38Winson    /**
567190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     * Updates on configuration change.
568ec417e4cc082e1734e7184c51762d21a430c0b38Winson     */
569190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    public void onConfigurationChanged(Configuration newConfig) {
570e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        int currentUser = sSystemServicesProxy.getCurrentUser();
571e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        if (sSystemServicesProxy.isSystemUser(currentUser)) {
572190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            mImpl.onConfigurationChanged();
5731e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung        } else {
574a00a785ec889602b66be3d09814c0babfb610b1cWinson            if (mSystemToUserCallbacks != null) {
575190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                IRecentsNonSystemUserCallbacks callbacks =
576a00a785ec889602b66be3d09814c0babfb610b1cWinson                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
577190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                if (callbacks != null) {
578190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    try {
579190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        callbacks.onConfigurationChanged();
580190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    } catch (RemoteException e) {
581190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        Log.e(TAG, "Callback failed", e);
582190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    }
583190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                } else {
584190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
585190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                }
586190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            }
5877048fea75c06324a748d49f25bc05be908cda9ffWinson Chung        }
5881e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung    }
5897048fea75c06324a748d49f25bc05be908cda9ffWinson Chung
590d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    /**
591190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     * Handle Recents activity visibility changed.
592d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung     */
593190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    public final void onBusEvent(final RecentsVisibilityChangedEvent event) {
5948873754f66527d2cc9feab295dd4eef23298212aWinson        SystemServicesProxy ssp = Recents.getSystemServices();
5958873754f66527d2cc9feab295dd4eef23298212aWinson        int processUser = ssp.getProcessUser();
5968873754f66527d2cc9feab295dd4eef23298212aWinson        if (ssp.isSystemUser(processUser)) {
597190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            mImpl.onVisibilityChanged(event.applicationContext, event.visible);
598190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        } else {
599190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            postToSystemUser(new Runnable() {
600190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                @Override
601190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                public void run() {
602190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    try {
603a00a785ec889602b66be3d09814c0babfb610b1cWinson                        mUserToSystemCallbacks.updateRecentsVisibility(event.visible);
604190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    } catch (RemoteException e) {
605190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        Log.e(TAG, "Callback failed", e);
606190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    }
607190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                }
608190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            });
609bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        }
610d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    }
611d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung
612d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    /**
613190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     * Handle screen pinning request.
614d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung     */
615190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    public final void onBusEvent(final ScreenPinningRequestEvent event) {
61683c1b07a99a6ddd80c30cfc101f3de037a0d215dWinson        int processUser = sSystemServicesProxy.getProcessUser();
61783c1b07a99a6ddd80c30cfc101f3de037a0d215dWinson        if (sSystemServicesProxy.isSystemUser(processUser)) {
6180f051f5abdb31024d862a954cc4c4716b1dde616Andrii Kulian            mImpl.onStartScreenPinning(event.applicationContext, event.taskId);
619900fb48d269e2fbf3baea995c6324e4c08ad7c22Jorim Jaggi        } else {
620190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            postToSystemUser(new Runnable() {
621190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                @Override
622190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                public void run() {
623190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    try {
6240f051f5abdb31024d862a954cc4c4716b1dde616Andrii Kulian                        mUserToSystemCallbacks.startScreenPinning(event.taskId);
625190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    } catch (RemoteException e) {
626190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        Log.e(TAG, "Callback failed", e);
627190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    }
628190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                }
629190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            });
630d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        }
631d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    }
632d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung
63311cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi    public final void onBusEvent(final RecentsDrawnEvent event) {
63411cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi        int processUser = sSystemServicesProxy.getProcessUser();
63511cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi        if (!sSystemServicesProxy.isSystemUser(processUser)) {
63611cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi            postToSystemUser(new Runnable() {
63711cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi                @Override
63811cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi                public void run() {
63911cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi                    try {
640a00a785ec889602b66be3d09814c0babfb610b1cWinson                        mUserToSystemCallbacks.sendRecentsDrawnEvent();
64111cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi                    } catch (RemoteException e) {
64211cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi                        Log.e(TAG, "Callback failed", e);
64311cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi                    }
64411cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi                }
64511cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi            });
64611cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi        }
64711cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi    }
64811cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi
649899327f5cbbfb0eae5562b262ccea860c98f6bc4Jorim Jaggi    public final void onBusEvent(final DockedTopTaskEvent event) {
650cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi        int processUser = sSystemServicesProxy.getProcessUser();
651cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi        if (!sSystemServicesProxy.isSystemUser(processUser)) {
652cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi            postToSystemUser(new Runnable() {
653cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                @Override
654cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                public void run() {
655cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                    try {
656899327f5cbbfb0eae5562b262ccea860c98f6bc4Jorim Jaggi                        mUserToSystemCallbacks.sendDockingTopTaskEvent(event.dragMode,
657899327f5cbbfb0eae5562b262ccea860c98f6bc4Jorim Jaggi                                event.initialRect);
658cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                    } catch (RemoteException e) {
659cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                        Log.e(TAG, "Callback failed", e);
660cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                    }
661cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                }
662cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi            });
663cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi        }
664cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi    }
665cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi
666cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi    public final void onBusEvent(final RecentsActivityStartingEvent event) {
667cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi        int processUser = sSystemServicesProxy.getProcessUser();
668cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi        if (!sSystemServicesProxy.isSystemUser(processUser)) {
669cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi            postToSystemUser(new Runnable() {
670cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                @Override
671cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                public void run() {
672cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                    try {
673a00a785ec889602b66be3d09814c0babfb610b1cWinson                        mUserToSystemCallbacks.sendLaunchRecentsEvent();
674cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                    } catch (RemoteException e) {
675cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                        Log.e(TAG, "Callback failed", e);
676cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                    }
677cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                }
678cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi            });
679cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi        }
680cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi    }
681cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi
682003eda6c230a1b1c4e3709466c46660e7602d740Winson    public final void onBusEvent(ConfigurationChangedEvent event) {
683003eda6c230a1b1c4e3709466c46660e7602d740Winson        // Update the configuration for the Recents component when the activity configuration
684003eda6c230a1b1c4e3709466c46660e7602d740Winson        // changes as well
685003eda6c230a1b1c4e3709466c46660e7602d740Winson        mImpl.onConfigurationChanged();
686003eda6c230a1b1c4e3709466c46660e7602d740Winson    }
687003eda6c230a1b1c4e3709466c46660e7602d740Winson
688675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson    public final void onBusEvent(ShowUserToastEvent event) {
689675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson        int currentUser = sSystemServicesProxy.getCurrentUser();
690675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson        if (sSystemServicesProxy.isSystemUser(currentUser)) {
691675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson            mImpl.onShowCurrentUserToast(event.msgResId, event.msgLength);
692675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson        } else {
693675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson            if (mSystemToUserCallbacks != null) {
694675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson                IRecentsNonSystemUserCallbacks callbacks =
695675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
696675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson                if (callbacks != null) {
697675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson                    try {
698675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson                        callbacks.showCurrentUserToast(event.msgResId, event.msgLength);
699675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson                    } catch (RemoteException e) {
700675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson                        Log.e(TAG, "Callback failed", e);
701675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson                    }
702675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson                } else {
703675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
704675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson                }
705675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson            }
706675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson        }
707675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson    }
708675c5d8e5a6fd98e8324798e1ef31df20cee5b0fWinson
70911cc01df271fce5ec3eb05a7281032d1271cc782Jorim Jaggi    /**
710190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     * Attempts to register with the system user.
711900fb48d269e2fbf3baea995c6324e4c08ad7c22Jorim Jaggi     */
712190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    private void registerWithSystemUser() {
713e7f138c7f0a190c86cec10fb32fa106aacae4093Winson        final int processUser = sSystemServicesProxy.getProcessUser();
714190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        postToSystemUser(new Runnable() {
715900fb48d269e2fbf3baea995c6324e4c08ad7c22Jorim Jaggi            @Override
716190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            public void run() {
717190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                try {
718a00a785ec889602b66be3d09814c0babfb610b1cWinson                    mUserToSystemCallbacks.registerNonSystemUserCallbacks(
719cdb06caebb5f6f554b2ed8c76963970d8cc0ab54Jorim Jaggi                            new RecentsImplProxy(mImpl), processUser);
720190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                } catch (RemoteException e) {
721190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    Log.e(TAG, "Failed to register", e);
722190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                }
723900fb48d269e2fbf3baea995c6324e4c08ad7c22Jorim Jaggi            }
724190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        });
725900fb48d269e2fbf3baea995c6324e4c08ad7c22Jorim Jaggi    }
726900fb48d269e2fbf3baea995c6324e4c08ad7c22Jorim Jaggi
727900fb48d269e2fbf3baea995c6324e4c08ad7c22Jorim Jaggi    /**
728190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     * Runs the runnable in the system user's Recents context, connecting to the service if
729190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     * necessary.
730900fb48d269e2fbf3baea995c6324e4c08ad7c22Jorim Jaggi     */
731190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    private void postToSystemUser(final Runnable onConnectRunnable) {
732190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        mOnConnectRunnables.add(onConnectRunnable);
733a00a785ec889602b66be3d09814c0babfb610b1cWinson        if (mUserToSystemCallbacks == null) {
734190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            Intent systemUserServiceIntent = new Intent();
735190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            systemUserServiceIntent.setClass(mContext, RecentsSystemUserService.class);
736190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            boolean bound = mContext.bindServiceAsUser(systemUserServiceIntent,
737a00a785ec889602b66be3d09814c0babfb610b1cWinson                    mUserToSystemServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
738a00a785ec889602b66be3d09814c0babfb610b1cWinson            EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
739a00a785ec889602b66be3d09814c0babfb610b1cWinson                    EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_BIND_SERVICE,
740a00a785ec889602b66be3d09814c0babfb610b1cWinson                    sSystemServicesProxy.getProcessUser());
741190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            if (!bound) {
742190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                // Retry after a fixed duration
743190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                mHandler.postDelayed(new Runnable() {
744190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    @Override
745190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    public void run() {
746190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                        registerWithSystemUser();
747190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                    }
748190fe3bf88388fcb109af64571e3baa0d01f1c37Winson                }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
749d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung            }
7507048fea75c06324a748d49f25bc05be908cda9ffWinson Chung        } else {
751190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            runAndFlushOnConnectRunnables();
752d0aa8a374f4de4b02d99d2eef6580ef0f5762912Winson Chung        }
753d0aa8a374f4de4b02d99d2eef6580ef0f5762912Winson Chung    }
754d0aa8a374f4de4b02d99d2eef6580ef0f5762912Winson Chung
755a91c293be26b2deb5434eb827a800fa0c80dc92cWinson Chung    /**
756190fe3bf88388fcb109af64571e3baa0d01f1c37Winson     * Runs all the queued runnables after a service connection is made.
757a91c293be26b2deb5434eb827a800fa0c80dc92cWinson Chung     */
758190fe3bf88388fcb109af64571e3baa0d01f1c37Winson    private void runAndFlushOnConnectRunnables() {
759190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        for (Runnable r : mOnConnectRunnables) {
760190fe3bf88388fcb109af64571e3baa0d01f1c37Winson            r.run();
761b0a28ea5d381cd3a8477cf7fd82797199c80ca67Winson Chung        }
762190fe3bf88388fcb109af64571e3baa0d01f1c37Winson        mOnConnectRunnables.clear();
763b0a28ea5d381cd3a8477cf7fd82797199c80ca67Winson Chung    }
7644727ab9322661eb0c1684d750ce11bdc06312c1cWinson
7654727ab9322661eb0c1684d750ce11bdc06312c1cWinson    /**
766e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson     * @return whether this device is provisioned and the current user is set up.
767e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson     */
768e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson    private boolean isUserSetup() {
769e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        ContentResolver cr = mContext.getContentResolver();
770e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson        return (Settings.Global.getInt(cr, Settings.Global.DEVICE_PROVISIONED, 0) != 0) &&
771e6309aa57ee2e33cf1aa0f177948f5b454d8bb12Winson                (Settings.Secure.getInt(cr, Settings.Secure.USER_SETUP_COMPLETE, 0) != 0);
772e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson    }
773e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson
774e924356ddf8d7e84306d0ee6a63dc6ed6f8b6675Winson    /**
7754727ab9322661eb0c1684d750ce11bdc06312c1cWinson     * Attempts to proxy the following action to the override recents package.
7764727ab9322661eb0c1684d750ce11bdc06312c1cWinson     * @return whether the proxying was successful
7774727ab9322661eb0c1684d750ce11bdc06312c1cWinson     */
7784727ab9322661eb0c1684d750ce11bdc06312c1cWinson    private boolean proxyToOverridePackage(String action) {
7794727ab9322661eb0c1684d750ce11bdc06312c1cWinson        if (mOverrideRecentsPackageName != null) {
7804727ab9322661eb0c1684d750ce11bdc06312c1cWinson            Intent intent = new Intent(action);
7814727ab9322661eb0c1684d750ce11bdc06312c1cWinson            intent.setPackage(mOverrideRecentsPackageName);
7824727ab9322661eb0c1684d750ce11bdc06312c1cWinson            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
7834727ab9322661eb0c1684d750ce11bdc06312c1cWinson            mContext.sendBroadcast(intent);
7844727ab9322661eb0c1684d750ce11bdc06312c1cWinson            return true;
7854727ab9322661eb0c1684d750ce11bdc06312c1cWinson        }
7864727ab9322661eb0c1684d750ce11bdc06312c1cWinson        return false;
7874727ab9322661eb0c1684d750ce11bdc06312c1cWinson    }
788ee69756d542c9e65389e2907c2dc7aa8cca1250dWinson Chung
789ee69756d542c9e65389e2907c2dc7aa8cca1250dWinson Chung    @Override
790ee69756d542c9e65389e2907c2dc7aa8cca1250dWinson Chung    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
791ee69756d542c9e65389e2907c2dc7aa8cca1250dWinson Chung        pw.println("Recents");
792ee69756d542c9e65389e2907c2dc7aa8cca1250dWinson Chung        pw.println("  currentUserId=" + SystemServicesProxy.getInstance(mContext).getCurrentUser());
793ee69756d542c9e65389e2907c2dc7aa8cca1250dWinson Chung    }
7947048fea75c06324a748d49f25bc05be908cda9ffWinson Chung}
795