RecentsActivity.java revision 04d0f756782e697a171aebbb35ae86c86b839a27
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.model.RecentsTaskLoader; 39import com.android.systemui.recents.model.SpaceNode; 40import com.android.systemui.recents.model.TaskStack; 41import com.android.systemui.recents.views.FullscreenTransitionOverlayView; 42import com.android.systemui.recents.views.RecentsView; 43import com.android.systemui.recents.views.SystemBarScrimViews; 44import com.android.systemui.recents.views.ViewAnimation; 45 46import java.lang.reflect.InvocationTargetException; 47import java.util.ArrayList; 48 49/* Activity */ 50public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks, 51 RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks, 52 FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks { 53 54 RecentsView mRecentsView; 55 SystemBarScrimViews mScrimViews; 56 ViewStub mEmptyViewStub; 57 View mEmptyView; 58 ViewStub mFullscreenOverlayStub; 59 FullscreenTransitionOverlayView mFullScreenOverlayView; 60 61 RecentsConfiguration mConfig; 62 63 RecentsAppWidgetHost mAppWidgetHost; 64 AppWidgetProviderInfo mSearchAppWidgetInfo; 65 AppWidgetHostView mSearchAppWidgetHostView; 66 67 boolean mVisible; 68 boolean mTaskLaunched; 69 70 // Runnables to finish the Recents activity 71 FinishRecentsRunnable mFinishRunnable = new FinishRecentsRunnable(true); 72 FinishRecentsRunnable mFinishLaunchHomeRunnable; 73 74 /** 75 * A Runnable to finish Recents either with/without a transition, and either by calling finish() 76 * or just launching the specified intent. 77 */ 78 class FinishRecentsRunnable implements Runnable { 79 boolean mUseCustomFinishTransition; 80 Intent mLaunchIntent; 81 ActivityOptions mLaunchOpts; 82 83 public FinishRecentsRunnable(boolean withTransition) { 84 mUseCustomFinishTransition = withTransition; 85 } 86 87 /** 88 * Creates a finish runnable that starts the specified intent, using the given 89 * ActivityOptions. 90 */ 91 public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) { 92 mLaunchIntent = launchIntent; 93 mLaunchOpts = opts; 94 } 95 96 @Override 97 public void run() { 98 // Mark Recents as no longer visible 99 AlternateRecentsComponent.notifyVisibilityChanged(false); 100 // Finish Recents 101 if (mLaunchIntent != null) { 102 if (mLaunchOpts != null) { 103 startActivityAsUser(mLaunchIntent, new UserHandle(UserHandle.USER_CURRENT)); 104 } else { 105 startActivityAsUser(mLaunchIntent, mLaunchOpts.toBundle(), 106 new UserHandle(UserHandle.USER_CURRENT)); 107 } 108 } else { 109 finish(); 110 if (mUseCustomFinishTransition) { 111 overridePendingTransition(R.anim.recents_to_launcher_enter, 112 R.anim.recents_to_launcher_exit); 113 } 114 } 115 } 116 } 117 118 // Broadcast receiver to handle messages from our RecentsService 119 final BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() { 120 @Override 121 public void onReceive(Context context, Intent intent) { 122 String action = intent.getAction(); 123 if (Console.Enabled) { 124 Console.log(Constants.Log.App.SystemUIHandshake, 125 "[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed); 126 } 127 if (action.equals(RecentsService.ACTION_HIDE_RECENTS_ACTIVITY)) { 128 if (intent.getBooleanExtra(RecentsService.EXTRA_TRIGGERED_FROM_ALT_TAB, false)) { 129 // Dismiss recents, launching the focused task 130 dismissRecentsIfVisible(); 131 } else { 132 // If we are mid-animation into Recents, then reverse it and finish 133 if (mFullScreenOverlayView == null || 134 !mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) { 135 // Otherwise, either finish Recents, or launch Home directly 136 ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(context, 137 null, mFinishLaunchHomeRunnable, null); 138 mRecentsView.startExitToHomeAnimation( 139 new ViewAnimation.TaskViewExitContext(exitTrigger)); 140 } 141 } 142 } else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) { 143 // Try and unfilter and filtered stacks 144 if (!mRecentsView.unfilterFilteredStacks()) { 145 // If there are no filtered stacks, dismiss recents and launch the first task 146 dismissRecentsIfVisible(); 147 } 148 } else if (action.equals(RecentsService.ACTION_START_ENTER_ANIMATION)) { 149 // Try and start the enter animation (or restart it on configuration changed) 150 mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenOverlayView)); 151 // Call our callback 152 onEnterAnimationTriggered(); 153 } 154 } 155 }; 156 157 // Broadcast receiver to handle messages from the system 158 final BroadcastReceiver mSystemBroadcastReceiver = new BroadcastReceiver() { 159 @Override 160 public void onReceive(Context context, Intent intent) { 161 String action = intent.getAction(); 162 if (action.equals(Intent.ACTION_SCREEN_OFF)) { 163 mFinishLaunchHomeRunnable.run(); 164 } else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) { 165 // Refresh the search widget 166 refreshSearchWidget(); 167 } 168 } 169 }; 170 171 // Debug trigger 172 final DebugTrigger mDebugTrigger = new DebugTrigger(new Runnable() { 173 @Override 174 public void run() { 175 onDebugModeTriggered(); 176 } 177 }); 178 179 /** Updates the set of recent tasks */ 180 void updateRecentsTasks(Intent launchIntent) { 181 RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); 182 SpaceNode root = loader.reload(this, Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount); 183 ArrayList<TaskStack> stacks = root.getStacks(); 184 if (!stacks.isEmpty()) { 185 mRecentsView.setBSP(root); 186 } 187 188 // Update the configuration based on the launch intent 189 mConfig.launchedFromHome = launchIntent.getBooleanExtra( 190 AlternateRecentsComponent.EXTRA_FROM_HOME, false); 191 mConfig.launchedFromAppWithThumbnail = launchIntent.getBooleanExtra( 192 AlternateRecentsComponent.EXTRA_FROM_APP_THUMBNAIL, false); 193 mConfig.launchedFromAppWithScreenshot = launchIntent.getBooleanExtra( 194 AlternateRecentsComponent.EXTRA_FROM_APP_FULL_SCREENSHOT, false); 195 mConfig.launchedWithAltTab = launchIntent.getBooleanExtra( 196 AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false); 197 mConfig.launchedWithNoRecentTasks = !root.hasTasks(); 198 199 // Show the scrim if we animate into Recents without window transitions 200 mScrimViews.prepareEnterRecentsAnimation(); 201 202 // Add the default no-recents layout 203 if (mEmptyView == null) { 204 mEmptyView = mEmptyViewStub.inflate(); 205 } 206 if (mConfig.launchedWithNoRecentTasks) { 207 mEmptyView.setVisibility(View.VISIBLE); 208 } else { 209 mEmptyView.setVisibility(View.GONE); 210 } 211 } 212 213 /** Attempts to allocate and bind the search bar app widget */ 214 void bindSearchBarAppWidget() { 215 if (Constants.DebugFlags.App.EnableSearchLayout) { 216 SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy(); 217 218 // Reset the host view and widget info 219 mSearchAppWidgetHostView = null; 220 mSearchAppWidgetInfo = null; 221 222 // Try and load the app widget id from the settings 223 int appWidgetId = mConfig.searchBarAppWidgetId; 224 if (appWidgetId >= 0) { 225 mSearchAppWidgetInfo = ssp.getAppWidgetInfo(appWidgetId); 226 if (mSearchAppWidgetInfo == null) { 227 // If there is no actual widget associated with that id, then delete it and 228 // prepare to bind another app widget in its place 229 ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId); 230 appWidgetId = -1; 231 } 232 if (Console.Enabled) { 233 Console.log(Constants.Log.App.SystemUIHandshake, 234 "[RecentsActivity|onCreate|settings|appWidgetId]", 235 "Id: " + appWidgetId, 236 Console.AnsiBlue); 237 } 238 } 239 240 // If there is no id, then bind a new search app widget 241 if (appWidgetId < 0) { 242 Pair<Integer, AppWidgetProviderInfo> widgetInfo = 243 ssp.bindSearchAppWidget(mAppWidgetHost); 244 if (widgetInfo != null) { 245 if (Console.Enabled) { 246 Console.log(Constants.Log.App.SystemUIHandshake, 247 "[RecentsActivity|onCreate|searchWidget]", 248 "Id: " + widgetInfo.first + " Info: " + widgetInfo.second, 249 Console.AnsiBlue); 250 } 251 252 // Save the app widget id into the settings 253 mConfig.updateSearchBarAppWidgetId(this, widgetInfo.first); 254 mSearchAppWidgetInfo = widgetInfo.second; 255 } 256 } 257 } 258 } 259 260 /** Creates the search bar app widget view */ 261 void addSearchBarAppWidgetView() { 262 if (Constants.DebugFlags.App.EnableSearchLayout) { 263 int appWidgetId = mConfig.searchBarAppWidgetId; 264 if (appWidgetId >= 0) { 265 if (Console.Enabled) { 266 Console.log(Constants.Log.App.SystemUIHandshake, 267 "[RecentsActivity|onCreate|addSearchAppWidgetView]", 268 "Id: " + appWidgetId, 269 Console.AnsiBlue); 270 } 271 mSearchAppWidgetHostView = mAppWidgetHost.createView(this, appWidgetId, 272 mSearchAppWidgetInfo); 273 Bundle opts = new Bundle(); 274 opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, 275 AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS); 276 mSearchAppWidgetHostView.updateAppWidgetOptions(opts); 277 // Set the padding to 0 for this search widget 278 mSearchAppWidgetHostView.setPadding(0, 0, 0, 0); 279 mRecentsView.setSearchBar(mSearchAppWidgetHostView); 280 } else { 281 mRecentsView.setSearchBar(null); 282 } 283 } 284 } 285 286 /** Dismisses recents if we are already visible and the intent is to toggle the recents view */ 287 boolean dismissRecentsIfVisible() { 288 if (mVisible) { 289 // If we are mid-animation into Recents, then reverse it and finish 290 if (mFullScreenOverlayView == null || 291 !mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) { 292 // If we have a focused task, then launch that task 293 if (!mRecentsView.launchFocusedTask()) { 294 if (mConfig.launchedFromHome) { 295 // Just start the animation out of recents 296 ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this, 297 null, mFinishLaunchHomeRunnable, null); 298 mRecentsView.startExitToHomeAnimation( 299 new ViewAnimation.TaskViewExitContext(exitTrigger)); 300 } else { 301 // Otherwise, try and launch the first task 302 if (!mRecentsView.launchFirstTask()) { 303 // If there are no tasks, then just finish recents 304 mFinishLaunchHomeRunnable.run(); 305 } 306 } 307 } 308 } 309 return true; 310 } 311 return false; 312 } 313 314 /** Called with the activity is first created. */ 315 @Override 316 public void onCreate(Bundle savedInstanceState) { 317 super.onCreate(savedInstanceState); 318 if (Console.Enabled) { 319 Console.logDivider(Constants.Log.App.SystemUIHandshake); 320 Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onCreate]", 321 getIntent().getAction() + " visible: " + mVisible, Console.AnsiRed); 322 Console.logTraceTime(Constants.Log.App.TimeRecentsStartup, 323 Constants.Log.App.TimeRecentsStartupKey, "onCreate"); 324 } 325 326 // Initialize the loader and the configuration 327 RecentsTaskLoader.initialize(this); 328 mConfig = RecentsConfiguration.reinitialize(this); 329 330 // Create the home intent runnable 331 Intent homeIntent = new Intent(Intent.ACTION_MAIN, null); 332 homeIntent.addCategory(Intent.CATEGORY_HOME); 333 homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 334 Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 335 mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent, 336 ActivityOptions.makeCustomAnimation(this, R.anim.recents_to_launcher_enter, 337 R.anim.recents_to_launcher_exit)); 338 339 // Initialize the widget host (the host id is static and does not change) 340 mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId); 341 342 // Set the Recents layout 343 setContentView(R.layout.recents); 344 mRecentsView = (RecentsView) findViewById(R.id.recents_view); 345 mRecentsView.setCallbacks(this); 346 mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | 347 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | 348 View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); 349 mEmptyViewStub = (ViewStub) findViewById(R.id.empty_view_stub); 350 mFullscreenOverlayStub = (ViewStub) findViewById(R.id.fullscreen_overlay_stub); 351 mScrimViews = new SystemBarScrimViews(this, mConfig); 352 353 // Update the recent tasks 354 updateRecentsTasks(getIntent()); 355 356 // Prepare the screenshot transition if necessary 357 if (Constants.DebugFlags.App.EnableScreenshotAppTransition) { 358 mFullScreenOverlayView = (FullscreenTransitionOverlayView) mFullscreenOverlayStub.inflate(); 359 mFullScreenOverlayView.setCallbacks(this); 360 mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot()); 361 } 362 363 // Bind the search app widget when we first start up 364 bindSearchBarAppWidget(); 365 // Add the search bar layout 366 addSearchBarAppWidgetView(); 367 368 // Update if we are getting a configuration change 369 if (savedInstanceState != null) { 370 onConfigurationChange(); 371 } 372 373 // Register the broadcast receiver to handle messages when the screen is turned off 374 IntentFilter filter = new IntentFilter(); 375 filter.addAction(Intent.ACTION_SCREEN_OFF); 376 filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED); 377 registerReceiver(mSystemBroadcastReceiver, filter); 378 379 // Register any broadcast receivers for the task loader 380 RecentsTaskLoader.getInstance().registerReceivers(this, mRecentsView); 381 382 // Private API calls to make the shadows look better 383 try { 384 Utilities.setShadowProperty("ambientShadowStrength", String.valueOf(35f)); 385 Utilities.setShadowProperty("ambientRatio", String.valueOf(0.5f)); 386 } catch (IllegalAccessException e) { 387 e.printStackTrace(); 388 } catch (InvocationTargetException e) { 389 e.printStackTrace(); 390 } 391 } 392 393 void onConfigurationChange() { 394 // Try and start the enter animation (or restart it on configuration changed) 395 mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenOverlayView)); 396 // Call our callback 397 onEnterAnimationTriggered(); 398 } 399 400 @Override 401 protected void onNewIntent(Intent intent) { 402 super.onNewIntent(intent); 403 // Reset the task launched flag if we encounter an onNewIntent() before onStop() 404 mTaskLaunched = false; 405 406 if (Console.Enabled) { 407 Console.logDivider(Constants.Log.App.SystemUIHandshake); 408 Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onNewIntent]", 409 intent.getAction() + " visible: " + mVisible, Console.AnsiRed); 410 Console.logTraceTime(Constants.Log.App.TimeRecentsStartup, 411 Constants.Log.App.TimeRecentsStartupKey, "onNewIntent"); 412 } 413 414 // Initialize the loader and the configuration 415 RecentsTaskLoader.initialize(this); 416 mConfig = RecentsConfiguration.reinitialize(this); 417 418 // Update the recent tasks 419 updateRecentsTasks(intent); 420 421 // Prepare the screenshot transition if necessary 422 if (Constants.DebugFlags.App.EnableScreenshotAppTransition) { 423 mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot()); 424 } 425 426 // Don't attempt to rebind the search bar widget, but just add the search bar layout 427 addSearchBarAppWidgetView(); 428 } 429 430 @Override 431 protected void onStart() { 432 if (Console.Enabled) { 433 Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onStart]", "", 434 Console.AnsiRed); 435 } 436 super.onStart(); 437 438 // Register the broadcast receiver to handle messages from our service 439 IntentFilter filter = new IntentFilter(); 440 filter.addAction(RecentsService.ACTION_HIDE_RECENTS_ACTIVITY); 441 filter.addAction(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY); 442 filter.addAction(RecentsService.ACTION_START_ENTER_ANIMATION); 443 registerReceiver(mServiceBroadcastReceiver, filter); 444 445 // Start listening for widget package changes if there is one bound 446 if (mConfig.searchBarAppWidgetId >= 0) { 447 mAppWidgetHost.startListening(this); 448 } 449 450 mVisible = true; 451 } 452 453 @Override 454 protected void onResume() { 455 if (Console.Enabled) { 456 Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onResume]", "", 457 Console.AnsiRed); 458 } 459 super.onResume(); 460 } 461 462 @Override 463 public void onAttachedToWindow() { 464 if (Console.Enabled) { 465 Console.log(Constants.Log.App.SystemUIHandshake, 466 "[RecentsActivity|onAttachedToWindow]", "", 467 Console.AnsiRed); 468 } 469 super.onAttachedToWindow(); 470 } 471 472 @Override 473 public void onDetachedFromWindow() { 474 if (Console.Enabled) { 475 Console.log(Constants.Log.App.SystemUIHandshake, 476 "[RecentsActivity|onDetachedFromWindow]", "", 477 Console.AnsiRed); 478 } 479 super.onDetachedFromWindow(); 480 } 481 482 @Override 483 protected void onPause() { 484 if (Console.Enabled) { 485 Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onPause]", "", 486 Console.AnsiRed); 487 } 488 super.onPause(); 489 } 490 491 @Override 492 protected void onStop() { 493 if (Console.Enabled) { 494 Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onStop]", "", 495 Console.AnsiRed); 496 } 497 super.onStop(); 498 499 // Unregister the RecentsService receiver 500 unregisterReceiver(mServiceBroadcastReceiver); 501 502 // Stop listening for widget package changes if there was one bound 503 if (mConfig.searchBarAppWidgetId >= 0) { 504 mAppWidgetHost.stopListening(); 505 } 506 507 mVisible = false; 508 mTaskLaunched = false; 509 } 510 511 @Override 512 protected void onDestroy() { 513 if (Console.Enabled) { 514 Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onDestroy]", "", 515 Console.AnsiRed); 516 } 517 super.onDestroy(); 518 519 // Unregister the screen off receiver 520 unregisterReceiver(mSystemBroadcastReceiver); 521 RecentsTaskLoader.getInstance().unregisterReceivers(); 522 } 523 524 @Override 525 public void onTrimMemory(int level) { 526 RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); 527 if (loader != null) { 528 loader.onTrimMemory(level); 529 } 530 } 531 532 @Override 533 public boolean onKeyDown(int keyCode, KeyEvent event) { 534 if (keyCode == KeyEvent.KEYCODE_TAB) { 535 // Focus the next task in the stack 536 final boolean backward = event.isShiftPressed(); 537 mRecentsView.focusNextTask(!backward); 538 return true; 539 } 540 // Pass through the debug trigger 541 mDebugTrigger.onKeyEvent(keyCode); 542 return super.onKeyDown(keyCode, event); 543 } 544 545 @Override 546 public void onUserInteraction() { 547 mRecentsView.onUserInteraction(); 548 } 549 550 @Override 551 public void onBackPressed() { 552 // Test mode where back does not do anything 553 if (mConfig.debugModeEnabled) return; 554 555 // If we are mid-animation into Recents, then reverse it and finish 556 if (mFullScreenOverlayView == null || 557 !mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) { 558 // If we are currently filtering in any stacks, unfilter them first 559 if (!mRecentsView.unfilterFilteredStacks()) { 560 if (mConfig.launchedFromHome) { 561 // Just start the animation out of recents 562 ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this, 563 null, mFinishLaunchHomeRunnable, null); 564 mRecentsView.startExitToHomeAnimation( 565 new ViewAnimation.TaskViewExitContext(exitTrigger)); 566 } else { 567 // Otherwise, try and launch the first task 568 if (!mRecentsView.launchFirstTask()) { 569 // If there are no tasks, then just finish recents 570 mFinishLaunchHomeRunnable.run(); 571 } 572 } 573 } 574 } 575 } 576 577 /** Called when debug mode is triggered */ 578 public void onDebugModeTriggered() { 579 if (mConfig.developerOptionsEnabled) { 580 SharedPreferences settings = getSharedPreferences(getPackageName(), 0); 581 if (settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false)) { 582 // Disable the debug mode 583 settings.edit().remove(Constants.Values.App.Key_DebugModeEnabled).apply(); 584 } else { 585 // Enable the debug mode 586 settings.edit().putBoolean(Constants.Values.App.Key_DebugModeEnabled, true).apply(); 587 } 588 Toast.makeText(this, "Debug mode (" + Constants.Values.App.DebugModeVersion + 589 ") toggled, please restart Recents now", Toast.LENGTH_SHORT).show(); 590 } 591 } 592 593 /** Called when the enter recents animation is triggered. */ 594 public void onEnterAnimationTriggered() { 595 // Animate the scrims in 596 mScrimViews.startEnterRecentsAnimation(); 597 } 598 599 /**** FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks Implementation ****/ 600 601 @Override 602 public void onEnterAnimationComplete(boolean canceled) { 603 if (!canceled) { 604 // Reset the full screenshot transition view 605 if (Constants.DebugFlags.App.EnableScreenshotAppTransition) { 606 mFullScreenOverlayView.reset(); 607 } 608 609 // XXX: We should clean up the screenshot in this case as well, but it needs to happen 610 // after to animate up 611 } 612 // Recycle the full screen screenshot 613 AlternateRecentsComponent.consumeLastScreenshot(); 614 } 615 616 /**** RecentsView.RecentsViewCallbacks Implementation ****/ 617 618 @Override 619 public void onExitToHomeAnimationTriggered() { 620 // Animate the scrims out 621 mScrimViews.startExitRecentsAnimation(); 622 } 623 624 @Override 625 public void onTaskLaunching() { 626 mTaskLaunched = true; 627 628 // Mark recents as no longer visible 629 AlternateRecentsComponent.notifyVisibilityChanged(false); 630 } 631 632 @Override 633 public void onLastTaskRemoved() { 634 mFinishLaunchHomeRunnable.run(); 635 } 636 637 /**** RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks Implementation ****/ 638 639 @Override 640 public void refreshSearchWidget() { 641 // Load the Search widget again 642 bindSearchBarAppWidget(); 643 addSearchBarAppWidgetView(); 644 } 645} 646