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