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