RecentsActivity.java revision 480dd72daf927283997bdb4060091299add66832
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;
35dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chungimport android.view.ViewGroup;
368e548f7025ce930810479a8e628c325d09557fa3Winson Chungimport android.view.ViewStub;
37dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chungimport android.widget.FrameLayout;
388eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chungimport android.widget.Toast;
3947c4c69575e94635a9356e8a1faf4b56a0120452Winson Chungimport com.android.systemui.R;
40ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.DebugTrigger;
41ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.ReferenceCountedTrigger;
42ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.SystemServicesProxy;
43ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.misc.Utilities;
44f1fbd77cf057e43926f9a0347692611386d09f40Winson Chungimport com.android.systemui.recents.model.RecentsTaskLoader;
45303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport com.android.systemui.recents.model.SpaceNode;
46dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chungimport com.android.systemui.recents.model.Task;
47303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport com.android.systemui.recents.model.TaskStack;
48dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chungimport com.android.systemui.recents.views.DebugOverlayView;
49303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport com.android.systemui.recents.views.RecentsView;
50cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chungimport com.android.systemui.recents.views.SystemBarScrimViews;
51d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chungimport com.android.systemui.recents.views.ViewAnimation;
52303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
53083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chungimport java.lang.ref.WeakReference;
54b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chungimport java.lang.reflect.InvocationTargetException;
55303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chungimport java.util.ArrayList;
56303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
5785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung/**
5885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung * The main Recents activity that is started from AlternateRecentsComponent.
5985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung */
60f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chungpublic class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
61dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks {
62d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung
6385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    // Actions and Extras sent from AlternateRecentsComponent
64ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    final static String EXTRA_TRIGGERED_FROM_ALT_TAB = "extra_triggered_from_alt_tab";
65ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    final static String ACTION_START_ENTER_ANIMATION = "action_start_enter_animation";
66ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    final static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
67ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    final static String ACTION_HIDE_RECENTS_ACTIVITY = "action_hide_recents_activity";
68ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung
6985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    RecentsConfiguration mConfig;
7085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    boolean mVisible;
7185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung
7285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    // Top level views
73cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    RecentsView mRecentsView;
74cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    SystemBarScrimViews mScrimViews;
758e548f7025ce930810479a8e628c325d09557fa3Winson Chung    ViewStub mEmptyViewStub;
76cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    View mEmptyView;
77dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung    DebugOverlayView mDebugOverlay;
78cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung
7985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    // Search AppWidget
80cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    RecentsAppWidgetHost mAppWidgetHost;
81cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    AppWidgetProviderInfo mSearchAppWidgetInfo;
82cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    AppWidgetHostView mSearchAppWidgetHostView;
83cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung
84cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    // Runnables to finish the Recents activity
85cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    FinishRecentsRunnable mFinishLaunchHomeRunnable;
86cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung
87d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    /**
8885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * A common Runnable to finish Recents either by calling finish() (with a custom animation) or
8985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * launching Home with some ActivityOptions.  Generally we always launch home when we exit
9085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * Recents rather than just finishing the activity since we don't know what is behind Recents in
9185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * the task stack.  The only case where we finish() directly is when we are cancelling the full
9285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * screen transition from the app.
93d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung     */
94d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    class FinishRecentsRunnable implements Runnable {
95d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        Intent mLaunchIntent;
96d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        ActivityOptions mLaunchOpts;
97d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
98d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung        /**
99d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung         * Creates a finish runnable that starts the specified intent, using the given
100d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung         * ActivityOptions.
101d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung         */
102d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
103d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            mLaunchIntent = launchIntent;
104d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            mLaunchOpts = opts;
105d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        }
106d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
107d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        @Override
108d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        public void run() {
109d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            // Mark Recents as no longer visible
110d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            AlternateRecentsComponent.notifyVisibilityChanged(false);
1111e44934f0213caf5c434f63a69c9f05fa76e891dWinson Chung            mVisible = false;
112d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            // Finish Recents
113d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            if (mLaunchIntent != null) {
114d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                if (mLaunchOpts != null) {
11585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    startActivityAsUser(mLaunchIntent, UserHandle.CURRENT);
116d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                } else {
11785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    startActivityAsUser(mLaunchIntent, mLaunchOpts.toBundle(), UserHandle.CURRENT);
118d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                }
119d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            } else {
120d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                finish();
12185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                overridePendingTransition(R.anim.recents_to_launcher_enter,
12285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                        R.anim.recents_to_launcher_exit);
123d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung            }
124d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        }
125d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    }
126d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
12785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    /**
12885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * Broadcast receiver to handle messages from AlternateRecentsComponent.
12985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     */
1308eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    final BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
13147c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung        @Override
13247c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung        public void onReceive(Context context, Intent intent) {
13347c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung            String action = intent.getAction();
134ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung            if (action.equals(ACTION_HIDE_RECENTS_ACTIVITY)) {
135ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung                if (intent.getBooleanExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, false)) {
13685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    // If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
13785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    dismissRecentsToFocusedTaskOrHome(false);
1386cb485fd2e2f8ace05e1ff281ab0fc824d3652cbWinson Chung                } else {
13985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    // Otherwise, dismiss Recents to Home
14085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    dismissRecentsToHome(true);
1416cb485fd2e2f8ace05e1ff281ab0fc824d3652cbWinson Chung                }
142ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung            } else if (action.equals(ACTION_TOGGLE_RECENTS_ACTIVITY)) {
14385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                // If we are toggling Recents, then first unfilter any filtered stacks first
14485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                dismissRecentsToFocusedTaskOrHome(true);
145ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung            } else if (action.equals(ACTION_START_ENTER_ANIMATION)) {
146521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung                // Try and start the enter animation (or restart it on configuration changed)
147c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung                ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null);
148dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
149d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung                onEnterAnimationTriggered();
15047c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung            }
15147c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung        }
15247c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung    };
153303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
15485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    /**
15585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * Broadcast receiver to handle messages from the system
15685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     */
15731d66c60d8f518ce3a70972db348d797db92f42cWinson Chung    final BroadcastReceiver mSystemBroadcastReceiver = new BroadcastReceiver() {
1586736905dc0e10689f7c63f6da43b31325caf966aWinson Chung        @Override
1596736905dc0e10689f7c63f6da43b31325caf966aWinson Chung        public void onReceive(Context context, Intent intent) {
16031d66c60d8f518ce3a70972db348d797db92f42cWinson Chung            String action = intent.getAction();
16185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (action.equals(Intent.ACTION_SCREEN_OFF)) {
16285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                // When the screen turns off, dismiss Recents to Home
16385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                dismissRecentsToHome(false);
16431d66c60d8f518ce3a70972db348d797db92f42cWinson Chung            } else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) {
16585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                // When the search activity changes, update the Search widget
16631d66c60d8f518ce3a70972db348d797db92f42cWinson Chung                refreshSearchWidget();
16731d66c60d8f518ce3a70972db348d797db92f42cWinson Chung            }
168d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        }
169d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    };
170d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung
17185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    /**
17285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     * A custom debug trigger to listen for a debug key chord.
17385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung     */
1748eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    final DebugTrigger mDebugTrigger = new DebugTrigger(new Runnable() {
1758eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        @Override
1768eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        public void run() {
1778eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung            onDebugModeTriggered();
1788eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        }
1798eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    });
1808eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung
181303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    /** Updates the set of recent tasks */
182b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung    void updateRecentsTasks(Intent launchIntent) {
183dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        // Load all the tasks
184969f586533096999f10f5587f901949791154fa2Winson Chung        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
185969f586533096999f10f5587f901949791154fa2Winson Chung        SpaceNode root = loader.reload(this, Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
186969f586533096999f10f5587f901949791154fa2Winson Chung        ArrayList<TaskStack> stacks = root.getStacks();
187969f586533096999f10f5587f901949791154fa2Winson Chung        if (!stacks.isEmpty()) {
188dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung            mRecentsView.setTaskStacks(root.getStacks());
189969f586533096999f10f5587f901949791154fa2Winson Chung        }
190969f586533096999f10f5587f901949791154fa2Winson Chung
191b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung        // Update the configuration based on the launch intent
192d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mConfig.launchedFromHome = launchIntent.getBooleanExtra(
193d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung                AlternateRecentsComponent.EXTRA_FROM_HOME, false);
194d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mConfig.launchedFromAppWithThumbnail = launchIntent.getBooleanExtra(
195d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung                AlternateRecentsComponent.EXTRA_FROM_APP_THUMBNAIL, false);
196d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mConfig.launchedFromAppWithScreenshot = launchIntent.getBooleanExtra(
197d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung                AlternateRecentsComponent.EXTRA_FROM_APP_FULL_SCREENSHOT, false);
198d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mConfig.launchedWithAltTab = launchIntent.getBooleanExtra(
199d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung                AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false);
200969f586533096999f10f5587f901949791154fa2Winson Chung        mConfig.launchedWithNoRecentTasks = !root.hasTasks();
2016057c91563402f900dfc7714a46e952d86172e2fWinson Chung        mConfig.launchedToTaskId = launchIntent.getIntExtra(
2026057c91563402f900dfc7714a46e952d86172e2fWinson Chung                AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_TASK_ID, -1);
203303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
204dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        // Mark the task that is the launch target
205dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        int taskStackCount = stacks.size();
206dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        if (mConfig.launchedToTaskId != -1) {
207dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung            for (int i = 0; i < taskStackCount; i++) {
208dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                TaskStack stack = stacks.get(i);
209dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                ArrayList<Task> tasks = stack.getTasks();
210dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                int taskCount = tasks.size();
211dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                for (int j = 0; j < taskCount; j++) {
212dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                    Task t = tasks.get(j);
213dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                    if (t.key.id == mConfig.launchedToTaskId) {
214dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                        t.isLaunchTarget = true;
215dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                        break;
216dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                    }
217dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                }
218dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung            }
219dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        }
220dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung
22185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Update the top level view's visibilities
222969f586533096999f10f5587f901949791154fa2Winson Chung        if (mConfig.launchedWithNoRecentTasks) {
22385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (mEmptyView == null) {
22485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                mEmptyView = mEmptyViewStub.inflate();
22585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            }
226303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung            mEmptyView.setVisibility(View.VISIBLE);
227772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung            mRecentsView.setSearchBarVisibility(View.GONE);
228303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        } else {
22985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (mEmptyView != null) {
23085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                mEmptyView.setVisibility(View.GONE);
23185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            }
232772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung            if (mRecentsView.hasSearchBar()) {
233772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung                mRecentsView.setSearchBarVisibility(View.VISIBLE);
234772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung            } else {
235772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung                addSearchBarAppWidgetView();
236772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung            }
237303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        }
2387aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung
23985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Animate the SystemUI scrims into view
2407aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung        mScrimViews.prepareEnterRecentsAnimation();
241303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
242303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
243f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    /** Attempts to allocate and bind the search bar app widget */
244f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    void bindSearchBarAppWidget() {
245814086db674d8eb298541b7e601e29c5c68e2074Winson Chung        if (Constants.DebugFlags.App.EnableSearchLayout) {
246f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
247f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
248f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            // Reset the host view and widget info
249f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            mSearchAppWidgetHostView = null;
250f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            mSearchAppWidgetInfo = null;
251f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
252f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            // Try and load the app widget id from the settings
253d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung            int appWidgetId = mConfig.searchBarAppWidgetId;
254f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            if (appWidgetId >= 0) {
255f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                mSearchAppWidgetInfo = ssp.getAppWidgetInfo(appWidgetId);
256f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                if (mSearchAppWidgetInfo == null) {
257f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                    // If there is no actual widget associated with that id, then delete it and
258f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                    // prepare to bind another app widget in its place
259f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                    ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
260f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                    appWidgetId = -1;
261f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                }
262f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            }
263f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
264f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            // If there is no id, then bind a new search app widget
265f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            if (appWidgetId < 0) {
266f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                Pair<Integer, AppWidgetProviderInfo> widgetInfo =
267f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                        ssp.bindSearchAppWidget(mAppWidgetHost);
268f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                if (widgetInfo != null) {
269f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                    // Save the app widget id into the settings
270d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung                    mConfig.updateSearchBarAppWidgetId(this, widgetInfo.first);
271f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                    mSearchAppWidgetInfo = widgetInfo.second;
272f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                }
273f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            }
274f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        }
275f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    }
276f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
277f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    /** Creates the search bar app widget view */
278f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    void addSearchBarAppWidgetView() {
279814086db674d8eb298541b7e601e29c5c68e2074Winson Chung        if (Constants.DebugFlags.App.EnableSearchLayout) {
280d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung            int appWidgetId = mConfig.searchBarAppWidgetId;
281f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            if (appWidgetId >= 0) {
282f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                mSearchAppWidgetHostView = mAppWidgetHost.createView(this, appWidgetId,
283f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                        mSearchAppWidgetInfo);
284f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                Bundle opts = new Bundle();
285f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
286f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                        AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
287f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                mSearchAppWidgetHostView.updateAppWidgetOptions(opts);
288f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                // Set the padding to 0 for this search widget
289f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                mSearchAppWidgetHostView.setPadding(0, 0, 0, 0);
290f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                mRecentsView.setSearchBar(mSearchAppWidgetHostView);
291f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            } else {
292f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung                mRecentsView.setSearchBar(null);
293f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            }
294f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        }
295f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    }
296f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
297303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    /** Dismisses recents if we are already visible and the intent is to toggle the recents view */
29885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    boolean dismissRecentsToFocusedTaskOrHome(boolean checkFilteredStackState) {
29947c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung        if (mVisible) {
30085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // If we currently have filtered stacks, then unfilter those first
30185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (checkFilteredStackState &&
30285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                mRecentsView.unfilterFilteredStacks()) return true;
30385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // If we have a focused Task, launch that Task now
30485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (mRecentsView.launchFocusedTask()) return true;
30585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // If we launched from Home, then return to Home
30685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            if (mConfig.launchedFromHome) {
30785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                dismissRecentsToHomeRaw(true);
30885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                return true;
309303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung            }
310dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung            // Otherwise, try and return to the Task that Recents was launched from
311dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung            if (mRecentsView.launchPreviousTask()) return true;
31285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // If none of the other cases apply, then just go Home
31385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            dismissRecentsToHomeRaw(true);
31485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            return true;
31585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        }
31685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        return false;
31785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    }
31885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung
31985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    /** Dismisses Recents directly to Home. */
32085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    void dismissRecentsToHomeRaw(boolean animated) {
32185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        if (animated) {
32285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
32385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    null, mFinishLaunchHomeRunnable, null);
32485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            mRecentsView.startExitToHomeAnimation(
32585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    new ViewAnimation.TaskViewExitContext(exitTrigger));
32685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        } else {
32785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            mFinishLaunchHomeRunnable.run();
32885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        }
32985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    }
33085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung
33185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    /** Dismisses Recents directly to Home if we currently aren't transitioning. */
33285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    boolean dismissRecentsToHome(boolean animated) {
33385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        if (mVisible) {
33485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            // Return to Home
33585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            dismissRecentsToHomeRaw(animated);
33647c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung            return true;
337303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        }
338303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        return false;
339303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
340303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
341303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    /** Called with the activity is first created. */
342303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    @Override
343303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    public void onCreate(Bundle savedInstanceState) {
344303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        super.onCreate(savedInstanceState);
345303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
346303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        // Initialize the loader and the configuration
347303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        RecentsTaskLoader.initialize(this);
34856e09b42a0f1670970872bef611a8036904ad6bfJason Monk        mConfig = RecentsConfiguration.reinitialize(this,
34956e09b42a0f1670970872bef611a8036904ad6bfJason Monk                RecentsTaskLoader.getInstance().getSystemServicesProxy());
350303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
351d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        // Create the home intent runnable
352d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
353d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        homeIntent.addCategory(Intent.CATEGORY_HOME);
354d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
355d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
356d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent,
357d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                ActivityOptions.makeCustomAnimation(this, R.anim.recents_to_launcher_enter,
358d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung                        R.anim.recents_to_launcher_exit));
359d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
360f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        // Initialize the widget host (the host id is static and does not change)
361d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId);
362f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
3638e548f7025ce930810479a8e628c325d09557fa3Winson Chung        // Set the Recents layout
3648e548f7025ce930810479a8e628c325d09557fa3Winson Chung        setContentView(R.layout.recents);
3658e548f7025ce930810479a8e628c325d09557fa3Winson Chung        mRecentsView = (RecentsView) findViewById(R.id.recents_view);
36647c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung        mRecentsView.setCallbacks(this);
367653f70c223f8742e2a3696641fe1d4b82bc2ca36Winson Chung        mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
368653f70c223f8742e2a3696641fe1d4b82bc2ca36Winson Chung                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
369653f70c223f8742e2a3696641fe1d4b82bc2ca36Winson Chung                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
3708e548f7025ce930810479a8e628c325d09557fa3Winson Chung        mEmptyViewStub = (ViewStub) findViewById(R.id.empty_view_stub);
3718e548f7025ce930810479a8e628c325d09557fa3Winson Chung        mScrimViews = new SystemBarScrimViews(this, mConfig);
372dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        inflateDebugOverlay();
373303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
374f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        // Bind the search app widget when we first start up
375f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        bindSearchBarAppWidget();
376772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung        // Update the recent tasks
377772b6b12a323b7999d8d3f335c199e6eb4e621e2Winson Chung        updateRecentsTasks(getIntent());
378521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung
37931d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        // Register the broadcast receiver to handle messages when the screen is turned off
38031d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        IntentFilter filter = new IntentFilter();
38131d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        filter.addAction(Intent.ACTION_SCREEN_OFF);
38231d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
38331d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        registerReceiver(mSystemBroadcastReceiver, filter);
38431d66c60d8f518ce3a70972db348d797db92f42cWinson Chung
38531d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        // Register any broadcast receivers for the task loader
38631d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        RecentsTaskLoader.getInstance().registerReceivers(this, mRecentsView);
38731d66c60d8f518ce3a70972db348d797db92f42cWinson Chung
388cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung        // Private API calls to make the shadows look better
389b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chung        try {
390cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung            Utilities.setShadowProperty("ambientShadowStrength", String.valueOf(35f));
391cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung            Utilities.setShadowProperty("ambientRatio", String.valueOf(0.5f));
392b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chung        } catch (IllegalAccessException e) {
393b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chung            e.printStackTrace();
394b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chung        } catch (InvocationTargetException e) {
395b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chung            e.printStackTrace();
396b13c46e8b78272c4398068eed41f49ee4d403bccWinson Chung        }
3977aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung
3986057c91563402f900dfc7714a46e952d86172e2fWinson Chung        // Update if we are getting a configuration change
3996057c91563402f900dfc7714a46e952d86172e2fWinson Chung        if (savedInstanceState != null) {
4006057c91563402f900dfc7714a46e952d86172e2fWinson Chung            mConfig.updateOnConfigurationChange();
4016057c91563402f900dfc7714a46e952d86172e2fWinson Chung            onConfigurationChange();
4026057c91563402f900dfc7714a46e952d86172e2fWinson Chung        }
403521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung    }
404521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung
405dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung    /** Inflates the debug overlay if debug mode is enabled. */
406dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung    void inflateDebugOverlay() {
407dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        if (mConfig.debugModeEnabled && mDebugOverlay == null) {
408dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung            ViewGroup parent = (ViewGroup) findViewById(android.R.id.content).getRootView();
409dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung            mDebugOverlay = new DebugOverlayView(this);
410dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
411dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                            ViewGroup.LayoutParams.MATCH_PARENT,
412dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                            ViewGroup.LayoutParams.MATCH_PARENT);
413dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung            parent.addView(mDebugOverlay, lp);
414dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung            mRecentsView.setDebugOverlay(mDebugOverlay);
415dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        }
416dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung    }
417dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung
418521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung    void onConfigurationChange() {
41985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Update RecentsConfiguration
42056e09b42a0f1670970872bef611a8036904ad6bfJason Monk        mConfig = RecentsConfiguration.reinitialize(this,
42156e09b42a0f1670970872bef611a8036904ad6bfJason Monk                RecentsTaskLoader.getInstance().getSystemServicesProxy());
42285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung
423521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung        // Try and start the enter animation (or restart it on configuration changed)
424c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung        ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
425dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
426d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        onEnterAnimationTriggered();
427303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
428303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
429303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    @Override
430303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    protected void onNewIntent(Intent intent) {
431303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        super.onNewIntent(intent);
4326057c91563402f900dfc7714a46e952d86172e2fWinson Chung        setIntent(intent);
43347c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung
434480dd72daf927283997bdb4060091299add66832Winson Chung        // Reinitialize the configuration
435480dd72daf927283997bdb4060091299add66832Winson Chung        RecentsConfiguration.reinitialize(this, RecentsTaskLoader.getInstance().getSystemServicesProxy());
436480dd72daf927283997bdb4060091299add66832Winson Chung
437dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        // Clear any debug rects
438dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        if (mDebugOverlay != null) {
439dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung            mDebugOverlay.clear();
440dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        }
441dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung
442303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        // Update the recent tasks
443b44c24fb50845dfbc1f49e78085cf5e01a32067fWinson Chung        updateRecentsTasks(intent);
444303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
445303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
446303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    @Override
447303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    protected void onStart() {
448303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        super.onStart();
44947a3e65acc35cd3061bf3867e8b20753870fd892Winson Chung
45031d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        // Register the broadcast receiver to handle messages from our service
45131d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        IntentFilter filter = new IntentFilter();
452ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        filter.addAction(ACTION_HIDE_RECENTS_ACTIVITY);
453ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        filter.addAction(ACTION_TOGGLE_RECENTS_ACTIVITY);
454ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        filter.addAction(ACTION_START_ENTER_ANIMATION);
45531d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        registerReceiver(mServiceBroadcastReceiver, filter);
456303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
457303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
458303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    @Override
459303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    protected void onResume() {
460303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        super.onResume();
461083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung
462083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung        // Start listening for widget package changes if there is one bound, post it since we don't
463083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung        // want it stalling the startup
464083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung        if (mConfig.searchBarAppWidgetId >= 0) {
465083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung            final WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks> callback =
466083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                    new WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks>(this);
467083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung            mRecentsView.postDelayed(new Runnable() {
468083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                @Override
469083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                public void run() {
470083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                    RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks cb = callback.get();
471083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                    if (cb != null) {
472083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                        mAppWidgetHost.startListening(cb);
473083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                    }
474083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung                }
475083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung            }, 1);
476083baf99ff1228e96ede96aac88c8200c4fdc2b2Winson Chung        }
47793748a11cba1b44edbc2e888c997533461355594Winson Chung
47885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Mark Recents as visible
47993748a11cba1b44edbc2e888c997533461355594Winson Chung        mVisible = true;
4806736905dc0e10689f7c63f6da43b31325caf966aWinson Chung    }
4816736905dc0e10689f7c63f6da43b31325caf966aWinson Chung
4826736905dc0e10689f7c63f6da43b31325caf966aWinson Chung    @Override
483303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    protected void onStop() {
484303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung        super.onStop();
48547c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung
48631d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        // Unregister the RecentsService receiver
48731d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        unregisterReceiver(mServiceBroadcastReceiver);
48831d66c60d8f518ce3a70972db348d797db92f42cWinson Chung
48931d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        // Stop listening for widget package changes if there was one bound
49085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        if (mAppWidgetHost.isListening()) {
49131d66c60d8f518ce3a70972db348d797db92f42cWinson Chung            mAppWidgetHost.stopListening();
49231d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        }
49347c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung    }
49447c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung
49547c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung    @Override
49647c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung    protected void onDestroy() {
49747c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung        super.onDestroy();
49831d66c60d8f518ce3a70972db348d797db92f42cWinson Chung
49985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Unregister the system broadcast receivers
50031d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        unregisterReceiver(mSystemBroadcastReceiver);
50131d66c60d8f518ce3a70972db348d797db92f42cWinson Chung        RecentsTaskLoader.getInstance().unregisterReceivers();
502303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
503303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung
504303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    @Override
5054d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung    public void onTrimMemory(int level) {
5064d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
5074d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung        if (loader != null) {
5084d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung            loader.onTrimMemory(level);
5094d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung        }
5104d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung    }
5114d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung
5124d7b092a866d2fce3e11b5a12cda2b87a83af52dWinson Chung    @Override
5131e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung    public boolean onKeyDown(int keyCode, KeyEvent event) {
5141e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung        if (keyCode == KeyEvent.KEYCODE_TAB) {
5151e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung            // Focus the next task in the stack
5161e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung            final boolean backward = event.isShiftPressed();
5171e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung            mRecentsView.focusNextTask(!backward);
5181e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung            return true;
519c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung        } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
520c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung            mRecentsView.focusNextTask(true);
521c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung            return true;
522c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung        } else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
523c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung            mRecentsView.focusNextTask(false);
524c6011deffc80eaee6dfb1c7975e050bc71e5ea96Winson Chung            return true;
5251e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung        }
5268eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        // Pass through the debug trigger
5278eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        mDebugTrigger.onKeyEvent(keyCode);
5281e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung        return super.onKeyDown(keyCode, event);
5291e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung    }
5301e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung
5311e8d71b605b4872e93200706a80a88a3ff25498cWinson Chung    @Override
532a26fb7822ddf3511796279b847cc216bee9e7f70Winson Chung    public void onUserInteraction() {
533a26fb7822ddf3511796279b847cc216bee9e7f70Winson Chung        mRecentsView.onUserInteraction();
534a26fb7822ddf3511796279b847cc216bee9e7f70Winson Chung    }
535a26fb7822ddf3511796279b847cc216bee9e7f70Winson Chung
536a26fb7822ddf3511796279b847cc216bee9e7f70Winson Chung    @Override
537303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    public void onBackPressed() {
53804d0f756782e697a171aebbb35ae86c86b839a27Winson Chung        // Test mode where back does not do anything
53904d0f756782e697a171aebbb35ae86c86b839a27Winson Chung        if (mConfig.debugModeEnabled) return;
54004d0f756782e697a171aebbb35ae86c86b839a27Winson Chung
54185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Dismiss Recents to the focused Task or Home
54285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        dismissRecentsToFocusedTaskOrHome(true);
543303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung    }
54447c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung
5458eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    /** Called when debug mode is triggered */
5468eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    public void onDebugModeTriggered() {
547dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung
5488eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        if (mConfig.developerOptionsEnabled) {
5498eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung            SharedPreferences settings = getSharedPreferences(getPackageName(), 0);
5508eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung            if (settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false)) {
5518eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung                // Disable the debug mode
5528eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung                settings.edit().remove(Constants.Values.App.Key_DebugModeEnabled).apply();
553dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                mConfig.debugModeEnabled = false;
554dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                inflateDebugOverlay();
555dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                mDebugOverlay.disable();
5568eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung            } else {
5578eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung                // Enable the debug mode
5588eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung                settings.edit().putBoolean(Constants.Values.App.Key_DebugModeEnabled, true).apply();
559dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                mConfig.debugModeEnabled = true;
560dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                inflateDebugOverlay();
561dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                mDebugOverlay.enable();
5628eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung            }
563dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung            Toast.makeText(this, "Debug mode (" + Constants.Values.App.DebugModeVersion + ") " +
564dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                (mConfig.debugModeEnabled ? "Enabled" : "Disabled") + ", please restart Recents now",
565dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung                Toast.LENGTH_SHORT).show();
5668eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung        }
5678eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    }
5688eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung
5698eaeb7dc93ed71b768a2ea8d45021cca010e8263Winson Chung    /** Called when the enter recents animation is triggered. */
570521e7dc0a6782371a710ee81bf804f7e97aaa292Winson Chung    public void onEnterAnimationTriggered() {
57185cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Animate the SystemUI scrim views
572cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung        mScrimViews.startEnterRecentsAnimation();
573969f586533096999f10f5587f901949791154fa2Winson Chung    }
574969f586533096999f10f5587f901949791154fa2Winson Chung
575d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    /**** RecentsView.RecentsViewCallbacks Implementation ****/
576d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
577d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    @Override
578cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung    public void onExitToHomeAnimationTriggered() {
57985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Animate the SystemUI scrim views out
580cdbbb7e33033d7ae368aa5b7007ec2b20ebdaff1Winson Chung        mScrimViews.startExitRecentsAnimation();
581d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    }
582d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
583d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    @Override
5847aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung    public void onTaskViewClicked() {
5859214eff52adf56b7c9532e40b784d52f9f94b6d1Winson Chung        // Mark recents as no longer visible
5869214eff52adf56b7c9532e40b784d52f9f94b6d1Winson Chung        AlternateRecentsComponent.notifyVisibilityChanged(false);
5871e44934f0213caf5c434f63a69c9f05fa76e891dWinson Chung        mVisible = false;
58847c4c69575e94635a9356e8a1faf4b56a0120452Winson Chung    }
589f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
590d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung    @Override
5917aceb9a07fd3883c8f301ba93726d55494b0446eWinson Chung    public void onAllTaskViewsDismissed() {
592d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung        mFinishLaunchHomeRunnable.run();
593d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung    }
594d7b2cb12ac90956843413c212769639044a0b6f2Winson Chung
595d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    /**** RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks Implementation ****/
596d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung
597f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    @Override
598d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung    public void refreshSearchWidget() {
599d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        bindSearchBarAppWidget();
600d543c1bea4d227470f5b6d6535b70e5090064c9aWinson Chung        addSearchBarAppWidgetView();
601f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    }
602303e1ff1fec8b240b587bb18b981247a99833aa8Winson Chung}
603