blob: 917a56fbc99d32e3172fbaba7e32f7e4ff96b74c [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;
69 private boolean mScrimAlphaBelowThreshold;
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020070 private boolean mInvertLightNavBarWithScrim;
Jorim Jaggi40db0292016-06-27 17:58:03 -070071 private float mScrimAlpha;
72
73 private final Rect mLastFullscreenBounds = new Rect();
74 private final Rect mLastDockedBounds = new Rect();
75
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020076 public LightBarController(Context ctx) {
77 mDarkModeColor = Color.valueOf(ctx.getColor(R.color.dark_mode_icon_color_single_tone));
Jason Monkaa573e92017-01-27 17:00:29 -050078 mStatusBarIconController = Dependency.get(DarkIconDispatcher.class);
Jason Monk9c7844c2017-01-18 15:21:53 -050079 mBatteryController = Dependency.get(BatteryController.class);
80 mBatteryController.addCallback(this);
Jorim Jaggi40db0292016-06-27 17:58:03 -070081 }
82
Jason Monk49fa0162017-01-11 09:21:56 -050083 public void setNavigationBar(LightBarTransitionsController navigationBar) {
84 mNavigationBarController = navigationBar;
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020085 updateNavigation();
Jason Monk49fa0162017-01-11 09:21:56 -050086 }
87
Jorim Jaggi40db0292016-06-27 17:58:03 -070088 public void setFingerprintUnlockController(
89 FingerprintUnlockController fingerprintUnlockController) {
90 mFingerprintUnlockController = fingerprintUnlockController;
91 }
92
Jason Monk49fa0162017-01-11 09:21:56 -050093 public void onSystemUiVisibilityChanged(int fullscreenStackVis, int dockedStackVis,
Jorim Jaggi40db0292016-06-27 17:58:03 -070094 int mask, Rect fullscreenStackBounds, Rect dockedStackBounds, boolean sbModeChanged,
Jason Monk49fa0162017-01-11 09:21:56 -050095 int statusBarMode) {
Jorim Jaggi40db0292016-06-27 17:58:03 -070096 int oldFullscreen = mFullscreenStackVisibility;
97 int newFullscreen = (oldFullscreen & ~mask) | (fullscreenStackVis & mask);
98 int diffFullscreen = newFullscreen ^ oldFullscreen;
99 int oldDocked = mDockedStackVisibility;
100 int newDocked = (oldDocked & ~mask) | (dockedStackVis & mask);
101 int diffDocked = newDocked ^ oldDocked;
102 if ((diffFullscreen & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
103 || (diffDocked & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0
104 || sbModeChanged
105 || !mLastFullscreenBounds.equals(fullscreenStackBounds)
106 || !mLastDockedBounds.equals(dockedStackBounds)) {
107
108 mFullscreenLight = isLight(newFullscreen, statusBarMode,
109 View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
110 mDockedLight = isLight(newDocked, statusBarMode, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
111 updateStatus(fullscreenStackBounds, dockedStackBounds);
112 }
113
Jason Monk49fa0162017-01-11 09:21:56 -0500114 mFullscreenStackVisibility = newFullscreen;
115 mDockedStackVisibility = newDocked;
116 mLastStatusBarMode = statusBarMode;
117 mLastFullscreenBounds.set(fullscreenStackBounds);
118 mLastDockedBounds.set(dockedStackBounds);
119 }
120
121 public void onNavigationVisibilityChanged(int vis, int mask, boolean nbModeChanged,
122 int navigationBarMode) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700123 int oldVis = mSystemUiVisibility;
124 int newVis = (oldVis & ~mask) | (vis & mask);
125 int diffVis = newVis ^ oldVis;
126 if ((diffVis & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0
127 || nbModeChanged) {
128 boolean last = mNavigationLight;
Selim Cinekfb6ee6d2016-12-29 16:49:26 +0100129 mHasLightNavigationBar = isLight(vis, navigationBarMode,
130 View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
Jorim Jaggiff46d4c2017-07-17 16:46:00 +0200131 mNavigationLight = mHasLightNavigationBar
132 && (mScrimAlphaBelowThreshold || !mInvertLightNavBarWithScrim);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700133 if (mNavigationLight != last) {
134 updateNavigation();
135 }
136 }
Jorim Jaggi40db0292016-06-27 17:58:03 -0700137 mSystemUiVisibility = newVis;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700138 mLastNavigationBarMode = navigationBarMode;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700139 }
140
141 private void reevaluate() {
Jason Monk49fa0162017-01-11 09:21:56 -0500142 onSystemUiVisibilityChanged(mFullscreenStackVisibility,
Jorim Jaggi40db0292016-06-27 17:58:03 -0700143 mDockedStackVisibility, 0 /* mask */, mLastFullscreenBounds, mLastDockedBounds,
Jason Monk49fa0162017-01-11 09:21:56 -0500144 true /* sbModeChange*/, mLastStatusBarMode);
145 onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */, true /* nbModeChanged */,
Jorim Jaggi40db0292016-06-27 17:58:03 -0700146 mLastNavigationBarMode);
147 }
148
149 public void setScrimAlpha(float alpha) {
150 mScrimAlpha = alpha;
Selim Cinekfb6ee6d2016-12-29 16:49:26 +0100151 boolean belowThresholdBefore = mScrimAlphaBelowThreshold;
152 mScrimAlphaBelowThreshold = mScrimAlpha < NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD;
153 if (mHasLightNavigationBar && belowThresholdBefore != mScrimAlphaBelowThreshold) {
154 reevaluate();
155 }
Jorim Jaggi40db0292016-06-27 17:58:03 -0700156 }
157
Jorim Jaggiff46d4c2017-07-17 16:46:00 +0200158 public void setScrimColor(GradientColors colors) {
159 boolean invertLightNavBarWithScrimBefore = mInvertLightNavBarWithScrim;
160 mInvertLightNavBarWithScrim = !colors.supportsDarkText();
161 if (mHasLightNavigationBar
162 && invertLightNavBarWithScrimBefore != mInvertLightNavBarWithScrim) {
163 reevaluate();
164 }
165 }
166
Jorim Jaggi40db0292016-06-27 17:58:03 -0700167 private boolean isLight(int vis, int barMode, int flag) {
168 boolean isTransparentBar = (barMode == MODE_TRANSPARENT
169 || barMode == MODE_LIGHTS_OUT_TRANSPARENT);
170 boolean allowLight = isTransparentBar && !mBatteryController.isPowerSave();
171 boolean light = (vis & flag) != 0;
172 return allowLight && light;
173 }
174
175 private boolean animateChange() {
176 if (mFingerprintUnlockController == null) {
177 return false;
178 }
179 int unlockMode = mFingerprintUnlockController.getMode();
180 return unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
181 && unlockMode != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
182 }
183
184 private void updateStatus(Rect fullscreenStackBounds, Rect dockedStackBounds) {
185 boolean hasDockedStack = !dockedStackBounds.isEmpty();
186
187 // If both are light or fullscreen is light and there is no docked stack, all icons get
188 // dark.
189 if ((mFullscreenLight && mDockedLight) || (mFullscreenLight && !hasDockedStack)) {
190 mStatusBarIconController.setIconsDarkArea(null);
191 mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
192
193 }
194
195 // If no one is light or the fullscreen is not light and there is no docked stack,
196 // all icons become white.
197 else if ((!mFullscreenLight && !mDockedLight) || (!mFullscreenLight && !hasDockedStack)) {
198 mStatusBarIconController.getTransitionsController().setIconsDark(
199 false, animateChange());
200 }
201
202 // Not the same for every stack, magic!
203 else {
204 Rect bounds = mFullscreenLight ? fullscreenStackBounds : dockedStackBounds;
205 if (bounds.isEmpty()) {
206 mStatusBarIconController.setIconsDarkArea(null);
207 } else {
208 mStatusBarIconController.setIconsDarkArea(bounds);
209 }
210 mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
211 }
212 }
213
214 private void updateNavigation() {
Jason Monk49fa0162017-01-11 09:21:56 -0500215 if (mNavigationBarController != null) {
216 mNavigationBarController.setIconsDark(
Jorim Jaggi40db0292016-06-27 17:58:03 -0700217 mNavigationLight, animateChange());
218 }
219 }
220
221 @Override
222 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
223
224 }
225
226 @Override
227 public void onPowerSaveChanged(boolean isPowerSave) {
228 reevaluate();
229 }
Adrian Roos1bf60772017-02-03 15:47:43 -0800230
231 @Override
232 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
233 pw.println("LightBarController: ");
234 pw.print(" mSystemUiVisibility=0x"); pw.print(
235 Integer.toHexString(mSystemUiVisibility));
236 pw.print(" mFullscreenStackVisibility=0x"); pw.print(
237 Integer.toHexString(mFullscreenStackVisibility));
238 pw.print(" mDockedStackVisibility=0x"); pw.println(
239 Integer.toHexString(mDockedStackVisibility));
240
241 pw.print(" mFullscreenLight="); pw.print(mFullscreenLight);
242 pw.print(" mDockedLight="); pw.println(mDockedLight);
243
244 pw.print(" mLastFullscreenBounds="); pw.print(mLastFullscreenBounds);
245 pw.print(" mLastDockedBounds="); pw.println(mLastDockedBounds);
246
247 pw.print(" mNavigationLight="); pw.print(mNavigationLight);
248 pw.print(" mHasLightNavigationBar="); pw.println(mHasLightNavigationBar);
249
250 pw.print(" mLastStatusBarMode="); pw.print(mLastStatusBarMode);
251 pw.print(" mLastNavigationBarMode="); pw.println(mLastNavigationBarMode);
252
253 pw.print(" mScrimAlpha="); pw.print(mScrimAlpha);
254 pw.print(" mScrimAlphaBelowThreshold="); pw.println(mScrimAlphaBelowThreshold);
255 pw.println();
256 pw.println(" StatusBarTransitionsController:");
257 mStatusBarIconController.getTransitionsController().dump(fd, pw, args);
258 pw.println();
259 pw.println(" NavigationBarTransitionsController:");
260 mNavigationBarController.dump(fd, pw, args);
261 pw.println();
262 }
Jorim Jaggi40db0292016-06-27 17:58:03 -0700263}