• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.launcher3.taskbar;
17 
18 import android.animation.AnimatorSet;
19 import android.content.pm.ActivityInfo.Config;
20 
21 import androidx.annotation.NonNull;
22 import androidx.annotation.Nullable;
23 import androidx.annotation.VisibleForTesting;
24 
25 import com.android.launcher3.anim.AnimatedFloat;
26 import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
27 import com.android.launcher3.taskbar.bubbles.BubbleControllers;
28 import com.android.launcher3.taskbar.growth.NudgeController;
29 import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
30 import com.android.systemui.shared.rotation.RotationButtonController;
31 import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
32 
33 import java.io.PrintWriter;
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.Optional;
37 
38 /**
39  * Hosts various taskbar controllers to facilitate passing between one another.
40  */
41 public class TaskbarControllers {
42 
43     public final TaskbarActivityContext taskbarActivityContext;
44 
45     public final TaskbarDragController taskbarDragController;
46     public final TaskbarNavButtonController navButtonController;
47     public final NavbarButtonsViewController navbarButtonsViewController;
48     public final RotationButtonController rotationButtonController;
49     public final TaskbarDragLayerController taskbarDragLayerController;
50     public final TaskbarScrimViewController taskbarScrimViewController;
51     public final TaskbarViewController taskbarViewController;
52     public final TaskbarUnfoldAnimationController taskbarUnfoldAnimationController;
53     public final TaskbarKeyguardController taskbarKeyguardController;
54     public final StashedHandleViewController stashedHandleViewController;
55     public final TaskbarStashController taskbarStashController;
56     public final TaskbarAutohideSuspendController taskbarAutohideSuspendController;
57     public final TaskbarPopupController taskbarPopupController;
58     public final TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController;
59     public final TaskbarAllAppsController taskbarAllAppsController;
60     public final TaskbarInsetsController taskbarInsetsController;
61     public final VoiceInteractionWindowController voiceInteractionWindowController;
62     public final TaskbarRecentAppsController taskbarRecentAppsController;
63     public final TaskbarTranslationController taskbarTranslationController;
64     public final TaskbarSpringOnStashController taskbarSpringOnStashController;
65     public final TaskbarOverlayController taskbarOverlayController;
66     public final TaskbarEduTooltipController taskbarEduTooltipController;
67     public final KeyboardQuickSwitchController keyboardQuickSwitchController;
68     public final TaskbarPinningController taskbarPinningController;
69     public final Optional<BubbleControllers> bubbleControllers;
70     public final TaskbarDesktopModeController taskbarDesktopModeController;
71     public final NudgeController nudgeController;
72 
73     @Nullable private LoggableTaskbarController[] mControllersToLog = null;
74     @Nullable private BackgroundRendererController[] mBackgroundRendererControllers = null;
75 
76     /** Do not store this controller, as it may change at runtime. */
77     @NonNull public TaskbarUIController uiController = TaskbarUIController.DEFAULT;
78 
79     private boolean mAreAllControllersInitialized;
80     private final List<Runnable> mPostInitCallbacks = new ArrayList<>();
81 
82     @Nullable private TaskbarSharedState mSharedState = null;
83 
84     // Roundness property for round corner above taskbar .
85     private final AnimatedFloat mCornerRoundness = new AnimatedFloat(this::updateCornerRoundness);
86 
87     /**
88      * Want to add a new controller? Don't forget to:
89      *   * Call init
90      *   * Call onDestroy
91      *   * Add to mControllersToLog
92      *   * Add tests by adding this controller to TaskbarBaseTestCase.kt and extending that class
93      */
TaskbarControllers(TaskbarActivityContext taskbarActivityContext, TaskbarDragController taskbarDragController, TaskbarNavButtonController navButtonController, NavbarButtonsViewController navbarButtonsViewController, RotationButtonController rotationButtonController, TaskbarDragLayerController taskbarDragLayerController, TaskbarViewController taskbarViewController, TaskbarScrimViewController taskbarScrimViewController, TaskbarUnfoldAnimationController taskbarUnfoldAnimationController, TaskbarKeyguardController taskbarKeyguardController, StashedHandleViewController stashedHandleViewController, TaskbarStashController taskbarStashController, TaskbarAutohideSuspendController taskbarAutoHideSuspendController, TaskbarPopupController taskbarPopupController, TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController, TaskbarOverlayController taskbarOverlayController, TaskbarAllAppsController taskbarAllAppsController, TaskbarInsetsController taskbarInsetsController, VoiceInteractionWindowController voiceInteractionWindowController, TaskbarTranslationController taskbarTranslationController, TaskbarSpringOnStashController taskbarSpringOnStashController, TaskbarRecentAppsController taskbarRecentAppsController, TaskbarEduTooltipController taskbarEduTooltipController, KeyboardQuickSwitchController keyboardQuickSwitchController, TaskbarPinningController taskbarPinningController, Optional<BubbleControllers> bubbleControllers, TaskbarDesktopModeController taskbarDesktopModeController, NudgeController nudgeController)94     public TaskbarControllers(TaskbarActivityContext taskbarActivityContext,
95             TaskbarDragController taskbarDragController,
96             TaskbarNavButtonController navButtonController,
97             NavbarButtonsViewController navbarButtonsViewController,
98             RotationButtonController rotationButtonController,
99             TaskbarDragLayerController taskbarDragLayerController,
100             TaskbarViewController taskbarViewController,
101             TaskbarScrimViewController taskbarScrimViewController,
102             TaskbarUnfoldAnimationController taskbarUnfoldAnimationController,
103             TaskbarKeyguardController taskbarKeyguardController,
104             StashedHandleViewController stashedHandleViewController,
105             TaskbarStashController taskbarStashController,
106             TaskbarAutohideSuspendController taskbarAutoHideSuspendController,
107             TaskbarPopupController taskbarPopupController,
108             TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController,
109             TaskbarOverlayController taskbarOverlayController,
110             TaskbarAllAppsController taskbarAllAppsController,
111             TaskbarInsetsController taskbarInsetsController,
112             VoiceInteractionWindowController voiceInteractionWindowController,
113             TaskbarTranslationController taskbarTranslationController,
114             TaskbarSpringOnStashController taskbarSpringOnStashController,
115             TaskbarRecentAppsController taskbarRecentAppsController,
116             TaskbarEduTooltipController taskbarEduTooltipController,
117             KeyboardQuickSwitchController keyboardQuickSwitchController,
118             TaskbarPinningController taskbarPinningController,
119             Optional<BubbleControllers> bubbleControllers,
120             TaskbarDesktopModeController taskbarDesktopModeController,
121             NudgeController nudgeController) {
122         this.taskbarActivityContext = taskbarActivityContext;
123         this.taskbarDragController = taskbarDragController;
124         this.navButtonController = navButtonController;
125         this.navbarButtonsViewController = navbarButtonsViewController;
126         this.rotationButtonController = rotationButtonController;
127         this.taskbarDragLayerController = taskbarDragLayerController;
128         this.taskbarViewController = taskbarViewController;
129         this.taskbarScrimViewController = taskbarScrimViewController;
130         this.taskbarUnfoldAnimationController = taskbarUnfoldAnimationController;
131         this.taskbarKeyguardController = taskbarKeyguardController;
132         this.stashedHandleViewController = stashedHandleViewController;
133         this.taskbarStashController = taskbarStashController;
134         this.taskbarAutohideSuspendController = taskbarAutoHideSuspendController;
135         this.taskbarPopupController = taskbarPopupController;
136         this.taskbarForceVisibleImmersiveController = taskbarForceVisibleImmersiveController;
137         this.taskbarOverlayController = taskbarOverlayController;
138         this.taskbarAllAppsController = taskbarAllAppsController;
139         this.taskbarInsetsController = taskbarInsetsController;
140         this.voiceInteractionWindowController = voiceInteractionWindowController;
141         this.taskbarTranslationController = taskbarTranslationController;
142         this.taskbarSpringOnStashController = taskbarSpringOnStashController;
143         this.taskbarRecentAppsController = taskbarRecentAppsController;
144         this.taskbarEduTooltipController = taskbarEduTooltipController;
145         this.keyboardQuickSwitchController = keyboardQuickSwitchController;
146         this.taskbarPinningController = taskbarPinningController;
147         this.bubbleControllers = bubbleControllers;
148         this.taskbarDesktopModeController = taskbarDesktopModeController;
149         this.nudgeController = nudgeController;
150     }
151 
152     /**
153      * Initializes all controllers. Note that controllers can now reference each other through this
154      * TaskbarControllers instance, but should be careful to only access things that were created
155      * in constructors for now, as some controllers may still be waiting for init().
156      */
init(@onNull TaskbarSharedState sharedState, AnimatorSet startAnimation)157     public void init(@NonNull TaskbarSharedState sharedState, AnimatorSet startAnimation) {
158         mAreAllControllersInitialized = false;
159         mSharedState = sharedState;
160 
161         taskbarDragController.init(this);
162         navbarButtonsViewController.init(this);
163         rotationButtonController.init();
164         taskbarDragLayerController.init(this, startAnimation);
165         taskbarViewController.init(this, startAnimation);
166         taskbarScrimViewController.init(this);
167         taskbarUnfoldAnimationController.init(this);
168         taskbarKeyguardController.init(navbarButtonsViewController);
169         taskbarSpringOnStashController.init(this);
170         stashedHandleViewController.init(this);
171         taskbarStashController.init(this, sharedState.setupUIVisible, mSharedState);
172         taskbarPopupController.init(this);
173         taskbarForceVisibleImmersiveController.init(this);
174         taskbarOverlayController.init(this);
175         taskbarAllAppsController.init(this, sharedState.allAppsVisible);
176         navButtonController.init(this);
177         bubbleControllers.ifPresent(controllers -> controllers.init(sharedState, this));
178         taskbarInsetsController.init(this);
179         voiceInteractionWindowController.init(this);
180         taskbarRecentAppsController.init(this);
181         taskbarTranslationController.init(this);
182         taskbarEduTooltipController.init(this);
183         keyboardQuickSwitchController.init(this);
184         taskbarPinningController.init(this, mSharedState);
185         taskbarDesktopModeController.init(this, mSharedState);
186         nudgeController.init(this);
187 
188         mControllersToLog = new LoggableTaskbarController[] {
189                 taskbarDragController, navButtonController, navbarButtonsViewController,
190                 taskbarDragLayerController, taskbarScrimViewController, taskbarViewController,
191                 taskbarUnfoldAnimationController, taskbarKeyguardController,
192                 stashedHandleViewController, taskbarStashController,
193                 taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController,
194                 voiceInteractionWindowController, taskbarRecentAppsController,
195                 taskbarTranslationController, taskbarEduTooltipController,
196                 keyboardQuickSwitchController, taskbarPinningController,
197                 nudgeController
198         };
199         mBackgroundRendererControllers = new BackgroundRendererController[] {
200                 taskbarDragLayerController, taskbarScrimViewController,
201                 voiceInteractionWindowController
202         };
203 
204         // TODO(b/401061748): get primary status from
205         //  TaskbarDesktopModeController/DesktopVisibilityController.
206         if (taskbarDesktopModeController.isInDesktopModeAndNotInOverview(
207                 taskbarActivityContext.getDisplayId())
208                 || !taskbarActivityContext.isPrimaryDisplay()) {
209             mCornerRoundness.value = taskbarDesktopModeController.getTaskbarCornerRoundness(
210                     mSharedState.showCornerRadiusInDesktopMode);
211         } else {
212             mCornerRoundness.value = TaskbarBackgroundRenderer.MAX_ROUNDNESS;
213         }
214         updateCornerRoundness();
215         onPostInit();
216     }
217 
218     @VisibleForTesting
onPostInit()219     public void onPostInit() {
220         mAreAllControllersInitialized = true;
221         for (Runnable postInitCallback : mPostInitCallbacks) {
222             postInitCallback.run();
223         }
224         mPostInitCallbacks.clear();
225     }
226 
227     /**
228      * Sets the ui controller.
229      */
setUiController(@onNull TaskbarUIController newUiController)230     public void setUiController(@NonNull TaskbarUIController newUiController) {
231         uiController.onDestroy();
232         uiController = newUiController;
233         uiController.init(this);
234         uiController.updateStateForSysuiFlags(mSharedState.sysuiStateFlags);
235         // if bubble controllers are present configure the UI controller
236         bubbleControllers.ifPresentOrElse(bubbleControllers -> {
237             BubbleBarLocation location =
238                     bubbleControllers.bubbleBarViewController.getBubbleBarLocation();
239             boolean hiddenForBubbles =
240                     bubbleControllers.bubbleBarViewController.isHiddenForNoBubbles();
241             if (!hiddenForBubbles) {
242                 uiController.adjustHotseatForBubbleBar(/* isBubbleBarVisible= */ true);
243             }
244             uiController.onBubbleBarLocationUpdated(location);
245         }, () -> uiController.onBubbleBarLocationUpdated(null));
246         // Notify that the ui controller has changed
247         navbarButtonsViewController.onUiControllerChanged();
248     }
249 
250     @Nullable
getSharedState()251     public TaskbarSharedState getSharedState() {
252         // This should only be null if called before init() and after destroy().
253         return mSharedState;
254     }
255 
onConfigurationChanged(@onfig int configChanges)256     public void onConfigurationChanged(@Config int configChanges) {
257         navbarButtonsViewController.onConfigurationChanged(configChanges);
258         taskbarDragLayerController.onConfigurationChanged();
259         keyboardQuickSwitchController.onConfigurationChanged(configChanges);
260     }
261 
262     /**
263      * Cleans up all controllers.
264      */
onDestroy()265     public void onDestroy() {
266         mAreAllControllersInitialized = false;
267         mSharedState = null;
268 
269         taskbarDragController.onDestroy();
270         navbarButtonsViewController.onDestroy();
271         uiController.onDestroy();
272         rotationButtonController.onDestroy();
273         taskbarDragLayerController.onDestroy();
274         taskbarUnfoldAnimationController.onDestroy();
275         taskbarViewController.onDestroy();
276         stashedHandleViewController.onDestroy();
277         taskbarAutohideSuspendController.onDestroy();
278         taskbarPopupController.onDestroy();
279         taskbarForceVisibleImmersiveController.onDestroy();
280         taskbarOverlayController.onDestroy();
281         taskbarAllAppsController.onDestroy();
282         navButtonController.onDestroy();
283         taskbarInsetsController.onDestroy();
284         voiceInteractionWindowController.onDestroy();
285         taskbarRecentAppsController.onDestroy();
286         keyboardQuickSwitchController.onDestroy();
287         taskbarStashController.onDestroy();
288         bubbleControllers.ifPresent(controllers -> controllers.onDestroy());
289         taskbarDesktopModeController.onDestroy();
290         mControllersToLog = null;
291         mBackgroundRendererControllers = null;
292     }
293 
294     /**
295      * If all controllers are already initialized, runs the given callback immediately. Otherwise,
296      * queues it to run after calling init() on all controllers. This should likely be used in any
297      * case where one controller is telling another controller to do something inside init().
298      */
runAfterInit(Runnable callback)299     public void runAfterInit(Runnable callback) {
300         if (mAreAllControllersInitialized) {
301             callback.run();
302         } else {
303             mPostInitCallbacks.add(callback);
304         }
305     }
306 
dumpLogs(String prefix, PrintWriter pw)307     protected void dumpLogs(String prefix, PrintWriter pw) {
308         pw.println(prefix + "TaskbarControllers:");
309 
310         if (mControllersToLog == null) {
311             pw.println(String.format(
312                     "%s\t%s", prefix, "All taskbar controllers have already been destroyed."));
313             return;
314         }
315 
316         pw.println(String.format(
317                 "%s\tmAreAllControllersInitialized=%b", prefix, mAreAllControllersInitialized));
318         for (LoggableTaskbarController controller : mControllersToLog) {
319             controller.dumpLogs(prefix + "\t", pw);
320         }
321         uiController.dumpLogs(prefix + "\t", pw);
322         rotationButtonController.dumpLogs(prefix + "\t", pw);
323         if (bubbleControllers.isPresent()) {
324             bubbleControllers.get().dump(pw);
325         } else {
326             pw.println(String.format("%s\t%s", prefix, "Bubble controllers are empty."));
327         }
328     }
329 
330     /**
331      * Returns a float property that animates roundness of the round corner above Taskbar.
332      */
getTaskbarCornerRoundness()333     public AnimatedFloat getTaskbarCornerRoundness() {
334         return mCornerRoundness;
335     }
336 
updateCornerRoundness()337     private void updateCornerRoundness() {
338         if (mBackgroundRendererControllers == null) {
339             return;
340         }
341 
342         for (BackgroundRendererController controller : mBackgroundRendererControllers) {
343             controller.setCornerRoundness(mCornerRoundness.value);
344         }
345     }
346 
347     @VisibleForTesting
getTaskbarActivityContext()348     TaskbarActivityContext getTaskbarActivityContext() {
349         // Used to mock
350         return taskbarActivityContext;
351     }
352 
353     public interface LoggableTaskbarController {
dumpLogs(String prefix, PrintWriter pw)354         void dumpLogs(String prefix, PrintWriter pw);
355     }
356 
357     protected interface BackgroundRendererController {
358         /**
359          * Sets the roundness of the round corner above Taskbar.
360          * @param cornerRoundness 0 has no round corner, 1 has complete round corner.
361          */
setCornerRoundness(float cornerRoundness)362         void setCornerRoundness(float cornerRoundness);
363     }
364 }
365