1 /* 2 * Copyright (C) 2019 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 package com.android.quickstep; 17 18 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; 19 20 import android.app.PendingIntent; 21 import android.app.PictureInPictureParams; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.ActivityInfo; 26 import android.graphics.Bitmap; 27 import android.graphics.Insets; 28 import android.graphics.Rect; 29 import android.os.Bundle; 30 import android.os.IBinder; 31 import android.os.IBinder.DeathRecipient; 32 import android.os.RemoteException; 33 import android.os.UserHandle; 34 import android.util.Log; 35 import android.view.MotionEvent; 36 import android.view.SurfaceControl; 37 38 import com.android.launcher3.util.MainThreadInitializedObject; 39 import com.android.launcher3.util.SplitConfigurationOptions; 40 import com.android.systemui.shared.recents.ISystemUiProxy; 41 import com.android.systemui.shared.recents.model.Task; 42 import com.android.systemui.shared.system.RemoteTransitionCompat; 43 import com.android.systemui.shared.system.smartspace.ISmartspaceCallback; 44 import com.android.systemui.shared.system.smartspace.ISmartspaceTransitionController; 45 import com.android.wm.shell.onehanded.IOneHanded; 46 import com.android.wm.shell.pip.IPip; 47 import com.android.wm.shell.pip.IPipAnimationListener; 48 import com.android.wm.shell.splitscreen.ISplitScreen; 49 import com.android.wm.shell.splitscreen.ISplitScreenListener; 50 import com.android.wm.shell.startingsurface.IStartingWindow; 51 import com.android.wm.shell.startingsurface.IStartingWindowListener; 52 import com.android.wm.shell.transition.IShellTransitions; 53 54 /** 55 * Holds the reference to SystemUI. 56 */ 57 public class SystemUiProxy implements ISystemUiProxy, 58 SysUINavigationMode.NavigationModeChangeListener { 59 private static final String TAG = SystemUiProxy.class.getSimpleName(); 60 61 public static final MainThreadInitializedObject<SystemUiProxy> INSTANCE = 62 new MainThreadInitializedObject<>(SystemUiProxy::new); 63 64 private ISystemUiProxy mSystemUiProxy; 65 private IPip mPip; 66 private ISmartspaceTransitionController mSmartspaceTransitionController; 67 private ISplitScreen mSplitScreen; 68 private IOneHanded mOneHanded; 69 private IShellTransitions mShellTransitions; 70 private IStartingWindow mStartingWindow; 71 private final DeathRecipient mSystemUiProxyDeathRecipient = () -> { 72 MAIN_EXECUTOR.execute(() -> clearProxy()); 73 }; 74 75 // Save the listeners passed into the proxy since when set/register these listeners, 76 // setProxy may not have been called, eg. OverviewProxyService is not connected yet. 77 private IPipAnimationListener mPendingPipAnimationListener; 78 private ISplitScreenListener mPendingSplitScreenListener; 79 private IStartingWindowListener mPendingStartingWindowListener; 80 private ISmartspaceCallback mPendingSmartspaceCallback; 81 82 // Used to dedupe calls to SystemUI 83 private int mLastShelfHeight; 84 private boolean mLastShelfVisible; 85 private float mLastNavButtonAlpha; 86 private boolean mLastNavButtonAnimate; 87 private boolean mHasNavButtonAlphaBeenSet = false; 88 89 // TODO(141886704): Find a way to remove this 90 private int mLastSystemUiStateFlags; 91 SystemUiProxy(Context context)92 public SystemUiProxy(Context context) { 93 SysUINavigationMode.INSTANCE.get(context).addModeChangeListener(this); 94 } 95 96 @Override onNavigationModeChanged(SysUINavigationMode.Mode newMode)97 public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) { 98 // Whenever the nav mode changes, force reset the nav button alpha 99 setNavBarButtonAlpha(1f, false); 100 } 101 102 @Override onBackPressed()103 public void onBackPressed() { 104 if (mSystemUiProxy != null) { 105 try { 106 mSystemUiProxy.onBackPressed(); 107 } catch (RemoteException e) { 108 Log.w(TAG, "Failed call onBackPressed", e); 109 } 110 } 111 } 112 113 @Override setHomeRotationEnabled(boolean enabled)114 public void setHomeRotationEnabled(boolean enabled) { 115 if (mSystemUiProxy != null) { 116 try { 117 mSystemUiProxy.setHomeRotationEnabled(enabled); 118 } catch (RemoteException e) { 119 Log.w(TAG, "Failed call onBackPressed", e); 120 } 121 } 122 } 123 124 @Override asBinder()125 public IBinder asBinder() { 126 // Do nothing 127 return null; 128 } 129 setProxy(ISystemUiProxy proxy, IPip pip, ISplitScreen splitScreen, IOneHanded oneHanded, IShellTransitions shellTransitions, IStartingWindow startingWindow, ISmartspaceTransitionController smartSpaceTransitionController)130 public void setProxy(ISystemUiProxy proxy, IPip pip, ISplitScreen splitScreen, 131 IOneHanded oneHanded, IShellTransitions shellTransitions, 132 IStartingWindow startingWindow, 133 ISmartspaceTransitionController smartSpaceTransitionController) { 134 unlinkToDeath(); 135 mSystemUiProxy = proxy; 136 mPip = pip; 137 mSplitScreen = splitScreen; 138 mOneHanded = oneHanded; 139 mShellTransitions = shellTransitions; 140 mStartingWindow = startingWindow; 141 mSmartspaceTransitionController = smartSpaceTransitionController; 142 linkToDeath(); 143 // re-attach the listeners once missing due to setProxy has not been initialized yet. 144 if (mPendingPipAnimationListener != null && mPip != null) { 145 setPinnedStackAnimationListener(mPendingPipAnimationListener); 146 mPendingPipAnimationListener = null; 147 } 148 if (mPendingSplitScreenListener != null && mSplitScreen != null) { 149 registerSplitScreenListener(mPendingSplitScreenListener); 150 mPendingSplitScreenListener = null; 151 } 152 if (mPendingStartingWindowListener != null && mStartingWindow != null) { 153 setStartingWindowListener(mPendingStartingWindowListener); 154 mPendingStartingWindowListener = null; 155 } 156 if (mPendingSmartspaceCallback != null && mSmartspaceTransitionController != null) { 157 setSmartspaceCallback(mPendingSmartspaceCallback); 158 mPendingSmartspaceCallback = null; 159 } 160 } 161 clearProxy()162 public void clearProxy() { 163 setProxy(null, null, null, null, null, null, null); 164 } 165 166 // TODO(141886704): Find a way to remove this setLastSystemUiStateFlags(int stateFlags)167 public void setLastSystemUiStateFlags(int stateFlags) { 168 mLastSystemUiStateFlags = stateFlags; 169 } 170 171 // TODO(141886704): Find a way to remove this getLastSystemUiStateFlags()172 public int getLastSystemUiStateFlags() { 173 return mLastSystemUiStateFlags; 174 } 175 isActive()176 public boolean isActive() { 177 return mSystemUiProxy != null; 178 } 179 linkToDeath()180 private void linkToDeath() { 181 if (mSystemUiProxy != null) { 182 try { 183 mSystemUiProxy.asBinder().linkToDeath(mSystemUiProxyDeathRecipient, 0 /* flags */); 184 } catch (RemoteException e) { 185 Log.e(TAG, "Failed to link sysui proxy death recipient"); 186 } 187 } 188 } 189 unlinkToDeath()190 private void unlinkToDeath() { 191 if (mSystemUiProxy != null) { 192 mSystemUiProxy.asBinder().unlinkToDeath(mSystemUiProxyDeathRecipient, 0 /* flags */); 193 } 194 } 195 196 @Override startScreenPinning(int taskId)197 public void startScreenPinning(int taskId) { 198 if (mSystemUiProxy != null) { 199 try { 200 mSystemUiProxy.startScreenPinning(taskId); 201 } catch (RemoteException e) { 202 Log.w(TAG, "Failed call startScreenPinning", e); 203 } 204 } 205 } 206 207 @Override onOverviewShown(boolean fromHome)208 public void onOverviewShown(boolean fromHome) { 209 onOverviewShown(fromHome, TAG); 210 } 211 onOverviewShown(boolean fromHome, String tag)212 public void onOverviewShown(boolean fromHome, String tag) { 213 if (mSystemUiProxy != null) { 214 try { 215 mSystemUiProxy.onOverviewShown(fromHome); 216 } catch (RemoteException e) { 217 Log.w(tag, "Failed call onOverviewShown from: " + (fromHome ? "home" : "app"), e); 218 } 219 } 220 } 221 222 @Override getNonMinimizedSplitScreenSecondaryBounds()223 public Rect getNonMinimizedSplitScreenSecondaryBounds() { 224 if (mSystemUiProxy != null) { 225 try { 226 return mSystemUiProxy.getNonMinimizedSplitScreenSecondaryBounds(); 227 } catch (RemoteException e) { 228 Log.w(TAG, "Failed call getNonMinimizedSplitScreenSecondaryBounds", e); 229 } 230 } 231 return null; 232 } 233 getLastNavButtonAlpha()234 public float getLastNavButtonAlpha() { 235 return mLastNavButtonAlpha; 236 } 237 238 @Override setNavBarButtonAlpha(float alpha, boolean animate)239 public void setNavBarButtonAlpha(float alpha, boolean animate) { 240 boolean changed = Float.compare(alpha, mLastNavButtonAlpha) != 0 241 || animate != mLastNavButtonAnimate 242 || !mHasNavButtonAlphaBeenSet; 243 if (mSystemUiProxy != null && changed) { 244 mLastNavButtonAlpha = alpha; 245 mLastNavButtonAnimate = animate; 246 mHasNavButtonAlphaBeenSet = true; 247 try { 248 mSystemUiProxy.setNavBarButtonAlpha(alpha, animate); 249 } catch (RemoteException e) { 250 Log.w(TAG, "Failed call setNavBarButtonAlpha", e); 251 } 252 } 253 } 254 255 @Override onStatusBarMotionEvent(MotionEvent event)256 public void onStatusBarMotionEvent(MotionEvent event) { 257 if (mSystemUiProxy != null) { 258 try { 259 mSystemUiProxy.onStatusBarMotionEvent(event); 260 } catch (RemoteException e) { 261 Log.w(TAG, "Failed call onStatusBarMotionEvent", e); 262 } 263 } 264 } 265 266 @Override onAssistantProgress(float progress)267 public void onAssistantProgress(float progress) { 268 if (mSystemUiProxy != null) { 269 try { 270 mSystemUiProxy.onAssistantProgress(progress); 271 } catch (RemoteException e) { 272 Log.w(TAG, "Failed call onAssistantProgress with progress: " + progress, e); 273 } 274 } 275 } 276 277 @Override onAssistantGestureCompletion(float velocity)278 public void onAssistantGestureCompletion(float velocity) { 279 if (mSystemUiProxy != null) { 280 try { 281 mSystemUiProxy.onAssistantGestureCompletion(velocity); 282 } catch (RemoteException e) { 283 Log.w(TAG, "Failed call onAssistantGestureCompletion", e); 284 } 285 } 286 } 287 288 @Override startAssistant(Bundle args)289 public void startAssistant(Bundle args) { 290 if (mSystemUiProxy != null) { 291 try { 292 mSystemUiProxy.startAssistant(args); 293 } catch (RemoteException e) { 294 Log.w(TAG, "Failed call startAssistant", e); 295 } 296 } 297 } 298 299 @Override notifyAccessibilityButtonClicked(int displayId)300 public void notifyAccessibilityButtonClicked(int displayId) { 301 if (mSystemUiProxy != null) { 302 try { 303 mSystemUiProxy.notifyAccessibilityButtonClicked(displayId); 304 } catch (RemoteException e) { 305 Log.w(TAG, "Failed call notifyAccessibilityButtonClicked", e); 306 } 307 } 308 } 309 310 @Override notifyAccessibilityButtonLongClicked()311 public void notifyAccessibilityButtonLongClicked() { 312 if (mSystemUiProxy != null) { 313 try { 314 mSystemUiProxy.notifyAccessibilityButtonLongClicked(); 315 } catch (RemoteException e) { 316 Log.w(TAG, "Failed call notifyAccessibilityButtonLongClicked", e); 317 } 318 } 319 } 320 321 @Override stopScreenPinning()322 public void stopScreenPinning() { 323 if (mSystemUiProxy != null) { 324 try { 325 mSystemUiProxy.stopScreenPinning(); 326 } catch (RemoteException e) { 327 Log.w(TAG, "Failed call stopScreenPinning", e); 328 } 329 } 330 } 331 332 @Override handleImageAsScreenshot(Bitmap bitmap, Rect rect, Insets insets, int i)333 public void handleImageAsScreenshot(Bitmap bitmap, Rect rect, Insets insets, int i) { 334 if (mSystemUiProxy != null) { 335 try { 336 mSystemUiProxy.handleImageAsScreenshot(bitmap, rect, insets, i); 337 } catch (RemoteException e) { 338 Log.w(TAG, "Failed call handleImageAsScreenshot", e); 339 } 340 } 341 } 342 343 @Override setSplitScreenMinimized(boolean minimized)344 public void setSplitScreenMinimized(boolean minimized) { 345 if (mSystemUiProxy != null) { 346 try { 347 mSystemUiProxy.setSplitScreenMinimized(minimized); 348 } catch (RemoteException e) { 349 Log.w(TAG, "Failed call stopScreenPinning", e); 350 } 351 } 352 } 353 354 @Override notifySwipeUpGestureStarted()355 public void notifySwipeUpGestureStarted() { 356 if (mSystemUiProxy != null) { 357 try { 358 mSystemUiProxy.notifySwipeUpGestureStarted(); 359 } catch (RemoteException e) { 360 Log.w(TAG, "Failed call notifySwipeUpGestureStarted", e); 361 } 362 } 363 } 364 365 /** 366 * Notifies that swipe-to-home action is finished. 367 */ 368 @Override notifySwipeToHomeFinished()369 public void notifySwipeToHomeFinished() { 370 if (mSystemUiProxy != null) { 371 try { 372 mSystemUiProxy.notifySwipeToHomeFinished(); 373 } catch (RemoteException e) { 374 Log.w(TAG, "Failed call notifySwipeToHomeFinished", e); 375 } 376 } 377 } 378 379 @Override notifyPrioritizedRotation(int rotation)380 public void notifyPrioritizedRotation(int rotation) { 381 if (mSystemUiProxy != null) { 382 try { 383 mSystemUiProxy.notifyPrioritizedRotation(rotation); 384 } catch (RemoteException e) { 385 Log.w(TAG, "Failed call notifyPrioritizedRotation with arg: " + rotation, e); 386 } 387 } 388 } 389 390 @Override handleImageBundleAsScreenshot(Bundle screenImageBundle, Rect locationInScreen, Insets visibleInsets, Task.TaskKey task)391 public void handleImageBundleAsScreenshot(Bundle screenImageBundle, Rect locationInScreen, 392 Insets visibleInsets, Task.TaskKey task) { 393 if (mSystemUiProxy != null) { 394 try { 395 mSystemUiProxy.handleImageBundleAsScreenshot(screenImageBundle, locationInScreen, 396 visibleInsets, task); 397 } catch (RemoteException e) { 398 Log.w(TAG, "Failed call handleImageBundleAsScreenshot"); 399 } 400 } 401 } 402 403 @Override expandNotificationPanel()404 public void expandNotificationPanel() { 405 if (mSystemUiProxy != null) { 406 try { 407 mSystemUiProxy.expandNotificationPanel(); 408 } catch (RemoteException e) { 409 Log.w(TAG, "Failed call expandNotificationPanel", e); 410 } 411 } 412 } 413 414 // 415 // Pip 416 // 417 418 /** 419 * Sets the shelf height. 420 */ setShelfHeight(boolean visible, int shelfHeight)421 public void setShelfHeight(boolean visible, int shelfHeight) { 422 boolean changed = visible != mLastShelfVisible || shelfHeight != mLastShelfHeight; 423 if (mPip != null && changed) { 424 mLastShelfVisible = visible; 425 mLastShelfHeight = shelfHeight; 426 try { 427 mPip.setShelfHeight(visible, shelfHeight); 428 } catch (RemoteException e) { 429 Log.w(TAG, "Failed call setShelfHeight visible: " + visible 430 + " height: " + shelfHeight, e); 431 } 432 } 433 } 434 435 /** 436 * Sets listener to get pinned stack animation callbacks. 437 */ setPinnedStackAnimationListener(IPipAnimationListener listener)438 public void setPinnedStackAnimationListener(IPipAnimationListener listener) { 439 if (mPip != null) { 440 try { 441 mPip.setPinnedStackAnimationListener(listener); 442 } catch (RemoteException e) { 443 Log.w(TAG, "Failed call setPinnedStackAnimationListener", e); 444 } 445 } else { 446 mPendingPipAnimationListener = listener; 447 } 448 } 449 startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo, PictureInPictureParams pictureInPictureParams, int launcherRotation, int shelfHeight)450 public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo, 451 PictureInPictureParams pictureInPictureParams, int launcherRotation, int shelfHeight) { 452 if (mPip != null) { 453 try { 454 return mPip.startSwipePipToHome(componentName, activityInfo, 455 pictureInPictureParams, launcherRotation, shelfHeight); 456 } catch (RemoteException e) { 457 Log.w(TAG, "Failed call startSwipePipToHome", e); 458 } 459 } 460 return null; 461 } 462 stopSwipePipToHome(ComponentName componentName, Rect destinationBounds, SurfaceControl overlay)463 public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds, 464 SurfaceControl overlay) { 465 if (mPip != null) { 466 try { 467 mPip.stopSwipePipToHome(componentName, destinationBounds, overlay); 468 } catch (RemoteException e) { 469 Log.w(TAG, "Failed call stopSwipePipToHome"); 470 } 471 } 472 } 473 474 // 475 // Splitscreen 476 // 477 registerSplitScreenListener(ISplitScreenListener listener)478 public void registerSplitScreenListener(ISplitScreenListener listener) { 479 if (mSplitScreen != null) { 480 try { 481 mSplitScreen.registerSplitScreenListener(listener); 482 } catch (RemoteException e) { 483 Log.w(TAG, "Failed call registerSplitScreenListener"); 484 } 485 } else { 486 mPendingSplitScreenListener = listener; 487 } 488 } 489 unregisterSplitScreenListener(ISplitScreenListener listener)490 public void unregisterSplitScreenListener(ISplitScreenListener listener) { 491 if (mSplitScreen != null) { 492 try { 493 mSplitScreen.unregisterSplitScreenListener(listener); 494 } catch (RemoteException e) { 495 Log.w(TAG, "Failed call unregisterSplitScreenListener"); 496 } 497 } 498 mPendingSplitScreenListener = null; 499 } 500 setSideStageVisibility(boolean visible)501 public void setSideStageVisibility(boolean visible) { 502 if (mSplitScreen != null) { 503 try { 504 mSplitScreen.setSideStageVisibility(visible); 505 } catch (RemoteException e) { 506 Log.w(TAG, "Failed call setSideStageVisibility"); 507 } 508 } 509 } 510 exitSplitScreen()511 public void exitSplitScreen() { 512 if (mSplitScreen != null) { 513 try { 514 mSplitScreen.exitSplitScreen(); 515 } catch (RemoteException e) { 516 Log.w(TAG, "Failed call exitSplitScreen"); 517 } 518 } 519 } 520 exitSplitScreenOnHide(boolean exitSplitScreenOnHide)521 public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) { 522 if (mSplitScreen != null) { 523 try { 524 mSplitScreen.exitSplitScreenOnHide(exitSplitScreenOnHide); 525 } catch (RemoteException e) { 526 Log.w(TAG, "Failed call exitSplitScreen"); 527 } 528 } 529 } 530 startTask(int taskId, int stage, int position, Bundle options)531 public void startTask(int taskId, int stage, int position, Bundle options) { 532 if (mSplitScreen != null) { 533 try { 534 mSplitScreen.startTask(taskId, stage, position, options); 535 } catch (RemoteException e) { 536 Log.w(TAG, "Failed call startTask"); 537 } 538 } 539 } 540 541 /** Start multiple tasks in split-screen simultaneously. */ startTasks(int mainTaskId, Bundle mainOptions, int sideTaskId, Bundle sideOptions, @SplitConfigurationOptions.StagePosition int sidePosition, RemoteTransitionCompat remoteTransition)542 public void startTasks(int mainTaskId, Bundle mainOptions, int sideTaskId, Bundle sideOptions, 543 @SplitConfigurationOptions.StagePosition int sidePosition, 544 RemoteTransitionCompat remoteTransition) { 545 if (mSystemUiProxy != null) { 546 try { 547 mSplitScreen.startTasks(mainTaskId, mainOptions, sideTaskId, sideOptions, 548 sidePosition, remoteTransition.getTransition()); 549 } catch (RemoteException e) { 550 Log.w(TAG, "Failed call startTask"); 551 } 552 } 553 } 554 startShortcut(String packageName, String shortcutId, int stage, int position, Bundle options, UserHandle user)555 public void startShortcut(String packageName, String shortcutId, int stage, int position, 556 Bundle options, UserHandle user) { 557 if (mSplitScreen != null) { 558 try { 559 mSplitScreen.startShortcut(packageName, shortcutId, stage, position, options, 560 user); 561 } catch (RemoteException e) { 562 Log.w(TAG, "Failed call startShortcut"); 563 } 564 } 565 } 566 startIntent(PendingIntent intent, Intent fillInIntent, int stage, int position, Bundle options)567 public void startIntent(PendingIntent intent, Intent fillInIntent, int stage, int position, 568 Bundle options) { 569 if (mSplitScreen != null) { 570 try { 571 mSplitScreen.startIntent(intent, fillInIntent, stage, position, options); 572 } catch (RemoteException e) { 573 Log.w(TAG, "Failed call startIntent"); 574 } 575 } 576 } 577 removeFromSideStage(int taskId)578 public void removeFromSideStage(int taskId) { 579 if (mSplitScreen != null) { 580 try { 581 mSplitScreen.removeFromSideStage(taskId); 582 } catch (RemoteException e) { 583 Log.w(TAG, "Failed call removeFromSideStage"); 584 } 585 } 586 } 587 588 // 589 // One handed 590 // 591 startOneHandedMode()592 public void startOneHandedMode() { 593 if (mOneHanded != null) { 594 try { 595 mOneHanded.startOneHanded(); 596 } catch (RemoteException e) { 597 Log.w(TAG, "Failed call startOneHandedMode", e); 598 } 599 } 600 } 601 stopOneHandedMode()602 public void stopOneHandedMode() { 603 if (mOneHanded != null) { 604 try { 605 mOneHanded.stopOneHanded(); 606 } catch (RemoteException e) { 607 Log.w(TAG, "Failed call stopOneHandedMode", e); 608 } 609 } 610 } 611 612 // 613 // Remote transitions 614 // 615 registerRemoteTransition(RemoteTransitionCompat remoteTransition)616 public void registerRemoteTransition(RemoteTransitionCompat remoteTransition) { 617 if (mShellTransitions != null) { 618 try { 619 mShellTransitions.registerRemote(remoteTransition.getFilter(), 620 remoteTransition.getTransition()); 621 } catch (RemoteException e) { 622 Log.w(TAG, "Failed call registerRemoteTransition"); 623 } 624 } 625 } 626 unregisterRemoteTransition(RemoteTransitionCompat remoteTransition)627 public void unregisterRemoteTransition(RemoteTransitionCompat remoteTransition) { 628 if (mShellTransitions != null) { 629 try { 630 mShellTransitions.unregisterRemote(remoteTransition.getTransition()); 631 } catch (RemoteException e) { 632 Log.w(TAG, "Failed call registerRemoteTransition"); 633 } 634 } 635 } 636 637 // 638 // Starting window 639 // 640 641 /** 642 * Sets listener to get callbacks when launching a task. 643 */ setStartingWindowListener(IStartingWindowListener listener)644 public void setStartingWindowListener(IStartingWindowListener listener) { 645 if (mStartingWindow != null) { 646 try { 647 mStartingWindow.setStartingWindowListener(listener); 648 } catch (RemoteException e) { 649 Log.w(TAG, "Failed call setStartingWindowListener", e); 650 } 651 } else { 652 mPendingStartingWindowListener = listener; 653 } 654 } 655 656 657 // 658 // SmartSpace transitions 659 // 660 setSmartspaceCallback(ISmartspaceCallback callback)661 public void setSmartspaceCallback(ISmartspaceCallback callback) { 662 if (mSmartspaceTransitionController != null) { 663 try { 664 mSmartspaceTransitionController.setSmartspace(callback); 665 } catch (RemoteException e) { 666 Log.w(TAG, "Failed call setStartingWindowListener", e); 667 } 668 } else { 669 mPendingSmartspaceCallback = callback; 670 } 671 } 672 } 673