RecentsActivity.java revision 85cfec811e35025dbde54f4dc09fe0e1337c36b8
1303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung/*
2303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * Copyright (C) 2014 The Android Open Source Project
3303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung *
4303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * Licensed under the Apache License, Version 2.0 (the "License");
5303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * you may not use this file except in compliance with the License.
6303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * You may obtain a copy of the License at
7303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung *
8303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung *      http://www.apache.org/licenses/LICENSE-2.0
9303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung *
10303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * Unless required by applicable law or agreed to in writing, software
11303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * distributed under the License is distributed on an "AS IS" BASIS,
12303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * See the License for the specific language governing permissions and
14303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung * limitations under the License.
15303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung */
16303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
17303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungpackage com.android.systemui.recents;
18303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
19303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport android.app.Activity;
20d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chungimport android.app.ActivityOptions;
218eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chungimport android.app.SearchManager;
22f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chungimport android.appwidget.AppWidgetHostView;
23f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chungimport android.appwidget.AppWidgetManager;
24f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chungimport android.appwidget.AppWidgetProviderInfo;
2547c4c69575e94635a9356e8a1faf4b56a0120452Winson Chungimport android.content.BroadcastReceiver;
2647c4c69575e94635a9356e8a1faf4b56a0120452Winson Chungimport android.content.Context;
27303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport android.content.Intent;
2847c4c69575e94635a9356e8a1faf4b56a0120452Winson Chungimport android.content.IntentFilter;
298eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chungimport android.content.SharedPreferences;
30303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport android.os.Bundle;
31d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chungimport android.os.UserHandle;
32f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chungimport android.util.Pair;
331e8d71b605b4872e93200706a80a88a3ff25498cWinson Chungimport android.view.KeyEvent;
34303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport android.view.View;
358e548f7025ce930810479a8e628c325d09557fa3Winson Chungimport android.view.ViewStub;
368eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chungimport android.widget.Toast;
3747c4c69575e94635a9356e8a1faf4b56a0120452Winson Chungimport com.android.systemui.R;
38ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.Console;
39ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.DebugTrigger;
40ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.ReferenceCountedTrigger;
41ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.SystemServicesProxy;
42ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.Utilities;
43f1fbd77cf057e43926f9a0347692611386d09f40Winson Chungimport com.android.systemui.recents.model.RecentsTaskLoader;
44303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport com.android.systemui.recents.model.SpaceNode;
45303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport com.android.systemui.recents.model.TaskStack;
468e548f7025ce930810479a8e628c325d09557fa3Winson Chungimport com.android.systemui.recents.views.FullscreenTransitionOverlayView;
47303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport com.android.systemui.recents.views.RecentsView;
48cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chungimport com.android.systemui.recents.views.SystemBarScrimViews;
49d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chungimport com.android.systemui.recents.views.ViewAnimation;
50303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
51083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chungimport java.lang.ref.WeakReference;
52b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chungimport java.lang.reflect.InvocationTargetException;
53303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport java.util.ArrayList;
54303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
5585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung/**
5685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung * The main Recents activity that is started from AlternateRecentsComponent.
5785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung */
58f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chungpublic class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
59d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks,
608e548f7025ce930810479a8e628c325d09557fa3Winson Chung        FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks {
61d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung
6285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    // Actions and Extras sent from AlternateRecentsComponent
63ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    final static String EXTRA_TRIGGERED_FROM_ALT_TAB = "extra_triggered_from_alt_tab";
64ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    final static String ACTION_START_ENTER_ANIMATION = "action_start_enter_animation";
65ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    final static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
66ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    final static String ACTION_HIDE_RECENTS_ACTIVITY = "action_hide_recents_activity";
67ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung
6885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    RecentsConfiguration mConfig;
6985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    boolean mVisible;
7085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung
7185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    // Top level views
72cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    RecentsView mRecentsView;
73cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    SystemBarScrimViews mScrimViews;
748e548f7025ce930810479a8e628c325d09557fa3Winson Chung    ViewStub mEmptyViewStub;
75cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    View mEmptyView;
768e548f7025ce930810479a8e628c325d09557fa3Winson Chung    ViewStub mFullscreenOverlayStub;
778e548f7025ce930810479a8e628c325d09557fa3Winson Chung    FullscreenTransitionOverlayView mFullScreenOverlayView;
78cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung
7985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    // Search AppWidget
80cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    RecentsAppWidgetHost mAppWidgetHost;
81cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    AppWidgetProviderInfo mSearchAppWidgetInfo;
82cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    AppWidgetHostView mSearchAppWidgetHostView;
83cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung
84cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung
85cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    // Runnables to finish the Recents activity
8685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    FinishRecentsRunnable mFinishRunnable = new FinishRecentsRunnable();
87cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    FinishRecentsRunnable mFinishLaunchHomeRunnable;
88cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung
89d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    /**
9085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * A common Runnable to finish Recents either by calling finish() (with a custom animation) or
9185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * launching Home with some ActivityOptions.  Generally we always launch home when we exit
9285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * Recents rather than just finishing the activity since we don't know what is behind Recents in
9385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * the task stack.  The only case where we finish() directly is when we are cancelling the full
9485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * screen transition from the app.
95d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung     */
96d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    class FinishRecentsRunnable implements Runnable {
97d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        Intent mLaunchIntent;
98d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        ActivityOptions mLaunchOpts;
99d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
10085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        public FinishRecentsRunnable() {
10185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // Do nothing
102d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        }
103d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
104d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung        /**
105d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung         * Creates a finish runnable that starts the specified intent, using the given
106d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung         * ActivityOptions.
107d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung         */
108d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
109d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            mLaunchIntent = launchIntent;
110d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            mLaunchOpts = opts;
111d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        }
112d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
113d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        @Override
114d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        public void run() {
115d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            // Mark Recents as no longer visible
116d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            AlternateRecentsComponent.notifyVisibilityChanged(false);
1171e44934f0213caf5c434f63a69c9f05fa76e891dWinson Chung            mVisible = false;
118d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            // Finish Recents
119d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            if (mLaunchIntent != null) {
120d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                if (mLaunchOpts != null) {
12185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    startActivityAsUser(mLaunchIntent, UserHandle.CURRENT);
122d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                } else {
12385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    startActivityAsUser(mLaunchIntent, mLaunchOpts.toBundle(), UserHandle.CURRENT);
124d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                }
125d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            } else {
126d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                finish();
12785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                overridePendingTransition(R.anim.recents_to_launcher_enter,
12885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                        R.anim.recents_to_launcher_exit);
129d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            }
130d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        }
131d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    }
132d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
13385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    /**
13485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * Broadcast receiver to handle messages from AlternateRecentsComponent.
13585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     */
1368eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    final BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
13747c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung        @Override
13847c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung        public void onReceive(Context context, Intent intent) {
13947c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung            String action = intent.getAction();
140ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung            if (action.equals(ACTION_HIDE_RECENTS_ACTIVITY)) {
141ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung                if (intent.getBooleanExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, false)) {
14285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    // If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
14385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    dismissRecentsToFocusedTaskOrHome(false);
1446cb485fd2e2f8ace05e1ff281ab0fc824d3652cbWinson Chung                } else {
14585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    // Otherwise, dismiss Recents to Home
14685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    dismissRecentsToHome(true);
1476cb485fd2e2f8ace05e1ff281ab0fc824d3652cbWinson Chung                }
148ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung            } else if (action.equals(ACTION_TOGGLE_RECENTS_ACTIVITY)) {
14985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                // If we are toggling Recents, then first unfilter any filtered stacks first
15085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                dismissRecentsToFocusedTaskOrHome(true);
151ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung            } else if (action.equals(ACTION_START_ENTER_ANIMATION)) {
152521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung                // Try and start the enter animation (or restart it on configuration changed)
153c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung                ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null);
154c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung                mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(
155c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung                        mFullScreenOverlayView, t));
156d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung                onEnterAnimationTriggered();
15747c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung            }
15847c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung        }
15947c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung    };
160303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
16185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    /**
16285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * Broadcast receiver to handle messages from the system
16385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     */
16431d66c60d8f518ce3a70972db348d797db92f42cWinson Chung    final BroadcastReceiver mSystemBroadcastReceiver = new BroadcastReceiver() {
1656736905dc0e10689f7c63f6da43b31325caf966aWinson Chung        @Override
1666736905dc0e10689f7c63f6da43b31325caf966aWinson Chung        public void onReceive(Context context, Intent intent) {
16731d66c60d8f518ce3a70972db348d797db92f42cWinson Chung            String action = intent.getAction();
16885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (action.equals(Intent.ACTION_SCREEN_OFF)) {
16985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                // When the screen turns off, dismiss Recents to Home
17085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                dismissRecentsToHome(false);
17131d66c60d8f518ce3a70972db348d797db92f42cWinson Chung            } else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) {
17285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                // When the search activity changes, update the Search widget
17331d66c60d8f518ce3a70972db348d797db92f42cWinson Chung                refreshSearchWidget();
17431d66c60d8f518ce3a70972db348d797db92f42cWinson Chung            }
175d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        }
176d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    };
177d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung
17885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    /**
17985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * A custom debug trigger to listen for a debug key chord.
18085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     */
1818eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    final DebugTrigger mDebugTrigger = new DebugTrigger(new Runnable() {
1828eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        @Override
1838eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        public void run() {
1848eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung            onDebugModeTriggered();
1858eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        }
1868eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    });
1878eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung
188303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    /** Updates the set of recent tasks */
189b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung    void updateRecentsTasks(Intent launchIntent) {
190969f586533096999f10f5587f901949791154fa2Winson Chung        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
191969f586533096999f10f5587f901949791154fa2Winson Chung        SpaceNode root = loader.reload(this, Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
192969f586533096999f10f5587f901949791154fa2Winson Chung        ArrayList<TaskStack> stacks = root.getStacks();
193969f586533096999f10f5587f901949791154fa2Winson Chung        if (!stacks.isEmpty()) {
194969f586533096999f10f5587f901949791154fa2Winson Chung            mRecentsView.setBSP(root);
195969f586533096999f10f5587f901949791154fa2Winson Chung        }
196969f586533096999f10f5587f901949791154fa2Winson Chung
197b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung        // Update the configuration based on the launch intent
198d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mConfig.launchedFromHome = launchIntent.getBooleanExtra(
199d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung                AlternateRecentsComponent.EXTRA_FROM_HOME, false);
200d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mConfig.launchedFromAppWithThumbnail = launchIntent.getBooleanExtra(
201d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung                AlternateRecentsComponent.EXTRA_FROM_APP_THUMBNAIL, false);
202d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mConfig.launchedFromAppWithScreenshot = launchIntent.getBooleanExtra(
203d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung                AlternateRecentsComponent.EXTRA_FROM_APP_FULL_SCREENSHOT, false);
204d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mConfig.launchedWithAltTab = launchIntent.getBooleanExtra(
205d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung                AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false);
206969f586533096999f10f5587f901949791154fa2Winson Chung        mConfig.launchedWithNoRecentTasks = !root.hasTasks();
2076057c91563402f900dfc7714a46e952d86172e2fWinson Chung        mConfig.launchedToTaskId = launchIntent.getIntExtra(
2086057c91563402f900dfc7714a46e952d86172e2fWinson Chung                AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_TASK_ID, -1);
209303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
21085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Update the top level view's visibilities
211969f586533096999f10f5587f901949791154fa2Winson Chung        if (mConfig.launchedWithNoRecentTasks) {
21285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (mEmptyView == null) {
21385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                mEmptyView = mEmptyViewStub.inflate();
21485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            }
215303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung            mEmptyView.setVisibility(View.VISIBLE);
216772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung            mRecentsView.setSearchBarVisibility(View.GONE);
217303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        } else {
21885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (mEmptyView != null) {
21985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                mEmptyView.setVisibility(View.GONE);
22085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            }
221772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung            if (mRecentsView.hasSearchBar()) {
222772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung                mRecentsView.setSearchBarVisibility(View.VISIBLE);
223772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung            } else {
224772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung                addSearchBarAppWidgetView();
225772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung            }
226303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        }
2277aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung
22885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Animate the SystemUI scrims into view
2297aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung        mScrimViews.prepareEnterRecentsAnimation();
230303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
231303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
232f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    /** Attempts to allocate and bind the search bar app widget */
233f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    void bindSearchBarAppWidget() {
234814086db674d8eb298541b7e601e29c5c68e2074Winson Chung        if (Constants.DebugFlags.App.EnableSearchLayout) {
235f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
236f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
237f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            // Reset the host view and widget info
238f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            mSearchAppWidgetHostView = null;
239f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            mSearchAppWidgetInfo = null;
240f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
241f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            // Try and load the app widget id from the settings
242d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung            int appWidgetId = mConfig.searchBarAppWidgetId;
243f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            if (appWidgetId >= 0) {
244f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                mSearchAppWidgetInfo = ssp.getAppWidgetInfo(appWidgetId);
245f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                if (mSearchAppWidgetInfo == null) {
246f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                    // If there is no actual widget associated with that id, then delete it and
247f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                    // prepare to bind another app widget in its place
248f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                    ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
249f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                    appWidgetId = -1;
250f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                }
251f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            }
252f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
253f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            // If there is no id, then bind a new search app widget
254f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            if (appWidgetId < 0) {
255f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                Pair<Integer, AppWidgetProviderInfo> widgetInfo =
256f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                        ssp.bindSearchAppWidget(mAppWidgetHost);
257f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                if (widgetInfo != null) {
258f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                    // Save the app widget id into the settings
259d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung                    mConfig.updateSearchBarAppWidgetId(this, widgetInfo.first);
260f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                    mSearchAppWidgetInfo = widgetInfo.second;
261f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                }
262f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            }
263f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        }
264f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    }
265f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
266f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    /** Creates the search bar app widget view */
267f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    void addSearchBarAppWidgetView() {
268814086db674d8eb298541b7e601e29c5c68e2074Winson Chung        if (Constants.DebugFlags.App.EnableSearchLayout) {
269d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung            int appWidgetId = mConfig.searchBarAppWidgetId;
270f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            if (appWidgetId >= 0) {
271f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                mSearchAppWidgetHostView = mAppWidgetHost.createView(this, appWidgetId,
272f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                        mSearchAppWidgetInfo);
273f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                Bundle opts = new Bundle();
274f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
275f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                        AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
276f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                mSearchAppWidgetHostView.updateAppWidgetOptions(opts);
277f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                // Set the padding to 0 for this search widget
278f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                mSearchAppWidgetHostView.setPadding(0, 0, 0, 0);
279f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                mRecentsView.setSearchBar(mSearchAppWidgetHostView);
280f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            } else {
281f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                mRecentsView.setSearchBar(null);
282f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            }
283f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        }
284f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    }
285f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
286303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    /** Dismisses recents if we are already visible and the intent is to toggle the recents view */
28785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    boolean dismissRecentsToFocusedTaskOrHome(boolean checkFilteredStackState) {
28847c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung        if (mVisible) {
28985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // If we are mid-animation into Recents, reverse the animation now
29085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (mFullScreenOverlayView != null &&
29185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) return true;
29285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // If we currently have filtered stacks, then unfilter those first
29385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (checkFilteredStackState &&
29485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                mRecentsView.unfilterFilteredStacks()) return true;
29585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // If we have a focused Task, launch that Task now
29685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (mRecentsView.launchFocusedTask()) return true;
29785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // If we launched from Home, then return to Home
29885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (mConfig.launchedFromHome) {
29985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                dismissRecentsToHomeRaw(true);
30085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                return true;
301303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung            }
30285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // Otherwise, try and return to the first Task in the stack
30385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (mRecentsView.launchFirstTask()) return true;
30485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // If none of the other cases apply, then just go Home
30585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            dismissRecentsToHomeRaw(true);
30685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            return true;
30785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        }
30885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        return false;
30985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    }
31085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung
31185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    /** Dismisses Recents directly to Home. */
31285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    void dismissRecentsToHomeRaw(boolean animated) {
31385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        if (animated) {
31485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
31585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    null, mFinishLaunchHomeRunnable, null);
31685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            mRecentsView.startExitToHomeAnimation(
31785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    new ViewAnimation.TaskViewExitContext(exitTrigger));
31885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        } else {
31985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            mFinishLaunchHomeRunnable.run();
32085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        }
32185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    }
32285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung
32385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    /** Dismisses Recents directly to Home if we currently aren't transitioning. */
32485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    boolean dismissRecentsToHome(boolean animated) {
32585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        if (mVisible) {
32685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // If we are mid-animation into Recents, reverse the animation now
32785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (mFullScreenOverlayView != null &&
32885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) return true;
32985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // Return to Home
33085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            dismissRecentsToHomeRaw(animated);
33147c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung            return true;
332303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        }
333303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        return false;
334303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
335303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
336303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    /** Called with the activity is first created. */
337303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    @Override
338303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    public void onCreate(Bundle savedInstanceState) {
339303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        super.onCreate(savedInstanceState);
340303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
341303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        // Initialize the loader and the configuration
342303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        RecentsTaskLoader.initialize(this);
343d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mConfig = RecentsConfiguration.reinitialize(this);
344303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
345d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        // Create the home intent runnable
346d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
347d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        homeIntent.addCategory(Intent.CATEGORY_HOME);
348d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
349d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
350d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent,
351d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                ActivityOptions.makeCustomAnimation(this, R.anim.recents_to_launcher_enter,
352d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                        R.anim.recents_to_launcher_exit));
353d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
354f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        // Initialize the widget host (the host id is static and does not change)
355d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId);
356f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
3578e548f7025ce930810479a8e628c325d09557fa3Winson Chung        // Set the Recents layout
3588e548f7025ce930810479a8e628c325d09557fa3Winson Chung        setContentView(R.layout.recents);
3598e548f7025ce930810479a8e628c325d09557fa3Winson Chung        mRecentsView = (RecentsView) findViewById(R.id.recents_view);
36047c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung        mRecentsView.setCallbacks(this);
361653f70c223f8742e2a3696641fe1d4b82bc2ca36Winson Chung        mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
362653f70c223f8742e2a3696641fe1d4b82bc2ca36Winson Chung                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
363653f70c223f8742e2a3696641fe1d4b82bc2ca36Winson Chung                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
3648e548f7025ce930810479a8e628c325d09557fa3Winson Chung        mEmptyViewStub = (ViewStub) findViewById(R.id.empty_view_stub);
3658e548f7025ce930810479a8e628c325d09557fa3Winson Chung        mFullscreenOverlayStub = (ViewStub) findViewById(R.id.fullscreen_overlay_stub);
3668e548f7025ce930810479a8e628c325d09557fa3Winson Chung        mScrimViews = new SystemBarScrimViews(this, mConfig);
367303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
368f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        // Bind the search app widget when we first start up
369f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        bindSearchBarAppWidget();
370772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung        // Update the recent tasks
371772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung        updateRecentsTasks(getIntent());
372521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung
37331d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        // Register the broadcast receiver to handle messages when the screen is turned off
37431d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        IntentFilter filter = new IntentFilter();
37531d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        filter.addAction(Intent.ACTION_SCREEN_OFF);
37631d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
37731d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        registerReceiver(mSystemBroadcastReceiver, filter);
37831d66c60d8f518ce3a70972db348d797db92f42cWinson Chung
37931d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        // Register any broadcast receivers for the task loader
38031d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        RecentsTaskLoader.getInstance().registerReceivers(this, mRecentsView);
38131d66c60d8f518ce3a70972db348d797db92f42cWinson Chung
382cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung        // Private API calls to make the shadows look better
383b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chung        try {
384cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung            Utilities.setShadowProperty("ambientShadowStrength", String.valueOf(35f));
385cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung            Utilities.setShadowProperty("ambientRatio", String.valueOf(0.5f));
386b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chung        } catch (IllegalAccessException e) {
387b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chung            e.printStackTrace();
388b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chung        } catch (InvocationTargetException e) {
389b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chung            e.printStackTrace();
390b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chung        }
3917aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung
3927aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung        // Prepare the screenshot transition if necessary
3937aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung        if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
3947aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung            mFullScreenOverlayView = (FullscreenTransitionOverlayView) mFullscreenOverlayStub.inflate();
3957aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung            mFullScreenOverlayView.setCallbacks(this);
3967aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung            mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
3977aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung        }
3986057c91563402f900dfc7714a46e952d86172e2fWinson Chung
3996057c91563402f900dfc7714a46e952d86172e2fWinson Chung        // Update if we are getting a configuration change
4006057c91563402f900dfc7714a46e952d86172e2fWinson Chung        if (savedInstanceState != null) {
4016057c91563402f900dfc7714a46e952d86172e2fWinson Chung            mConfig.updateOnConfigurationChange();
4026057c91563402f900dfc7714a46e952d86172e2fWinson Chung            onConfigurationChange();
4036057c91563402f900dfc7714a46e952d86172e2fWinson Chung        }
404521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung    }
405521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung
406521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung    void onConfigurationChange() {
40785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Update RecentsConfiguration
40885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        mConfig = RecentsConfiguration.reinitialize(this);
40985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung
410521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung        // Try and start the enter animation (or restart it on configuration changed)
411c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung        ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
412c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung        mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(
413c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung                mFullScreenOverlayView, t));
414d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        onEnterAnimationTriggered();
415303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
416303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
417303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    @Override
418303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    protected void onNewIntent(Intent intent) {
419303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        super.onNewIntent(intent);
4206057c91563402f900dfc7714a46e952d86172e2fWinson Chung        setIntent(intent);
42147c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung
422303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        // Update the recent tasks
423b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung        updateRecentsTasks(intent);
424f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
425d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        // Prepare the screenshot transition if necessary
426d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
4278e548f7025ce930810479a8e628c325d09557fa3Winson Chung            mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
428d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        }
429303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
430303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
431303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    @Override
432303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    protected void onStart() {
433303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        super.onStart();
43447a3e65acc35cd3061bf3867e8b20753870fd892Winson Chung
43531d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        // Register the broadcast receiver to handle messages from our service
43631d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        IntentFilter filter = new IntentFilter();
437ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        filter.addAction(ACTION_HIDE_RECENTS_ACTIVITY);
438ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        filter.addAction(ACTION_TOGGLE_RECENTS_ACTIVITY);
439ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        filter.addAction(ACTION_START_ENTER_ANIMATION);
44031d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        registerReceiver(mServiceBroadcastReceiver, filter);
441303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
442303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
443303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    @Override
444303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    protected void onResume() {
445303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        super.onResume();
446083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung
447083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung        // Start listening for widget package changes if there is one bound, post it since we don't
448083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung        // want it stalling the startup
449083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung        if (mConfig.searchBarAppWidgetId >= 0) {
450083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung            final WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks> callback =
451083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                    new WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks>(this);
452083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung            mRecentsView.postDelayed(new Runnable() {
453083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                @Override
454083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                public void run() {
455083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                    RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks cb = callback.get();
456083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                    if (cb != null) {
457083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                        mAppWidgetHost.startListening(cb);
458083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                    }
459083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                }
460083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung            }, 1);
461083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung        }
46293748a11cba1b44edbc2e888c997533461355594Winson Chung
46385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Mark Recents as visible
46493748a11cba1b44edbc2e888c997533461355594Winson Chung        mVisible = true;
4656736905dc0e10689f7c63f6da43b31325caf966aWinson Chung    }
4666736905dc0e10689f7c63f6da43b31325caf966aWinson Chung
4676736905dc0e10689f7c63f6da43b31325caf966aWinson Chung    @Override
468303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    protected void onStop() {
469303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        super.onStop();
47047c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung
47131d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        // Unregister the RecentsService receiver
47231d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        unregisterReceiver(mServiceBroadcastReceiver);
47331d66c60d8f518ce3a70972db348d797db92f42cWinson Chung
47431d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        // Stop listening for widget package changes if there was one bound
47585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        if (mAppWidgetHost.isListening()) {
47631d66c60d8f518ce3a70972db348d797db92f42cWinson Chung            mAppWidgetHost.stopListening();
47731d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        }
47847c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung    }
47947c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung
48047c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung    @Override
48147c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung    protected void onDestroy() {
48247c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung        super.onDestroy();
48331d66c60d8f518ce3a70972db348d797db92f42cWinson Chung
48485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Unregister the system broadcast receivers
48531d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        unregisterReceiver(mSystemBroadcastReceiver);
48631d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        RecentsTaskLoader.getInstance().unregisterReceivers();
487303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
488303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
489303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    @Override
4904d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung    public void onTrimMemory(int level) {
4914d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
4924d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung        if (loader != null) {
4934d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung            loader.onTrimMemory(level);
4944d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung        }
4954d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung    }
4964d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung
4974d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung    @Override
4981e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung    public boolean onKeyDown(int keyCode, KeyEvent event) {
4991e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung        if (keyCode == KeyEvent.KEYCODE_TAB) {
5001e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung            // Focus the next task in the stack
5011e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung            final boolean backward = event.isShiftPressed();
5021e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung            mRecentsView.focusNextTask(!backward);
5031e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung            return true;
504c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung        } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
505c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung            mRecentsView.focusNextTask(true);
506c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung            return true;
507c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung        } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
508c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung            mRecentsView.focusNextTask(false);
509c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung            return true;
5101e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung        }
5118eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        // Pass through the debug trigger
5128eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        mDebugTrigger.onKeyEvent(keyCode);
5131e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung        return super.onKeyDown(keyCode, event);
5141e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung    }
5151e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung
5161e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung    @Override
517a26fb7822ddf3511796279b847cc216bee9e7f70Winson Chung    public void onUserInteraction() {
518a26fb7822ddf3511796279b847cc216bee9e7f70Winson Chung        mRecentsView.onUserInteraction();
519a26fb7822ddf3511796279b847cc216bee9e7f70Winson Chung    }
520a26fb7822ddf3511796279b847cc216bee9e7f70Winson Chung
521a26fb7822ddf3511796279b847cc216bee9e7f70Winson Chung    @Override
522303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    public void onBackPressed() {
52304d0f756782e697a171aebbb35ae86c86b839a27Winson Chung        // Test mode where back does not do anything
52404d0f756782e697a171aebbb35ae86c86b839a27Winson Chung        if (mConfig.debugModeEnabled) return;
52504d0f756782e697a171aebbb35ae86c86b839a27Winson Chung
52685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Dismiss Recents to the focused Task or Home
52785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        dismissRecentsToFocusedTaskOrHome(true);
528303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
52947c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung
5308eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    /** Called when debug mode is triggered */
5318eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    public void onDebugModeTriggered() {
5328eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        if (mConfig.developerOptionsEnabled) {
5338eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung            SharedPreferences settings = getSharedPreferences(getPackageName(), 0);
5348eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung            if (settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false)) {
5358eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung                // Disable the debug mode
5368eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung                settings.edit().remove(Constants.Values.App.Key_DebugModeEnabled).apply();
5378eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung            } else {
5388eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung                // Enable the debug mode
5398eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung                settings.edit().putBoolean(Constants.Values.App.Key_DebugModeEnabled, true).apply();
5408eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung            }
5418eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung            Toast.makeText(this, "Debug mode (" + Constants.Values.App.DebugModeVersion +
5428eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung                    ") toggled, please restart Recents now", Toast.LENGTH_SHORT).show();
5438eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        }
5448eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    }
5458eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung
5468eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    /** Called when the enter recents animation is triggered. */
547521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung    public void onEnterAnimationTriggered() {
54885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Animate the SystemUI scrim views
549cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung        mScrimViews.startEnterRecentsAnimation();
550969f586533096999f10f5587f901949791154fa2Winson Chung    }
551969f586533096999f10f5587f901949791154fa2Winson Chung
5528e548f7025ce930810479a8e628c325d09557fa3Winson Chung    /**** FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks Implementation ****/
553521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung
554521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung    @Override
5556057c91563402f900dfc7714a46e952d86172e2fWinson Chung    public void onEnterAnimationComplete() {
5566057c91563402f900dfc7714a46e952d86172e2fWinson Chung        // Reset the full screenshot transition view
5576057c91563402f900dfc7714a46e952d86172e2fWinson Chung        if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
5586057c91563402f900dfc7714a46e952d86172e2fWinson Chung            mFullScreenOverlayView.reset();
559d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung
5606057c91563402f900dfc7714a46e952d86172e2fWinson Chung            // Recycle the full screen screenshot
5616057c91563402f900dfc7714a46e952d86172e2fWinson Chung            AlternateRecentsComponent.consumeLastScreenshot();
562d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        }
563d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    }
564d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung
565d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    /**** RecentsView.RecentsViewCallbacks Implementation ****/
566d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
567d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    @Override
568cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    public void onExitToHomeAnimationTriggered() {
56985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Animate the SystemUI scrim views out
570cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung        mScrimViews.startExitRecentsAnimation();
571d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    }
572d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
573d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    @Override
5747aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung    public void onTaskViewClicked() {
5759214eff52adf56b7c9532e40b784d52f9f94b6d1Winson Chung        // Mark recents as no longer visible
5769214eff52adf56b7c9532e40b784d52f9f94b6d1Winson Chung        AlternateRecentsComponent.notifyVisibilityChanged(false);
5771e44934f0213caf5c434f63a69c9f05fa76e891dWinson Chung        mVisible = false;
57847c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung    }
579f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
580d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung    @Override
5817aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung    public void onAllTaskViewsDismissed() {
582d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung        mFinishLaunchHomeRunnable.run();
583d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung    }
584d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung
585d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    /**** RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks Implementation ****/
586d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
587f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    @Override
588d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    public void refreshSearchWidget() {
589d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        bindSearchBarAppWidget();
590d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        addSearchBarAppWidgetView();
591f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    }
592303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung}
593