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.view.View.VISIBLE; 19 20 import static com.android.launcher3.taskbar.bubbles.BubbleBarController.isBubbleBarEnabled; 21 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED; 22 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED; 23 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE; 24 import static com.android.wm.shell.shared.bubbles.BubbleConstants.BUBBLE_EXPANDED_SCRIM_ALPHA; 25 26 import android.animation.ObjectAnimator; 27 import android.view.animation.Interpolator; 28 import android.view.animation.PathInterpolator; 29 30 import androidx.annotation.VisibleForTesting; 31 32 import com.android.launcher3.anim.AnimatedFloat; 33 import com.android.launcher3.taskbar.bubbles.BubbleControllers; 34 import com.android.quickstep.SystemUiProxy; 35 import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags; 36 37 import java.io.PrintWriter; 38 39 /** 40 * Handles properties/data collection, and passes the results to {@link TaskbarScrimView} to render. 41 */ 42 public class TaskbarScrimViewController implements TaskbarControllers.LoggableTaskbarController, 43 TaskbarControllers.BackgroundRendererController { 44 45 private static final Interpolator SCRIM_ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); 46 private static final Interpolator SCRIM_ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f); 47 48 private final TaskbarActivityContext mActivity; 49 private final TaskbarScrimView mScrimView; 50 private boolean mTaskbarVisible; 51 @SystemUiStateFlags 52 private long mSysUiStateFlags; 53 54 // Alpha property for the scrim. 55 private final AnimatedFloat mScrimAlpha = new AnimatedFloat(this::updateScrimAlpha); 56 57 // Initialized in init. 58 private TaskbarControllers mControllers; 59 TaskbarScrimViewController(TaskbarActivityContext activity, TaskbarScrimView scrimView)60 public TaskbarScrimViewController(TaskbarActivityContext activity, TaskbarScrimView scrimView) { 61 mActivity = activity; 62 mScrimView = scrimView; 63 } 64 65 /** 66 * Initializes the controller 67 */ init(TaskbarControllers controllers)68 public void init(TaskbarControllers controllers) { 69 mControllers = controllers; 70 onTaskbarVisibilityChanged(mControllers.taskbarViewController.getTaskbarVisibility()); 71 } 72 73 /** 74 * Called when the taskbar visibility changes. 75 * 76 * @param visibility the current visibility of {@link TaskbarView}. 77 */ onTaskbarVisibilityChanged(int visibility)78 public void onTaskbarVisibilityChanged(int visibility) { 79 mTaskbarVisible = visibility == VISIBLE; 80 if (shouldShowScrim()) { 81 showScrim(true, computeScrimAlpha(), false /* skipAnim */); 82 } else if (mScrimView.getScrimAlpha() > 0f) { 83 showScrim(false, 0, false /* skipAnim */); 84 } 85 } 86 87 /** 88 * Updates the scrim state based on the flags. 89 */ updateStateForSysuiFlags(@ystemUiStateFlags long stateFlags, boolean skipAnim)90 public void updateStateForSysuiFlags(@SystemUiStateFlags long stateFlags, boolean skipAnim) { 91 if (mActivity.isPhoneMode()) { 92 // There is no scrim for the bar in the phone mode. 93 return; 94 } 95 boolean isTransient = mActivity.isTransientTaskbar(); 96 if (isBubbleBarEnabled() && isTransient) { 97 // These scrims aren't used if bubble bar & transient taskbar are active. 98 return; 99 } 100 mSysUiStateFlags = stateFlags; 101 showScrim(shouldShowScrim(), computeScrimAlpha(), skipAnim); 102 } 103 shouldShowScrim()104 private boolean shouldShowScrim() { 105 final boolean bubblesExpanded = (mSysUiStateFlags & SYSUI_STATE_BUBBLES_EXPANDED) != 0; 106 boolean isShadeVisible = (mSysUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE) != 0; 107 BubbleControllers bubbleControllers = mActivity.getBubbleControllers(); 108 boolean isBubbleControllersPresented = bubbleControllers != null; 109 // when the taskbar is in persistent mode, we hide the task bar icons on bubble bar expand, 110 // which makes the taskbar invisible, so need to check if the bubble bar is not on home 111 // to show the scrim view 112 boolean showScrimForBubbles = bubblesExpanded 113 && !mTaskbarVisible 114 && isBubbleControllersPresented 115 && !mActivity.isTransientTaskbar() 116 && !bubbleControllers.bubbleStashController.isBubblesShowingOnHome(); 117 return bubblesExpanded && !mControllers.navbarButtonsViewController.isImeVisible() 118 && !isShadeVisible 119 && !mControllers.taskbarStashController.isStashed() 120 && (mTaskbarVisible || showScrimForBubbles) 121 && !mControllers.taskbarStashController.isHiddenForBubbles(); 122 } 123 computeScrimAlpha()124 private float computeScrimAlpha() { 125 boolean isTransient = mActivity.isTransientTaskbar(); 126 final boolean isPersistentTaskBarVisible = mTaskbarVisible && !isTransient; 127 final boolean manageMenuExpanded = 128 (mSysUiStateFlags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0; 129 if (isPersistentTaskBarVisible && manageMenuExpanded) { 130 // When manage menu shows for persistent task bar there's the first scrim and second 131 // scrim so figure out what the total transparency would be. 132 return BUBBLE_EXPANDED_SCRIM_ALPHA 133 + (BUBBLE_EXPANDED_SCRIM_ALPHA * (1 - BUBBLE_EXPANDED_SCRIM_ALPHA)); 134 } else if (shouldShowScrim()) { 135 return BUBBLE_EXPANDED_SCRIM_ALPHA; 136 } else { 137 return 0; 138 } 139 } 140 showScrim(boolean showScrim, float alpha, boolean skipAnim)141 private void showScrim(boolean showScrim, float alpha, boolean skipAnim) { 142 mScrimView.setOnClickListener(showScrim ? (view) -> onClick() : null); 143 mScrimView.setClickable(showScrim); 144 if (skipAnim) { 145 mScrimAlpha.updateValue(alpha); 146 } else { 147 ObjectAnimator anim = mScrimAlpha.animateToValue(showScrim ? alpha : 0); 148 anim.setInterpolator(showScrim ? SCRIM_ALPHA_IN : SCRIM_ALPHA_OUT); 149 anim.start(); 150 } 151 } 152 updateScrimAlpha()153 private void updateScrimAlpha() { 154 mScrimView.setScrimAlpha(mScrimAlpha.value); 155 } 156 onClick()157 private void onClick() { 158 SystemUiProxy.INSTANCE.get(mActivity).onBackEvent(null); 159 } 160 161 @Override setCornerRoundness(float cornerRoundness)162 public void setCornerRoundness(float cornerRoundness) { 163 mScrimView.setCornerRoundness(cornerRoundness); 164 } 165 166 @Override dumpLogs(String prefix, PrintWriter pw)167 public void dumpLogs(String prefix, PrintWriter pw) { 168 pw.println(prefix + "TaskbarScrimViewController:"); 169 170 pw.println(prefix + "\tmScrimAlpha.value=" + mScrimAlpha.value); 171 } 172 173 @VisibleForTesting getScrimView()174 TaskbarScrimView getScrimView() { 175 return mScrimView; 176 } 177 178 @VisibleForTesting getScrimAlpha()179 float getScrimAlpha() { 180 return mScrimAlpha.value; 181 } 182 } 183