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 android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY; 19 20 import static com.android.launcher3.Flags.syncAppLaunchWithTaskbarStash; 21 import static com.android.launcher3.QuickstepTransitionManager.TASKBAR_TO_APP_DURATION; 22 import static com.android.launcher3.QuickstepTransitionManager.TRANSIENT_TASKBAR_TRANSITION_DURATION; 23 import static com.android.launcher3.QuickstepTransitionManager.getTaskbarToHomeDuration; 24 import static com.android.launcher3.statemanager.BaseState.FLAG_NON_INTERACTIVE; 25 import static com.android.launcher3.taskbar.TaskbarEduTooltipControllerKt.TOOLTIP_STEP_FEATURES; 26 import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_VISIBLE; 27 import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IGNORE_IN_APP; 28 29 import android.animation.Animator; 30 import android.animation.AnimatorSet; 31 import android.window.RemoteTransition; 32 33 import androidx.annotation.NonNull; 34 import androidx.annotation.Nullable; 35 36 import com.android.launcher3.DeviceProfile; 37 import com.android.launcher3.Flags; 38 import com.android.launcher3.Hotseat; 39 import com.android.launcher3.LauncherState; 40 import com.android.launcher3.Utilities; 41 import com.android.launcher3.anim.AnimatedFloat; 42 import com.android.launcher3.logging.InstanceId; 43 import com.android.launcher3.logging.InstanceIdSequence; 44 import com.android.launcher3.model.data.ItemInfo; 45 import com.android.launcher3.taskbar.bubbles.BubbleBarController; 46 import com.android.launcher3.taskbar.bubbles.BubbleControllers; 47 import com.android.launcher3.uioverrides.QuickstepLauncher; 48 import com.android.launcher3.util.DisplayController; 49 import com.android.launcher3.util.MultiPropertyFactory; 50 import com.android.launcher3.util.OnboardingPrefs; 51 import com.android.quickstep.GestureState; 52 import com.android.quickstep.HomeVisibilityState; 53 import com.android.quickstep.LauncherActivityInterface; 54 import com.android.quickstep.RecentsAnimationCallbacks; 55 import com.android.quickstep.SystemUiProxy; 56 import com.android.quickstep.fallback.window.RecentsDisplayModel; 57 import com.android.quickstep.fallback.window.RecentsWindowFlags; 58 import com.android.quickstep.util.SplitTask; 59 import com.android.quickstep.views.RecentsView; 60 import com.android.quickstep.views.RecentsViewContainer; 61 import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags; 62 import com.android.wm.shell.shared.bubbles.BubbleBarLocation; 63 import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; 64 65 import java.io.PrintWriter; 66 import java.util.Arrays; 67 68 /** 69 * A data source which integrates with a Launcher instance 70 */ 71 public class LauncherTaskbarUIController extends TaskbarUIController { 72 73 private static final String TAG = "TaskbarUIController"; 74 75 public static final int MINUS_ONE_PAGE_PROGRESS_INDEX = 0; 76 public static final int ALL_APPS_PAGE_PROGRESS_INDEX = 1; 77 public static final int WIDGETS_PAGE_PROGRESS_INDEX = 2; 78 public static final int SYSUI_SURFACE_PROGRESS_INDEX = 3; 79 public static final int LAUNCHER_PAUSE_PROGRESS_INDEX = 4; 80 81 public static final int DISPLAY_PROGRESS_COUNT = 5; 82 83 private final AnimatedFloat mTaskbarInAppDisplayProgress = new AnimatedFloat( 84 this::onInAppDisplayProgressChanged); 85 private final MultiPropertyFactory<AnimatedFloat> mTaskbarInAppDisplayProgressMultiProp = 86 new MultiPropertyFactory<>(mTaskbarInAppDisplayProgress, 87 AnimatedFloat.VALUE, DISPLAY_PROGRESS_COUNT, Float::max); 88 private final AnimatedFloat mLauncherPauseProgress = new AnimatedFloat( 89 this::onLauncherPauseProgressUpdate); 90 91 private final QuickstepLauncher mLauncher; 92 private final HomeVisibilityState mHomeState; 93 94 private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener = 95 dp -> { 96 onStashedInAppChanged(dp); 97 postAdjustHotseatForBubbleBar(); 98 if (mControllers != null && mControllers.taskbarViewController != null) { 99 mControllers.taskbarViewController.onRotationChanged(dp); 100 } 101 }; 102 private final HomeVisibilityState.VisibilityChangeListener mVisibilityChangeListener = 103 this::onLauncherVisibilityChanged; 104 105 // Initialized in init. 106 private final TaskbarLauncherStateController 107 mTaskbarLauncherStateController = new TaskbarLauncherStateController(); 108 // When overview-in-a-window is enabled, that window is the container, else it is mLauncher. 109 private RecentsViewContainer mRecentsViewContainer; 110 LauncherTaskbarUIController(QuickstepLauncher launcher)111 public LauncherTaskbarUIController(QuickstepLauncher launcher) { 112 mLauncher = launcher; 113 mHomeState = SystemUiProxy.INSTANCE.get(mLauncher).getHomeVisibilityState(); 114 } 115 116 @Override init(TaskbarControllers taskbarControllers)117 protected void init(TaskbarControllers taskbarControllers) { 118 super.init(taskbarControllers); 119 120 mTaskbarLauncherStateController.init(mControllers, mLauncher, 121 mControllers.getSharedState().sysuiStateFlags); 122 final TaskbarActivityContext taskbarContext = mControllers.taskbarActivityContext; 123 if (RecentsWindowFlags.getEnableOverviewInWindow()) { 124 mRecentsViewContainer = RecentsDisplayModel.getINSTANCE() 125 .get(taskbarContext).getRecentsWindowManager(taskbarContext.getDisplayId()); 126 } 127 if (mRecentsViewContainer == null) { 128 mRecentsViewContainer = mLauncher; 129 } 130 mLauncher.setTaskbarUIController(this); 131 if (mRecentsViewContainer != mLauncher) { 132 mRecentsViewContainer.setTaskbarUIController(this); 133 } 134 135 mHomeState.addListener(mVisibilityChangeListener); 136 onLauncherVisibilityChanged( 137 Flags.useActivityOverlay() 138 ? mHomeState.isHomeVisible() : mLauncher.hasBeenResumed(), 139 true /* fromInit */); 140 141 onStashedInAppChanged(mLauncher.getDeviceProfile()); 142 mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener); 143 144 // Restore the in-app display progress from before Taskbar was recreated. 145 float[] prevProgresses = mControllers.getSharedState().inAppDisplayProgressMultiPropValues; 146 // Make a copy of the previous progress to set since updating the multiprop will update 147 // the property which also calls onInAppDisplayProgressChanged() which writes the current 148 // values into the shared state 149 prevProgresses = Arrays.copyOf(prevProgresses, prevProgresses.length); 150 for (int i = 0; i < prevProgresses.length; i++) { 151 mTaskbarInAppDisplayProgressMultiProp.get(i).setValue(prevProgresses[i]); 152 } 153 } 154 155 @Override onDestroy()156 protected void onDestroy() { 157 onLauncherVisibilityChanged(false /* isVisible */, true /* fromInitOrDestroy */); 158 mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener); 159 super.onDestroy(); 160 mTaskbarLauncherStateController.onDestroy(); 161 162 mLauncher.setTaskbarUIController(null); 163 if (mRecentsViewContainer != mLauncher) { 164 mRecentsViewContainer.setTaskbarUIController(null); 165 } 166 mHomeState.removeListener(mVisibilityChangeListener); 167 } 168 onInAppDisplayProgressChanged()169 private void onInAppDisplayProgressChanged() { 170 if (mControllers != null) { 171 // Update our shared state so we can restore it if taskbar gets recreated. 172 for (int i = 0; i < DISPLAY_PROGRESS_COUNT; i++) { 173 mControllers.getSharedState().inAppDisplayProgressMultiPropValues[i] = 174 mTaskbarInAppDisplayProgressMultiProp.get(i).getValue(); 175 } 176 // Ensure nav buttons react to our latest state if necessary. 177 mControllers.navbarButtonsViewController.updateNavButtonTranslationY(); 178 } 179 } 180 181 @Override isTaskbarTouchable()182 protected boolean isTaskbarTouchable() { 183 // Touching down during animation to Hotseat will end the transition and allow the touch to 184 // go through to the Hotseat directly. 185 return !isAnimatingToHotseat(); 186 } 187 setShouldDelayLauncherStateAnim(boolean shouldDelayLauncherStateAnim)188 public void setShouldDelayLauncherStateAnim(boolean shouldDelayLauncherStateAnim) { 189 mTaskbarLauncherStateController.setShouldDelayLauncherStateAnim( 190 shouldDelayLauncherStateAnim); 191 } 192 193 @Override stashHotseat(boolean stash)194 public void stashHotseat(boolean stash) { 195 mTaskbarLauncherStateController.stashHotseat(stash); 196 } 197 198 @Override unStashHotseatInstantly()199 public void unStashHotseatInstantly() { 200 mTaskbarLauncherStateController.unStashHotseatInstantly(); 201 } 202 203 /** 204 * Adds the Launcher resume animator to the given animator set. 205 * 206 * This should be used to run a Launcher resume animation whose progress matches a 207 * swipe progress. 208 * 209 * @param placeholderDuration a placeholder duration to be used to ensure all full-length 210 * sub-animations are properly coordinated. This duration should not 211 * actually be used since this animation tracks a swipe progress. 212 */ addLauncherVisibilityChangedAnimation(AnimatorSet animation, int placeholderDuration)213 protected void addLauncherVisibilityChangedAnimation(AnimatorSet animation, 214 int placeholderDuration) { 215 animation.play(onLauncherVisibilityChanged( 216 /* isResumed= */ true, 217 /* fromInit= */ false, 218 /* startAnimation= */ false, 219 placeholderDuration)); 220 } 221 222 /** 223 * Should be called from onResume() and onPause(), and animates the Taskbar accordingly. 224 */ 225 @Override onLauncherVisibilityChanged(boolean isVisible)226 public void onLauncherVisibilityChanged(boolean isVisible) { 227 if (DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(mLauncher) 228 && mControllers.taskbarActivityContext.isPrimaryDisplay()) { 229 DisplayController.INSTANCE.get(mLauncher).notifyConfigChange(); 230 } 231 232 onLauncherVisibilityChanged(isVisible, false /* fromInit */); 233 } 234 onLauncherVisibilityChanged(boolean isVisible, boolean fromInitOrDestroy)235 private void onLauncherVisibilityChanged(boolean isVisible, boolean fromInitOrDestroy) { 236 if (mControllers == null) { 237 return; 238 } 239 onLauncherVisibilityChanged( 240 isVisible, 241 fromInitOrDestroy, 242 /* startAnimation= */ true, 243 getTaskbarAnimationDuration(isVisible)); 244 } 245 getTaskbarAnimationDuration(boolean isVisible)246 private int getTaskbarAnimationDuration(boolean isVisible) { 247 // fast animation duration since we will not be playing workspace reveal animation. 248 boolean shouldOverrideToFastAnimation = !isHotseatIconOnTopWhenAligned(); 249 if (!Flags.predictiveBackToHomePolish()) { 250 shouldOverrideToFastAnimation |= mLauncher.getPredictiveBackToHomeInProgress(); 251 } 252 253 boolean isPinned = mControllers.taskbarActivityContext.isPinnedTaskbar(); 254 if (isVisible || isPinned) { 255 return getTaskbarToHomeDuration(shouldOverrideToFastAnimation, isPinned); 256 } else { 257 return (mControllers.taskbarActivityContext.isTransientTaskbar()) 258 ? TRANSIENT_TASKBAR_TRANSITION_DURATION : TASKBAR_TO_APP_DURATION; 259 } 260 } 261 262 @Nullable onLauncherVisibilityChanged( boolean isVisible, boolean fromInitOrDestroy, boolean startAnimation, int duration)263 private Animator onLauncherVisibilityChanged( 264 boolean isVisible, boolean fromInitOrDestroy, boolean startAnimation, int duration) { 265 // Launcher is resumed during the swipe-to-overview gesture under shell-transitions, so 266 // avoid updating taskbar state in that situation (when it's non-interactive -- or 267 // "background") to avoid premature animations. 268 LauncherState state = mTaskbarLauncherStateController.getLauncherState(); 269 boolean nonInteractiveState = state.hasFlag(FLAG_NON_INTERACTIVE) 270 && !state.isTaskbarAlignedWithHotseat(mLauncher); 271 if (isVisible && (nonInteractiveState || mSkipLauncherVisibilityChange)) { 272 return null; 273 } 274 275 if (!ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY.isTrue() 276 && mControllers.taskbarDesktopModeController 277 .isInDesktopModeAndNotInOverview(mLauncher.getDisplayId())) { 278 // TODO: b/333533253 - Remove after flag rollout 279 isVisible = false; 280 } 281 282 mTaskbarLauncherStateController.updateStateForFlag(FLAG_VISIBLE, isVisible); 283 if (fromInitOrDestroy) { 284 duration = 0; 285 } 286 return mTaskbarLauncherStateController.applyState(duration, startAnimation); 287 } 288 289 @Override onStateTransitionCompletedAfterSwipeToHome(LauncherState state)290 public void onStateTransitionCompletedAfterSwipeToHome(LauncherState state) { 291 mTaskbarLauncherStateController.onStateTransitionCompletedAfterSwipeToHome(state); 292 } 293 294 @Override refreshResumedState()295 public void refreshResumedState() { 296 onLauncherVisibilityChanged(Flags.useActivityOverlay() 297 ? mHomeState.isHomeVisible() : mLauncher.hasBeenResumed()); 298 } 299 300 @Override adjustHotseatForBubbleBar(boolean isBubbleBarVisible)301 public void adjustHotseatForBubbleBar(boolean isBubbleBarVisible) { 302 if (mLauncher.getHotseat() != null) { 303 mLauncher.getHotseat().adjustForBubbleBar(isBubbleBarVisible); 304 } 305 } 306 postAdjustHotseatForBubbleBar()307 private void postAdjustHotseatForBubbleBar() { 308 Hotseat hotseat = mLauncher.getHotseat(); 309 if (hotseat == null || !isBubbleBarVisible()) return; 310 hotseat.post(() -> { 311 if (mControllers == null) return; 312 adjustHotseatForBubbleBar(isBubbleBarVisible()); 313 }); 314 } 315 isBubbleBarVisible()316 private boolean isBubbleBarVisible() { 317 BubbleControllers bubbleControllers = mControllers.bubbleControllers.orElse(null); 318 return bubbleControllers != null 319 && bubbleControllers.bubbleBarViewController.isBubbleBarVisible(); 320 } 321 322 /** 323 * Create Taskbar animation when going from an app to Launcher as part of recents transition. 324 * {@inheritDoc} 325 */ 326 @Override getParallelAnimationToGestureEndTarget( GestureState.GestureEndTarget gestureEndTarget, long duration, RecentsAnimationCallbacks callbacks)327 public Animator getParallelAnimationToGestureEndTarget( 328 GestureState.GestureEndTarget gestureEndTarget, long duration, 329 RecentsAnimationCallbacks callbacks) { 330 return mTaskbarLauncherStateController.createAnimToLauncher( 331 LauncherActivityInterface.INSTANCE.stateFromGestureEndTarget(gestureEndTarget), 332 callbacks, 333 duration); 334 } 335 336 /** 337 * Create Taskbar animation to be played alongside the Launcher app launch animation. 338 */ createAnimToApp()339 public @Nullable Animator createAnimToApp() { 340 if (!syncAppLaunchWithTaskbarStash()) { 341 return null; 342 } 343 TaskbarStashController stashController = mControllers.taskbarStashController; 344 stashController.updateStateForFlag(TaskbarStashController.FLAG_IN_APP, true); 345 return stashController.createApplyStateAnimator(stashController.getStashDuration()); 346 } 347 348 /** 349 * Temporarily ignore FLAG_IN_APP for app launches to prevent premature taskbar stashing. 350 * This is needed because taskbar gets a signal to stash before we actually start the 351 * app launch animation. 352 */ setIgnoreInAppFlagForSync(boolean enabled)353 public void setIgnoreInAppFlagForSync(boolean enabled) { 354 if (syncAppLaunchWithTaskbarStash()) { 355 mControllers.taskbarStashController.updateStateForFlag(FLAG_IGNORE_IN_APP, enabled); 356 } 357 } 358 updateTaskbarLauncherStateGoingHome()359 public void updateTaskbarLauncherStateGoingHome() { 360 mTaskbarLauncherStateController.updateStateForFlag(FLAG_VISIBLE, true); 361 mTaskbarLauncherStateController.applyState(); 362 } 363 isDraggingItem()364 public boolean isDraggingItem() { 365 boolean bubblesDragging = false; 366 if (mControllers.bubbleControllers.isPresent()) { 367 bubblesDragging = 368 mControllers.bubbleControllers.get().bubbleDragController.isDragging(); 369 } 370 return mControllers.taskbarDragController.isDragging() || bubblesDragging; 371 } 372 373 @Override onStashedInAppChanged()374 protected void onStashedInAppChanged() { 375 onStashedInAppChanged(mLauncher.getDeviceProfile()); 376 } 377 onStashedInAppChanged(DeviceProfile deviceProfile)378 private void onStashedInAppChanged(DeviceProfile deviceProfile) { 379 boolean taskbarStashedInApps = mControllers.taskbarStashController.isStashedInApp(); 380 deviceProfile.isTaskbarPresentInApps = !taskbarStashedInApps; 381 } 382 383 /** 384 * Starts a Taskbar EDU flow, if the user should see one upon launching an application. 385 */ showEduOnAppLaunch()386 public void showEduOnAppLaunch() { 387 if (!shouldShowEduOnAppLaunch()) { 388 // Called in case the edu finishes and search edu is still pending 389 mControllers.taskbarEduTooltipController.maybeShowSearchEdu(); 390 return; 391 } 392 393 // Persistent features EDU tooltip. 394 if (!mControllers.taskbarActivityContext.isTransientTaskbar()) { 395 mControllers.taskbarEduTooltipController.maybeShowFeaturesEdu(); 396 return; 397 } 398 399 // Transient swipe EDU tooltip. 400 mControllers.taskbarEduTooltipController.maybeShowSwipeEdu(); 401 } 402 403 /** Will make the next onRecentsAnimationFinished() animation a no-op. */ setSkipNextRecentsAnimEnd()404 public void setSkipNextRecentsAnimEnd() { 405 mTaskbarLauncherStateController.setSkipNextRecentsAnimEnd(); 406 } 407 408 /** 409 * Returns {@code true} if a Taskbar education should be shown on application launch. 410 */ shouldShowEduOnAppLaunch()411 public boolean shouldShowEduOnAppLaunch() { 412 if (Utilities.isRunningInTestHarness()) { 413 return false; 414 } 415 416 // Persistent features EDU tooltip. 417 if (!mControllers.taskbarActivityContext.isTransientTaskbar()) { 418 return !OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP.hasReachedMax(mLauncher); 419 } 420 421 // Transient swipe EDU tooltip. 422 return mControllers.taskbarEduTooltipController.getTooltipStep() < TOOLTIP_STEP_FEATURES; 423 } 424 425 @Override onTaskbarIconLaunched(ItemInfo item)426 public void onTaskbarIconLaunched(ItemInfo item) { 427 super.onTaskbarIconLaunched(item); 428 InstanceId instanceId = new InstanceIdSequence().newInstanceId(); 429 mLauncher.logAppLaunch(mControllers.taskbarActivityContext.getStatsLogManager(), item, 430 instanceId); 431 } 432 433 /** 434 * Animates Taskbar elements during a transition to a Launcher state that should use in-app 435 * layouts. 436 * 437 * @param progress [0, 1] 438 * 0 => use home layout 439 * 1 => use in-app layout 440 */ onTaskbarInAppDisplayProgressUpdate(float progress, int progressIndex)441 public void onTaskbarInAppDisplayProgressUpdate(float progress, int progressIndex) { 442 mTaskbarInAppDisplayProgressMultiProp.get(progressIndex).setValue(progress); 443 if (mControllers == null) { 444 // This method can be called before init() is called. 445 return; 446 } 447 if (mControllers.uiController.isIconAlignedWithHotseat()) { 448 if (!mTaskbarLauncherStateController.isAnimatingToLauncher()) { 449 // Only animate the nav buttons while home and not animating home, otherwise let 450 // the TaskbarViewController handle it. 451 mControllers.navbarButtonsViewController 452 .getTaskbarNavButtonTranslationYForInAppDisplay() 453 .updateValue(mLauncher.getDeviceProfile().getTaskbarOffsetY() 454 * mTaskbarInAppDisplayProgress.value); 455 mControllers.navbarButtonsViewController 456 .getOnTaskbarBackgroundNavButtonColorOverride().updateValue(progress); 457 } 458 if (isBubbleBarEnabled()) { 459 mControllers.bubbleControllers.ifPresent( 460 c -> c.bubbleStashController.setInAppDisplayOverrideProgress( 461 mTaskbarInAppDisplayProgress.value)); 462 } 463 } 464 } 465 466 /** Returns true iff any in-app display progress > 0. */ shouldUseInAppLayout()467 public boolean shouldUseInAppLayout() { 468 return mTaskbarInAppDisplayProgress.value > 0; 469 } 470 isBubbleBarEnabled()471 public boolean isBubbleBarEnabled() { 472 return BubbleBarController.isBubbleBarEnabled(); 473 } 474 475 /** Whether the bubble bar has any bubbles. */ hasBubbles()476 public boolean hasBubbles() { 477 if (mControllers == null) { 478 return false; 479 } 480 if (mControllers.bubbleControllers.isEmpty()) { 481 return false; 482 } 483 return mControllers.bubbleControllers.get().bubbleBarViewController.hasBubbles(); 484 } 485 486 @Override onExpandPip()487 public void onExpandPip() { 488 super.onExpandPip(); 489 mTaskbarLauncherStateController.updateStateForFlag(FLAG_VISIBLE, false); 490 mTaskbarLauncherStateController.applyState(); 491 } 492 493 @Override updateStateForSysuiFlags(@ystemUiStateFlags long sysuiFlags)494 public void updateStateForSysuiFlags(@SystemUiStateFlags long sysuiFlags) { 495 mTaskbarLauncherStateController.updateStateForSysuiFlags(sysuiFlags); 496 } 497 498 @Override isIconAlignedWithHotseat()499 public boolean isIconAlignedWithHotseat() { 500 return mTaskbarLauncherStateController.isIconAlignedWithHotseat(); 501 } 502 503 @Override isHotseatIconOnTopWhenAligned()504 public boolean isHotseatIconOnTopWhenAligned() { 505 return mTaskbarLauncherStateController.isInHotseatOnTopStates() 506 && mTaskbarInAppDisplayProgressMultiProp.get(MINUS_ONE_PAGE_PROGRESS_INDEX) 507 .getValue() == 0; 508 } 509 510 @Override isAnimatingToHotseat()511 public boolean isAnimatingToHotseat() { 512 return mTaskbarLauncherStateController.isAnimatingToLauncher() 513 && isIconAlignedWithHotseat(); 514 } 515 516 @Override endAnimationToHotseat()517 public void endAnimationToHotseat() { 518 mTaskbarLauncherStateController.resetIconAlignment(); 519 } 520 521 @Override isInOverviewUi()522 protected boolean isInOverviewUi() { 523 return mTaskbarLauncherStateController.isInOverviewUi(); 524 } 525 526 @Override toggleAllApps(boolean focusSearch)527 protected void toggleAllApps(boolean focusSearch) { 528 boolean canToggleHomeAllApps = mLauncher.isResumed() 529 && !mTaskbarLauncherStateController.isInOverviewUi() 530 && !mLauncher.areDesktopTasksVisible(); 531 if (canToggleHomeAllApps) { 532 mLauncher.toggleAllApps(focusSearch); 533 return; 534 } 535 super.toggleAllApps(focusSearch); 536 } 537 538 @Override getRecentsView()539 public RecentsView getRecentsView() { 540 return mRecentsViewContainer.getOverviewPanel(); 541 } 542 543 @Override launchSplitTasks( @onNull SplitTask splitTask, @Nullable RemoteTransition remoteTransition)544 public void launchSplitTasks( 545 @NonNull SplitTask splitTask, @Nullable RemoteTransition remoteTransition) { 546 mLauncher.launchSplitTasks(splitTask, remoteTransition); 547 } 548 549 @Override onIconLayoutBoundsChanged()550 protected void onIconLayoutBoundsChanged() { 551 mTaskbarLauncherStateController.resetIconAlignment(); 552 } 553 554 @Override dumpLogs(String prefix, PrintWriter pw)555 public void dumpLogs(String prefix, PrintWriter pw) { 556 super.dumpLogs(prefix, pw); 557 558 pw.println(String.format("%s\tTaskbar in-app display progress: %.2f", prefix, 559 mTaskbarInAppDisplayProgress.value)); 560 mTaskbarInAppDisplayProgressMultiProp.dump( 561 prefix + "\t\t", 562 pw, 563 "mTaskbarInAppDisplayProgressMultiProp", 564 "MINUS_ONE_PAGE_PROGRESS_INDEX", 565 "ALL_APPS_PAGE_PROGRESS_INDEX", 566 "WIDGETS_PAGE_PROGRESS_INDEX", 567 "SYSUI_SURFACE_PROGRESS_INDEX", 568 "LAUNCHER_PAUSE_PROGRESS_INDEX"); 569 pw.println(String.format("%s\tmRecentsWindowContainer=%s", prefix, mRecentsViewContainer)); 570 571 mTaskbarLauncherStateController.dumpLogs(prefix + "\t", pw); 572 } 573 574 @Override getTaskbarUIControllerName()575 protected String getTaskbarUIControllerName() { 576 return "LauncherTaskbarUIController"; 577 } 578 579 @Override onBubbleBarLocationAnimated(BubbleBarLocation location)580 public void onBubbleBarLocationAnimated(BubbleBarLocation location) { 581 mTaskbarLauncherStateController.onBubbleBarLocationChanged(location, /* animate = */ true); 582 mLauncher.setBubbleBarLocation(location); 583 } 584 585 @Override onBubbleBarLocationUpdated(BubbleBarLocation location)586 public void onBubbleBarLocationUpdated(BubbleBarLocation location) { 587 mTaskbarLauncherStateController.onBubbleBarLocationChanged(location, /* animate = */ false); 588 mLauncher.setBubbleBarLocation(location); 589 } 590 591 @Override onSwipeToUnstashTaskbar()592 public void onSwipeToUnstashTaskbar() { 593 // Once taskbar is unstashed, the user cannot return back to the overlay. We can 594 // clear it here to set the expected state once the user goes home. 595 if (mLauncher.getWorkspace().isOverlayShown()) { 596 mLauncher.getWorkspace().onOverlayScrollChanged(0); 597 } 598 } 599 600 /** 601 * Called when Launcher Activity resumed while staying at home. 602 * <p> 603 * Shift nav buttons up to at-home position. 604 */ onLauncherResume()605 public void onLauncherResume() { 606 mLauncherPauseProgress.animateToValue(0.0f).start(); 607 } 608 609 /** 610 * Called when Launcher Activity paused while staying at home. 611 * <p> 612 * To avoid UI clash between taskbar & bottom sheet, shift nav buttons down to in-app position. 613 */ onLauncherPause()614 public void onLauncherPause() { 615 mLauncherPauseProgress.animateToValue(1.0f).start(); 616 } 617 618 /** 619 * On launcher stop, avoid animating taskbar & overriding pre-existing animations. 620 */ onLauncherStop()621 public void onLauncherStop() { 622 mLauncherPauseProgress.cancelAnimation(); 623 mLauncherPauseProgress.updateValue(0.0f); 624 } 625 onLauncherPauseProgressUpdate()626 private void onLauncherPauseProgressUpdate() { 627 // If we are not aligned with hotseat, setting this will clobber the 3 button nav position. 628 // So in that case, treat the progress as 0 instead. 629 float pauseProgress = isIconAlignedWithHotseat() ? mLauncherPauseProgress.value : 0; 630 onTaskbarInAppDisplayProgressUpdate(pauseProgress, LAUNCHER_PAUSE_PROGRESS_INDEX); 631 } 632 633 634 } 635