• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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