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