blob: b29889dac6f85dbaf611d6e4243cab710fc47bca [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
19import android.animation.ValueAnimator;
Jason Monkaa573e92017-01-27 17:00:29 -050020import android.content.Context;
Jason Monk49fa0162017-01-11 09:21:56 -050021import android.os.Bundle;
Jorim Jaggi40db0292016-06-27 17:58:03 -070022import android.os.Handler;
23import android.os.SystemClock;
Lucas Dupin51d24e02018-11-13 10:46:51 -080024import android.util.MathUtils;
Adrian Roos1bf60772017-02-03 15:47:43 -080025import android.util.TimeUtils;
Jorim Jaggi40db0292016-06-27 17:58:03 -070026
Jason Monkaa573e92017-01-27 17:00:29 -050027import com.android.systemui.Dependency;
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020028import com.android.systemui.Dumpable;
Jorim Jaggi40db0292016-06-27 17:58:03 -070029import com.android.systemui.Interpolators;
Jason Monkaa573e92017-01-27 17:00:29 -050030import com.android.systemui.SysUiServiceProvider;
31import com.android.systemui.statusbar.CommandQueue;
32import com.android.systemui.statusbar.CommandQueue.Callbacks;
Lucas Dupin51d24e02018-11-13 10:46:51 -080033import com.android.systemui.statusbar.StatusBarStateController;
Jason Monkaa573e92017-01-27 17:00:29 -050034import com.android.systemui.statusbar.policy.KeyguardMonitor;
Jorim Jaggi40db0292016-06-27 17:58:03 -070035
Adrian Roos1bf60772017-02-03 15:47:43 -080036import java.io.FileDescriptor;
37import java.io.PrintWriter;
38
Jorim Jaggi40db0292016-06-27 17:58:03 -070039/**
40 * Class to control all aspects about light bar changes.
41 */
Lucas Dupin51d24e02018-11-13 10:46:51 -080042public class LightBarTransitionsController implements Dumpable, Callbacks,
43 StatusBarStateController.StateListener {
Jorim Jaggi40db0292016-06-27 17:58:03 -070044
45 public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
Jason Monk49fa0162017-01-11 09:21:56 -050046 private static final String EXTRA_DARK_INTENSITY = "dark_intensity";
Jorim Jaggi40db0292016-06-27 17:58:03 -070047
48 private final Handler mHandler;
49 private final DarkIntensityApplier mApplier;
Jason Monkaa573e92017-01-27 17:00:29 -050050 private final KeyguardMonitor mKeyguardMonitor;
Lucas Dupin51d24e02018-11-13 10:46:51 -080051 private final StatusBarStateController mStatusBarStateController;
Jorim Jaggi40db0292016-06-27 17:58:03 -070052
53 private boolean mTransitionDeferring;
54 private long mTransitionDeferringStartTime;
55 private long mTransitionDeferringDuration;
56 private boolean mTransitionPending;
57 private boolean mTintChangePending;
58 private float mPendingDarkIntensity;
59 private ValueAnimator mTintAnimator;
60 private float mDarkIntensity;
Jason Monk49fa0162017-01-11 09:21:56 -050061 private float mNextDarkIntensity;
Lucas Dupin51d24e02018-11-13 10:46:51 -080062 private float mDozeAmount;
Jorim Jaggi40db0292016-06-27 17:58:03 -070063 private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
64 @Override
65 public void run() {
66 mTransitionDeferring = false;
67 }
68 };
69
Jason Monkaa573e92017-01-27 17:00:29 -050070 public LightBarTransitionsController(Context context, DarkIntensityApplier applier) {
Jorim Jaggi40db0292016-06-27 17:58:03 -070071 mApplier = applier;
72 mHandler = new Handler();
Jason Monkaa573e92017-01-27 17:00:29 -050073 mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
Lucas Dupin51d24e02018-11-13 10:46:51 -080074 mStatusBarStateController = Dependency.get(StatusBarStateController.class);
Jason Monkaa573e92017-01-27 17:00:29 -050075 SysUiServiceProvider.getComponent(context, CommandQueue.class)
76 .addCallbacks(this);
Lucas Dupin51d24e02018-11-13 10:46:51 -080077 mStatusBarStateController.addListener(this);
78 mDozeAmount = mStatusBarStateController.getDozeAmount();
Jason Monkaa573e92017-01-27 17:00:29 -050079 }
80
81 public void destroy(Context context) {
82 SysUiServiceProvider.getComponent(context, CommandQueue.class)
83 .removeCallbacks(this);
Lucas Dupin51d24e02018-11-13 10:46:51 -080084 mStatusBarStateController.removeListener(this);
Jorim Jaggi40db0292016-06-27 17:58:03 -070085 }
86
Jason Monk49fa0162017-01-11 09:21:56 -050087 public void saveState(Bundle outState) {
88 float intensity = mTintAnimator != null && mTintAnimator.isRunning()
89 ? mNextDarkIntensity : mDarkIntensity;
90 outState.putFloat(EXTRA_DARK_INTENSITY, intensity);
91 }
92
93 public void restoreState(Bundle savedInstanceState) {
94 setIconTintInternal(savedInstanceState.getFloat(EXTRA_DARK_INTENSITY, 0));
95 }
96
Jason Monkaa573e92017-01-27 17:00:29 -050097 @Override
98 public void appTransitionPending(boolean forced) {
99 if (mKeyguardMonitor.isKeyguardGoingAway() && !forced) {
100 return;
101 }
Jorim Jaggi40db0292016-06-27 17:58:03 -0700102 mTransitionPending = true;
103 }
104
Jason Monkaa573e92017-01-27 17:00:29 -0500105 @Override
Jorim Jaggi40db0292016-06-27 17:58:03 -0700106 public void appTransitionCancelled() {
107 if (mTransitionPending && mTintChangePending) {
108 mTintChangePending = false;
109 animateIconTint(mPendingDarkIntensity, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
110 }
111 mTransitionPending = false;
112 }
113
Jason Monkaa573e92017-01-27 17:00:29 -0500114 @Override
115 public void appTransitionStarting(long startTime, long duration, boolean forced) {
116 if (mKeyguardMonitor.isKeyguardGoingAway() && !forced) {
117 return;
118 }
Jorim Jaggi40db0292016-06-27 17:58:03 -0700119 if (mTransitionPending && mTintChangePending) {
120 mTintChangePending = false;
121 animateIconTint(mPendingDarkIntensity,
122 Math.max(0, startTime - SystemClock.uptimeMillis()),
123 duration);
124
125 } else if (mTransitionPending) {
126
127 // If we don't have a pending tint change yet, the change might come in the future until
128 // startTime is reached.
129 mTransitionDeferring = true;
130 mTransitionDeferringStartTime = startTime;
131 mTransitionDeferringDuration = duration;
132 mHandler.removeCallbacks(mTransitionDeferringDoneRunnable);
133 mHandler.postAtTime(mTransitionDeferringDoneRunnable, startTime);
134 }
135 mTransitionPending = false;
136 }
137
138 public void setIconsDark(boolean dark, boolean animate) {
139 if (!animate) {
140 setIconTintInternal(dark ? 1.0f : 0.0f);
Jorim Jaggiff46d4c2017-07-17 16:46:00 +0200141 mNextDarkIntensity = dark ? 1.0f : 0.0f;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700142 } else if (mTransitionPending) {
143 deferIconTintChange(dark ? 1.0f : 0.0f);
144 } else if (mTransitionDeferring) {
145 animateIconTint(dark ? 1.0f : 0.0f,
146 Math.max(0, mTransitionDeferringStartTime - SystemClock.uptimeMillis()),
147 mTransitionDeferringDuration);
148 } else {
149 animateIconTint(dark ? 1.0f : 0.0f, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
150 }
151 }
152
153 public float getCurrentDarkIntensity() {
154 return mDarkIntensity;
155 }
156
157 private void deferIconTintChange(float darkIntensity) {
158 if (mTintChangePending && darkIntensity == mPendingDarkIntensity) {
159 return;
160 }
161 mTintChangePending = true;
162 mPendingDarkIntensity = darkIntensity;
163 }
164
165 private void animateIconTint(float targetDarkIntensity, long delay,
166 long duration) {
Jorim Jaggiff46d4c2017-07-17 16:46:00 +0200167 if (mNextDarkIntensity == targetDarkIntensity) {
168 return;
169 }
Jorim Jaggi40db0292016-06-27 17:58:03 -0700170 if (mTintAnimator != null) {
171 mTintAnimator.cancel();
172 }
Jason Monk49fa0162017-01-11 09:21:56 -0500173 mNextDarkIntensity = targetDarkIntensity;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700174 mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
175 mTintAnimator.addUpdateListener(
176 animation -> setIconTintInternal((Float) animation.getAnimatedValue()));
177 mTintAnimator.setDuration(duration);
178 mTintAnimator.setStartDelay(delay);
Lucas Dupin0c1157e2017-07-18 21:40:28 -0700179 mTintAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700180 mTintAnimator.start();
181 }
182
183 private void setIconTintInternal(float darkIntensity) {
184 mDarkIntensity = darkIntensity;
Lucas Dupin51d24e02018-11-13 10:46:51 -0800185 dispatchDark();
186 }
187
188 private void dispatchDark() {
189 mApplier.applyDarkIntensity(MathUtils.lerp(mDarkIntensity, 0f, mDozeAmount));
Jorim Jaggi40db0292016-06-27 17:58:03 -0700190 }
191
Adrian Roos1bf60772017-02-03 15:47:43 -0800192 @Override
193 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
194 pw.print(" mTransitionDeferring="); pw.print(mTransitionDeferring);
195 if (mTransitionDeferring) {
196 pw.println();
197 pw.print(" mTransitionDeferringStartTime=");
198 pw.println(TimeUtils.formatUptime(mTransitionDeferringStartTime));
199
200 pw.print(" mTransitionDeferringDuration=");
201 TimeUtils.formatDuration(mTransitionDeferringDuration, pw);
202 pw.println();
203 }
204 pw.print(" mTransitionPending="); pw.print(mTransitionPending);
205 pw.print(" mTintChangePending="); pw.println(mTintChangePending);
206
207 pw.print(" mPendingDarkIntensity="); pw.print(mPendingDarkIntensity);
208 pw.print(" mDarkIntensity="); pw.print(mDarkIntensity);
209 pw.print(" mNextDarkIntensity="); pw.println(mNextDarkIntensity);
210 }
211
Lucas Dupin51d24e02018-11-13 10:46:51 -0800212 @Override
213 public void onStateChanged(int newState) { }
214
215 @Override
216 public void onDozeAmountChanged(float linear, float eased) {
217 mDozeAmount = eased;
218 dispatchDark();
219 }
220
Jorim Jaggi40db0292016-06-27 17:58:03 -0700221 /**
222 * Interface to apply a specific dark intensity.
223 */
224 public interface DarkIntensityApplier {
225 void applyDarkIntensity(float darkIntensity);
226 }
227}