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