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 TaskbarDividerPopupController 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, TaskbarDividerPopupController 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 TaskbarDividerPopupController 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); 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, taskbarTranslationController, 184 taskbarEduTooltipController, keyboardQuickSwitchController, taskbarPinningController 185 }; 186 mBackgroundRendererControllers = new BackgroundRendererController[] { 187 taskbarDragLayerController, taskbarScrimViewController, 188 voiceInteractionWindowController 189 }; 190 mCornerRoundness.updateValue(TaskbarBackgroundRenderer.DEFAULT_ROUNDNESS); 191 192 mAreAllControllersInitialized = true; 193 for (Runnable postInitCallback : mPostInitCallbacks) { 194 postInitCallback.run(); 195 } 196 mPostInitCallbacks.clear(); 197 } 198 199 /** 200 * Sets the ui controller. 201 */ setUiController(@onNull TaskbarUIController newUiController)202 public void setUiController(@NonNull TaskbarUIController newUiController) { 203 uiController.onDestroy(); 204 uiController = newUiController; 205 uiController.init(this); 206 uiController.updateStateForSysuiFlags(mSharedState.sysuiStateFlags); 207 208 // Notify that the ui controller has changed 209 navbarButtonsViewController.onUiControllerChanged(); 210 } 211 212 @Nullable getSharedState()213 public TaskbarSharedState getSharedState() { 214 // This should only be null if called before init() and after destroy(). 215 return mSharedState; 216 } 217 onConfigurationChanged(@onfig int configChanges)218 public void onConfigurationChanged(@Config int configChanges) { 219 navbarButtonsViewController.onConfigurationChanged(configChanges); 220 taskbarDragLayerController.onConfigurationChanged(); 221 keyboardQuickSwitchController.onConfigurationChanged(configChanges); 222 } 223 224 /** 225 * Cleans up all controllers. 226 */ onDestroy()227 public void onDestroy() { 228 mAreAllControllersInitialized = false; 229 mSharedState = null; 230 231 navbarButtonsViewController.onDestroy(); 232 uiController.onDestroy(); 233 rotationButtonController.onDestroy(); 234 taskbarDragLayerController.onDestroy(); 235 taskbarUnfoldAnimationController.onDestroy(); 236 taskbarViewController.onDestroy(); 237 stashedHandleViewController.onDestroy(); 238 taskbarAutohideSuspendController.onDestroy(); 239 taskbarPopupController.onDestroy(); 240 taskbarForceVisibleImmersiveController.onDestroy(); 241 taskbarOverlayController.onDestroy(); 242 taskbarAllAppsController.onDestroy(); 243 navButtonController.onDestroy(); 244 taskbarInsetsController.onDestroy(); 245 voiceInteractionWindowController.onDestroy(); 246 taskbarRecentAppsController.onDestroy(); 247 keyboardQuickSwitchController.onDestroy(); 248 taskbarStashController.onDestroy(); 249 bubbleControllers.ifPresent(controllers -> controllers.onDestroy()); 250 251 mControllersToLog = null; 252 mBackgroundRendererControllers = null; 253 } 254 255 /** 256 * If all controllers are already initialized, runs the given callback immediately. Otherwise, 257 * queues it to run after calling init() on all controllers. This should likely be used in any 258 * case where one controller is telling another controller to do something inside init(). 259 */ runAfterInit(Runnable callback)260 public void runAfterInit(Runnable callback) { 261 if (mAreAllControllersInitialized) { 262 callback.run(); 263 } else { 264 mPostInitCallbacks.add(callback); 265 } 266 } 267 dumpLogs(String prefix, PrintWriter pw)268 protected void dumpLogs(String prefix, PrintWriter pw) { 269 pw.println(prefix + "TaskbarControllers:"); 270 271 if (mControllersToLog == null) { 272 pw.println(String.format( 273 "%s\t%s", prefix, "All taskbar controllers have already been destroyed.")); 274 return; 275 } 276 277 pw.println(String.format( 278 "%s\tmAreAllControllersInitialized=%b", prefix, mAreAllControllersInitialized)); 279 for (LoggableTaskbarController controller : mControllersToLog) { 280 controller.dumpLogs(prefix + "\t", pw); 281 } 282 uiController.dumpLogs(prefix + "\t", pw); 283 rotationButtonController.dumpLogs(prefix + "\t", pw); 284 } 285 286 /** 287 * Returns a float property that animates roundness of the round corner above Taskbar. 288 */ getTaskbarCornerRoundness()289 public AnimatedFloat getTaskbarCornerRoundness() { 290 return mCornerRoundness; 291 } 292 updateCornerRoundness()293 private void updateCornerRoundness() { 294 if (mBackgroundRendererControllers == null) { 295 return; 296 } 297 298 for (BackgroundRendererController controller : mBackgroundRendererControllers) { 299 controller.setCornerRoundness(mCornerRoundness.value); 300 } 301 } 302 303 @VisibleForTesting getTaskbarActivityContext()304 TaskbarActivityContext getTaskbarActivityContext() { 305 // Used to mock 306 return taskbarActivityContext; 307 } 308 309 protected interface LoggableTaskbarController { dumpLogs(String prefix, PrintWriter pw)310 void dumpLogs(String prefix, PrintWriter pw); 311 } 312 313 protected interface BackgroundRendererController { 314 /** 315 * Sets the roundness of the round corner above Taskbar. 316 * @param cornerRoundness 0 has no round corner, 1 has complete round corner. 317 */ setCornerRoundness(float cornerRoundness)318 void setCornerRoundness(float cornerRoundness); 319 } 320 } 321