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