blob: fdf406b9d0c6eda844ecd3572031575bf5ba0d29 [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;
Adrian Roos1bf60772017-02-03 15:47:43 -080024import android.util.TimeUtils;
Jorim Jaggi40db0292016-06-27 17:58:03 -070025
Adrian Roos1bf60772017-02-03 15:47:43 -080026import com.android.systemui.Dumpable;
Jason Monkaa573e92017-01-27 17:00:29 -050027import com.android.systemui.Dependency;
Jorim Jaggi40db0292016-06-27 17:58:03 -070028import com.android.systemui.Interpolators;
Jason Monkaa573e92017-01-27 17:00:29 -050029import com.android.systemui.SysUiServiceProvider;
30import com.android.systemui.statusbar.CommandQueue;
31import com.android.systemui.statusbar.CommandQueue.Callbacks;
32import com.android.systemui.statusbar.policy.KeyguardMonitor;
Jorim Jaggi40db0292016-06-27 17:58:03 -070033
Adrian Roos1bf60772017-02-03 15:47:43 -080034import java.io.FileDescriptor;
35import java.io.PrintWriter;
36
Jorim Jaggi40db0292016-06-27 17:58:03 -070037/**
38 * Class to control all aspects about light bar changes.
39 */
Jason Monkaa573e92017-01-27 17:00:29 -050040public class LightBarTransitionsController implements Dumpable, Callbacks {
Jorim Jaggi40db0292016-06-27 17:58:03 -070041
42 public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
Jason Monk49fa0162017-01-11 09:21:56 -050043 private static final String EXTRA_DARK_INTENSITY = "dark_intensity";
Jorim Jaggi40db0292016-06-27 17:58:03 -070044
45 private final Handler mHandler;
46 private final DarkIntensityApplier mApplier;
Jason Monkaa573e92017-01-27 17:00:29 -050047 private final KeyguardMonitor mKeyguardMonitor;
Jorim Jaggi40db0292016-06-27 17:58:03 -070048
49 private boolean mTransitionDeferring;
50 private long mTransitionDeferringStartTime;
51 private long mTransitionDeferringDuration;
52 private boolean mTransitionPending;
53 private boolean mTintChangePending;
54 private float mPendingDarkIntensity;
55 private ValueAnimator mTintAnimator;
56 private float mDarkIntensity;
Jason Monk49fa0162017-01-11 09:21:56 -050057 private float mNextDarkIntensity;
Jorim Jaggi40db0292016-06-27 17:58:03 -070058
59 private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
60 @Override
61 public void run() {
62 mTransitionDeferring = false;
63 }
64 };
65
Jason Monkaa573e92017-01-27 17:00:29 -050066 public LightBarTransitionsController(Context context, DarkIntensityApplier applier) {
Jorim Jaggi40db0292016-06-27 17:58:03 -070067 mApplier = applier;
68 mHandler = new Handler();
Jason Monkaa573e92017-01-27 17:00:29 -050069 mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
70 SysUiServiceProvider.getComponent(context, CommandQueue.class)
71 .addCallbacks(this);
72 }
73
74 public void destroy(Context context) {
75 SysUiServiceProvider.getComponent(context, CommandQueue.class)
76 .removeCallbacks(this);
Jorim Jaggi40db0292016-06-27 17:58:03 -070077 }
78
Jason Monk49fa0162017-01-11 09:21:56 -050079 public void saveState(Bundle outState) {
80 float intensity = mTintAnimator != null && mTintAnimator.isRunning()
81 ? mNextDarkIntensity : mDarkIntensity;
82 outState.putFloat(EXTRA_DARK_INTENSITY, intensity);
83 }
84
85 public void restoreState(Bundle savedInstanceState) {
86 setIconTintInternal(savedInstanceState.getFloat(EXTRA_DARK_INTENSITY, 0));
87 }
88
Jason Monkaa573e92017-01-27 17:00:29 -050089 @Override
90 public void appTransitionPending(boolean forced) {
91 if (mKeyguardMonitor.isKeyguardGoingAway() && !forced) {
92 return;
93 }
Jorim Jaggi40db0292016-06-27 17:58:03 -070094 mTransitionPending = true;
95 }
96
Jason Monkaa573e92017-01-27 17:00:29 -050097 @Override
Jorim Jaggi40db0292016-06-27 17:58:03 -070098 public void appTransitionCancelled() {
99 if (mTransitionPending && mTintChangePending) {
100 mTintChangePending = false;
101 animateIconTint(mPendingDarkIntensity, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
102 }
103 mTransitionPending = false;
104 }
105
Jason Monkaa573e92017-01-27 17:00:29 -0500106 @Override
107 public void appTransitionStarting(long startTime, long duration, boolean forced) {
108 if (mKeyguardMonitor.isKeyguardGoingAway() && !forced) {
109 return;
110 }
Jorim Jaggi40db0292016-06-27 17:58:03 -0700111 if (mTransitionPending && mTintChangePending) {
112 mTintChangePending = false;
113 animateIconTint(mPendingDarkIntensity,
114 Math.max(0, startTime - SystemClock.uptimeMillis()),
115 duration);
116
117 } else if (mTransitionPending) {
118
119 // If we don't have a pending tint change yet, the change might come in the future until
120 // startTime is reached.
121 mTransitionDeferring = true;
122 mTransitionDeferringStartTime = startTime;
123 mTransitionDeferringDuration = duration;
124 mHandler.removeCallbacks(mTransitionDeferringDoneRunnable);
125 mHandler.postAtTime(mTransitionDeferringDoneRunnable, startTime);
126 }
127 mTransitionPending = false;
128 }
129
130 public void setIconsDark(boolean dark, boolean animate) {
131 if (!animate) {
132 setIconTintInternal(dark ? 1.0f : 0.0f);
133 } else if (mTransitionPending) {
134 deferIconTintChange(dark ? 1.0f : 0.0f);
135 } else if (mTransitionDeferring) {
136 animateIconTint(dark ? 1.0f : 0.0f,
137 Math.max(0, mTransitionDeferringStartTime - SystemClock.uptimeMillis()),
138 mTransitionDeferringDuration);
139 } else {
140 animateIconTint(dark ? 1.0f : 0.0f, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
141 }
142 }
143
144 public float getCurrentDarkIntensity() {
145 return mDarkIntensity;
146 }
147
148 private void deferIconTintChange(float darkIntensity) {
149 if (mTintChangePending && darkIntensity == mPendingDarkIntensity) {
150 return;
151 }
152 mTintChangePending = true;
153 mPendingDarkIntensity = darkIntensity;
154 }
155
156 private void animateIconTint(float targetDarkIntensity, long delay,
157 long duration) {
158 if (mTintAnimator != null) {
159 mTintAnimator.cancel();
160 }
161 if (mDarkIntensity == targetDarkIntensity) {
162 return;
163 }
Jason Monk49fa0162017-01-11 09:21:56 -0500164 mNextDarkIntensity = targetDarkIntensity;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700165 mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
166 mTintAnimator.addUpdateListener(
167 animation -> setIconTintInternal((Float) animation.getAnimatedValue()));
168 mTintAnimator.setDuration(duration);
169 mTintAnimator.setStartDelay(delay);
Lucas Dupin0c1157e2017-07-18 21:40:28 -0700170 mTintAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700171 mTintAnimator.start();
172 }
173
174 private void setIconTintInternal(float darkIntensity) {
175 mDarkIntensity = darkIntensity;
176 mApplier.applyDarkIntensity(darkIntensity);
177 }
178
Adrian Roos1bf60772017-02-03 15:47:43 -0800179 @Override
180 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
181 pw.print(" mTransitionDeferring="); pw.print(mTransitionDeferring);
182 if (mTransitionDeferring) {
183 pw.println();
184 pw.print(" mTransitionDeferringStartTime=");
185 pw.println(TimeUtils.formatUptime(mTransitionDeferringStartTime));
186
187 pw.print(" mTransitionDeferringDuration=");
188 TimeUtils.formatDuration(mTransitionDeferringDuration, pw);
189 pw.println();
190 }
191 pw.print(" mTransitionPending="); pw.print(mTransitionPending);
192 pw.print(" mTintChangePending="); pw.println(mTintChangePending);
193
194 pw.print(" mPendingDarkIntensity="); pw.print(mPendingDarkIntensity);
195 pw.print(" mDarkIntensity="); pw.print(mDarkIntensity);
196 pw.print(" mNextDarkIntensity="); pw.println(mNextDarkIntensity);
197 }
198
Jorim Jaggi40db0292016-06-27 17:58:03 -0700199 /**
200 * Interface to apply a specific dark intensity.
201 */
202 public interface DarkIntensityApplier {
203 void applyDarkIntensity(float darkIntensity);
204 }
205}