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 
17 package com.android.wm.shell;
18 
19 import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
20 
21 import com.android.wm.shell.apppairs.AppPairsController;
22 import com.android.wm.shell.bubbles.BubbleController;
23 import com.android.wm.shell.common.DisplayController;
24 import com.android.wm.shell.common.DisplayImeController;
25 import com.android.wm.shell.common.DisplayInsetsController;
26 import com.android.wm.shell.common.ShellExecutor;
27 import com.android.wm.shell.common.annotations.ExternalThread;
28 import com.android.wm.shell.draganddrop.DragAndDropController;
29 import com.android.wm.shell.freeform.FreeformTaskListener;
30 import com.android.wm.shell.fullscreen.FullscreenTaskListener;
31 import com.android.wm.shell.fullscreen.FullscreenUnfoldController;
32 import com.android.wm.shell.pip.phone.PipTouchHandler;
33 import com.android.wm.shell.recents.RecentTasksController;
34 import com.android.wm.shell.splitscreen.SplitScreenController;
35 import com.android.wm.shell.startingsurface.StartingWindowController;
36 import com.android.wm.shell.transition.Transitions;
37 
38 import java.util.Optional;
39 
40 /**
41  * The entry point implementation into the shell for initializing shell internal state.
42  */
43 public class ShellInitImpl {
44     private static final String TAG = ShellInitImpl.class.getSimpleName();
45 
46     private final DisplayController mDisplayController;
47     private final DisplayImeController mDisplayImeController;
48     private final DisplayInsetsController mDisplayInsetsController;
49     private final DragAndDropController mDragAndDropController;
50     private final ShellTaskOrganizer mShellTaskOrganizer;
51     private final Optional<BubbleController> mBubblesOptional;
52     private final Optional<SplitScreenController> mSplitScreenOptional;
53     private final Optional<AppPairsController> mAppPairsOptional;
54     private final Optional<PipTouchHandler> mPipTouchHandlerOptional;
55     private final FullscreenTaskListener mFullscreenTaskListener;
56     private final Optional<FullscreenUnfoldController> mFullscreenUnfoldController;
57     private final Optional<FreeformTaskListener> mFreeformTaskListenerOptional;
58     private final ShellExecutor mMainExecutor;
59     private final Transitions mTransitions;
60     private final StartingWindowController mStartingWindow;
61     private final Optional<RecentTasksController> mRecentTasks;
62 
63     private final InitImpl mImpl = new InitImpl();
64 
ShellInitImpl( 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> fullscreenUnfoldTransitionController, Optional<FreeformTaskListener> freeformTaskListenerOptional, Optional<RecentTasksController> recentTasks, Transitions transitions, StartingWindowController startingWindow, ShellExecutor mainExecutor)65     public ShellInitImpl(
66             DisplayController displayController,
67             DisplayImeController displayImeController,
68             DisplayInsetsController displayInsetsController,
69             DragAndDropController dragAndDropController,
70             ShellTaskOrganizer shellTaskOrganizer,
71             Optional<BubbleController> bubblesOptional,
72             Optional<SplitScreenController> splitScreenOptional,
73             Optional<AppPairsController> appPairsOptional,
74             Optional<PipTouchHandler> pipTouchHandlerOptional,
75             FullscreenTaskListener fullscreenTaskListener,
76             Optional<FullscreenUnfoldController> fullscreenUnfoldTransitionController,
77             Optional<FreeformTaskListener> freeformTaskListenerOptional,
78             Optional<RecentTasksController> recentTasks,
79             Transitions transitions,
80             StartingWindowController startingWindow,
81             ShellExecutor mainExecutor) {
82         mDisplayController = displayController;
83         mDisplayImeController = displayImeController;
84         mDisplayInsetsController = displayInsetsController;
85         mDragAndDropController = dragAndDropController;
86         mShellTaskOrganizer = shellTaskOrganizer;
87         mBubblesOptional = bubblesOptional;
88         mSplitScreenOptional = splitScreenOptional;
89         mAppPairsOptional = appPairsOptional;
90         mFullscreenTaskListener = fullscreenTaskListener;
91         mPipTouchHandlerOptional = pipTouchHandlerOptional;
92         mFullscreenUnfoldController = fullscreenUnfoldTransitionController;
93         mFreeformTaskListenerOptional = freeformTaskListenerOptional;
94         mRecentTasks = recentTasks;
95         mTransitions = transitions;
96         mMainExecutor = mainExecutor;
97         mStartingWindow = startingWindow;
98     }
99 
asShellInit()100     public ShellInit asShellInit() {
101         return mImpl;
102     }
103 
init()104     private void init() {
105         // Start listening for display and insets changes
106         mDisplayController.initialize();
107         mDisplayInsetsController.initialize();
108         mDisplayImeController.startMonitorDisplays();
109 
110         // Setup the shell organizer
111         mShellTaskOrganizer.addListenerForType(
112                 mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN);
113         mShellTaskOrganizer.initStartingWindow(mStartingWindow);
114         mShellTaskOrganizer.registerOrganizer();
115 
116         mAppPairsOptional.ifPresent(AppPairsController::onOrganizerRegistered);
117         mSplitScreenOptional.ifPresent(SplitScreenController::onOrganizerRegistered);
118         mBubblesOptional.ifPresent(BubbleController::initialize);
119 
120         // Bind the splitscreen impl to the drag drop controller
121         mDragAndDropController.initialize(mSplitScreenOptional);
122 
123         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
124             mTransitions.register(mShellTaskOrganizer);
125         }
126 
127         // TODO(b/181599115): This should really be the pip controller, but until we can provide the
128         // controller instead of the feature interface, can just initialize the touch handler if
129         // needed
130         mPipTouchHandlerOptional.ifPresent((handler) -> handler.init());
131 
132         // Initialize optional freeform
133         mFreeformTaskListenerOptional.ifPresent(f ->
134                 mShellTaskOrganizer.addListenerForType(
135                         f, ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM));
136 
137         mFullscreenUnfoldController.ifPresent(FullscreenUnfoldController::init);
138         mRecentTasks.ifPresent(RecentTasksController::init);
139     }
140 
141     @ExternalThread
142     private class InitImpl implements ShellInit {
143         @Override
init()144         public void init() {
145             try {
146                 mMainExecutor.executeBlocking(() -> ShellInitImpl.this.init());
147             } catch (InterruptedException e) {
148                 throw new RuntimeException("Failed to initialize the Shell in 2s", e);
149             }
150         }
151     }
152 }
153