blob: 8b8cbfef990da37e95baf174cd468a9180e11033 [file] [log] [blame]
Jorim Jaggi40db0292016-06-27 17:58:03 -07001/*
2 * Copyright (C) 2016 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
17package com.android.systemui.statusbar.phone;
18
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020019import android.app.WallpaperColors;
20import android.content.Context;
21import android.graphics.Color;
Jorim Jaggi40db0292016-06-27 17:58:03 -070022import android.graphics.Rect;
23import android.view.View;
24
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020025import com.android.internal.colorextraction.ColorExtractor.GradientColors;
Jason Monk9c7844c2017-01-18 15:21:53 -050026import com.android.systemui.Dependency;
Adrian Roos1bf60772017-02-03 15:47:43 -080027import com.android.systemui.Dumpable;
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020028import com.android.systemui.R;
Jorim Jaggi40db0292016-06-27 17:58:03 -070029import com.android.systemui.statusbar.policy.BatteryController;
Jason Monkaa573e92017-01-27 17:00:29 -050030import com.android.systemui.statusbar.policy.DarkIconDispatcher;
Jorim Jaggi40db0292016-06-27 17:58:03 -070031
Adrian Roos1bf60772017-02-03 15:47:43 -080032import java.io.FileDescriptor;
33import java.io.PrintWriter;
34
Jorim Jaggi40db0292016-06-27 17:58:03 -070035import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
36import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
37
38/**
39 * Controls how light status bar flag applies to the icons.
40 */
Adrian Roos1bf60772017-02-03 15:47:43 -080041public class LightBarController implements BatteryController.BatteryStateChangeCallback, Dumpable {
Jorim Jaggi40db0292016-06-27 17:58:03 -070042
43 private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f;
44
Jason Monkaa573e92017-01-27 17:00:29 -050045 private final DarkIconDispatcher mStatusBarIconController;
Jorim Jaggi40db0292016-06-27 17:58:03 -070046 private final BatteryController mBatteryController;
47 private FingerprintUnlockController mFingerprintUnlockController;
Jorim Jaggi40db0292016-06-27 17:58:03 -070048
Jason Monk49fa0162017-01-11 09:21:56 -050049 private LightBarTransitionsController mNavigationBarController;
Jorim Jaggi40db0292016-06-27 17:58:03 -070050 private int mSystemUiVisibility;
51 private int mFullscreenStackVisibility;
52 private int mDockedStackVisibility;
53 private boolean mFullscreenLight;
54 private boolean mDockedLight;
55 private int mLastStatusBarMode;
56 private int mLastNavigationBarMode;
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020057 private final Color mDarkModeColor;
Selim Cinekfb6ee6d2016-12-29 16:49:26 +010058
59 /**
60 * Whether the navigation bar should be light factoring in already how much alpha the scrim has
61 */
Jorim Jaggi40db0292016-06-27 17:58:03 -070062 private boolean mNavigationLight;
Selim Cinekfb6ee6d2016-12-29 16:49:26 +010063
64 /**
65 * Whether the flags indicate that a light status bar is requested. This doesn't factor in the
66 * scrim alpha yet.
67 */
68 private boolean mHasLightNavigationBar;
Yohei Yukawa795f0102018-04-13 14:55:30 -070069
70 /**
71 * {@code true} if {@link #mHasLightNavigationBar} should be ignored and forcefully make
72 * {@link #mNavigationLight} {@code false}.
73 */
74 private boolean mForceDarkForScrim;
Jorim Jaggi40db0292016-06-27 17:58:03 -070075
76 private final Rect mLastFullscreenBounds = new Rect();
77 private final Rect mLastDockedBounds = new Rect();
Jason Monk73112d32017-09-06 16:53:53 -040078 private boolean mQsCustomizing;
Jorim Jaggi40db0292016-06-27 17:58:03 -070079
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020080 public LightBarController(Context ctx) {
81 mDarkModeColor = Color.valueOf(ctx.getColor(R.color.dark_mode_icon_color_single_tone));
Jason Monkaa573e92017-01-27 17:00:29 -050082 mStatusBarIconController = Dependency.get(DarkIconDispatcher.class);
Jason Monk9c7844c2017-01-18 15:21:53 -050083 mBatteryController = Dependency.get(BatteryController.class);
84 mBatteryController.addCallback(this);
Jorim Jaggi40db0292016-06-27 17:58:03 -070085 }
86
Jason Monk49fa0162017-01-11 09:21:56 -050087 public void setNavigationBar(LightBarTransitionsController navigationBar) {
88 mNavigationBarController = navigationBar;
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020089 updateNavigation();
Jason Monk49fa0162017-01-11 09:21:56 -050090 }
91
Jorim Jaggi40db0292016-06-27 17:58:03 -070092 public void setFingerprintUnlockController(
93 FingerprintUnlockController fingerprintUnlockController) {
94 mFingerprintUnlockController = fingerprintUnlockController;
95 }
96
Jason Monk49fa0162017-01-11 09:21:56 -050097 public void onSystemUiVisibilityChanged(int fullscreenStackVis, int dockedStackVis,
Jorim Jaggi40db0292016-06-27 17:58:03 -070098 int mask, Rect fullscreenStackBounds, Rect dockedStackBounds, boolean sbModeChanged,
Jason Monk49fa0162017-01-11 09:21:56 -050099 int statusBarMode) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700100 int oldFullscreen = mFullscreenStackVisibility;
101 int newFullscreen = (oldFullscreen & ~mask) | (fullscreenStackVis & mask);
102 int diffFullscreen = newFullscreen ^ oldFullscreen;
103 int oldDocked = mDockedStackVisibility;
104 int newDocked = (oldDocked & ~mask) | (dockedStackVis & mask);
105 int diffDocked = newDocked ^ oldDocked;
106 if ((diffFullscreen & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
107 || (diffDocked & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
108 || sbModeChanged
109 || !mLastFullscreenBounds.equals(fullscreenStackBounds)
110 || !mLastDockedBounds.equals(dockedStackBounds)) {
111
112 mFullscreenLight = isLight(newFullscreen, statusBarMode,
113 View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
114 mDockedLight = isLight(newDocked, statusBarMode, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
115 updateStatus(fullscreenStackBounds, dockedStackBounds);
116 }
117
Jason Monk49fa0162017-01-11 09:21:56 -0500118 mFullscreenStackVisibility = newFullscreen;
119 mDockedStackVisibility = newDocked;
120 mLastStatusBarMode = statusBarMode;
121 mLastFullscreenBounds.set(fullscreenStackBounds);
122 mLastDockedBounds.set(dockedStackBounds);
123 }
124
125 public void onNavigationVisibilityChanged(int vis, int mask, boolean nbModeChanged,
126 int navigationBarMode) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700127 int oldVis = mSystemUiVisibility;
128 int newVis = (oldVis & ~mask) | (vis & mask);
129 int diffVis = newVis ^ oldVis;
130 if ((diffVis & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0
131 || nbModeChanged) {
132 boolean last = mNavigationLight;
Selim Cinekfb6ee6d2016-12-29 16:49:26 +0100133 mHasLightNavigationBar = isLight(vis, navigationBarMode,
134 View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
Yohei Yukawa795f0102018-04-13 14:55:30 -0700135 mNavigationLight = mHasLightNavigationBar && !mForceDarkForScrim && !mQsCustomizing;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700136 if (mNavigationLight != last) {
137 updateNavigation();
138 }
139 }
Jorim Jaggi40db0292016-06-27 17:58:03 -0700140 mSystemUiVisibility = newVis;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700141 mLastNavigationBarMode = navigationBarMode;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700142 }
143
144 private void reevaluate() {
Jason Monk49fa0162017-01-11 09:21:56 -0500145 onSystemUiVisibilityChanged(mFullscreenStackVisibility,
Jorim Jaggi40db0292016-06-27 17:58:03 -0700146 mDockedStackVisibility, 0 /* mask */, mLastFullscreenBounds, mLastDockedBounds,
Jason Monk49fa0162017-01-11 09:21:56 -0500147 true /* sbModeChange*/, mLastStatusBarMode);
148 onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */, true /* nbModeChanged */,
Jorim Jaggi40db0292016-06-27 17:58:03 -0700149 mLastNavigationBarMode);
150 }
151
Jason Monk73112d32017-09-06 16:53:53 -0400152 public void setQsCustomizing(boolean customizing) {
153 if (mQsCustomizing == customizing) return;
154 mQsCustomizing = customizing;
155 reevaluate();
156 }
157
Yohei Yukawa795f0102018-04-13 14:55:30 -0700158 public void setScrimState(ScrimState scrimState, float scrimBehindAlpha,
159 GradientColors scrimInFrontColor) {
160 boolean forceDarkForScrimLast = mForceDarkForScrim;
161 // For BOUNCER/BOUNCER_SCRIMMED cases, we assume that alpha is always below threshold.
162 // This enables IMEs to control the navigation bar color.
163 // For other cases, scrim should be able to veto the light navigation bar.
164 mForceDarkForScrim = scrimState != ScrimState.BOUNCER
165 && scrimState != ScrimState.BOUNCER_SCRIMMED
166 && scrimBehindAlpha >= NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD
167 && !scrimInFrontColor.supportsDarkText();
168 if (mHasLightNavigationBar && (mForceDarkForScrim != forceDarkForScrimLast)) {
Jorim Jaggiff46d4c2017-07-17 16:46:00 +0200169 reevaluate();
170 }
171 }
172
Jorim Jaggi40db0292016-06-27 17:58:03 -0700173 private boolean isLight(int vis, int barMode, int flag) {
174 boolean isTransparentBar = (barMode == MODE_TRANSPARENT
175 || barMode == MODE_LIGHTS_OUT_TRANSPARENT);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700176 boolean light = (vis & flag) != 0;
Makoto Onukie4c508c2017-11-06 13:01:29 -0800177 return isTransparentBar && light;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700178 }
179
180 private boolean animateChange() {
181 if (mFingerprintUnlockController == null) {
182 return false;
183 }
184 int unlockMode = mFingerprintUnlockController.getMode();
185 return unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
186 && unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
187 }
188
189 private void updateStatus(Rect fullscreenStackBounds, Rect dockedStackBounds) {
190 boolean hasDockedStack = !dockedStackBounds.isEmpty();
191
192 // If both are light or fullscreen is light and there is no docked stack, all icons get
193 // dark.
194 if ((mFullscreenLight && mDockedLight) || (mFullscreenLight && !hasDockedStack)) {
195 mStatusBarIconController.setIconsDarkArea(null);
196 mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
197
198 }
199
200 // If no one is light or the fullscreen is not light and there is no docked stack,
201 // all icons become white.
202 else if ((!mFullscreenLight && !mDockedLight) || (!mFullscreenLight && !hasDockedStack)) {
203 mStatusBarIconController.getTransitionsController().setIconsDark(
204 false, animateChange());
205 }
206
207 // Not the same for every stack, magic!
208 else {
209 Rect bounds = mFullscreenLight ? fullscreenStackBounds : dockedStackBounds;
210 if (bounds.isEmpty()) {
211 mStatusBarIconController.setIconsDarkArea(null);
212 } else {
213 mStatusBarIconController.setIconsDarkArea(bounds);
214 }
215 mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
216 }
217 }
218
219 private void updateNavigation() {
Jason Monk49fa0162017-01-11 09:21:56 -0500220 if (mNavigationBarController != null) {
221 mNavigationBarController.setIconsDark(
Jorim Jaggi40db0292016-06-27 17:58:03 -0700222 mNavigationLight, animateChange());
223 }
224 }
225
226 @Override
227 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
228
229 }
230
231 @Override
232 public void onPowerSaveChanged(boolean isPowerSave) {
233 reevaluate();
234 }
Adrian Roos1bf60772017-02-03 15:47:43 -0800235
236 @Override
237 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
238 pw.println("LightBarController: ");
239 pw.print(" mSystemUiVisibility=0x"); pw.print(
240 Integer.toHexString(mSystemUiVisibility));
241 pw.print(" mFullscreenStackVisibility=0x"); pw.print(
242 Integer.toHexString(mFullscreenStackVisibility));
243 pw.print(" mDockedStackVisibility=0x"); pw.println(
244 Integer.toHexString(mDockedStackVisibility));
245
246 pw.print(" mFullscreenLight="); pw.print(mFullscreenLight);
247 pw.print(" mDockedLight="); pw.println(mDockedLight);
248
249 pw.print(" mLastFullscreenBounds="); pw.print(mLastFullscreenBounds);
250 pw.print(" mLastDockedBounds="); pw.println(mLastDockedBounds);
251
252 pw.print(" mNavigationLight="); pw.print(mNavigationLight);
253 pw.print(" mHasLightNavigationBar="); pw.println(mHasLightNavigationBar);
254
255 pw.print(" mLastStatusBarMode="); pw.print(mLastStatusBarMode);
256 pw.print(" mLastNavigationBarMode="); pw.println(mLastNavigationBarMode);
257
Yohei Yukawa795f0102018-04-13 14:55:30 -0700258 pw.print(" mForceDarkForScrim="); pw.print(mForceDarkForScrim);
259 pw.print(" mQsCustomizing="); pw.println(mQsCustomizing);
260
Adrian Roos1bf60772017-02-03 15:47:43 -0800261 pw.println();
Evan Laird94dcd332018-03-01 14:07:15 -0500262
263 LightBarTransitionsController transitionsController =
264 mStatusBarIconController.getTransitionsController();
265 if (transitionsController != null) {
266 pw.println(" StatusBarTransitionsController:");
267 transitionsController.dump(fd, pw, args);
268 pw.println();
269 }
270
Mark Urbanus77e9ad12017-09-27 15:43:41 -0700271 if (mNavigationBarController != null) {
272 pw.println(" NavigationBarTransitionsController:");
273 mNavigationBarController.dump(fd, pw, args);
274 pw.println();
275 }
Adrian Roos1bf60772017-02-03 15:47:43 -0800276 }
Jorim Jaggi40db0292016-06-27 17:58:03 -0700277}