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