blob: 1532c4f977e0556d4e27358b2456b7d4d62fb7a2 [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 Jaggi956ca412019-01-07 14:49:14 +010019import static android.view.WindowInsetsController.APPEARANCE_LIGHT_SIDE_BARS;
20import static android.view.WindowInsetsController.APPEARANCE_LIGHT_TOP_BAR;
21
Gus Prevasab336792018-11-14 13:52:20 -050022import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
23import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
24
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020025import android.content.Context;
26import android.graphics.Color;
Jorim Jaggi956ca412019-01-07 14:49:14 +010027import android.view.InsetsFlags;
28import android.view.ViewDebug;
29import android.view.WindowInsetsController.Appearance;
Jorim Jaggi40db0292016-06-27 17:58:03 -070030
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020031import com.android.internal.colorextraction.ColorExtractor.GradientColors;
Jorim Jaggi956ca412019-01-07 14:49:14 +010032import com.android.internal.view.AppearanceRegion;
Adrian Roos1bf60772017-02-03 15:47:43 -080033import com.android.systemui.Dumpable;
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020034import com.android.systemui.R;
Beverly1be62f42018-12-19 17:17:48 -050035import com.android.systemui.plugins.DarkIconDispatcher;
Jorim Jaggi40db0292016-06-27 17:58:03 -070036import com.android.systemui.statusbar.policy.BatteryController;
37
Adrian Roos1bf60772017-02-03 15:47:43 -080038import java.io.FileDescriptor;
39import java.io.PrintWriter;
40
Jason Monk196d6392018-12-20 13:25:34 -050041import javax.inject.Inject;
42import javax.inject.Singleton;
43
Jorim Jaggi40db0292016-06-27 17:58:03 -070044/**
45 * Controls how light status bar flag applies to the icons.
46 */
Jason Monk196d6392018-12-20 13:25:34 -050047@Singleton
Adrian Roos1bf60772017-02-03 15:47:43 -080048public class LightBarController implements BatteryController.BatteryStateChangeCallback, Dumpable {
Jorim Jaggi40db0292016-06-27 17:58:03 -070049
50 private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f;
51
Beverly1be62f42018-12-19 17:17:48 -050052 private final SysuiDarkIconDispatcher mStatusBarIconController;
Jorim Jaggi40db0292016-06-27 17:58:03 -070053 private final BatteryController mBatteryController;
Gilad Brettercb51b8b2018-03-22 17:04:51 +020054 private BiometricUnlockController mBiometricUnlockController;
Jorim Jaggi40db0292016-06-27 17:58:03 -070055
Jason Monk49fa0162017-01-11 09:21:56 -050056 private LightBarTransitionsController mNavigationBarController;
Jorim Jaggi956ca412019-01-07 14:49:14 +010057 private @Appearance int mAppearance;
58 private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
59 private int mStatusBarMode;
60 private int mNavigationBarMode;
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020061 private final Color mDarkModeColor;
Selim Cinekfb6ee6d2016-12-29 16:49:26 +010062
63 /**
64 * Whether the navigation bar should be light factoring in already how much alpha the scrim has
65 */
Jorim Jaggi40db0292016-06-27 17:58:03 -070066 private boolean mNavigationLight;
Selim Cinekfb6ee6d2016-12-29 16:49:26 +010067
68 /**
69 * Whether the flags indicate that a light status bar is requested. This doesn't factor in the
70 * scrim alpha yet.
71 */
72 private boolean mHasLightNavigationBar;
Yohei Yukawa795f0102018-04-13 14:55:30 -070073
74 /**
75 * {@code true} if {@link #mHasLightNavigationBar} should be ignored and forcefully make
76 * {@link #mNavigationLight} {@code false}.
77 */
78 private boolean mForceDarkForScrim;
Jorim Jaggi40db0292016-06-27 17:58:03 -070079
Jason Monk73112d32017-09-06 16:53:53 -040080 private boolean mQsCustomizing;
Jorim Jaggi40db0292016-06-27 17:58:03 -070081
Tarandeep Singhe439dec2019-04-22 12:28:43 -070082 private boolean mDirectReplying;
83 private boolean mNavbarColorManagedByIme;
84
Jason Monk196d6392018-12-20 13:25:34 -050085 @Inject
Jason Monke8e471d2018-12-21 15:56:48 -050086 public LightBarController(Context ctx, DarkIconDispatcher darkIconDispatcher,
87 BatteryController batteryController) {
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020088 mDarkModeColor = Color.valueOf(ctx.getColor(R.color.dark_mode_icon_color_single_tone));
Beverly1be62f42018-12-19 17:17:48 -050089 mStatusBarIconController = (SysuiDarkIconDispatcher) darkIconDispatcher;
Jason Monke8e471d2018-12-21 15:56:48 -050090 mBatteryController = batteryController;
Jason Monk9c7844c2017-01-18 15:21:53 -050091 mBatteryController.addCallback(this);
Jorim Jaggi40db0292016-06-27 17:58:03 -070092 }
93
Jason Monk49fa0162017-01-11 09:21:56 -050094 public void setNavigationBar(LightBarTransitionsController navigationBar) {
95 mNavigationBarController = navigationBar;
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020096 updateNavigation();
Jason Monk49fa0162017-01-11 09:21:56 -050097 }
98
Gilad Brettercb51b8b2018-03-22 17:04:51 +020099 public void setBiometricUnlockController(
100 BiometricUnlockController biometricUnlockController) {
101 mBiometricUnlockController = biometricUnlockController;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700102 }
103
Jorim Jaggi956ca412019-01-07 14:49:14 +0100104 void onStatusBarAppearanceChanged(AppearanceRegion[] appearanceRegions, boolean sbModeChanged,
Tarandeep Singhe439dec2019-04-22 12:28:43 -0700105 int statusBarMode, boolean navbarColorManagedByIme) {
Jorim Jaggi956ca412019-01-07 14:49:14 +0100106 final int numStacks = appearanceRegions.length;
107 boolean stackAppearancesChanged = mAppearanceRegions.length != numStacks;
108 for (int i = 0; i < numStacks && !stackAppearancesChanged; i++) {
109 stackAppearancesChanged |= !appearanceRegions[i].equals(mAppearanceRegions[i]);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700110 }
Jorim Jaggi956ca412019-01-07 14:49:14 +0100111 if (stackAppearancesChanged || sbModeChanged) {
112 mAppearanceRegions = appearanceRegions;
113 onStatusBarModeChanged(statusBarMode);
114 }
Tarandeep Singhe439dec2019-04-22 12:28:43 -0700115 mNavbarColorManagedByIme = navbarColorManagedByIme;
Jason Monk49fa0162017-01-11 09:21:56 -0500116 }
117
Jorim Jaggi956ca412019-01-07 14:49:14 +0100118 void onStatusBarModeChanged(int newBarMode) {
119 mStatusBarMode = newBarMode;
120 updateStatus();
121 }
122
123 void onNavigationBarAppearanceChanged(@Appearance int appearance, boolean nbModeChanged,
Tarandeep Singhe439dec2019-04-22 12:28:43 -0700124 int navigationBarMode, boolean navbarColorManagedByIme) {
Jorim Jaggi956ca412019-01-07 14:49:14 +0100125 int diff = appearance ^ mAppearance;
126 if ((diff & APPEARANCE_LIGHT_SIDE_BARS) != 0 || nbModeChanged) {
127 final boolean last = mNavigationLight;
128 mHasLightNavigationBar = isLight(appearance, navigationBarMode,
129 APPEARANCE_LIGHT_SIDE_BARS);
Tarandeep Singhe439dec2019-04-22 12:28:43 -0700130 mNavigationLight = mHasLightNavigationBar
131 && (mDirectReplying && mNavbarColorManagedByIme || !mForceDarkForScrim)
132 && !mQsCustomizing;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700133 if (mNavigationLight != last) {
134 updateNavigation();
135 }
136 }
Jorim Jaggi956ca412019-01-07 14:49:14 +0100137 mAppearance = appearance;
138 mNavigationBarMode = navigationBarMode;
Tarandeep Singhe439dec2019-04-22 12:28:43 -0700139 mNavbarColorManagedByIme = navbarColorManagedByIme;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700140 }
141
Jorim Jaggi956ca412019-01-07 14:49:14 +0100142 void onNavigationBarModeChanged(int newBarMode) {
143 mHasLightNavigationBar = isLight(mAppearance, newBarMode, APPEARANCE_LIGHT_SIDE_BARS);
144 }
145
Jorim Jaggi40db0292016-06-27 17:58:03 -0700146 private void reevaluate() {
Jorim Jaggi956ca412019-01-07 14:49:14 +0100147 onStatusBarAppearanceChanged(mAppearanceRegions, true /* sbModeChange */, mStatusBarMode,
148 mNavbarColorManagedByIme);
149 onNavigationBarAppearanceChanged(mAppearance, true /* nbModeChanged */,
150 mNavigationBarMode, mNavbarColorManagedByIme);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700151 }
152
Jason Monk73112d32017-09-06 16:53:53 -0400153 public void setQsCustomizing(boolean customizing) {
154 if (mQsCustomizing == customizing) return;
155 mQsCustomizing = customizing;
156 reevaluate();
157 }
158
Tarandeep Singhe439dec2019-04-22 12:28:43 -0700159 /**
160 * Sets whether the direct-reply is in use or not.
161 * @param directReplying {@code true} when the direct-reply is in-use.
162 */
163 public void setDirectReplying(boolean directReplying) {
164 if (mDirectReplying == directReplying) return;
165 mDirectReplying = directReplying;
166 reevaluate();
167 }
168
Yohei Yukawa795f0102018-04-13 14:55:30 -0700169 public void setScrimState(ScrimState scrimState, float scrimBehindAlpha,
170 GradientColors scrimInFrontColor) {
171 boolean forceDarkForScrimLast = mForceDarkForScrim;
172 // For BOUNCER/BOUNCER_SCRIMMED cases, we assume that alpha is always below threshold.
173 // This enables IMEs to control the navigation bar color.
174 // For other cases, scrim should be able to veto the light navigation bar.
175 mForceDarkForScrim = scrimState != ScrimState.BOUNCER
176 && scrimState != ScrimState.BOUNCER_SCRIMMED
177 && scrimBehindAlpha >= NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD
178 && !scrimInFrontColor.supportsDarkText();
179 if (mHasLightNavigationBar && (mForceDarkForScrim != forceDarkForScrimLast)) {
Jorim Jaggiff46d4c2017-07-17 16:46:00 +0200180 reevaluate();
181 }
182 }
183
Jorim Jaggi956ca412019-01-07 14:49:14 +0100184 private static boolean isLight(int appearance, int barMode, int flag) {
185 final boolean isTransparentBar = (barMode == MODE_TRANSPARENT
Jorim Jaggi40db0292016-06-27 17:58:03 -0700186 || barMode == MODE_LIGHTS_OUT_TRANSPARENT);
Jorim Jaggi956ca412019-01-07 14:49:14 +0100187 final boolean light = (appearance & flag) != 0;
Makoto Onukie4c508c2017-11-06 13:01:29 -0800188 return isTransparentBar && light;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700189 }
190
191 private boolean animateChange() {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200192 if (mBiometricUnlockController == null) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700193 return false;
194 }
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200195 int unlockMode = mBiometricUnlockController.getMode();
196 return unlockMode != BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
197 && unlockMode != BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700198 }
199
Jorim Jaggi956ca412019-01-07 14:49:14 +0100200 private void updateStatus() {
201 final int numStacks = mAppearanceRegions.length;
202 int numLightStacks = 0;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700203
Jorim Jaggi956ca412019-01-07 14:49:14 +0100204 // We can only have maximum one light stack.
205 int indexLightStack = -1;
206
207 for (int i = 0; i < numStacks; i++) {
208 if (isLight(mAppearanceRegions[i].getAppearance(), mStatusBarMode,
209 APPEARANCE_LIGHT_TOP_BAR)) {
210 numLightStacks++;
211 indexLightStack = i;
212 }
213 }
214
215 // If all stacks are light, all icons get dark.
216 if (numLightStacks == numStacks) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700217 mStatusBarIconController.setIconsDarkArea(null);
218 mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
219
220 }
221
Jorim Jaggi956ca412019-01-07 14:49:14 +0100222 // If no one is light, all icons become white.
223 else if (numLightStacks == 0) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700224 mStatusBarIconController.getTransitionsController().setIconsDark(
225 false, animateChange());
226 }
227
228 // Not the same for every stack, magic!
229 else {
Jorim Jaggi956ca412019-01-07 14:49:14 +0100230 mStatusBarIconController.setIconsDarkArea(
231 mAppearanceRegions[indexLightStack].getBounds());
Jorim Jaggi40db0292016-06-27 17:58:03 -0700232 mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
233 }
234 }
235
236 private void updateNavigation() {
Jason Monk49fa0162017-01-11 09:21:56 -0500237 if (mNavigationBarController != null) {
Jorim Jaggi956ca412019-01-07 14:49:14 +0100238 mNavigationBarController.setIconsDark(mNavigationLight, animateChange());
Jorim Jaggi40db0292016-06-27 17:58:03 -0700239 }
240 }
241
242 @Override
Jorim Jaggi40db0292016-06-27 17:58:03 -0700243 public void onPowerSaveChanged(boolean isPowerSave) {
244 reevaluate();
245 }
Adrian Roos1bf60772017-02-03 15:47:43 -0800246
247 @Override
248 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
249 pw.println("LightBarController: ");
Tiger Huang0dbd5372019-10-26 00:24:22 +0800250 pw.print(" mAppearance="); pw.println(ViewDebug.flagsToString(
Jorim Jaggi956ca412019-01-07 14:49:14 +0100251 InsetsFlags.class, "appearance", mAppearance));
252 final int numStacks = mAppearanceRegions.length;
253 for (int i = 0; i < numStacks; i++) {
254 final boolean isLight = isLight(mAppearanceRegions[i].getAppearance(), mStatusBarMode,
255 APPEARANCE_LIGHT_TOP_BAR);
256 pw.print(" stack #"); pw.print(i); pw.print(": ");
257 pw.print(mAppearanceRegions[i].toString()); pw.print(" isLight="); pw.println(isLight);
258 }
Adrian Roos1bf60772017-02-03 15:47:43 -0800259
260 pw.print(" mNavigationLight="); pw.print(mNavigationLight);
261 pw.print(" mHasLightNavigationBar="); pw.println(mHasLightNavigationBar);
262
Jorim Jaggi956ca412019-01-07 14:49:14 +0100263 pw.print(" mStatusBarMode="); pw.print(mStatusBarMode);
264 pw.print(" mNavigationBarMode="); pw.println(mNavigationBarMode);
Adrian Roos1bf60772017-02-03 15:47:43 -0800265
Yohei Yukawa795f0102018-04-13 14:55:30 -0700266 pw.print(" mForceDarkForScrim="); pw.print(mForceDarkForScrim);
Tarandeep Singhe439dec2019-04-22 12:28:43 -0700267 pw.print(" mQsCustomizing="); pw.print(mQsCustomizing);
268 pw.print(" mDirectReplying="); pw.println(mDirectReplying);
269 pw.print(" mNavbarColorManagedByIme="); pw.println(mNavbarColorManagedByIme);
Yohei Yukawa795f0102018-04-13 14:55:30 -0700270
Adrian Roos1bf60772017-02-03 15:47:43 -0800271 pw.println();
Evan Laird94dcd332018-03-01 14:07:15 -0500272
273 LightBarTransitionsController transitionsController =
274 mStatusBarIconController.getTransitionsController();
275 if (transitionsController != null) {
276 pw.println(" StatusBarTransitionsController:");
277 transitionsController.dump(fd, pw, args);
278 pw.println();
279 }
280
Mark Urbanus77e9ad12017-09-27 15:43:41 -0700281 if (mNavigationBarController != null) {
282 pw.println(" NavigationBarTransitionsController:");
283 mNavigationBarController.dump(fd, pw, args);
284 pw.println();
285 }
Adrian Roos1bf60772017-02-03 15:47:43 -0800286 }
Jorim Jaggi40db0292016-06-27 17:58:03 -0700287}