1 /*
2  * Copyright (C) 2021 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 
17 package com.android.wm.shell.dagger;
18 
19 import static com.android.wm.shell.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE;
20 
21 import android.app.ActivityTaskManager;
22 import android.content.Context;
23 import android.content.pm.PackageManager;
24 import android.os.Handler;
25 import android.os.SystemProperties;
26 import android.view.IWindowManager;
27 
28 import com.android.internal.logging.UiEventLogger;
29 import com.android.launcher3.icons.IconProvider;
30 import com.android.wm.shell.RootDisplayAreaOrganizer;
31 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
32 import com.android.wm.shell.ShellCommandHandler;
33 import com.android.wm.shell.ShellCommandHandlerImpl;
34 import com.android.wm.shell.ShellInit;
35 import com.android.wm.shell.ShellInitImpl;
36 import com.android.wm.shell.ShellTaskOrganizer;
37 import com.android.wm.shell.TaskViewFactory;
38 import com.android.wm.shell.TaskViewFactoryController;
39 import com.android.wm.shell.WindowManagerShellWrapper;
40 import com.android.wm.shell.apppairs.AppPairs;
41 import com.android.wm.shell.apppairs.AppPairsController;
42 import com.android.wm.shell.bubbles.BubbleController;
43 import com.android.wm.shell.bubbles.Bubbles;
44 import com.android.wm.shell.common.DisplayController;
45 import com.android.wm.shell.common.DisplayImeController;
46 import com.android.wm.shell.common.DisplayInsetsController;
47 import com.android.wm.shell.common.DisplayLayout;
48 import com.android.wm.shell.common.FloatingContentCoordinator;
49 import com.android.wm.shell.common.ShellExecutor;
50 import com.android.wm.shell.common.SyncTransactionQueue;
51 import com.android.wm.shell.common.SystemWindows;
52 import com.android.wm.shell.common.TaskStackListenerImpl;
53 import com.android.wm.shell.common.TransactionPool;
54 import com.android.wm.shell.common.annotations.ShellAnimationThread;
55 import com.android.wm.shell.common.annotations.ShellMainThread;
56 import com.android.wm.shell.common.annotations.ShellSplashscreenThread;
57 import com.android.wm.shell.compatui.CompatUI;
58 import com.android.wm.shell.compatui.CompatUIController;
59 import com.android.wm.shell.displayareahelper.DisplayAreaHelper;
60 import com.android.wm.shell.displayareahelper.DisplayAreaHelperController;
61 import com.android.wm.shell.draganddrop.DragAndDrop;
62 import com.android.wm.shell.draganddrop.DragAndDropController;
63 import com.android.wm.shell.freeform.FreeformTaskListener;
64 import com.android.wm.shell.fullscreen.FullscreenTaskListener;
65 import com.android.wm.shell.fullscreen.FullscreenUnfoldController;
66 import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
67 import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
68 import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
69 import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
70 import com.android.wm.shell.onehanded.OneHanded;
71 import com.android.wm.shell.onehanded.OneHandedController;
72 import com.android.wm.shell.pip.Pip;
73 import com.android.wm.shell.pip.PipMediaController;
74 import com.android.wm.shell.pip.PipSurfaceTransactionHelper;
75 import com.android.wm.shell.pip.PipUiEventLogger;
76 import com.android.wm.shell.pip.phone.PipAppOpsListener;
77 import com.android.wm.shell.pip.phone.PipTouchHandler;
78 import com.android.wm.shell.recents.RecentTasks;
79 import com.android.wm.shell.recents.RecentTasksController;
80 import com.android.wm.shell.splitscreen.SplitScreen;
81 import com.android.wm.shell.splitscreen.SplitScreenController;
82 import com.android.wm.shell.startingsurface.StartingSurface;
83 import com.android.wm.shell.startingsurface.StartingWindowController;
84 import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
85 import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm;
86 import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
87 import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelperController;
88 import com.android.wm.shell.transition.ShellTransitions;
89 import com.android.wm.shell.transition.Transitions;
90 import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
91 
92 import java.util.Optional;
93 
94 import dagger.BindsOptionalOf;
95 import dagger.Module;
96 import dagger.Provides;
97 
98 /**
99  * Provides basic dependencies from {@link com.android.wm.shell}, these dependencies are only
100  * accessible from components within the WM subcomponent (can be explicitly exposed to the
101  * SysUIComponent, see {@link WMComponent}).
102  *
103  * This module only defines *common* dependencies across various SystemUI implementations,
104  * dependencies that are device/form factor SystemUI implementation specific should go into their
105  * respective modules (ie. {@link WMShellModule} for handheld, {@link TvWMShellModule} for tv, etc.)
106  */
107 @Module(includes = WMShellConcurrencyModule.class)
108 public abstract class WMShellBaseModule {
109 
110     //
111     // Internal common - Components used internally by multiple shell features
112     //
113 
114     @WMSingleton
115     @Provides
provideDisplayController(Context context, IWindowManager wmService, @ShellMainThread ShellExecutor mainExecutor)116     static DisplayController provideDisplayController(Context context,
117             IWindowManager wmService, @ShellMainThread ShellExecutor mainExecutor) {
118         return new DisplayController(context, wmService, mainExecutor);
119     }
120 
121     @WMSingleton
122     @Provides
provideDisplayInsetsController( IWindowManager wmService, DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor)123     static DisplayInsetsController provideDisplayInsetsController( IWindowManager wmService,
124             DisplayController displayController,
125             @ShellMainThread ShellExecutor mainExecutor) {
126         return new DisplayInsetsController(wmService, displayController, mainExecutor);
127     }
128 
129     // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
130     @BindsOptionalOf
131     @DynamicOverride
optionalDisplayImeController()132     abstract DisplayImeController optionalDisplayImeController();
133 
134     @WMSingleton
135     @Provides
provideDisplayImeController( @ynamicOverride Optional<DisplayImeController> overrideDisplayImeController, IWindowManager wmService, DisplayController displayController, DisplayInsetsController displayInsetsController, @ShellMainThread ShellExecutor mainExecutor, TransactionPool transactionPool )136     static DisplayImeController provideDisplayImeController(
137             @DynamicOverride Optional<DisplayImeController> overrideDisplayImeController,
138             IWindowManager wmService,
139             DisplayController displayController,
140             DisplayInsetsController displayInsetsController,
141             @ShellMainThread ShellExecutor mainExecutor,
142             TransactionPool transactionPool
143     ) {
144         if (overrideDisplayImeController.isPresent()) {
145             return overrideDisplayImeController.get();
146         }
147         return new DisplayImeController(wmService, displayController, displayInsetsController,
148                 mainExecutor, transactionPool);
149     }
150 
151     @WMSingleton
152     @Provides
provideDisplayLayout()153     static DisplayLayout provideDisplayLayout() {
154         return new DisplayLayout();
155     }
156 
157     @WMSingleton
158     @Provides
provideDragAndDropController(Context context, DisplayController displayController, UiEventLogger uiEventLogger, IconProvider iconProvider, @ShellMainThread ShellExecutor mainExecutor)159     static DragAndDropController provideDragAndDropController(Context context,
160             DisplayController displayController, UiEventLogger uiEventLogger,
161             IconProvider iconProvider, @ShellMainThread ShellExecutor mainExecutor) {
162         return new DragAndDropController(context, displayController, uiEventLogger, iconProvider,
163                 mainExecutor);
164     }
165 
166     @WMSingleton
167     @Provides
provideDragAndDrop(DragAndDropController dragAndDropController)168     static DragAndDrop provideDragAndDrop(DragAndDropController dragAndDropController) {
169         return dragAndDropController.asDragAndDrop();
170     }
171 
172     @WMSingleton
173     @Provides
provideShellTaskOrganizer(@hellMainThread ShellExecutor mainExecutor, Context context, CompatUIController compatUI, Optional<RecentTasksController> recentTasksOptional )174     static ShellTaskOrganizer provideShellTaskOrganizer(@ShellMainThread ShellExecutor mainExecutor,
175             Context context,
176             CompatUIController compatUI,
177             Optional<RecentTasksController> recentTasksOptional
178     ) {
179         return new ShellTaskOrganizer(mainExecutor, context, compatUI, recentTasksOptional);
180     }
181 
182     @WMSingleton
183     @Provides
provideCompatUI(CompatUIController compatUIController)184     static CompatUI provideCompatUI(CompatUIController compatUIController) {
185         return compatUIController.asCompatUI();
186     }
187 
188     @WMSingleton
189     @Provides
provideCompatUIController(Context context, DisplayController displayController, DisplayInsetsController displayInsetsController, DisplayImeController imeController, SyncTransactionQueue syncQueue, @ShellMainThread ShellExecutor mainExecutor)190     static CompatUIController provideCompatUIController(Context context,
191             DisplayController displayController, DisplayInsetsController displayInsetsController,
192             DisplayImeController imeController, SyncTransactionQueue syncQueue,
193             @ShellMainThread ShellExecutor mainExecutor) {
194         return new CompatUIController(context, displayController, displayInsetsController,
195                 imeController, syncQueue, mainExecutor);
196     }
197 
198     @WMSingleton
199     @Provides
provideSyncTransactionQueue(TransactionPool pool, @ShellMainThread ShellExecutor mainExecutor)200     static SyncTransactionQueue provideSyncTransactionQueue(TransactionPool pool,
201             @ShellMainThread ShellExecutor mainExecutor) {
202         return new SyncTransactionQueue(pool, mainExecutor);
203     }
204 
205     @WMSingleton
206     @Provides
provideSystemWindows(DisplayController displayController, IWindowManager wmService)207     static SystemWindows provideSystemWindows(DisplayController displayController,
208             IWindowManager wmService) {
209         return new SystemWindows(displayController, wmService);
210     }
211 
212     @WMSingleton
213     @Provides
provideIconProvider(Context context)214     static IconProvider provideIconProvider(Context context) {
215         return new IconProvider(context);
216     }
217 
218     // We currently dedupe multiple messages, so we use the shell main handler directly
219     @WMSingleton
220     @Provides
providerTaskStackListenerImpl( @hellMainThread Handler mainHandler)221     static TaskStackListenerImpl providerTaskStackListenerImpl(
222             @ShellMainThread Handler mainHandler) {
223         return new TaskStackListenerImpl(mainHandler);
224     }
225 
226     @WMSingleton
227     @Provides
provideTransactionPool()228     static TransactionPool provideTransactionPool() {
229         return new TransactionPool();
230     }
231 
232     @WMSingleton
233     @Provides
provideWindowManagerShellWrapper( @hellMainThread ShellExecutor mainExecutor)234     static WindowManagerShellWrapper provideWindowManagerShellWrapper(
235             @ShellMainThread ShellExecutor mainExecutor) {
236         return new WindowManagerShellWrapper(mainExecutor);
237     }
238 
239     //
240     // Bubbles (optional feature)
241     //
242 
243     @WMSingleton
244     @Provides
provideBubbles(Optional<BubbleController> bubbleController)245     static Optional<Bubbles> provideBubbles(Optional<BubbleController> bubbleController) {
246         return bubbleController.map((controller) -> controller.asBubbles());
247     }
248 
249     @BindsOptionalOf
optionalBubblesController()250     abstract BubbleController optionalBubblesController();
251 
252     //
253     // Fullscreen
254     //
255 
256     @WMSingleton
257     @Provides
provideFullscreenTaskListener( SyncTransactionQueue syncQueue, Optional<FullscreenUnfoldController> optionalFullscreenUnfoldController, Optional<RecentTasksController> recentTasksOptional )258     static FullscreenTaskListener provideFullscreenTaskListener(
259             SyncTransactionQueue syncQueue,
260             Optional<FullscreenUnfoldController> optionalFullscreenUnfoldController,
261             Optional<RecentTasksController> recentTasksOptional
262     ) {
263         return new FullscreenTaskListener(syncQueue, optionalFullscreenUnfoldController,
264                 recentTasksOptional);
265     }
266 
267     //
268     // Unfold transition
269     //
270 
271     @BindsOptionalOf
optionalShellUnfoldProgressProvider()272     abstract ShellUnfoldProgressProvider optionalShellUnfoldProgressProvider();
273 
274     // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
275     @BindsOptionalOf
276     @DynamicOverride
optionalFullscreenUnfoldController()277     abstract FullscreenUnfoldController optionalFullscreenUnfoldController();
278 
279     @WMSingleton
280     @Provides
provideFullscreenUnfoldController( @ynamicOverride Optional<FullscreenUnfoldController> fullscreenUnfoldController, Optional<ShellUnfoldProgressProvider> progressProvider)281     static Optional<FullscreenUnfoldController> provideFullscreenUnfoldController(
282             @DynamicOverride Optional<FullscreenUnfoldController> fullscreenUnfoldController,
283             Optional<ShellUnfoldProgressProvider> progressProvider) {
284         if (progressProvider.isPresent()
285                 && progressProvider.get() != ShellUnfoldProgressProvider.NO_PROVIDER) {
286             return fullscreenUnfoldController;
287         }
288         return Optional.empty();
289     }
290 
291     //
292     // Freeform (optional feature)
293     //
294 
295     // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
296     @BindsOptionalOf
297     @DynamicOverride
optionalFreeformTaskListener()298     abstract FreeformTaskListener optionalFreeformTaskListener();
299 
300     @WMSingleton
301     @Provides
provideFreeformTaskListener( @ynamicOverride Optional<FreeformTaskListener> freeformTaskListener, Context context)302     static Optional<FreeformTaskListener> provideFreeformTaskListener(
303             @DynamicOverride Optional<FreeformTaskListener> freeformTaskListener,
304             Context context) {
305         if (FreeformTaskListener.isFreeformEnabled(context)) {
306             return freeformTaskListener;
307         }
308         return Optional.empty();
309     }
310 
311     //
312     // Hide display cutout
313     //
314 
315     @WMSingleton
316     @Provides
provideHideDisplayCutout( Optional<HideDisplayCutoutController> hideDisplayCutoutController)317     static Optional<HideDisplayCutout> provideHideDisplayCutout(
318             Optional<HideDisplayCutoutController> hideDisplayCutoutController) {
319         return hideDisplayCutoutController.map((controller) -> controller.asHideDisplayCutout());
320     }
321 
322     @WMSingleton
323     @Provides
provideHideDisplayCutoutController(Context context, DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor)324     static Optional<HideDisplayCutoutController> provideHideDisplayCutoutController(Context context,
325             DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor) {
326         return Optional.ofNullable(
327                 HideDisplayCutoutController.create(context, displayController, mainExecutor));
328     }
329 
330     //
331     // One handed mode (optional feature)
332     //
333 
334     @WMSingleton
335     @Provides
provideOneHanded(Optional<OneHandedController> oneHandedController)336     static Optional<OneHanded> provideOneHanded(Optional<OneHandedController> oneHandedController) {
337         return oneHandedController.map((controller) -> controller.asOneHanded());
338     }
339 
340     // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
341     @BindsOptionalOf
342     @DynamicOverride
optionalOneHandedController()343     abstract OneHandedController optionalOneHandedController();
344 
345     @WMSingleton
346     @Provides
providesOneHandedController( @ynamicOverride Optional<OneHandedController> oneHandedController)347     static Optional<OneHandedController> providesOneHandedController(
348             @DynamicOverride Optional<OneHandedController> oneHandedController) {
349         if (SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
350             return oneHandedController;
351         }
352         return Optional.empty();
353     }
354 
355 
356     //
357     // Task to Surface communication
358     //
359 
360     @WMSingleton
361     @Provides
provideTaskSurfaceHelper( Optional<TaskSurfaceHelperController> taskSurfaceController)362     static Optional<TaskSurfaceHelper> provideTaskSurfaceHelper(
363             Optional<TaskSurfaceHelperController> taskSurfaceController) {
364         return taskSurfaceController.map((controller) -> controller.asTaskSurfaceHelper());
365     }
366 
367     @Provides
provideTaskSurfaceHelperController( ShellTaskOrganizer taskOrganizer, @ShellMainThread ShellExecutor mainExecutor)368     static Optional<TaskSurfaceHelperController> provideTaskSurfaceHelperController(
369             ShellTaskOrganizer taskOrganizer, @ShellMainThread ShellExecutor mainExecutor) {
370         return Optional.ofNullable(new TaskSurfaceHelperController(taskOrganizer, mainExecutor));
371     }
372 
373     //
374     // Pip (optional feature)
375     //
376 
377     @WMSingleton
378     @Provides
provideFloatingContentCoordinator()379     static FloatingContentCoordinator provideFloatingContentCoordinator() {
380         return new FloatingContentCoordinator();
381     }
382 
383     @WMSingleton
384     @Provides
providePipAppOpsListener(Context context, PipTouchHandler pipTouchHandler, @ShellMainThread ShellExecutor mainExecutor)385     static PipAppOpsListener providePipAppOpsListener(Context context,
386             PipTouchHandler pipTouchHandler,
387             @ShellMainThread ShellExecutor mainExecutor) {
388         return new PipAppOpsListener(context, pipTouchHandler.getMotionHelper(), mainExecutor);
389     }
390 
391     // Needs handler for registering broadcast receivers
392     @WMSingleton
393     @Provides
providePipMediaController(Context context, @ShellMainThread Handler mainHandler)394     static PipMediaController providePipMediaController(Context context,
395             @ShellMainThread Handler mainHandler) {
396         return new PipMediaController(context, mainHandler);
397     }
398 
399     @WMSingleton
400     @Provides
providePipSurfaceTransactionHelper()401     static PipSurfaceTransactionHelper providePipSurfaceTransactionHelper() {
402         return new PipSurfaceTransactionHelper();
403     }
404 
405     @WMSingleton
406     @Provides
providePipUiEventLogger(UiEventLogger uiEventLogger, PackageManager packageManager)407     static PipUiEventLogger providePipUiEventLogger(UiEventLogger uiEventLogger,
408             PackageManager packageManager) {
409         return new PipUiEventLogger(uiEventLogger, packageManager);
410     }
411 
412     @BindsOptionalOf
optionalPipTouchHandler()413     abstract PipTouchHandler optionalPipTouchHandler();
414 
415     //
416     // Recent tasks
417     //
418 
419     @WMSingleton
420     @Provides
provideRecentTasks( Optional<RecentTasksController> recentTasksController)421     static Optional<RecentTasks> provideRecentTasks(
422             Optional<RecentTasksController> recentTasksController) {
423         return recentTasksController.map((controller) -> controller.asRecentTasks());
424     }
425 
426     @WMSingleton
427     @Provides
provideRecentTasksController( Context context, TaskStackListenerImpl taskStackListener, @ShellMainThread ShellExecutor mainExecutor )428     static Optional<RecentTasksController> provideRecentTasksController(
429             Context context,
430             TaskStackListenerImpl taskStackListener,
431             @ShellMainThread ShellExecutor mainExecutor
432     ) {
433         return Optional.ofNullable(
434                 RecentTasksController.create(context, taskStackListener, mainExecutor));
435     }
436 
437     //
438     // Shell transitions
439     //
440 
441     @WMSingleton
442     @Provides
provideRemoteTransitions(Transitions transitions)443     static ShellTransitions provideRemoteTransitions(Transitions transitions) {
444         return transitions.asRemoteTransitions();
445     }
446 
447     @WMSingleton
448     @Provides
provideTransitions(ShellTaskOrganizer organizer, TransactionPool pool, DisplayController displayController, Context context, @ShellMainThread ShellExecutor mainExecutor, @ShellAnimationThread ShellExecutor animExecutor)449     static Transitions provideTransitions(ShellTaskOrganizer organizer, TransactionPool pool,
450             DisplayController displayController, Context context,
451             @ShellMainThread ShellExecutor mainExecutor,
452             @ShellAnimationThread ShellExecutor animExecutor) {
453         return new Transitions(organizer, pool, displayController, context, mainExecutor,
454                 animExecutor);
455     }
456 
457     //
458     // Display areas
459     //
460 
461     @WMSingleton
462     @Provides
provideRootTaskDisplayAreaOrganizer( @hellMainThread ShellExecutor mainExecutor, Context context)463     static RootTaskDisplayAreaOrganizer provideRootTaskDisplayAreaOrganizer(
464             @ShellMainThread ShellExecutor mainExecutor, Context context) {
465         return new RootTaskDisplayAreaOrganizer(mainExecutor, context);
466     }
467 
468     @WMSingleton
469     @Provides
provideRootDisplayAreaOrganizer( @hellMainThread ShellExecutor mainExecutor)470     static RootDisplayAreaOrganizer provideRootDisplayAreaOrganizer(
471             @ShellMainThread ShellExecutor mainExecutor) {
472         return new RootDisplayAreaOrganizer(mainExecutor);
473     }
474 
475     @WMSingleton
476     @Provides
provideDisplayAreaHelper( @hellMainThread ShellExecutor mainExecutor, RootDisplayAreaOrganizer rootDisplayAreaOrganizer)477     static Optional<DisplayAreaHelper> provideDisplayAreaHelper(
478             @ShellMainThread ShellExecutor mainExecutor,
479             RootDisplayAreaOrganizer rootDisplayAreaOrganizer) {
480         return Optional.of(new DisplayAreaHelperController(mainExecutor,
481                 rootDisplayAreaOrganizer));
482     }
483 
484     //
485     // Splitscreen (optional feature)
486     //
487 
488     @WMSingleton
489     @Provides
provideSplitScreen( Optional<SplitScreenController> splitScreenController)490     static Optional<SplitScreen> provideSplitScreen(
491             Optional<SplitScreenController> splitScreenController) {
492         return splitScreenController.map((controller) -> controller.asSplitScreen());
493     }
494 
495     // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
496     @BindsOptionalOf
497     @DynamicOverride
optionalSplitScreenController()498     abstract SplitScreenController optionalSplitScreenController();
499 
500     @WMSingleton
501     @Provides
providesSplitScreenController( @ynamicOverride Optional<SplitScreenController> splitscreenController, Context context)502     static Optional<SplitScreenController> providesSplitScreenController(
503             @DynamicOverride Optional<SplitScreenController> splitscreenController,
504             Context context) {
505         if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
506             return splitscreenController;
507         }
508         return Optional.empty();
509     }
510 
511     // Legacy split (optional feature)
512 
513     @WMSingleton
514     @Provides
provideLegacySplitScreen( Optional<LegacySplitScreenController> splitScreenController)515     static Optional<LegacySplitScreen> provideLegacySplitScreen(
516             Optional<LegacySplitScreenController> splitScreenController) {
517         return splitScreenController.map((controller) -> controller.asLegacySplitScreen());
518     }
519 
520     @BindsOptionalOf
optionalLegacySplitScreenController()521     abstract LegacySplitScreenController optionalLegacySplitScreenController();
522 
523     // App Pairs (optional feature)
524 
525     @WMSingleton
526     @Provides
provideAppPairs(Optional<AppPairsController> appPairsController)527     static Optional<AppPairs> provideAppPairs(Optional<AppPairsController> appPairsController) {
528         return appPairsController.map((controller) -> controller.asAppPairs());
529     }
530 
531     @BindsOptionalOf
optionalAppPairs()532     abstract AppPairsController optionalAppPairs();
533 
534     //
535     // Starting window
536     //
537 
538     @WMSingleton
539     @Provides
provideStartingSurface( StartingWindowController startingWindowController)540     static Optional<StartingSurface> provideStartingSurface(
541             StartingWindowController startingWindowController) {
542         return Optional.of(startingWindowController.asStartingSurface());
543     }
544 
545     @WMSingleton
546     @Provides
provideStartingWindowController(Context context, @ShellSplashscreenThread ShellExecutor splashScreenExecutor, StartingWindowTypeAlgorithm startingWindowTypeAlgorithm, IconProvider iconProvider, TransactionPool pool)547     static StartingWindowController provideStartingWindowController(Context context,
548             @ShellSplashscreenThread ShellExecutor splashScreenExecutor,
549             StartingWindowTypeAlgorithm startingWindowTypeAlgorithm, IconProvider iconProvider,
550             TransactionPool pool) {
551         return new StartingWindowController(context, splashScreenExecutor,
552                 startingWindowTypeAlgorithm, iconProvider, pool);
553     }
554 
555     // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
556     @BindsOptionalOf
557     @DynamicOverride
optionalStartingWindowTypeAlgorithm()558     abstract StartingWindowTypeAlgorithm optionalStartingWindowTypeAlgorithm();
559 
560     @WMSingleton
561     @Provides
provideStartingWindowTypeAlgorithm( @ynamicOverride Optional<StartingWindowTypeAlgorithm> startingWindowTypeAlgorithm )562     static StartingWindowTypeAlgorithm provideStartingWindowTypeAlgorithm(
563             @DynamicOverride Optional<StartingWindowTypeAlgorithm> startingWindowTypeAlgorithm
564     ) {
565         if (startingWindowTypeAlgorithm.isPresent()) {
566             return startingWindowTypeAlgorithm.get();
567         }
568         // Default to phone starting window type
569         return new PhoneStartingWindowTypeAlgorithm();
570     }
571 
572     //
573     // Task view factory
574     //
575 
576     @WMSingleton
577     @Provides
provideTaskViewFactory( TaskViewFactoryController taskViewFactoryController)578     static Optional<TaskViewFactory> provideTaskViewFactory(
579             TaskViewFactoryController taskViewFactoryController) {
580         return Optional.of(taskViewFactoryController.asTaskViewFactory());
581     }
582 
583     @WMSingleton
584     @Provides
provideTaskViewFactoryController( ShellTaskOrganizer shellTaskOrganizer, @ShellMainThread ShellExecutor mainExecutor, SyncTransactionQueue syncQueue)585     static TaskViewFactoryController provideTaskViewFactoryController(
586             ShellTaskOrganizer shellTaskOrganizer,
587             @ShellMainThread ShellExecutor mainExecutor,
588             SyncTransactionQueue syncQueue) {
589         return new TaskViewFactoryController(shellTaskOrganizer, mainExecutor, syncQueue);
590     }
591 
592     //
593     // Misc
594     //
595 
596     @WMSingleton
597     @Provides
provideShellInit(ShellInitImpl impl)598     static ShellInit provideShellInit(ShellInitImpl impl) {
599         return impl.asShellInit();
600     }
601 
602     @WMSingleton
603     @Provides
provideShellInitImpl(DisplayController displayController, DisplayImeController displayImeController, DisplayInsetsController displayInsetsController, DragAndDropController dragAndDropController, ShellTaskOrganizer shellTaskOrganizer, Optional<BubbleController> bubblesOptional, Optional<SplitScreenController> splitScreenOptional, Optional<AppPairsController> appPairsOptional, Optional<PipTouchHandler> pipTouchHandlerOptional, FullscreenTaskListener fullscreenTaskListener, Optional<FullscreenUnfoldController> appUnfoldTransitionController, Optional<FreeformTaskListener> freeformTaskListener, Optional<RecentTasksController> recentTasksOptional, Transitions transitions, StartingWindowController startingWindow, @ShellMainThread ShellExecutor mainExecutor)604     static ShellInitImpl provideShellInitImpl(DisplayController displayController,
605             DisplayImeController displayImeController,
606             DisplayInsetsController displayInsetsController,
607             DragAndDropController dragAndDropController,
608             ShellTaskOrganizer shellTaskOrganizer,
609             Optional<BubbleController> bubblesOptional,
610             Optional<SplitScreenController> splitScreenOptional,
611             Optional<AppPairsController> appPairsOptional,
612             Optional<PipTouchHandler> pipTouchHandlerOptional,
613             FullscreenTaskListener fullscreenTaskListener,
614             Optional<FullscreenUnfoldController> appUnfoldTransitionController,
615             Optional<FreeformTaskListener> freeformTaskListener,
616             Optional<RecentTasksController> recentTasksOptional,
617             Transitions transitions,
618             StartingWindowController startingWindow,
619             @ShellMainThread ShellExecutor mainExecutor) {
620         return new ShellInitImpl(displayController,
621                 displayImeController,
622                 displayInsetsController,
623                 dragAndDropController,
624                 shellTaskOrganizer,
625                 bubblesOptional,
626                 splitScreenOptional,
627                 appPairsOptional,
628                 pipTouchHandlerOptional,
629                 fullscreenTaskListener,
630                 appUnfoldTransitionController,
631                 freeformTaskListener,
632                 recentTasksOptional,
633                 transitions,
634                 startingWindow,
635                 mainExecutor);
636     }
637 
638     /**
639      * Note, this is only optional because we currently pass this to the SysUI component scope and
640      * for non-primary users, we may inject a null-optional for that dependency.
641      */
642     @WMSingleton
643     @Provides
provideShellCommandHandler(ShellCommandHandlerImpl impl)644     static Optional<ShellCommandHandler> provideShellCommandHandler(ShellCommandHandlerImpl impl) {
645         return Optional.of(impl.asShellCommandHandler());
646     }
647 
648     @WMSingleton
649     @Provides
provideShellCommandHandlerImpl( ShellTaskOrganizer shellTaskOrganizer, Optional<LegacySplitScreenController> legacySplitScreenOptional, Optional<SplitScreenController> splitScreenOptional, Optional<Pip> pipOptional, Optional<OneHandedController> oneHandedOptional, Optional<HideDisplayCutoutController> hideDisplayCutout, Optional<AppPairsController> appPairsOptional, Optional<RecentTasksController> recentTasksOptional, @ShellMainThread ShellExecutor mainExecutor)650     static ShellCommandHandlerImpl provideShellCommandHandlerImpl(
651             ShellTaskOrganizer shellTaskOrganizer,
652             Optional<LegacySplitScreenController> legacySplitScreenOptional,
653             Optional<SplitScreenController> splitScreenOptional,
654             Optional<Pip> pipOptional,
655             Optional<OneHandedController> oneHandedOptional,
656             Optional<HideDisplayCutoutController> hideDisplayCutout,
657             Optional<AppPairsController> appPairsOptional,
658             Optional<RecentTasksController> recentTasksOptional,
659             @ShellMainThread ShellExecutor mainExecutor) {
660         return new ShellCommandHandlerImpl(shellTaskOrganizer,
661                 legacySplitScreenOptional, splitScreenOptional, pipOptional, oneHandedOptional,
662                 hideDisplayCutout, appPairsOptional, recentTasksOptional, mainExecutor);
663     }
664 }
665