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 static com.android.launcher3.taskbar.TaskbarPinningController.PINNING_PERSISTENT; 19 import static com.android.launcher3.taskbar.TaskbarPinningController.PINNING_TRANSIENT; 20 21 import android.content.res.Resources; 22 import android.graphics.Canvas; 23 import android.graphics.Point; 24 import android.graphics.Rect; 25 import android.os.SystemProperties; 26 import android.view.ViewTreeObserver; 27 28 import com.android.launcher3.DeviceProfile; 29 import com.android.launcher3.R; 30 import com.android.launcher3.anim.AnimatedFloat; 31 import com.android.launcher3.util.DimensionUtils; 32 import com.android.launcher3.util.DisplayController; 33 import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; 34 import com.android.launcher3.util.TouchController; 35 36 import java.io.PrintWriter; 37 38 /** 39 * Handles properties/data collection, then passes the results to TaskbarDragLayer to render. 40 */ 41 public class TaskbarDragLayerController implements TaskbarControllers.LoggableTaskbarController, 42 TaskbarControllers.BackgroundRendererController { 43 44 private static final boolean DEBUG = SystemProperties.getBoolean( 45 "persist.debug.draw_taskbar_debug_ui", false); 46 47 private final TaskbarActivityContext mActivity; 48 private final TaskbarDragLayer mTaskbarDragLayer; 49 private final int mFolderMargin; 50 51 // Alpha properties for taskbar background. 52 private final AnimatedFloat mBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha); 53 private final AnimatedFloat mBgNavbar = new AnimatedFloat(this::updateBackgroundAlpha); 54 private final AnimatedFloat mKeyguardBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha); 55 private final AnimatedFloat mNotificationShadeBgTaskbar = new AnimatedFloat( 56 this::updateBackgroundAlpha); 57 private final AnimatedFloat mImeBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha); 58 private final AnimatedFloat mAssistantBgTaskbar = new AnimatedFloat( 59 this::updateBackgroundAlpha); 60 // Used to hide our background color when someone else (e.g. ScrimView) is handling it. 61 private final AnimatedFloat mBgOverride = new AnimatedFloat(this::updateBackgroundAlpha); 62 63 // Translation property for taskbar background. 64 private final AnimatedFloat mBgOffset = new AnimatedFloat(this::updateBackgroundOffset); 65 66 // Used to fade in/out the entirety of the taskbar, for a smooth transition before/after sysui 67 // changes the inset visibility. 68 private final AnimatedFloat mTaskbarAlpha = new AnimatedFloat(this::updateTaskbarAlpha); 69 70 private final AnimatedFloat mTaskbarBackgroundProgress = new AnimatedFloat( 71 this::updateTaskbarBackgroundProgress); 72 73 // Initialized in init. 74 private TaskbarControllers mControllers; 75 private TaskbarStashViaTouchController mTaskbarStashViaTouchController; 76 private AnimatedFloat mOnBackgroundNavButtonColorIntensity; 77 78 private MultiProperty mBackgroundRendererAlpha; 79 private float mLastSetBackgroundAlpha; 80 TaskbarDragLayerController(TaskbarActivityContext activity, TaskbarDragLayer taskbarDragLayer)81 public TaskbarDragLayerController(TaskbarActivityContext activity, 82 TaskbarDragLayer taskbarDragLayer) { 83 mActivity = activity; 84 mTaskbarDragLayer = taskbarDragLayer; 85 mBackgroundRendererAlpha = mTaskbarDragLayer.getBackgroundRendererAlpha(); 86 final Resources resources = mTaskbarDragLayer.getResources(); 87 mFolderMargin = resources.getDimensionPixelSize(R.dimen.taskbar_folder_margin); 88 } 89 init(TaskbarControllers controllers)90 public void init(TaskbarControllers controllers) { 91 mControllers = controllers; 92 mTaskbarStashViaTouchController = new TaskbarStashViaTouchController(mControllers); 93 mTaskbarDragLayer.init(new TaskbarDragLayerCallbacks()); 94 95 mOnBackgroundNavButtonColorIntensity = mControllers.navbarButtonsViewController 96 .getOnTaskbarBackgroundNavButtonColorOverride(); 97 98 mTaskbarBackgroundProgress.updateValue(DisplayController.isTransientTaskbar(mActivity) 99 ? PINNING_TRANSIENT 100 : PINNING_PERSISTENT); 101 102 mBgTaskbar.value = 1; 103 mKeyguardBgTaskbar.value = 1; 104 mNotificationShadeBgTaskbar.value = 1; 105 mImeBgTaskbar.value = 1; 106 mAssistantBgTaskbar.value = 1; 107 mBgOverride.value = 1; 108 updateBackgroundAlpha(); 109 110 mTaskbarAlpha.value = 1; 111 updateTaskbarAlpha(); 112 } 113 onDestroy()114 public void onDestroy() { 115 mTaskbarDragLayer.onDestroy(); 116 } 117 118 /** 119 * @return Bounds (in TaskbarDragLayer coordinates) where an opened Folder can display. 120 */ getFolderBoundingBox()121 public Rect getFolderBoundingBox() { 122 Rect boundingBox = new Rect(0, 0, mTaskbarDragLayer.getWidth(), 123 mTaskbarDragLayer.getHeight() - mActivity.getDeviceProfile().taskbarHeight 124 - mActivity.getDeviceProfile().taskbarBottomMargin); 125 boundingBox.inset(mFolderMargin, mFolderMargin); 126 return boundingBox; 127 } 128 getTaskbarBackgroundAlpha()129 public AnimatedFloat getTaskbarBackgroundAlpha() { 130 return mBgTaskbar; 131 } 132 getNavbarBackgroundAlpha()133 public AnimatedFloat getNavbarBackgroundAlpha() { 134 return mBgNavbar; 135 } 136 getKeyguardBgTaskbar()137 public AnimatedFloat getKeyguardBgTaskbar() { 138 return mKeyguardBgTaskbar; 139 } 140 getNotificationShadeBgTaskbar()141 public AnimatedFloat getNotificationShadeBgTaskbar() { 142 return mNotificationShadeBgTaskbar; 143 } 144 getImeBgTaskbar()145 public AnimatedFloat getImeBgTaskbar() { 146 return mImeBgTaskbar; 147 } 148 getAssistantBgTaskbar()149 public AnimatedFloat getAssistantBgTaskbar() { 150 return mAssistantBgTaskbar; 151 } 152 getTaskbarBackgroundOffset()153 public AnimatedFloat getTaskbarBackgroundOffset() { 154 return mBgOffset; 155 } 156 157 // AnimatedFloat is for animating between pinned and transient taskbar getTaskbarBackgroundProgress()158 public AnimatedFloat getTaskbarBackgroundProgress() { 159 return mTaskbarBackgroundProgress; 160 } 161 getTaskbarAlpha()162 public AnimatedFloat getTaskbarAlpha() { 163 return mTaskbarAlpha; 164 } 165 166 /** 167 * Make updates when configuration changes. 168 */ onConfigurationChanged()169 public void onConfigurationChanged() { 170 mTaskbarStashViaTouchController.updateGestureHeight(); 171 } 172 updateBackgroundAlpha()173 private void updateBackgroundAlpha() { 174 final float bgNavbar = mBgNavbar.value; 175 final float bgTaskbar = mBgTaskbar.value * mKeyguardBgTaskbar.value 176 * mNotificationShadeBgTaskbar.value * mImeBgTaskbar.value 177 * mAssistantBgTaskbar.value; 178 mLastSetBackgroundAlpha = mBgOverride.value * Math.max(bgNavbar, bgTaskbar); 179 mBackgroundRendererAlpha.setValue(mLastSetBackgroundAlpha); 180 181 updateOnBackgroundNavButtonColorIntensity(); 182 } 183 getBackgroundRendererAlphaForStash()184 public MultiProperty getBackgroundRendererAlphaForStash() { 185 return mTaskbarDragLayer.getBackgroundRendererAlphaForStash(); 186 } 187 188 /** 189 * Sets the translation of the background during the swipe up gesture. 190 */ setTranslationYForSwipe(float transY)191 public void setTranslationYForSwipe(float transY) { 192 mTaskbarDragLayer.setBackgroundTranslationYForSwipe(transY); 193 } 194 195 /** 196 * Sets the translation of the background during the spring on stash animation. 197 */ setTranslationYForStash(float transY)198 public void setTranslationYForStash(float transY) { 199 mTaskbarDragLayer.setBackgroundTranslationYForStash(transY); 200 } 201 updateBackgroundOffset()202 private void updateBackgroundOffset() { 203 mTaskbarDragLayer.setTaskbarBackgroundOffset(mBgOffset.value); 204 updateOnBackgroundNavButtonColorIntensity(); 205 } 206 updateTaskbarBackgroundProgress()207 private void updateTaskbarBackgroundProgress() { 208 mTaskbarDragLayer.setTaskbarBackgroundProgress(mTaskbarBackgroundProgress.value); 209 } 210 updateTaskbarAlpha()211 private void updateTaskbarAlpha() { 212 mTaskbarDragLayer.setAlpha(mTaskbarAlpha.value); 213 } 214 215 @Override setCornerRoundness(float cornerRoundness)216 public void setCornerRoundness(float cornerRoundness) { 217 mTaskbarDragLayer.setCornerRoundness(cornerRoundness); 218 } 219 220 /** 221 * Set if another controller is temporarily handling background drawing. In this case we 222 * override our background alpha to be {@code 0}. 223 */ setIsBackgroundDrawnElsewhere(boolean isBackgroundDrawnElsewhere)224 public void setIsBackgroundDrawnElsewhere(boolean isBackgroundDrawnElsewhere) { 225 mBgOverride.updateValue(isBackgroundDrawnElsewhere ? 0 : 1); 226 } 227 updateOnBackgroundNavButtonColorIntensity()228 private void updateOnBackgroundNavButtonColorIntensity() { 229 mOnBackgroundNavButtonColorIntensity.updateValue( 230 mLastSetBackgroundAlpha * (1 - mBgOffset.value)); 231 } 232 233 /** 234 * Sets the width percentage to inset the transient taskbar's background from the left and from 235 * the right. 236 */ setBackgroundHorizontalInsets(float insetPercentage)237 public void setBackgroundHorizontalInsets(float insetPercentage) { 238 mTaskbarDragLayer.setBackgroundHorizontalInsets(insetPercentage); 239 240 } 241 242 @Override dumpLogs(String prefix, PrintWriter pw)243 public void dumpLogs(String prefix, PrintWriter pw) { 244 pw.println(prefix + "TaskbarDragLayerController:"); 245 246 pw.println(prefix + "\tmBgOffset=" + mBgOffset.value); 247 pw.println(prefix + "\tmTaskbarAlpha=" + mTaskbarAlpha.value); 248 pw.println(prefix + "\tmFolderMargin=" + mFolderMargin); 249 pw.println(prefix + "\tmLastSetBackgroundAlpha=" + mLastSetBackgroundAlpha); 250 pw.println(prefix + "\t\tmBgOverride=" + mBgOverride.value); 251 pw.println(prefix + "\t\tmBgNavbar=" + mBgNavbar.value); 252 pw.println(prefix + "\t\tmBgTaskbar=" + mBgTaskbar.value); 253 pw.println(prefix + "\t\tmKeyguardBgTaskbar=" + mKeyguardBgTaskbar.value); 254 pw.println(prefix + "\t\tmNotificationShadeBgTaskbar=" + mNotificationShadeBgTaskbar.value); 255 pw.println(prefix + "\t\tmImeBgTaskbar=" + mImeBgTaskbar.value); 256 pw.println(prefix + "\t\tmAssistantBgTaskbar=" + mAssistantBgTaskbar.value); 257 } 258 259 /** 260 * Callbacks for {@link TaskbarDragLayer} to interact with its controller. 261 */ 262 public class TaskbarDragLayerCallbacks { 263 264 /** 265 * Called to update the touchable insets. 266 * @see ViewTreeObserver.InternalInsetsInfo#setTouchableInsets(int) 267 */ updateInsetsTouchability(ViewTreeObserver.InternalInsetsInfo insetsInfo)268 public void updateInsetsTouchability(ViewTreeObserver.InternalInsetsInfo insetsInfo) { 269 mControllers.taskbarInsetsController.updateInsetsTouchability(insetsInfo); 270 } 271 272 /** 273 * Called when an IME inset is changed. 274 */ onImeInsetChanged()275 public void onImeInsetChanged() { 276 mControllers.taskbarStashController.onImeInsetChanged(); 277 } 278 279 /** 280 * Called when a child is removed from TaskbarDragLayer. 281 */ onDragLayerViewRemoved()282 public void onDragLayerViewRemoved() { 283 mActivity.onDragEndOrViewRemoved(); 284 } 285 286 /** 287 * Returns how tall the background should be drawn at the bottom of the screen. 288 */ getTaskbarBackgroundHeight()289 public int getTaskbarBackgroundHeight() { 290 DeviceProfile deviceProfile = mActivity.getDeviceProfile(); 291 if (mActivity.isPhoneMode()) { 292 Resources resources = mActivity.getResources(); 293 Point taskbarDimensions = DimensionUtils.getTaskbarPhoneDimensions(deviceProfile, 294 resources, true /* isPhoneMode */); 295 return taskbarDimensions.y == -1 ? 296 deviceProfile.getDisplayInfo().currentSize.y : 297 taskbarDimensions.y; 298 } else { 299 return deviceProfile.taskbarHeight; 300 } 301 } 302 303 /** 304 * Returns touch controllers. 305 */ getTouchControllers()306 public TouchController[] getTouchControllers() { 307 return new TouchController[] { 308 mActivity.getDragController(), 309 mControllers.taskbarForceVisibleImmersiveController, 310 mControllers.navbarButtonsViewController.getTouchController(), 311 mTaskbarStashViaTouchController, 312 }; 313 } 314 315 /** 316 * Draws debug UI on top of everything in TaskbarDragLayer. 317 */ drawDebugUi(Canvas canvas)318 public void drawDebugUi(Canvas canvas) { 319 if (!DEBUG) { 320 return; 321 } 322 mControllers.taskbarInsetsController.drawDebugTouchableRegionBounds(canvas); 323 } 324 } 325 } 326