blob: ad5aa57f12ea294fa53bfc57ea561c76e41c811e [file] [log] [blame]
Jason Monk1fd3fc32018-08-14 17:20:09 -04001/*
Beverly8fdb5332019-02-04 14:29:49 -05002 * Copyright (C) 2019 The Android Open Source Project
Jason Monk1fd3fc32018-08-14 17:20:09 -04003 *
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
Beverly8fdb5332019-02-04 14:29:49 -050014 * limitations under the License.
Jason Monk1fd3fc32018-08-14 17:20:09 -040015 */
16
17package com.android.systemui.statusbar;
18
Lucas Dupin1a8b33d2018-11-12 18:18:15 -080019import android.animation.ObjectAnimator;
20import android.animation.ValueAnimator;
Lucas Dupin1a8b33d2018-11-12 18:18:15 -080021import android.util.FloatProperty;
22import android.view.animation.Interpolator;
23
Evan Laird91d0f102018-09-18 17:39:55 -040024import com.android.internal.annotations.GuardedBy;
Lucas Dupin1a8b33d2018-11-12 18:18:15 -080025import com.android.systemui.Interpolators;
Beverly8fdb5332019-02-04 14:29:49 -050026import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
Lucas Dupin1a8b33d2018-11-12 18:18:15 -080027import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
Jason Monkaf08c152018-12-04 11:12:39 -050028import com.android.systemui.statusbar.policy.CallbackController;
Lucas Dupin1a8b33d2018-11-12 18:18:15 -080029
Evan Laird91d0f102018-09-18 17:39:55 -040030import java.util.ArrayList;
31import java.util.Comparator;
Jason Monk1fd3fc32018-08-14 17:20:09 -040032
Jason Monk27d01a622018-12-10 15:57:09 -050033import javax.inject.Inject;
34import javax.inject.Singleton;
35
Jason Monk1fd3fc32018-08-14 17:20:09 -040036/**
37 * Tracks and reports on {@link StatusBarState}.
38 */
Jason Monk27d01a622018-12-10 15:57:09 -050039@Singleton
Beverly8fdb5332019-02-04 14:29:49 -050040public class StatusBarStateControllerImpl implements SysuiStatusBarStateController,
41 CallbackController<StateListener> {
Evan Laird91d0f102018-09-18 17:39:55 -040042 private static final String TAG = "SbStateController";
Jason Monk1fd3fc32018-08-14 17:20:09 -040043
44 private static final int MAX_STATE = StatusBarState.FULLSCREEN_USER_SWITCHER;
45 private static final int MIN_STATE = StatusBarState.SHADE;
46
Beverly8fdb5332019-02-04 14:29:49 -050047 private static final Comparator<RankedListener> sComparator =
48 Comparator.comparingInt(o -> o.mRank);
49 private static final FloatProperty<StatusBarStateControllerImpl> SET_DARK_AMOUNT_PROPERTY =
50 new FloatProperty<StatusBarStateControllerImpl>("mDozeAmount") {
Lucas Dupin1a8b33d2018-11-12 18:18:15 -080051
52 @Override
Beverly8fdb5332019-02-04 14:29:49 -050053 public void setValue(StatusBarStateControllerImpl object, float value) {
Lucas Dupin1a8b33d2018-11-12 18:18:15 -080054 object.setDozeAmountInternal(value);
55 }
56
57 @Override
Beverly8fdb5332019-02-04 14:29:49 -050058 public Float get(StatusBarStateControllerImpl object) {
Lucas Dupin1a8b33d2018-11-12 18:18:15 -080059 return object.mDozeAmount;
60 }
61 };
Evan Laird91d0f102018-09-18 17:39:55 -040062
63 private final ArrayList<RankedListener> mListeners = new ArrayList<>();
Jason Monk1fd3fc32018-08-14 17:20:09 -040064 private int mState;
65 private int mLastState;
66 private boolean mLeaveOpenOnKeyguardHide;
Jason Monk297c04e2018-08-23 17:16:59 -040067 private boolean mKeyguardRequested;
Jason Monk1fd3fc32018-08-14 17:20:09 -040068
Lucas Dupin1a8b33d2018-11-12 18:18:15 -080069 /**
70 * If the device is currently dozing or not.
71 */
72 private boolean mIsDozing;
73
74 /**
75 * Current {@link #mDozeAmount} animator.
76 */
77 private ValueAnimator mDarkAnimator;
78
79 /**
80 * Current doze amount in this frame.
81 */
82 private float mDozeAmount;
83
84 /**
85 * Where the animator will stop.
86 */
87 private float mDozeAmountTarget;
88
89 /**
90 * The type of interpolator that should be used to the doze animation.
91 */
92 private Interpolator mDozeInterpolator = Interpolators.FAST_OUT_SLOW_IN;
93
Jason Monk27d01a622018-12-10 15:57:09 -050094 @Inject
Beverly8fdb5332019-02-04 14:29:49 -050095 public StatusBarStateControllerImpl() {
Jason Monk27d01a622018-12-10 15:57:09 -050096 }
97
Beverly8fdb5332019-02-04 14:29:49 -050098 @Override
Jason Monk1fd3fc32018-08-14 17:20:09 -040099 public int getState() {
100 return mState;
101 }
102
Beverly8fdb5332019-02-04 14:29:49 -0500103 @Override
Evan Laird91d0f102018-09-18 17:39:55 -0400104 public boolean setState(int state) {
Jason Monk1fd3fc32018-08-14 17:20:09 -0400105 if (state > MAX_STATE || state < MIN_STATE) {
106 throw new IllegalArgumentException("Invalid state " + state);
107 }
108 if (state == mState) {
Evan Laird91d0f102018-09-18 17:39:55 -0400109 return false;
Jason Monk1fd3fc32018-08-14 17:20:09 -0400110 }
111 synchronized (mListeners) {
Evan Laird91d0f102018-09-18 17:39:55 -0400112 for (RankedListener rl : new ArrayList<>(mListeners)) {
Beverly8fdb5332019-02-04 14:29:49 -0500113 rl.mListener.onStatePreChange(mState, state);
Jason Monk1fd3fc32018-08-14 17:20:09 -0400114 }
115 mLastState = mState;
116 mState = state;
Evan Laird91d0f102018-09-18 17:39:55 -0400117 for (RankedListener rl : new ArrayList<>(mListeners)) {
Beverly8fdb5332019-02-04 14:29:49 -0500118 rl.mListener.onStateChanged(mState);
Evan Laird91d0f102018-09-18 17:39:55 -0400119 }
120
121 for (RankedListener rl : new ArrayList<>(mListeners)) {
Beverly8fdb5332019-02-04 14:29:49 -0500122 rl.mListener.onStatePostChange();
Jason Monk1fd3fc32018-08-14 17:20:09 -0400123 }
124 }
Evan Laird91d0f102018-09-18 17:39:55 -0400125
126 return true;
Jason Monk1fd3fc32018-08-14 17:20:09 -0400127 }
128
Beverly8fdb5332019-02-04 14:29:49 -0500129 @Override
Evan Lairde84d8552018-10-15 15:08:45 -0400130 public boolean isDozing() {
131 return mIsDozing;
132 }
133
Beverly8fdb5332019-02-04 14:29:49 -0500134 @Override
Lucas Dupin1a8b33d2018-11-12 18:18:15 -0800135 public float getDozeAmount() {
136 return mDozeAmount;
137 }
138
Beverly8fdb5332019-02-04 14:29:49 -0500139 @Override
Lucas Dupin1a8b33d2018-11-12 18:18:15 -0800140 public float getInterpolatedDozeAmount() {
141 return mDozeInterpolator.getInterpolation(mDozeAmount);
142 }
143
Beverly8fdb5332019-02-04 14:29:49 -0500144 @Override
Evan Lairde84d8552018-10-15 15:08:45 -0400145 public boolean setIsDozing(boolean isDozing) {
146 if (mIsDozing == isDozing) {
147 return false;
148 }
149
150 mIsDozing = isDozing;
151
152 synchronized (mListeners) {
153 for (RankedListener rl : new ArrayList<>(mListeners)) {
Beverly8fdb5332019-02-04 14:29:49 -0500154 rl.mListener.onDozingChanged(isDozing);
Evan Lairde84d8552018-10-15 15:08:45 -0400155 }
156 }
157
158 return true;
159 }
160
Beverly8fdb5332019-02-04 14:29:49 -0500161 @Override
Lucas Dupin1a8b33d2018-11-12 18:18:15 -0800162 public void setDozeAmount(float dozeAmount, boolean animated) {
163 if (mDarkAnimator != null && mDarkAnimator.isRunning()) {
164 if (animated && mDozeAmountTarget == dozeAmount) {
165 return;
166 } else {
167 mDarkAnimator.cancel();
168 }
169 }
170
171 mDozeAmountTarget = dozeAmount;
172 if (animated) {
173 startDozeAnimation();
174 } else {
175 setDozeAmountInternal(dozeAmount);
176 }
177 }
178
179 private void startDozeAnimation() {
180 if (mDozeAmount == 0f || mDozeAmount == 1f) {
181 mDozeInterpolator = mIsDozing
182 ? Interpolators.FAST_OUT_SLOW_IN
183 : Interpolators.TOUCH_RESPONSE_REVERSE;
184 }
185 mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, mDozeAmountTarget);
186 mDarkAnimator.setInterpolator(Interpolators.LINEAR);
187 mDarkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
188 mDarkAnimator.start();
189 }
190
191 private void setDozeAmountInternal(float dozeAmount) {
192 mDozeAmount = dozeAmount;
193 float interpolatedAmount = mDozeInterpolator.getInterpolation(dozeAmount);
194 synchronized (mListeners) {
195 for (RankedListener rl : new ArrayList<>(mListeners)) {
Beverly8fdb5332019-02-04 14:29:49 -0500196 rl.mListener.onDozeAmountChanged(mDozeAmount, interpolatedAmount);
Lucas Dupin1a8b33d2018-11-12 18:18:15 -0800197 }
198 }
199 }
200
Beverly8fdb5332019-02-04 14:29:49 -0500201 @Override
Jason Monk1fd3fc32018-08-14 17:20:09 -0400202 public boolean goingToFullShade() {
203 return mState == StatusBarState.SHADE && mLeaveOpenOnKeyguardHide;
204 }
205
Beverly8fdb5332019-02-04 14:29:49 -0500206 @Override
Jason Monk1fd3fc32018-08-14 17:20:09 -0400207 public void setLeaveOpenOnKeyguardHide(boolean leaveOpen) {
208 mLeaveOpenOnKeyguardHide = leaveOpen;
209 }
210
Beverly8fdb5332019-02-04 14:29:49 -0500211 @Override
Jason Monk1fd3fc32018-08-14 17:20:09 -0400212 public boolean leaveOpenOnKeyguardHide() {
213 return mLeaveOpenOnKeyguardHide;
214 }
215
Beverly8fdb5332019-02-04 14:29:49 -0500216 @Override
Jason Monk1fd3fc32018-08-14 17:20:09 -0400217 public boolean fromShadeLocked() {
218 return mLastState == StatusBarState.SHADE_LOCKED;
219 }
220
Beverly8fdb5332019-02-04 14:29:49 -0500221 @Override
Jason Monkaf08c152018-12-04 11:12:39 -0500222 public void addCallback(StateListener listener) {
Jason Monk1fd3fc32018-08-14 17:20:09 -0400223 synchronized (mListeners) {
Evan Laird91d0f102018-09-18 17:39:55 -0400224 addListenerInternalLocked(listener, Integer.MAX_VALUE);
Jason Monk1fd3fc32018-08-14 17:20:09 -0400225 }
226 }
227
Evan Laird91d0f102018-09-18 17:39:55 -0400228 /**
229 * Add a listener and a rank based on the priority of this message
230 * @param listener the listener
231 * @param rank the order in which you'd like to be called. Ranked listeners will be
232 * notified before unranked, and we will sort ranked listeners from low to high
233 *
234 * @deprecated This method exists only to solve latent inter-dependencies from refactoring
235 * StatusBarState out of StatusBar.java. Any new listeners should be built not to need ranking
236 * (i.e., they are non-dependent on the order of operations of StatusBarState listeners).
237 */
Beverly8fdb5332019-02-04 14:29:49 -0500238 @Deprecated
239 @Override
Jason Monkaf08c152018-12-04 11:12:39 -0500240 public void addCallback(StateListener listener, @SbStateListenerRank int rank) {
Evan Laird91d0f102018-09-18 17:39:55 -0400241 synchronized (mListeners) {
242 addListenerInternalLocked(listener, rank);
243 }
244 }
245
246 @GuardedBy("mListeners")
247 private void addListenerInternalLocked(StateListener listener, int rank) {
248 // Protect against double-subscribe
249 for (RankedListener rl : mListeners) {
Beverly8fdb5332019-02-04 14:29:49 -0500250 if (rl.mListener.equals(listener)) {
Evan Laird91d0f102018-09-18 17:39:55 -0400251 return;
252 }
253 }
254
Beverly8fdb5332019-02-04 14:29:49 -0500255 RankedListener rl = new SysuiStatusBarStateController.RankedListener(listener, rank);
Evan Laird91d0f102018-09-18 17:39:55 -0400256 mListeners.add(rl);
Beverly8fdb5332019-02-04 14:29:49 -0500257 mListeners.sort(sComparator);
Evan Laird91d0f102018-09-18 17:39:55 -0400258 }
259
Beverly8fdb5332019-02-04 14:29:49 -0500260
261 @Override
Jason Monkaf08c152018-12-04 11:12:39 -0500262 public void removeCallback(StateListener listener) {
Jason Monk1fd3fc32018-08-14 17:20:09 -0400263 synchronized (mListeners) {
Beverly8fdb5332019-02-04 14:29:49 -0500264 mListeners.removeIf((it) -> it.mListener.equals(listener));
Jason Monk1fd3fc32018-08-14 17:20:09 -0400265 }
266 }
267
Beverly8fdb5332019-02-04 14:29:49 -0500268 @Override
Jason Monk297c04e2018-08-23 17:16:59 -0400269 public void setKeyguardRequested(boolean keyguardRequested) {
270 mKeyguardRequested = keyguardRequested;
271 }
272
Beverly8fdb5332019-02-04 14:29:49 -0500273 @Override
Jason Monk297c04e2018-08-23 17:16:59 -0400274 public boolean isKeyguardRequested() {
275 return mKeyguardRequested;
276 }
277
Beverly8fdb5332019-02-04 14:29:49 -0500278 /**
279 * Returns String readable state of status bar from {@link StatusBarState}
280 */
Evan Laird91d0f102018-09-18 17:39:55 -0400281 public static String describe(int state) {
282 return StatusBarState.toShortString(state);
283 }
Jason Monk1fd3fc32018-08-14 17:20:09 -0400284}