• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 
17 package com.android.wm.shell.back;
18 
19 import static android.view.Display.DEFAULT_DISPLAY;
20 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
21 
22 import static com.android.window.flags.Flags.enableMultidisplayTrackpadBackGesture;
23 
24 import android.annotation.NonNull;
25 import android.annotation.Nullable;
26 import android.graphics.Color;
27 import android.graphics.Rect;
28 import android.view.SurfaceControl;
29 
30 import com.android.internal.graphics.ColorUtils;
31 import com.android.internal.view.AppearanceRegion;
32 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
33 
34 /**
35  * Controls background surface for the back animations
36  */
37 public class BackAnimationBackground {
38     private static final int BACKGROUND_LAYER = -1;
39 
40     private static final int NO_APPEARANCE = 0;
41 
42     private final RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer;
43     private SurfaceControl mBackgroundSurface;
44 
45     private StatusBarCustomizer mCustomizer;
46     private boolean mIsRequestingStatusBarAppearance;
47     private boolean mBackgroundIsDark;
48     private Rect mStartBounds;
49     private int mStatusbarHeight;
50 
BackAnimationBackground(RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer)51     public BackAnimationBackground(RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
52         mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
53     }
54 
55     /**
56      * Ensures the back animation background color layer is present.
57      *
58      * @param startRect The start bounds of the closing target.
59      * @param color The background color.
60      * @param transaction The animation transaction.
61      * @param statusbarHeight The height of the statusbar (in px).
62      */
ensureBackground(Rect startRect, int color, @NonNull SurfaceControl.Transaction transaction, int statusbarHeight, int displayId)63     public void ensureBackground(Rect startRect, int color,
64             @NonNull SurfaceControl.Transaction transaction, int statusbarHeight, int displayId) {
65         ensureBackground(startRect, color, transaction, statusbarHeight,
66                 null /* cropBounds */, 0 /* cornerRadius */, displayId);
67     }
68 
69     /**
70      * Ensures the back animation background color layer is present.
71      *
72      * @param startRect The start bounds of the closing target.
73      * @param color The background color.
74      * @param transaction The animation transaction.
75      * @param statusbarHeight The height of the statusbar (in px).
76      * @param cropBounds The crop bounds of the surface, set to non-empty to show wallpaper.
77      * @param cornerRadius The radius of corner, only work when cropBounds is not empty.
78      */
ensureBackground(Rect startRect, int color, @NonNull SurfaceControl.Transaction transaction, int statusbarHeight, @Nullable Rect cropBounds, float cornerRadius, int displayId)79     public void ensureBackground(Rect startRect, int color,
80             @NonNull SurfaceControl.Transaction transaction, int statusbarHeight,
81             @Nullable Rect cropBounds, float cornerRadius, int displayId) {
82         if (mBackgroundSurface != null) {
83             return;
84         }
85 
86         mBackgroundIsDark = ColorUtils.calculateLuminance(color) < 0.5f;
87 
88         final float[] colorComponents = new float[] { Color.red(color) / 255.f,
89                 Color.green(color) / 255.f, Color.blue(color) / 255.f };
90 
91         final SurfaceControl.Builder colorLayerBuilder = new SurfaceControl.Builder()
92                 .setName("back-animation-background")
93                 .setCallsite("BackAnimationBackground")
94                 .setColorLayer();
95 
96         if (enableMultidisplayTrackpadBackGesture()) {
97             mRootTaskDisplayAreaOrganizer.attachToDisplayArea(displayId, colorLayerBuilder);
98         } else {
99             mRootTaskDisplayAreaOrganizer.attachToDisplayArea(DEFAULT_DISPLAY, colorLayerBuilder);
100         }
101         mBackgroundSurface = colorLayerBuilder.build();
102         transaction.setColor(mBackgroundSurface, colorComponents)
103                 .setLayer(mBackgroundSurface, BACKGROUND_LAYER)
104                 .show(mBackgroundSurface);
105         if (cropBounds != null && !cropBounds.isEmpty()) {
106             transaction.setCrop(mBackgroundSurface, cropBounds)
107                     .setCornerRadius(mBackgroundSurface, cornerRadius);
108         }
109         mStartBounds = startRect;
110         mIsRequestingStatusBarAppearance = false;
111         mStatusbarHeight = statusbarHeight;
112     }
113 
114     /**
115      * Remove the back animation background.
116      *
117      * @param transaction The animation transaction.
118      */
119     public void removeBackground(@NonNull SurfaceControl.Transaction transaction) {
120         if (mBackgroundSurface == null) {
121             return;
122         }
123 
124         if (mBackgroundSurface.isValid()) {
125             transaction.remove(mBackgroundSurface);
126         }
127         mBackgroundSurface = null;
128         mIsRequestingStatusBarAppearance = false;
129     }
130 
131     /**
132      * Attach a {@link StatusBarCustomizer} instance to allow status bar animate with back progress.
133      *
134      * @param customizer The {@link StatusBarCustomizer} to be used.
135      */
136     void setStatusBarCustomizer(StatusBarCustomizer customizer) {
137         mCustomizer = customizer;
138     }
139 
140     /**
141      * Update back animation background with for the progress.
142      *
143      * @param top The top coordinate of the closing target
144      */
145     public void customizeStatusBarAppearance(int top) {
146         if (mCustomizer == null || mStartBounds.isEmpty()) {
147             return;
148         }
149 
150         final boolean shouldCustomizeSystemBar = top > mStatusbarHeight / 2;
151         if (shouldCustomizeSystemBar == mIsRequestingStatusBarAppearance) {
152             return;
153         }
154 
155         mIsRequestingStatusBarAppearance = shouldCustomizeSystemBar;
156         if (mIsRequestingStatusBarAppearance) {
157             final AppearanceRegion region = new AppearanceRegion(!mBackgroundIsDark
158                     ? APPEARANCE_LIGHT_STATUS_BARS : NO_APPEARANCE,
159                     mStartBounds);
160             mCustomizer.customizeStatusBarAppearance(region);
161         } else {
162             resetStatusBarCustomization();
163         }
164     }
165 
166     /**
167      * Resets the statusbar customization
168      */
resetStatusBarCustomization()169     public void resetStatusBarCustomization() {
170         mCustomizer.customizeStatusBarAppearance(null);
171     }
172 }
173