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