blob: ba3bcc79da4423cd193cb8fb08cfc2fb417a0593 [file] [log] [blame]
Winson Chung303e1ff2014-03-07 15:06:19 -08001/*
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 *
Peter Schillerb124d562015-12-11 21:31:17 -08008 * http://www.apache.org/licenses/LICENSE-2.0
Winson Chung303e1ff2014-03-07 15:06:19 -08009 *
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
19import android.app.Activity;
Winsona4fab412016-09-15 16:28:22 -070020import android.app.ActivityManager;
Winson Chungd543c1b2014-06-23 15:06:45 -070021import android.app.ActivityOptions;
Winson2536c7e2015-10-01 15:49:31 -070022import android.app.TaskStackBuilder;
Winson Chung47c4c692014-03-17 10:17:11 -070023import android.content.BroadcastReceiver;
24import android.content.Context;
Winson Chung303e1ff2014-03-07 15:06:19 -080025import android.content.Intent;
Winson Chung47c4c692014-03-17 10:17:11 -070026import android.content.IntentFilter;
Winsona1809852016-03-15 11:41:37 -070027import android.content.res.Configuration;
Winson2536c7e2015-10-01 15:49:31 -070028import android.net.Uri;
Winson Chung303e1ff2014-03-07 15:06:19 -080029import android.os.Bundle;
Winson3f32e7e2016-04-20 17:18:08 -070030import android.os.Handler;
Winson Chung15a2ba82014-11-18 11:19:24 -080031import android.os.SystemClock;
Winson Chungd543c1b2014-06-23 15:06:45 -070032import android.os.UserHandle;
Winson2536c7e2015-10-01 15:49:31 -070033import android.provider.Settings;
Winson Chung28217a42017-02-15 13:46:52 -080034import android.provider.Settings.Secure;
Winson1b585612015-11-06 09:16:26 -080035import android.util.Log;
Winson Chung1e8d71b2014-05-16 17:05:22 -070036import android.view.KeyEvent;
Winson Chung303e1ff2014-03-07 15:06:19 -080037import android.view.View;
Filip Gruszczynski14b4e572015-11-03 15:53:55 -080038import android.view.ViewTreeObserver;
Jorim Jaggi3273f312016-05-05 17:32:44 -070039import android.view.ViewTreeObserver.OnPreDrawListener;
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -080040import android.view.WindowManager;
Jorim Jaggic69bd222016-03-15 14:38:37 +010041import android.view.WindowManager.LayoutParams;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050042
Winson Chung5c9f4b92015-06-25 16:16:46 -070043import com.android.internal.logging.MetricsLogger;
Tamas Berghammer383db5eb2016-06-22 15:21:38 +010044import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Jorim Jaggie05256e2016-09-08 14:58:20 -070045import com.android.systemui.DejankUtils;
Winson9b001392016-04-08 14:54:02 -070046import com.android.systemui.Interpolators;
Jorim Jaggid0565172016-09-15 16:31:14 -070047import com.android.keyguard.LatencyTracker;
Winson Chung47c4c692014-03-17 10:17:11 -070048import com.android.systemui.R;
Winsonb78bb4f2015-09-24 17:22:57 -070049import com.android.systemui.recents.events.EventBus;
Winson13d30662015-11-06 15:30:29 -080050import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
Winsone693aaf2016-03-01 12:05:59 -080051import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
Winsonb1e71d02015-11-23 12:40:23 -080052import com.android.systemui.recents.events.activity.DebugFlagsChangedEvent;
Winsonef064132016-01-05 12:11:31 -080053import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
Jorim Jaggi192086e2016-03-11 17:17:03 +010054import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
Jorim Jaggi3273f312016-05-05 17:32:44 -070055import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
Winson3fb67562015-11-11 10:39:03 -080056import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
Winson1b585612015-11-06 09:16:26 -080057import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
Winsonef064132016-01-05 12:11:31 -080058import com.android.systemui.recents.events.activity.ExitRecentsWindowFirstAnimationFrameEvent;
Winson412e1802015-10-20 16:57:57 -070059import com.android.systemui.recents.events.activity.HideRecentsEvent;
Winson0d14d4d2015-10-26 17:05:04 -070060import com.android.systemui.recents.events.activity.IterateRecentsEvent;
Winson83c1b072015-11-09 10:48:04 -080061import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
62import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
Winson88737542016-02-17 13:27:33 -080063import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
Winson412e1802015-10-20 16:57:57 -070064import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
Winson Chungb5026902017-05-03 12:45:13 -070065import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
Winson190fe3bf2015-10-20 14:57:24 -070066import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
67import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
Winson397ae742015-11-20 11:27:33 -080068import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
Winsonef064132016-01-05 12:11:31 -080069import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
Winson9b001392016-04-08 14:54:02 -070070import com.android.systemui.recents.events.ui.HideIncompatibleAppOverlayEvent;
Jorim Jaggi11cc01d2016-01-22 19:39:23 -080071import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
Winson2536c7e2015-10-01 15:49:31 -070072import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent;
Winson9b001392016-04-08 14:54:02 -070073import com.android.systemui.recents.events.ui.ShowIncompatibleAppOverlayEvent;
Winsone5f1faa2015-11-20 12:26:23 -080074import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
Winsonb1e71d02015-11-23 12:40:23 -080075import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
Winsone7f138c2015-10-22 16:15:21 -070076import com.android.systemui.recents.events.ui.UserInteractionEvent;
Winson0d14d4d2015-10-26 17:05:04 -070077import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
78import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
79import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
Jiaquan Hec0e18132017-01-11 14:47:00 -080080import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
81import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent.Direction;
Winson0d14d4d2015-10-26 17:05:04 -070082import com.android.systemui.recents.misc.DozeTrigger;
Winson Chungffa2ec62014-07-03 15:54:42 -070083import com.android.systemui.recents.misc.SystemServicesProxy;
Winson9b001392016-04-08 14:54:02 -070084import com.android.systemui.recents.misc.Utilities;
Winsone6c90732015-09-24 16:06:29 -070085import com.android.systemui.recents.model.RecentsPackageMonitor;
Winson Chunga91c2932014-11-07 15:02:38 -080086import com.android.systemui.recents.model.RecentsTaskLoadPlan;
Winson Chungf1fbd772014-06-24 18:06:58 -070087import com.android.systemui.recents.model.RecentsTaskLoader;
Winson Chungdcfa7972014-07-22 12:27:13 -070088import com.android.systemui.recents.model.Task;
Winson Chung303e1ff2014-03-07 15:06:19 -080089import com.android.systemui.recents.model.TaskStack;
90import com.android.systemui.recents.views.RecentsView;
Winson Chungcdbbb7e2014-06-24 12:11:49 -070091import com.android.systemui.recents.views.SystemBarScrimViews;
Jason Monk2a6ea9c2017-01-26 11:14:51 -050092import com.android.systemui.statusbar.phone.StatusBar;
Winson Chung303e1ff2014-03-07 15:06:19 -080093
Winsond72c3152016-04-05 15:33:35 -070094import java.io.FileDescriptor;
95import java.io.PrintWriter;
Winsona4fab412016-09-15 16:28:22 -070096import java.util.List;
Winsond72c3152016-04-05 15:33:35 -070097
Winson Chung85cfec82014-07-14 14:16:04 -070098/**
Winson27c28f82016-05-05 16:16:50 -070099 * The main Recents activity that is started from RecentsComponent.
Winson Chung85cfec82014-07-14 14:16:04 -0700100 */
Winson397ae742015-11-20 11:27:33 -0800101public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreDrawListener {
Winson Chungd42a6cf2014-06-03 16:24:04 -0700102
Winson0d14d4d2015-10-26 17:05:04 -0700103 private final static String TAG = "RecentsActivity";
104 private final static boolean DEBUG = false;
105
Winsone6c90732015-09-24 16:06:29 -0700106 public final static int EVENT_BUS_PRIORITY = Recents.EVENT_BUS_PRIORITY + 1;
Winson9b001392016-04-08 14:54:02 -0700107 public final static int INCOMPATIBLE_APP_ALPHA_DURATION = 150;
Winsone6c90732015-09-24 16:06:29 -0700108
Winsone5f1faa2015-11-20 12:26:23 -0800109 private RecentsPackageMonitor mPackageMonitor;
Winson3f32e7e2016-04-20 17:18:08 -0700110 private Handler mHandler = new Handler();
Winsone5f1faa2015-11-20 12:26:23 -0800111 private long mLastTabKeyEventTime;
Winson67c79572016-04-13 14:02:18 -0700112 private int mLastDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
Jorim Jaggi25160db2016-04-18 16:03:36 -0700113 private int mLastDisplayDensity;
Winsone5f1faa2015-11-20 12:26:23 -0800114 private boolean mFinishedOnStartup;
115 private boolean mIgnoreAltTabRelease;
Winson88737542016-02-17 13:27:33 -0800116 private boolean mIsVisible;
Winson Chung85cfec82014-07-14 14:16:04 -0700117
118 // Top level views
Winsone5f1faa2015-11-20 12:26:23 -0800119 private RecentsView mRecentsView;
120 private SystemBarScrimViews mScrimViews;
Winson9b001392016-04-08 14:54:02 -0700121 private View mIncompatibleAppOverlay;
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700122
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700123 // Runnables to finish the Recents activity
Winsone693aaf2016-03-01 12:05:59 -0800124 private Intent mHomeIntent;
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700125
Winson0d14d4d2015-10-26 17:05:04 -0700126 // The trigger to automatically launch the current task
Peter Schillerb124d562015-12-11 21:31:17 -0800127 private int mFocusTimerDuration;
128 private DozeTrigger mIterateTrigger;
Winson4b9cded2016-01-26 16:26:47 -0800129 private final UserInteractionEvent mUserInteractionEvent = new UserInteractionEvent();
Winson0d14d4d2015-10-26 17:05:04 -0700130
Winson Chungd543c1b2014-06-23 15:06:45 -0700131 /**
Winson3fb67562015-11-11 10:39:03 -0800132 * A common Runnable to finish Recents by launching Home with an animation depending on the
Peter Schillerb124d562015-12-11 21:31:17 -0800133 * last activity launch state. Generally we always launch home when we exit Recents rather than
Winson3fb67562015-11-11 10:39:03 -0800134 * just finishing the activity since we don't know what is behind Recents in the task stack.
Winson Chungd543c1b2014-06-23 15:06:45 -0700135 */
Winsone693aaf2016-03-01 12:05:59 -0800136 class LaunchHomeRunnable implements Runnable {
Winson49df4202016-01-25 17:33:34 -0800137
Winson Chungd543c1b2014-06-23 15:06:45 -0700138 Intent mLaunchIntent;
Winson49df4202016-01-25 17:33:34 -0800139 ActivityOptions mOpts;
Winson Chungd543c1b2014-06-23 15:06:45 -0700140
Winson Chungd7b2cb12014-06-26 15:08:50 -0700141 /**
Winson3fb67562015-11-11 10:39:03 -0800142 * Creates a finish runnable that starts the specified intent.
Winson Chungd7b2cb12014-06-26 15:08:50 -0700143 */
Winsone693aaf2016-03-01 12:05:59 -0800144 public LaunchHomeRunnable(Intent launchIntent, ActivityOptions opts) {
Winson Chungd543c1b2014-06-23 15:06:45 -0700145 mLaunchIntent = launchIntent;
Winson40a22732016-02-02 18:07:00 -0800146 mOpts = opts;
Winson Chungd543c1b2014-06-23 15:06:45 -0700147 }
148
149 @Override
150 public void run() {
Winson2b9c1d32015-10-05 15:44:23 -0700151 try {
Winson3f32e7e2016-04-20 17:18:08 -0700152 mHandler.post(() -> {
153 ActivityOptions opts = mOpts;
154 if (opts == null) {
155 opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
156 R.anim.recents_to_launcher_enter, R.anim.recents_to_launcher_exit);
157 }
158 startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
159 });
Winson2b9c1d32015-10-05 15:44:23 -0700160 } catch (Exception e) {
Winson1b585612015-11-06 09:16:26 -0800161 Log.e(TAG, getString(R.string.recents_launch_error_message, "Home"), e);
Winson Chungd543c1b2014-06-23 15:06:45 -0700162 }
163 }
164 }
165
Winson Chung85cfec82014-07-14 14:16:04 -0700166 /**
Winson Chung85cfec82014-07-14 14:16:04 -0700167 * Broadcast receiver to handle messages from the system
168 */
Winson Chung31d66c62014-06-30 13:12:54 -0700169 final BroadcastReceiver mSystemBroadcastReceiver = new BroadcastReceiver() {
Winson Chung67369052014-04-07 17:35:48 -0700170 @Override
Winsona4fab412016-09-15 16:28:22 -0700171 public void onReceive(Context ctx, Intent intent) {
Winson Chung31d66c62014-06-30 13:12:54 -0700172 String action = intent.getAction();
Winson Chung85cfec82014-07-14 14:16:04 -0700173 if (action.equals(Intent.ACTION_SCREEN_OFF)) {
174 // When the screen turns off, dismiss Recents to Home
Winson2b9c1d32015-10-05 15:44:23 -0700175 dismissRecentsToHomeIfVisible(false);
Winson Chung36f3f032016-09-08 23:29:43 +0000176 } else if (action.equals(Intent.ACTION_TIME_CHANGED)) {
Winsona4fab412016-09-15 16:28:22 -0700177 // If the time shifts but the currentTime >= lastStackActiveTime, then that boundary
178 // is still valid. Otherwise, we need to reset the lastStackactiveTime to the
179 // currentTime and remove the old tasks in between which would not be previously
180 // visible, but currently would be in the new currentTime
Winson Chung28217a42017-02-15 13:46:52 -0800181 int currentUser = SystemServicesProxy.getInstance(RecentsActivity.this)
182 .getCurrentUser();
183 long oldLastStackActiveTime = Settings.Secure.getLongForUser(getContentResolver(),
184 Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, -1, currentUser);
Winsona4fab412016-09-15 16:28:22 -0700185 if (oldLastStackActiveTime != -1) {
186 long currentTime = System.currentTimeMillis();
187 if (currentTime < oldLastStackActiveTime) {
188 // We are only removing tasks that are between the new current time
189 // and the old last stack active time, they were not visible and in the
190 // TaskStack so we don't need to remove any associated TaskViews but we do
191 // need to load the task id's from the system
Winson Chungf3cfa892017-04-24 12:23:47 -0700192 RecentsTaskLoader loader = Recents.getTaskLoader();
193 RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(ctx);
194 loader.preloadRawTasks(loadPlan, false /* includeFrontMostExcludedTask */);
Winsona4fab412016-09-15 16:28:22 -0700195 List<ActivityManager.RecentTaskInfo> tasks = loadPlan.getRawTasks();
196 for (int i = tasks.size() - 1; i >= 0; i--) {
197 ActivityManager.RecentTaskInfo task = tasks.get(i);
198 if (currentTime <= task.lastActiveTime && task.lastActiveTime <
199 oldLastStackActiveTime) {
200 Recents.getSystemServices().removeTask(task.persistentId);
201 }
202 }
Jorim Jaggief496ea2017-05-13 23:16:44 +0200203 Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
204 currentTime, currentUser);
Winson Chungb5026902017-05-03 12:45:13 -0700205
206 // Clear the last PiP task time, it's an edge case and we'd rather it
207 // not relaunch the PiP task if the user double taps
208 RecentsImpl.clearLastPipTime();
Winsona4fab412016-09-15 16:28:22 -0700209 }
210 }
Winson Chung31d66c62014-06-30 13:12:54 -0700211 }
Winson Chungd42a6cf2014-06-03 16:24:04 -0700212 }
213 };
214
Jorim Jaggi3273f312016-05-05 17:32:44 -0700215 private final OnPreDrawListener mRecentsDrawnEventListener =
216 new ViewTreeObserver.OnPreDrawListener() {
217 @Override
218 public boolean onPreDraw() {
219 mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
220 EventBus.getDefault().post(new RecentsDrawnEvent());
Jorim Jaggie05256e2016-09-08 14:58:20 -0700221 if (LatencyTracker.isEnabled(getApplicationContext())) {
222 DejankUtils.postAfterTraversal(() -> LatencyTracker.getInstance(
223 getApplicationContext()).onActionEnd(
224 LatencyTracker.ACTION_TOGGLE_RECENTS));
225 }
Jorim Jaggi44f4bcb2017-05-12 15:40:43 +0200226 DejankUtils.postAfterTraversal(() -> {
227 Recents.getTaskLoader().startLoader(RecentsActivity.this);
228 Recents.getTaskLoader().getHighResThumbnailLoader().setVisible(true);
229 });
Jorim Jaggi3273f312016-05-05 17:32:44 -0700230 return true;
231 }
232 };
233
Winson0d14d4d2015-10-26 17:05:04 -0700234 /**
235 * Dismisses recents if we are already visible and the intent is to toggle the recents view.
236 */
Winson42329522016-02-05 10:39:46 -0800237 boolean dismissRecentsToFocusedTask(int logCategory) {
Winson0d14d4d2015-10-26 17:05:04 -0700238 SystemServicesProxy ssp = Recents.getSystemServices();
Winsond46b7272016-04-20 11:54:27 -0700239 if (ssp.isRecentsActivityVisible()) {
Winson0d14d4d2015-10-26 17:05:04 -0700240 // If we have a focused Task, launch that Task now
Winson42329522016-02-05 10:39:46 -0800241 if (mRecentsView.launchFocusedTask(logCategory)) return true;
Winson0d14d4d2015-10-26 17:05:04 -0700242 }
243 return false;
244 }
245
246 /**
Winsona0731a12015-12-02 15:10:14 -0800247 * Dismisses recents back to the launch target task.
248 */
249 boolean dismissRecentsToLaunchTargetTaskOrHome() {
250 SystemServicesProxy ssp = Recents.getSystemServices();
Winsond46b7272016-04-20 11:54:27 -0700251 if (ssp.isRecentsActivityVisible()) {
Winsona0731a12015-12-02 15:10:14 -0800252 // If we have a focused Task, launch that Task now
253 if (mRecentsView.launchPreviousTask()) return true;
254 // If none of the other cases apply, then just go Home
Winsonef064132016-01-05 12:11:31 -0800255 dismissRecentsToHome(true /* animateTaskViews */);
Winsona0731a12015-12-02 15:10:14 -0800256 }
257 return false;
258 }
259
260 /**
Winson0d14d4d2015-10-26 17:05:04 -0700261 * Dismisses recents if we are already visible and the intent is to toggle the recents view.
262 */
Winson397ae742015-11-20 11:27:33 -0800263 boolean dismissRecentsToFocusedTaskOrHome() {
Winsone7f138c2015-10-22 16:15:21 -0700264 SystemServicesProxy ssp = Recents.getSystemServices();
Winsond46b7272016-04-20 11:54:27 -0700265 if (ssp.isRecentsActivityVisible()) {
Winson Chung85cfec82014-07-14 14:16:04 -0700266 // If we have a focused Task, launch that Task now
Winson42329522016-02-05 10:39:46 -0800267 if (mRecentsView.launchFocusedTask(0 /* logCategory */)) return true;
Winson Chung85cfec82014-07-14 14:16:04 -0700268 // If none of the other cases apply, then just go Home
Winsonef064132016-01-05 12:11:31 -0800269 dismissRecentsToHome(true /* animateTaskViews */);
Winson Chung85cfec82014-07-14 14:16:04 -0700270 return true;
271 }
272 return false;
273 }
274
Winson2b9c1d32015-10-05 15:44:23 -0700275 /**
276 * Dismisses Recents directly to Home without checking whether it is currently visible.
277 */
Winsonef064132016-01-05 12:11:31 -0800278 void dismissRecentsToHome(boolean animateTaskViews) {
Winson49df4202016-01-25 17:33:34 -0800279 dismissRecentsToHome(animateTaskViews, null);
280 }
281
282 /**
283 * Dismisses Recents directly to Home without checking whether it is currently visible.
284 *
285 * @param overrideAnimation If not null, will override the default animation that is based on
286 * how Recents was launched.
287 */
288 void dismissRecentsToHome(boolean animateTaskViews, ActivityOptions overrideAnimation) {
Winsonef064132016-01-05 12:11:31 -0800289 DismissRecentsToHomeAnimationStarted dismissEvent =
290 new DismissRecentsToHomeAnimationStarted(animateTaskViews);
Winsone693aaf2016-03-01 12:05:59 -0800291 dismissEvent.addPostAnimationCallback(new LaunchHomeRunnable(mHomeIntent,
292 overrideAnimation));
Winson3ca10282016-04-21 15:20:21 -0700293 Recents.getSystemServices().sendCloseSystemWindows(
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500294 StatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
Winsonef064132016-01-05 12:11:31 -0800295 EventBus.getDefault().send(dismissEvent);
Wale Ogunwaled351ada2015-04-04 11:53:14 -0700296 }
297
Winson Chung85cfec82014-07-14 14:16:04 -0700298 /** Dismisses Recents directly to Home if we currently aren't transitioning. */
Winson2b9c1d32015-10-05 15:44:23 -0700299 boolean dismissRecentsToHomeIfVisible(boolean animated) {
Winsone7f138c2015-10-22 16:15:21 -0700300 SystemServicesProxy ssp = Recents.getSystemServices();
Winsond46b7272016-04-20 11:54:27 -0700301 if (ssp.isRecentsActivityVisible()) {
Winson Chung85cfec82014-07-14 14:16:04 -0700302 // Return to Home
Winson2b9c1d32015-10-05 15:44:23 -0700303 dismissRecentsToHome(animated);
Winson Chung47c4c692014-03-17 10:17:11 -0700304 return true;
Winson Chung303e1ff2014-03-07 15:06:19 -0800305 }
306 return false;
307 }
308
309 /** Called with the activity is first created. */
310 @Override
311 public void onCreate(Bundle savedInstanceState) {
312 super.onCreate(savedInstanceState);
Winson3150e572015-10-23 15:07:24 -0700313 mFinishedOnStartup = false;
314
315 // In the case that the activity starts up before the Recents component has initialized
316 // (usually when debugging/pushing the SysUI apk), just finish this activity.
317 SystemServicesProxy ssp = Recents.getSystemServices();
318 if (ssp == null) {
319 mFinishedOnStartup = true;
320 finish();
321 return;
322 }
Winsonb78bb4f2015-09-24 17:22:57 -0700323
324 // Register this activity with the event bus
325 EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
326
Winson008ee15f2016-03-18 17:17:25 -0700327 // Initialize the package monitor
Winsone7f138c2015-10-22 16:15:21 -0700328 mPackageMonitor = new RecentsPackageMonitor();
329 mPackageMonitor.register(this);
Winson Chungf7bca432014-04-30 17:11:13 -0700330
Winson Chung8e548f72014-06-24 14:40:53 -0700331 // Set the Recents layout
332 setContentView(R.layout.recents);
Winson88737542016-02-17 13:27:33 -0800333 takeKeyEvents(true);
Alan Viverette51efddb2017-04-05 10:00:01 -0400334 mRecentsView = findViewById(R.id.recents_view);
Winson Chung653f70c22014-05-19 14:49:42 -0700335 mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
336 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
337 View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
Winson35f30502015-09-28 11:24:36 -0700338 mScrimViews = new SystemBarScrimViews(this);
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -0800339 getWindow().getAttributes().privateFlags |=
340 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
Winson Chung303e1ff2014-03-07 15:06:19 -0800341
Jorim Jaggi25160db2016-04-18 16:03:36 -0700342 Configuration appConfiguration = Utilities.getAppConfiguration(this);
343 mLastDeviceOrientation = appConfiguration.orientation;
344 mLastDisplayDensity = appConfiguration.densityDpi;
Peter Schillerb124d562015-12-11 21:31:17 -0800345 mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration);
346 mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() {
347 @Override
348 public void run() {
Winson42329522016-02-05 10:39:46 -0800349 dismissRecentsToFocusedTask(MetricsEvent.OVERVIEW_SELECT_TIMEOUT);
Peter Schillerb124d562015-12-11 21:31:17 -0800350 }
351 });
352
Winsone8a4eff2016-03-28 16:20:35 -0700353 // Set the window background
354 getWindow().setBackgroundDrawable(mRecentsView.getBackgroundScrim());
355
Winson3fb67562015-11-11 10:39:03 -0800356 // Create the home intent runnable
Winsone693aaf2016-03-01 12:05:59 -0800357 mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
358 mHomeIntent.addCategory(Intent.CATEGORY_HOME);
359 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Winson3fb67562015-11-11 10:39:03 -0800360 Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Winson3fb67562015-11-11 10:39:03 -0800361
Winson Chung31d66c62014-06-30 13:12:54 -0700362 // Register the broadcast receiver to handle messages when the screen is turned off
363 IntentFilter filter = new IntentFilter();
364 filter.addAction(Intent.ACTION_SCREEN_OFF);
Winson Chung36f3f032016-09-08 23:29:43 +0000365 filter.addAction(Intent.ACTION_TIME_CHANGED);
Winson Chung31d66c62014-06-30 13:12:54 -0700366 registerReceiver(mSystemBroadcastReceiver, filter);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100367
368 getWindow().addPrivateFlags(LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION);
Winsona1ededd2016-03-25 12:23:12 -0700369
370 // Reload the stack view
371 reloadStackView();
Winson Chung521e7dc2014-06-02 15:31:56 -0700372 }
373
Winson Chung303e1ff2014-03-07 15:06:19 -0800374 @Override
Winson Chung303e1ff2014-03-07 15:06:19 -0800375 protected void onStart() {
Winson Chung303e1ff2014-03-07 15:06:19 -0800376 super.onStart();
Winson Chung303e1ff2014-03-07 15:06:19 -0800377
Winsone7f138c2015-10-22 16:15:21 -0700378 // Notify that recents is now visible
Winson88737542016-02-17 13:27:33 -0800379 EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500380 MetricsLogger.visible(this, MetricsEvent.OVERVIEW_ACTIVITY);
Jorim Jaggid6a39492016-04-25 17:31:22 -0700381
382 // Notify of the next draw
Jorim Jaggi3273f312016-05-05 17:32:44 -0700383 mRecentsView.getViewTreeObserver().addOnPreDrawListener(mRecentsDrawnEventListener);
Winson Chung67369052014-04-07 17:35:48 -0700384 }
385
386 @Override
Winsona1ededd2016-03-25 12:23:12 -0700387 protected void onNewIntent(Intent intent) {
388 super.onNewIntent(intent);
389
390 // Reload the stack view
391 reloadStackView();
Winson3fb67562015-11-11 10:39:03 -0800392 }
393
Winsona1ededd2016-03-25 12:23:12 -0700394 /**
395 * Reloads the stack views upon launching Recents.
396 */
397 private void reloadStackView() {
Winson Chungb5026902017-05-03 12:45:13 -0700398
Winson88737542016-02-17 13:27:33 -0800399 // If the Recents component has preloaded a load plan, then use that to prevent
400 // reconstructing the task stack
401 RecentsTaskLoader loader = Recents.getTaskLoader();
402 RecentsTaskLoadPlan loadPlan = RecentsImpl.consumeInstanceLoadPlan();
403 if (loadPlan == null) {
404 loadPlan = loader.createLoadPlan(this);
405 }
406
407 // Start loading tasks according to the load plan
408 RecentsConfiguration config = Recents.getConfiguration();
409 RecentsActivityLaunchState launchState = config.getLaunchState();
410 if (!loadPlan.hasTasks()) {
Winson96e61342016-03-15 16:47:19 -0700411 loader.preloadTasks(loadPlan, launchState.launchedToTaskId,
Yoshinori Hirano7bccd432016-11-21 15:42:20 +0900412 !launchState.launchedFromHome && !launchState.launchedViaDockGesture);
Winson88737542016-02-17 13:27:33 -0800413 }
414
415 RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
416 loadOpts.runningTaskId = launchState.launchedToTaskId;
417 loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
418 loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
419 loader.loadTasks(this, loadPlan, loadOpts);
420 TaskStack stack = loadPlan.getTaskStack();
Winsona1ededd2016-03-25 12:23:12 -0700421 mRecentsView.onReload(mIsVisible, stack.getTaskCount() == 0);
Winsond2a03062016-04-15 11:19:07 -0700422 mRecentsView.updateStack(stack, true /* setStackViewTasks */);
Winson88737542016-02-17 13:27:33 -0800423
Winsona1ededd2016-03-25 12:23:12 -0700424 // Update the nav bar scrim, but defer the animation until the enter-window event
Winsonc69249f2016-03-28 13:38:39 -0700425 boolean animateNavBarScrim = !launchState.launchedViaDockGesture;
Winson500ba752016-03-30 11:59:22 -0700426 mScrimViews.updateNavBarScrim(animateNavBarScrim, stack.getTaskCount() > 0, null);
Winson88737542016-02-17 13:27:33 -0800427
Winsona1ededd2016-03-25 12:23:12 -0700428 // If this is a new instance relaunched by AM, without going through the normal mechanisms,
429 // then we have to manually trigger the enter animation state
Winson88737542016-02-17 13:27:33 -0800430 boolean wasLaunchedByAm = !launchState.launchedFromHome &&
431 !launchState.launchedFromApp;
Winsona1ededd2016-03-25 12:23:12 -0700432 if (wasLaunchedByAm) {
Winson88737542016-02-17 13:27:33 -0800433 EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
434 }
435
Winson88737542016-02-17 13:27:33 -0800436 // Keep track of whether we launched from the nav bar button or via alt-tab
437 if (launchState.launchedWithAltTab) {
438 MetricsLogger.count(this, "overview_trigger_alttab", 1);
439 } else {
440 MetricsLogger.count(this, "overview_trigger_nav_btn", 1);
441 }
442
443 // Keep track of whether we launched from an app or from home
444 if (launchState.launchedFromApp) {
Winsona1ededd2016-03-25 12:23:12 -0700445 Task launchTarget = stack.getLaunchTarget();
446 int launchTaskIndexInStack = launchTarget != null
447 ? stack.indexOfStackTask(launchTarget)
448 : 0;
Winson88737542016-02-17 13:27:33 -0800449 MetricsLogger.count(this, "overview_source_app", 1);
450 // If from an app, track the stack index of the app in the stack (for affiliated tasks)
451 MetricsLogger.histogram(this, "overview_source_app_index", launchTaskIndexInStack);
452 } else {
453 MetricsLogger.count(this, "overview_source_home", 1);
454 }
455
456 // Keep track of the total stack task count
Winsona1ededd2016-03-25 12:23:12 -0700457 int taskCount = mRecentsView.getStack().getTaskCount();
Winson88737542016-02-17 13:27:33 -0800458 MetricsLogger.histogram(this, "overview_task_count", taskCount);
459
460 // After we have resumed, set the visible state until the next onStop() call
461 mIsVisible = true;
Jorim Jaggi6e18e002015-06-02 17:07:39 -0700462 }
463
464 @Override
Winsona1ededd2016-03-25 12:23:12 -0700465 public void onEnterAnimationComplete() {
466 super.onEnterAnimationComplete();
Winson Chunged0e2b42017-05-18 23:12:27 -0700467 EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
Winsona1ededd2016-03-25 12:23:12 -0700468 }
469
470 @Override
Winson88737542016-02-17 13:27:33 -0800471 protected void onPause() {
472 super.onPause();
Winson190fe3bf2015-10-20 14:57:24 -0700473
Winsone5f1faa2015-11-20 12:26:23 -0800474 mIgnoreAltTabRelease = false;
Winson88737542016-02-17 13:27:33 -0800475 mIterateTrigger.stopDozing();
Winson88737542016-02-17 13:27:33 -0800476 }
Winsone7f138c2015-10-22 16:15:21 -0700477
Winson88737542016-02-17 13:27:33 -0800478 @Override
Winsona1809852016-03-15 11:41:37 -0700479 public void onConfigurationChanged(Configuration newConfig) {
480 super.onConfigurationChanged(newConfig);
481
Winson44849b82016-03-29 10:45:45 -0700482 // Notify of the config change
Jorim Jaggi25160db2016-04-18 16:03:36 -0700483 Configuration newDeviceConfiguration = Utilities.getAppConfiguration(this);
Winson500ba752016-03-30 11:59:22 -0700484 int numStackTasks = mRecentsView.getStack().getStackTaskCount();
Winson44849b82016-03-29 10:45:45 -0700485 EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */,
Jorim Jaggi25160db2016-04-18 16:03:36 -0700486 mLastDeviceOrientation != newDeviceConfiguration.orientation,
487 mLastDisplayDensity != newDeviceConfiguration.densityDpi, numStackTasks > 0));
488 mLastDeviceOrientation = newDeviceConfiguration.orientation;
489 mLastDisplayDensity = newDeviceConfiguration.densityDpi;
Winsona1809852016-03-15 11:41:37 -0700490 }
491
492 @Override
Andrii Kulian933076d2016-03-29 17:04:42 -0700493 public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
494 super.onMultiWindowModeChanged(isInMultiWindowMode);
Winson500ba752016-03-30 11:59:22 -0700495
Winson Chungb5026902017-05-03 12:45:13 -0700496 reloadTaskStack(isInMultiWindowMode, true /* sendConfigChangedEvent */);
Winsona1ededd2016-03-25 12:23:12 -0700497 }
498
499 @Override
Winson88737542016-02-17 13:27:33 -0800500 protected void onStop() {
501 super.onStop();
502
Winson88737542016-02-17 13:27:33 -0800503 // Notify that recents is now hidden
504 mIsVisible = false;
505 EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500506 MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
Jorim Jaggi6f9dbcb2017-03-17 17:22:47 +0100507 Recents.getTaskLoader().getHighResThumbnailLoader().setVisible(false);
Winson73492c52016-03-09 17:44:54 -0800508
Yoshinori Hirano7bccd432016-11-21 15:42:20 +0900509 if (!isChangingConfigurations()) {
510 // Workaround for b/22542869, if the RecentsActivity is started again, but without going
511 // through SystemUI, we need to reset the config launch flags to ensure that we do not
512 // wait on the system to send a signal that was never queued.
513 RecentsConfiguration config = Recents.getConfiguration();
514 RecentsActivityLaunchState launchState = config.getLaunchState();
515 launchState.reset();
516 }
Winson Chung69a9c172017-06-06 14:01:29 -0700517
518 // Force a gc to attempt to clean up bitmap references more quickly (b/38258699)
519 Recents.getSystemServices().gc();
Winson Chung47c4c692014-03-17 10:17:11 -0700520 }
521
522 @Override
523 protected void onDestroy() {
Winson Chung47c4c692014-03-17 10:17:11 -0700524 super.onDestroy();
Winson Chung31d66c62014-06-30 13:12:54 -0700525
Winson3150e572015-10-23 15:07:24 -0700526 // In the case that the activity finished on startup, just skip the unregistration below
527 if (mFinishedOnStartup) {
528 return;
529 }
530
Winson Chung85cfec82014-07-14 14:16:04 -0700531 // Unregister the system broadcast receivers
Winson Chung31d66c62014-06-30 13:12:54 -0700532 unregisterReceiver(mSystemBroadcastReceiver);
Winson Chung905950a2014-09-17 09:25:27 +0200533
Winsone7f138c2015-10-22 16:15:21 -0700534 // Unregister any broadcast receivers for the task loader
535 mPackageMonitor.unregister();
536
Winsonb78bb4f2015-09-24 17:22:57 -0700537 EventBus.getDefault().unregister(this);
Winson Chung303e1ff2014-03-07 15:06:19 -0800538 }
539
Winson412e1802015-10-20 16:57:57 -0700540 @Override
541 public void onAttachedToWindow() {
542 super.onAttachedToWindow();
543 EventBus.getDefault().register(mScrimViews, EVENT_BUS_PRIORITY);
544 }
Winson Chungaf3bb692015-06-03 17:31:39 -0700545
Winson412e1802015-10-20 16:57:57 -0700546 @Override
547 public void onDetachedFromWindow() {
548 super.onDetachedFromWindow();
549 EventBus.getDefault().unregister(mScrimViews);
Winson Chung353c0b92014-10-16 17:43:23 -0700550 }
551
552 @Override
Winson Chung4d7b0922014-03-13 17:14:17 -0700553 public void onTrimMemory(int level) {
Winsone7f138c2015-10-22 16:15:21 -0700554 RecentsTaskLoader loader = Recents.getTaskLoader();
Winson Chung4d7b0922014-03-13 17:14:17 -0700555 if (loader != null) {
556 loader.onTrimMemory(level);
557 }
558 }
559
560 @Override
Winson Chung1e8d71b2014-05-16 17:05:22 -0700561 public boolean onKeyDown(int keyCode, KeyEvent event) {
Winson Chunga0e88b52014-08-11 19:25:42 -0700562 switch (keyCode) {
563 case KeyEvent.KEYCODE_TAB: {
Winson35f30502015-09-28 11:24:36 -0700564 int altTabKeyDelay = getResources().getInteger(R.integer.recents_alt_tab_key_delay);
Winson Chung15a2ba82014-11-18 11:19:24 -0800565 boolean hasRepKeyTimeElapsed = (SystemClock.elapsedRealtime() -
Winson35f30502015-09-28 11:24:36 -0700566 mLastTabKeyEventTime) > altTabKeyDelay;
Winson Chunga0e88b52014-08-11 19:25:42 -0700567 if (event.getRepeatCount() <= 0 || hasRepKeyTimeElapsed) {
568 // Focus the next task in the stack
569 final boolean backward = event.isShiftPressed();
Winson0d14d4d2015-10-26 17:05:04 -0700570 if (backward) {
571 EventBus.getDefault().send(new FocusPreviousTaskViewEvent());
572 } else {
Peter Schillerb124d562015-12-11 21:31:17 -0800573 EventBus.getDefault().send(
Winson4b9cded2016-01-26 16:26:47 -0800574 new FocusNextTaskViewEvent(0 /* timerIndicatorDuration */));
Winson0d14d4d2015-10-26 17:05:04 -0700575 }
Winson Chung15a2ba82014-11-18 11:19:24 -0800576 mLastTabKeyEventTime = SystemClock.elapsedRealtime();
Winsone5f1faa2015-11-20 12:26:23 -0800577
578 // In the case of another ALT event, don't ignore the next release
579 if (event.isAltPressed()) {
580 mIgnoreAltTabRelease = false;
581 }
Winson Chunga0e88b52014-08-11 19:25:42 -0700582 }
583 return true;
584 }
Jiaquan Hec0e18132017-01-11 14:47:00 -0800585 case KeyEvent.KEYCODE_DPAD_UP:
586 case KeyEvent.KEYCODE_DPAD_DOWN:
587 case KeyEvent.KEYCODE_DPAD_LEFT:
588 case KeyEvent.KEYCODE_DPAD_RIGHT: {
589 final Direction direction = NavigateTaskViewEvent.getDirectionFromKeyCode(keyCode);
590 EventBus.getDefault().send(new NavigateTaskViewEvent(direction));
Winson Chunga0e88b52014-08-11 19:25:42 -0700591 return true;
592 }
593 case KeyEvent.KEYCODE_DEL:
594 case KeyEvent.KEYCODE_FORWARD_DEL: {
Winsondf3012b2016-01-12 15:35:05 -0800595 if (event.getRepeatCount() <= 0) {
596 EventBus.getDefault().send(new DismissFocusedTaskViewEvent());
Winson0d14d4d2015-10-26 17:05:04 -0700597
Winsondf3012b2016-01-12 15:35:05 -0800598 // Keep track of deletions by keyboard
599 MetricsLogger.histogram(this, "overview_task_dismissed_source",
600 Constants.Metrics.DismissSourceKeyboard);
601 return true;
602 }
Winson Chunga0e88b52014-08-11 19:25:42 -0700603 }
604 default:
605 break;
Winson Chung1e8d71b2014-05-16 17:05:22 -0700606 }
Winson Chung1e8d71b2014-05-16 17:05:22 -0700607 return super.onKeyDown(keyCode, event);
608 }
609
610 @Override
Winson Chunga26fb782014-06-12 17:52:39 -0700611 public void onUserInteraction() {
Winson4b9cded2016-01-26 16:26:47 -0800612 EventBus.getDefault().send(mUserInteractionEvent);
Winson Chunga26fb782014-06-12 17:52:39 -0700613 }
614
615 @Override
Winson Chung303e1ff2014-03-07 15:06:19 -0800616 public void onBackPressed() {
Winsona0731a12015-12-02 15:10:14 -0800617 // Back behaves like the recents button so just trigger a toggle event
618 EventBus.getDefault().send(new ToggleRecentsEvent());
Winson Chung303e1ff2014-03-07 15:06:19 -0800619 }
Winson Chung47c4c692014-03-17 10:17:11 -0700620
Winsonb78bb4f2015-09-24 17:22:57 -0700621 /**** EventBus events ****/
Winson Chungd543c1b2014-06-23 15:06:45 -0700622
Winson412e1802015-10-20 16:57:57 -0700623 public final void onBusEvent(ToggleRecentsEvent event) {
Winson8f6ee482016-03-18 17:51:48 -0700624 RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
625 if (launchState.launchedFromHome) {
626 dismissRecentsToHome(true /* animateTaskViews */);
627 } else {
628 dismissRecentsToLaunchTargetTaskOrHome();
Winsonc29ff002015-11-20 16:00:45 -0800629 }
Winson412e1802015-10-20 16:57:57 -0700630 }
631
Winson0d14d4d2015-10-26 17:05:04 -0700632 public final void onBusEvent(IterateRecentsEvent event) {
Winson8f6ee482016-03-18 17:51:48 -0700633 final RecentsDebugFlags debugFlags = Recents.getDebugFlags();
Peter Schillerb124d562015-12-11 21:31:17 -0800634
Winson8f6ee482016-03-18 17:51:48 -0700635 // Start dozing after the recents button is clicked
636 int timerIndicatorDuration = 0;
637 if (debugFlags.isFastToggleRecentsEnabled()) {
638 timerIndicatorDuration = getResources().getInteger(
639 R.integer.recents_subsequent_auto_advance_duration);
Winson4b9cded2016-01-26 16:26:47 -0800640
Winson8f6ee482016-03-18 17:51:48 -0700641 mIterateTrigger.setDozeDuration(timerIndicatorDuration);
642 if (!mIterateTrigger.isDozing()) {
643 mIterateTrigger.startDozing();
644 } else {
645 mIterateTrigger.poke();
Winson8b1871d2015-11-20 09:56:20 -0800646 }
647 }
Winson8f6ee482016-03-18 17:51:48 -0700648
649 // Focus the next task
650 EventBus.getDefault().send(new FocusNextTaskViewEvent(timerIndicatorDuration));
651
652 MetricsLogger.action(this, MetricsEvent.ACTION_OVERVIEW_PAGE);
Winson0d14d4d2015-10-26 17:05:04 -0700653 }
654
655 public final void onBusEvent(UserInteractionEvent event) {
Winsonb61e6542016-02-04 14:37:18 -0800656 // Stop the fast-toggle dozer
Winson0d14d4d2015-10-26 17:05:04 -0700657 mIterateTrigger.stopDozing();
658 }
659
Winson412e1802015-10-20 16:57:57 -0700660 public final void onBusEvent(HideRecentsEvent event) {
661 if (event.triggeredFromAltTab) {
662 // If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
Winsone5f1faa2015-11-20 12:26:23 -0800663 if (!mIgnoreAltTabRelease) {
664 dismissRecentsToFocusedTaskOrHome();
665 }
Winson412e1802015-10-20 16:57:57 -0700666 } else if (event.triggeredFromHomeKey) {
Winson8f6ee482016-03-18 17:51:48 -0700667 dismissRecentsToHome(true /* animateTaskViews */);
Winson4b9cded2016-01-26 16:26:47 -0800668
669 // Cancel any pending dozes
670 EventBus.getDefault().send(mUserInteractionEvent);
Winson412e1802015-10-20 16:57:57 -0700671 } else {
672 // Do nothing
673 }
674 }
675
Filip Gruszczynski1a5203d2015-10-29 17:43:49 -0700676 public final void onBusEvent(EnterRecentsWindowLastAnimationFrameEvent event) {
Winsonb1e71d02015-11-23 12:40:23 -0800677 EventBus.getDefault().send(new UpdateFreeformTaskViewVisibilityEvent(true));
Filip Gruszczynski14b4e572015-11-03 15:53:55 -0800678 mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
Winsonb1e71d02015-11-23 12:40:23 -0800679 mRecentsView.invalidate();
Filip Gruszczynski1a5203d2015-10-29 17:43:49 -0700680 }
681
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -0800682 public final void onBusEvent(ExitRecentsWindowFirstAnimationFrameEvent event) {
Winsonb1e71d02015-11-23 12:40:23 -0800683 if (mRecentsView.isLastTaskLaunchedFreeform()) {
684 EventBus.getDefault().send(new UpdateFreeformTaskViewVisibilityEvent(false));
685 }
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -0800686 mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
Winsonb1e71d02015-11-23 12:40:23 -0800687 mRecentsView.invalidate();
Filip Gruszczynski1a4dfe52015-11-15 10:58:57 -0800688 }
689
Jorim Jaggi192086e2016-03-11 17:17:03 +0100690 public final void onBusEvent(DockedFirstAnimationFrameEvent event) {
691 mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
692 mRecentsView.invalidate();
693 }
694
Winson13d30662015-11-06 15:30:29 -0800695 public final void onBusEvent(CancelEnterRecentsWindowAnimationEvent event) {
696 RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
697 int launchToTaskId = launchState.launchedToTaskId;
698 if (launchToTaskId != -1 &&
699 (event.launchTask == null || launchToTaskId != event.launchTask.key.id)) {
700 SystemServicesProxy ssp = Recents.getSystemServices();
701 ssp.cancelWindowTransition(launchState.launchedToTaskId);
702 ssp.cancelThumbnailTransition(getTaskId());
703 }
704 }
705
Winson2536c7e2015-10-01 15:49:31 -0700706 public final void onBusEvent(ShowApplicationInfoEvent event) {
707 // Create a new task stack with the application info details activity
Winson2536c7e2015-10-01 15:49:31 -0700708 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Winsone7f138c2015-10-22 16:15:21 -0700709 Uri.fromParts("package", event.task.key.getComponent().getPackageName(), null));
Winson2536c7e2015-10-01 15:49:31 -0700710 intent.setComponent(intent.resolveActivity(getPackageManager()));
711 TaskStackBuilder.create(this)
712 .addNextIntentWithParentStack(intent).startActivities(null,
Peter Schillerb124d562015-12-11 21:31:17 -0800713 new UserHandle(event.task.key.userId));
Winson2536c7e2015-10-01 15:49:31 -0700714
715 // Keep track of app-info invocations
716 MetricsLogger.count(this, "overview_app_info", 1);
717 }
718
Winson9b001392016-04-08 14:54:02 -0700719 public final void onBusEvent(ShowIncompatibleAppOverlayEvent event) {
720 if (mIncompatibleAppOverlay == null) {
721 mIncompatibleAppOverlay = Utilities.findViewStubById(this,
722 R.id.incompatible_app_overlay_stub).inflate();
723 mIncompatibleAppOverlay.setWillNotDraw(false);
724 mIncompatibleAppOverlay.setVisibility(View.VISIBLE);
725 }
726 mIncompatibleAppOverlay.animate()
727 .alpha(1f)
728 .setDuration(INCOMPATIBLE_APP_ALPHA_DURATION)
729 .setInterpolator(Interpolators.ALPHA_IN)
730 .start();
731 }
732
733 public final void onBusEvent(HideIncompatibleAppOverlayEvent event) {
734 if (mIncompatibleAppOverlay != null) {
735 mIncompatibleAppOverlay.animate()
736 .alpha(0f)
737 .setDuration(INCOMPATIBLE_APP_ALPHA_DURATION)
738 .setInterpolator(Interpolators.ALPHA_OUT)
739 .start();
740 }
741 }
742
Winsonef064132016-01-05 12:11:31 -0800743 public final void onBusEvent(DeleteTaskDataEvent event) {
Winson2536c7e2015-10-01 15:49:31 -0700744 // Remove any stored data from the loader
Winsone7f138c2015-10-22 16:15:21 -0700745 RecentsTaskLoader loader = Recents.getTaskLoader();
Winson2536c7e2015-10-01 15:49:31 -0700746 loader.deleteTaskData(event.task, false);
747
748 // Remove the task from activity manager
Winsone7f138c2015-10-22 16:15:21 -0700749 SystemServicesProxy ssp = Recents.getSystemServices();
750 ssp.removeTask(event.task.key.id);
Winson2536c7e2015-10-01 15:49:31 -0700751 }
752
Winson397ae742015-11-20 11:27:33 -0800753 public final void onBusEvent(AllTaskViewsDismissedEvent event) {
Winson Chung9a742902015-12-11 10:25:40 -0500754 SystemServicesProxy ssp = Recents.getSystemServices();
755 if (ssp.hasDockedTask()) {
Winson20684082016-03-16 17:13:34 -0700756 mRecentsView.showEmptyView(event.msgResId);
Winson Chung9a742902015-12-11 10:25:40 -0500757 } else {
758 // Just go straight home (no animation necessary because there are no more task views)
Winsonef064132016-01-05 12:11:31 -0800759 dismissRecentsToHome(false /* animateTaskViews */);
Winson Chung9a742902015-12-11 10:25:40 -0500760 }
Winson397ae742015-11-20 11:27:33 -0800761
762 // Keep track of all-deletions
763 MetricsLogger.count(this, "overview_task_all_dismissed", 1);
764 }
765
Winson83c1b072015-11-09 10:48:04 -0800766 public final void onBusEvent(LaunchTaskSucceededEvent event) {
767 MetricsLogger.histogram(this, "overview_task_launch_index", event.taskIndexFromStackFront);
768 }
769
770 public final void onBusEvent(LaunchTaskFailedEvent event) {
771 // Return to Home
Winsonef064132016-01-05 12:11:31 -0800772 dismissRecentsToHome(true /* animateTaskViews */);
Winson83c1b072015-11-09 10:48:04 -0800773
774 MetricsLogger.count(this, "overview_task_launch_failed", 1);
775 }
776
Winson412e1802015-10-20 16:57:57 -0700777 public final void onBusEvent(ScreenPinningRequestEvent event) {
778 MetricsLogger.count(this, "overview_screen_pinned", 1);
779 }
780
Winsonc742f972015-11-12 11:32:21 -0800781 public final void onBusEvent(DebugFlagsChangedEvent event) {
782 // Just finish recents so that we can reload the flags anew on the next instantiation
783 finish();
784 }
785
Winsone5f1faa2015-11-20 12:26:23 -0800786 public final void onBusEvent(StackViewScrolledEvent event) {
787 // Once the user has scrolled while holding alt-tab, then we should ignore the release of
788 // the key
789 mIgnoreAltTabRelease = true;
790 }
791
Jorim Jaggi3273f312016-05-05 17:32:44 -0700792 public final void onBusEvent(final DockedTopTaskEvent event) {
793 mRecentsView.getViewTreeObserver().addOnPreDrawListener(mRecentsDrawnEventListener);
794 mRecentsView.invalidate();
795 }
796
Winson Chungb5026902017-05-03 12:45:13 -0700797 public final void onBusEvent(final ActivityUnpinnedEvent event) {
798 if (mIsVisible) {
799 // Skip the configuration change event as the PiP activity does not actually affect the
800 // config of recents
801 reloadTaskStack(isInMultiWindowMode(), false /* sendConfigChangedEvent */);
802 }
803 }
804
805 private void reloadTaskStack(boolean isInMultiWindowMode, boolean sendConfigChangedEvent) {
806 // Reload the task stack completely
807 RecentsConfiguration config = Recents.getConfiguration();
808 RecentsActivityLaunchState launchState = config.getLaunchState();
809 RecentsTaskLoader loader = Recents.getTaskLoader();
810 RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
811 loader.preloadTasks(loadPlan, -1 /* runningTaskId */,
812 false /* includeFrontMostExcludedTask */);
813
814 RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
815 loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
816 loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
817 loader.loadTasks(this, loadPlan, loadOpts);
818
819 TaskStack stack = loadPlan.getTaskStack();
820 int numStackTasks = stack.getStackTaskCount();
821 boolean showDeferredAnimation = numStackTasks > 0;
822
823 if (sendConfigChangedEvent) {
824 EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
825 false /* fromDeviceOrientationChange */, false /* fromDisplayDensityChange */,
826 numStackTasks > 0));
827 }
828 EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode,
829 showDeferredAnimation, stack));
830 }
831
Filip Gruszczynski14b4e572015-11-03 15:53:55 -0800832 @Override
833 public boolean onPreDraw() {
834 mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
835 // We post to make sure that this information is delivered after this traversals is
836 // finished.
837 mRecentsView.post(new Runnable() {
838 @Override
839 public void run() {
840 Recents.getSystemServices().endProlongedAnimations();
841 }
842 });
843 return true;
844 }
Winsond72c3152016-04-05 15:33:35 -0700845
846 @Override
847 public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
848 super.dump(prefix, fd, writer, args);
Winson67c79572016-04-13 14:02:18 -0700849 EventBus.getDefault().dump(prefix, writer);
Winson29a763b2016-04-20 10:50:40 -0700850 Recents.getTaskLoader().dump(prefix, writer);
Winson67c79572016-04-13 14:02:18 -0700851
Winsond72c3152016-04-05 15:33:35 -0700852 String id = Integer.toHexString(System.identityHashCode(this));
Winson Chung28217a42017-02-15 13:46:52 -0800853 long lastStackActiveTime = Settings.Secure.getLongForUser(getContentResolver(),
854 Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, -1,
855 SystemServicesProxy.getInstance(this).getCurrentUser());
Winsond72c3152016-04-05 15:33:35 -0700856
857 writer.print(prefix); writer.print(TAG);
858 writer.print(" visible="); writer.print(mIsVisible ? "Y" : "N");
Winson Chung36f3f032016-09-08 23:29:43 +0000859 writer.print(" lastStackTaskActiveTime="); writer.print(lastStackActiveTime);
860 writer.print(" currentTime="); writer.print(System.currentTimeMillis());
Winsond72c3152016-04-05 15:33:35 -0700861 writer.print(" [0x"); writer.print(id); writer.print("]");
862 writer.println();
863
864 if (mRecentsView != null) {
865 mRecentsView.dump(prefix, writer);
866 }
Winsond72c3152016-04-05 15:33:35 -0700867 }
Winson Chung303e1ff2014-03-07 15:06:19 -0800868}