RecentsActivity.java revision 15155519ba9ce8302d5ca1771f7816cd683a2051
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.recents;
18
19import android.app.Activity;
20import android.app.ActivityOptions;
21import android.app.SearchManager;
22import android.appwidget.AppWidgetHostView;
23import android.appwidget.AppWidgetManager;
24import android.appwidget.AppWidgetProviderInfo;
25import android.content.BroadcastReceiver;
26import android.content.Context;
27import android.content.Intent;
28import android.content.IntentFilter;
29import android.content.SharedPreferences;
30import android.os.Bundle;
31import android.os.UserHandle;
32import android.util.Pair;
33import android.view.KeyEvent;
34import android.view.View;
35import android.view.ViewStub;
36import android.widget.Toast;
37import com.android.systemui.R;
38import com.android.systemui.recents.misc.DebugTrigger;
39import com.android.systemui.recents.misc.ReferenceCountedTrigger;
40import com.android.systemui.recents.misc.SystemServicesProxy;
41import com.android.systemui.recents.misc.Utilities;
42import com.android.systemui.recents.model.RecentsTaskLoader;
43import com.android.systemui.recents.model.SpaceNode;
44import com.android.systemui.recents.model.Task;
45import com.android.systemui.recents.model.TaskStack;
46import com.android.systemui.recents.views.DebugOverlayView;
47import com.android.systemui.recents.views.RecentsView;
48import com.android.systemui.recents.views.SystemBarScrimViews;
49import com.android.systemui.recents.views.ViewAnimation;
50
51import java.lang.ref.WeakReference;
52import java.lang.reflect.InvocationTargetException;
53import java.util.ArrayList;
54
55/**
56 * The main Recents activity that is started from AlternateRecentsComponent.
57 */
58public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
59        RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks,
60        DebugOverlayView.DebugOverlayViewCallbacks {
61
62    RecentsConfiguration mConfig;
63    boolean mVisible;
64    long mLastTabKeyEventTime;
65
66    // Top level views
67    RecentsView mRecentsView;
68    SystemBarScrimViews mScrimViews;
69    ViewStub mEmptyViewStub;
70    ViewStub mDebugOverlayStub;
71    View mEmptyView;
72    DebugOverlayView mDebugOverlay;
73
74    // Search AppWidget
75    RecentsAppWidgetHost mAppWidgetHost;
76    AppWidgetProviderInfo mSearchAppWidgetInfo;
77    AppWidgetHostView mSearchAppWidgetHostView;
78
79    // Runnables to finish the Recents activity
80    FinishRecentsRunnable mFinishLaunchHomeRunnable;
81
82    /**
83     * A common Runnable to finish Recents either by calling finish() (with a custom animation) or
84     * launching Home with some ActivityOptions.  Generally we always launch home when we exit
85     * Recents rather than just finishing the activity since we don't know what is behind Recents in
86     * the task stack.  The only case where we finish() directly is when we are cancelling the full
87     * screen transition from the app.
88     */
89    class FinishRecentsRunnable implements Runnable {
90        Intent mLaunchIntent;
91        ActivityOptions mLaunchOpts;
92
93        /**
94         * Creates a finish runnable that starts the specified intent, using the given
95         * ActivityOptions.
96         */
97        public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
98            mLaunchIntent = launchIntent;
99            mLaunchOpts = opts;
100        }
101
102        @Override
103        public void run() {
104            // Mark Recents as no longer visible
105            AlternateRecentsComponent.notifyVisibilityChanged(false);
106            mVisible = false;
107            // Finish Recents
108            if (mLaunchIntent != null) {
109                if (mLaunchOpts != null) {
110                    startActivityAsUser(mLaunchIntent, mLaunchOpts.toBundle(), UserHandle.CURRENT);
111                } else {
112                    startActivityAsUser(mLaunchIntent, UserHandle.CURRENT);
113                }
114            } else {
115                finish();
116                overridePendingTransition(R.anim.recents_to_launcher_enter,
117                        R.anim.recents_to_launcher_exit);
118            }
119        }
120    }
121
122    /**
123     * Broadcast receiver to handle messages from AlternateRecentsComponent.
124     */
125    final BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
126        @Override
127        public void onReceive(Context context, Intent intent) {
128            String action = intent.getAction();
129            if (action.equals(AlternateRecentsComponent.ACTION_HIDE_RECENTS_ACTIVITY)) {
130                // Mark Recents as no longer visible
131                AlternateRecentsComponent.notifyVisibilityChanged(false);
132                if (intent.getBooleanExtra(AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false)) {
133                    // If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
134                    dismissRecentsToFocusedTaskOrHome(false);
135                } else if (intent.getBooleanExtra(AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_HOME_KEY, false)) {
136                    // Otherwise, dismiss Recents to Home
137                    dismissRecentsToHome(true);
138                } else {
139                    // Do nothing, another activity is being launched on top of Recents
140                }
141            } else if (action.equals(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
142                // If we are toggling Recents, then first unfilter any filtered stacks first
143                dismissRecentsToFocusedTaskOrHome(true);
144            } else if (action.equals(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION)) {
145                // Try and start the enter animation (or restart it on configuration changed)
146                ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null);
147                mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
148                onEnterAnimationTriggered();
149            }
150        }
151    };
152
153    /**
154     * Broadcast receiver to handle messages from the system
155     */
156    final BroadcastReceiver mSystemBroadcastReceiver = new BroadcastReceiver() {
157        @Override
158        public void onReceive(Context context, Intent intent) {
159            String action = intent.getAction();
160            if (action.equals(Intent.ACTION_SCREEN_OFF)) {
161                // When the screen turns off, dismiss Recents to Home
162                dismissRecentsToHome(false);
163            } else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) {
164                // When the search activity changes, update the Search widget
165                refreshSearchWidget();
166            }
167        }
168    };
169
170    /**
171     * A custom debug trigger to listen for a debug key chord.
172     */
173    final DebugTrigger mDebugTrigger = new DebugTrigger(new Runnable() {
174        @Override
175        public void run() {
176            onDebugModeTriggered();
177        }
178    });
179
180    /** Updates the set of recent tasks */
181    void updateRecentsTasks(Intent launchIntent) {
182        // Load all the tasks
183        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
184        SpaceNode root = loader.reload(this, Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
185        ArrayList<TaskStack> stacks = root.getStacks();
186        if (!stacks.isEmpty()) {
187            mRecentsView.setTaskStacks(root.getStacks());
188        }
189
190        // Update the configuration based on the launch intent
191        boolean fromSearchHome = launchIntent.getBooleanExtra(
192                AlternateRecentsComponent.EXTRA_FROM_SEARCH_HOME, false);
193        mConfig.launchedFromHome = fromSearchHome || launchIntent.getBooleanExtra(
194                AlternateRecentsComponent.EXTRA_FROM_HOME, false);
195        mConfig.launchedFromAppWithThumbnail = launchIntent.getBooleanExtra(
196                AlternateRecentsComponent.EXTRA_FROM_APP_THUMBNAIL, false);
197        mConfig.launchedFromAppWithScreenshot = launchIntent.getBooleanExtra(
198                AlternateRecentsComponent.EXTRA_FROM_APP_FULL_SCREENSHOT, false);
199        mConfig.launchedToTaskId = launchIntent.getIntExtra(
200                AlternateRecentsComponent.EXTRA_FROM_TASK_ID, -1);
201        mConfig.launchedWithAltTab = launchIntent.getBooleanExtra(
202                AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false);
203        mConfig.launchedWithNoRecentTasks = !root.hasTasks();
204
205        // Create the home intent runnable
206        Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
207        homeIntent.addCategory(Intent.CATEGORY_HOME);
208        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
209                Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
210        mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent,
211            ActivityOptions.makeCustomAnimation(this,
212                fromSearchHome ? R.anim.recents_to_search_launcher_enter :
213                        R.anim.recents_to_launcher_enter,
214                fromSearchHome ? R.anim.recents_to_search_launcher_exit :
215                        R.anim.recents_to_launcher_exit));
216
217        // Mark the task that is the launch target
218        int taskStackCount = stacks.size();
219        if (mConfig.launchedToTaskId != -1) {
220            for (int i = 0; i < taskStackCount; i++) {
221                TaskStack stack = stacks.get(i);
222                ArrayList<Task> tasks = stack.getTasks();
223                int taskCount = tasks.size();
224                for (int j = 0; j < taskCount; j++) {
225                    Task t = tasks.get(j);
226                    if (t.key.id == mConfig.launchedToTaskId) {
227                        t.isLaunchTarget = true;
228                        break;
229                    }
230                }
231            }
232        }
233
234        // Update the top level view's visibilities
235        if (mConfig.launchedWithNoRecentTasks) {
236            if (mEmptyView == null) {
237                mEmptyView = mEmptyViewStub.inflate();
238            }
239            mEmptyView.setVisibility(View.VISIBLE);
240            mRecentsView.setSearchBarVisibility(View.GONE);
241        } else {
242            if (mEmptyView != null) {
243                mEmptyView.setVisibility(View.GONE);
244            }
245            if (mRecentsView.hasSearchBar()) {
246                mRecentsView.setSearchBarVisibility(View.VISIBLE);
247            } else {
248                addSearchBarAppWidgetView();
249            }
250        }
251
252        // Animate the SystemUI scrims into view
253        mScrimViews.prepareEnterRecentsAnimation();
254    }
255
256    /** Attempts to allocate and bind the search bar app widget */
257    void bindSearchBarAppWidget() {
258        if (Constants.DebugFlags.App.EnableSearchLayout) {
259            SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
260
261            // Reset the host view and widget info
262            mSearchAppWidgetHostView = null;
263            mSearchAppWidgetInfo = null;
264
265            // Try and load the app widget id from the settings
266            int appWidgetId = mConfig.searchBarAppWidgetId;
267            if (appWidgetId >= 0) {
268                mSearchAppWidgetInfo = ssp.getAppWidgetInfo(appWidgetId);
269                if (mSearchAppWidgetInfo == null) {
270                    // If there is no actual widget associated with that id, then delete it and
271                    // prepare to bind another app widget in its place
272                    ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
273                    appWidgetId = -1;
274                }
275            }
276
277            // If there is no id, then bind a new search app widget
278            if (appWidgetId < 0) {
279                Pair<Integer, AppWidgetProviderInfo> widgetInfo =
280                        ssp.bindSearchAppWidget(mAppWidgetHost);
281                if (widgetInfo != null) {
282                    // Save the app widget id into the settings
283                    mConfig.updateSearchBarAppWidgetId(this, widgetInfo.first);
284                    mSearchAppWidgetInfo = widgetInfo.second;
285                }
286            }
287        }
288    }
289
290    /** Creates the search bar app widget view */
291    void addSearchBarAppWidgetView() {
292        if (Constants.DebugFlags.App.EnableSearchLayout) {
293            int appWidgetId = mConfig.searchBarAppWidgetId;
294            if (appWidgetId >= 0) {
295                mSearchAppWidgetHostView = mAppWidgetHost.createView(this, appWidgetId,
296                        mSearchAppWidgetInfo);
297                Bundle opts = new Bundle();
298                opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
299                        AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
300                mSearchAppWidgetHostView.updateAppWidgetOptions(opts);
301                // Set the padding to 0 for this search widget
302                mSearchAppWidgetHostView.setPadding(0, 0, 0, 0);
303                mRecentsView.setSearchBar(mSearchAppWidgetHostView);
304            } else {
305                mRecentsView.setSearchBar(null);
306            }
307        }
308    }
309
310    /** Dismisses recents if we are already visible and the intent is to toggle the recents view */
311    boolean dismissRecentsToFocusedTaskOrHome(boolean checkFilteredStackState) {
312        if (mVisible) {
313            // If we currently have filtered stacks, then unfilter those first
314            if (checkFilteredStackState &&
315                mRecentsView.unfilterFilteredStacks()) return true;
316            // If we have a focused Task, launch that Task now
317            if (mRecentsView.launchFocusedTask()) return true;
318            // If we launched from Home, then return to Home
319            if (mConfig.launchedFromHome) {
320                dismissRecentsToHomeRaw(true);
321                return true;
322            }
323            // Otherwise, try and return to the Task that Recents was launched from
324            if (mRecentsView.launchPreviousTask()) return true;
325            // If none of the other cases apply, then just go Home
326            dismissRecentsToHomeRaw(true);
327            return true;
328        }
329        return false;
330    }
331
332    /** Dismisses Recents directly to Home. */
333    void dismissRecentsToHomeRaw(boolean animated) {
334        if (animated) {
335            ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
336                    null, mFinishLaunchHomeRunnable, null);
337            mRecentsView.startExitToHomeAnimation(
338                    new ViewAnimation.TaskViewExitContext(exitTrigger));
339        } else {
340            mFinishLaunchHomeRunnable.run();
341        }
342    }
343
344    /** Dismisses Recents directly to Home if we currently aren't transitioning. */
345    boolean dismissRecentsToHome(boolean animated) {
346        if (mVisible) {
347            // Return to Home
348            dismissRecentsToHomeRaw(animated);
349            return true;
350        }
351        return false;
352    }
353
354    /** Called with the activity is first created. */
355    @Override
356    public void onCreate(Bundle savedInstanceState) {
357        super.onCreate(savedInstanceState);
358        // For the non-primary user, ensure that the SystemSericesProxy is initialized
359        RecentsTaskLoader.initialize(this);
360
361        // Initialize the loader and the configuration
362        mConfig = RecentsConfiguration.reinitialize(this,
363                RecentsTaskLoader.getInstance().getSystemServicesProxy());
364
365        // Initialize the widget host (the host id is static and does not change)
366        mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId);
367
368        // Set the Recents layout
369        setContentView(R.layout.recents);
370        mRecentsView = (RecentsView) findViewById(R.id.recents_view);
371        mRecentsView.setCallbacks(this);
372        mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
373                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
374                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
375        mEmptyViewStub = (ViewStub) findViewById(R.id.empty_view_stub);
376        mDebugOverlayStub = (ViewStub) findViewById(R.id.debug_overlay_stub);
377        mScrimViews = new SystemBarScrimViews(this, mConfig);
378        inflateDebugOverlay();
379
380        // Bind the search app widget when we first start up
381        bindSearchBarAppWidget();
382        // Update the recent tasks
383        updateRecentsTasks(getIntent());
384
385        // Register the broadcast receiver to handle messages when the screen is turned off
386        IntentFilter filter = new IntentFilter();
387        filter.addAction(Intent.ACTION_SCREEN_OFF);
388        filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
389        registerReceiver(mSystemBroadcastReceiver, filter);
390
391        // Private API calls to make the shadows look better
392        try {
393            Utilities.setShadowProperty("ambientRatio", String.valueOf(1.5f));
394        } catch (IllegalAccessException e) {
395            e.printStackTrace();
396        } catch (InvocationTargetException e) {
397            e.printStackTrace();
398        }
399
400        // Update if we are getting a configuration change
401        if (savedInstanceState != null) {
402            mConfig.updateOnConfigurationChange();
403            onConfigurationChange();
404        }
405    }
406
407    /** Inflates the debug overlay if debug mode is enabled. */
408    void inflateDebugOverlay() {
409        if (mConfig.debugModeEnabled && mDebugOverlay == null) {
410            // Inflate the overlay and seek bars
411            mDebugOverlay = (DebugOverlayView) mDebugOverlayStub.inflate();
412            mDebugOverlay.setCallbacks(this);
413            mRecentsView.setDebugOverlay(mDebugOverlay);
414        }
415    }
416
417    void onConfigurationChange() {
418        // Update RecentsConfiguration
419        mConfig = RecentsConfiguration.reinitialize(this,
420                RecentsTaskLoader.getInstance().getSystemServicesProxy());
421
422        // Try and start the enter animation (or restart it on configuration changed)
423        ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
424        mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
425        onEnterAnimationTriggered();
426    }
427
428    @Override
429    protected void onNewIntent(Intent intent) {
430        super.onNewIntent(intent);
431        setIntent(intent);
432
433        // Reinitialize the configuration
434        RecentsConfiguration.reinitialize(this, RecentsTaskLoader.getInstance().getSystemServicesProxy());
435
436        // Clear any debug rects
437        if (mDebugOverlay != null) {
438            mDebugOverlay.clear();
439        }
440
441        // Update the recent tasks
442        updateRecentsTasks(intent);
443    }
444
445    @Override
446    protected void onStart() {
447        super.onStart();
448
449        // Register the broadcast receiver to handle messages from our service
450        IntentFilter filter = new IntentFilter();
451        filter.addAction(AlternateRecentsComponent.ACTION_HIDE_RECENTS_ACTIVITY);
452        filter.addAction(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY);
453        filter.addAction(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION);
454        registerReceiver(mServiceBroadcastReceiver, filter);
455
456        // Register any broadcast receivers for the task loader
457        RecentsTaskLoader.getInstance().registerReceivers(this, mRecentsView);
458    }
459
460    @Override
461    protected void onResume() {
462        super.onResume();
463
464        // Start listening for widget package changes if there is one bound, post it since we don't
465        // want it stalling the startup
466        if (mConfig.searchBarAppWidgetId >= 0) {
467            final WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks> callback =
468                    new WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks>(this);
469            mRecentsView.postDelayed(new Runnable() {
470                @Override
471                public void run() {
472                    RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks cb = callback.get();
473                    if (cb != null) {
474                        mAppWidgetHost.startListening(cb);
475                    }
476                }
477            }, 1);
478        }
479
480        // Mark Recents as visible
481        mVisible = true;
482    }
483
484    @Override
485    protected void onStop() {
486        super.onStop();
487
488        // Remove all the views
489        mRecentsView.removeAllTaskStacks();
490
491        // Unregister the RecentsService receiver
492        unregisterReceiver(mServiceBroadcastReceiver);
493
494        // Unregister any broadcast receivers for the task loader
495        RecentsTaskLoader.getInstance().unregisterReceivers();
496
497        // Stop listening for widget package changes if there was one bound
498        if (mAppWidgetHost.isListening()) {
499            mAppWidgetHost.stopListening();
500        }
501    }
502
503    @Override
504    protected void onDestroy() {
505        super.onDestroy();
506
507        // Unregister the system broadcast receivers
508        unregisterReceiver(mSystemBroadcastReceiver);
509    }
510
511    @Override
512    public void onTrimMemory(int level) {
513        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
514        if (loader != null) {
515            loader.onTrimMemory(level);
516        }
517    }
518
519    @Override
520    public boolean onKeyDown(int keyCode, KeyEvent event) {
521        switch (keyCode) {
522            case KeyEvent.KEYCODE_TAB: {
523                boolean hasRepKeyTimeElapsed = (System.currentTimeMillis() -
524                        mLastTabKeyEventTime) > mConfig.altTabKeyDelay;
525                if (event.getRepeatCount() <= 0 || hasRepKeyTimeElapsed) {
526                    // Focus the next task in the stack
527                    final boolean backward = event.isShiftPressed();
528                    mRecentsView.focusNextTask(!backward);
529                    mLastTabKeyEventTime = System.currentTimeMillis();
530                }
531                return true;
532            }
533            case KeyEvent.KEYCODE_DPAD_UP: {
534                mRecentsView.focusNextTask(true);
535                return true;
536            }
537            case KeyEvent.KEYCODE_DPAD_DOWN: {
538                mRecentsView.focusNextTask(false);
539                return true;
540            }
541            case KeyEvent.KEYCODE_DEL:
542            case KeyEvent.KEYCODE_FORWARD_DEL: {
543                mRecentsView.dismissFocusedTask();
544                return true;
545            }
546            default:
547                break;
548        }
549        // Pass through the debug trigger
550        mDebugTrigger.onKeyEvent(keyCode);
551        return super.onKeyDown(keyCode, event);
552    }
553
554    @Override
555    public void onUserInteraction() {
556        mRecentsView.onUserInteraction();
557    }
558
559    @Override
560    public void onBackPressed() {
561        // Test mode where back does not do anything
562        if (mConfig.debugModeEnabled) return;
563
564        // Dismiss Recents to the focused Task or Home
565        dismissRecentsToFocusedTaskOrHome(true);
566    }
567
568    /** Called when debug mode is triggered */
569    public void onDebugModeTriggered() {
570
571        if (mConfig.developerOptionsEnabled) {
572            SharedPreferences settings = getSharedPreferences(getPackageName(), 0);
573            if (settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false)) {
574                // Disable the debug mode
575                settings.edit().remove(Constants.Values.App.Key_DebugModeEnabled).apply();
576                mConfig.debugModeEnabled = false;
577                inflateDebugOverlay();
578                mDebugOverlay.disable();
579            } else {
580                // Enable the debug mode
581                settings.edit().putBoolean(Constants.Values.App.Key_DebugModeEnabled, true).apply();
582                mConfig.debugModeEnabled = true;
583                inflateDebugOverlay();
584                mDebugOverlay.enable();
585            }
586            Toast.makeText(this, "Debug mode (" + Constants.Values.App.DebugModeVersion + ") " +
587                (mConfig.debugModeEnabled ? "Enabled" : "Disabled") + ", please restart Recents now",
588                Toast.LENGTH_SHORT).show();
589        }
590    }
591
592    /** Called when the enter recents animation is triggered. */
593    public void onEnterAnimationTriggered() {
594        // Animate the SystemUI scrim views
595        mScrimViews.startEnterRecentsAnimation();
596    }
597
598    /**** RecentsView.RecentsViewCallbacks Implementation ****/
599
600    @Override
601    public void onExitToHomeAnimationTriggered() {
602        // Animate the SystemUI scrim views out
603        mScrimViews.startExitRecentsAnimation();
604    }
605
606    @Override
607    public void onTaskViewClicked() {
608        // Mark recents as no longer visible
609        AlternateRecentsComponent.notifyVisibilityChanged(false);
610        mVisible = false;
611    }
612
613    @Override
614    public void onAllTaskViewsDismissed() {
615        mFinishLaunchHomeRunnable.run();
616    }
617
618    /**** RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks Implementation ****/
619
620    @Override
621    public void refreshSearchWidget() {
622        bindSearchBarAppWidget();
623        addSearchBarAppWidgetView();
624    }
625
626    /**** DebugOverlayView.DebugOverlayViewCallbacks ****/
627
628    @Override
629    public void onPrimarySeekBarChanged(float progress) {
630        // Do nothing
631    }
632
633    @Override
634    public void onSecondarySeekBarChanged(float progress) {
635        // Do nothing
636    }
637}
638