blob: 417bef8575cb6b38c7bf48166024ba88420a26ab [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
Jason Monkaa573e92017-01-27 17:00:29 -050026import com.android.systemui.Dependency;
Jorim Jaggiff46d4c2017-07-17 16:46:00 +020027import com.android.systemui.Dumpable;
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 private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
59 @Override
60 public void run() {
61 mTransitionDeferring = false;
62 }
63 };
64
Jason Monkaa573e92017-01-27 17:00:29 -050065 public LightBarTransitionsController(Context context, DarkIntensityApplier applier) {
Jorim Jaggi40db0292016-06-27 17:58:03 -070066 mApplier = applier;
67 mHandler = new Handler();
Jason Monkaa573e92017-01-27 17:00:29 -050068 mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
69 SysUiServiceProvider.getComponent(context, CommandQueue.class)
70 .addCallbacks(this);
71 }
72
73 public void destroy(Context context) {
74 SysUiServiceProvider.getComponent(context, CommandQueue.class)
75 .removeCallbacks(this);
Jorim Jaggi40db0292016-06-27 17:58:03 -070076 }
77
Jason Monk49fa0162017-01-11 09:21:56 -050078 public void saveState(Bundle outState) {
79 float intensity = mTintAnimator != null && mTintAnimator.isRunning()
80 ? mNextDarkIntensity : mDarkIntensity;
81 outState.putFloat(EXTRA_DARK_INTENSITY, intensity);
82 }
83
84 public void restoreState(Bundle savedInstanceState) {
85 setIconTintInternal(savedInstanceState.getFloat(EXTRA_DARK_INTENSITY, 0));
86 }
87
Jason Monkaa573e92017-01-27 17:00:29 -050088 @Override
89 public void appTransitionPending(boolean forced) {
90 if (mKeyguardMonitor.isKeyguardGoingAway() && !forced) {
91 return;
92 }
Jorim Jaggi40db0292016-06-27 17:58:03 -070093 mTransitionPending = true;
94 }
95
Jason Monkaa573e92017-01-27 17:00:29 -050096 @Override
Jorim Jaggi40db0292016-06-27 17:58:03 -070097 public void appTransitionCancelled() {
98 if (mTransitionPending && mTintChangePending) {
99 mTintChangePending = false;
100 animateIconTint(mPendingDarkIntensity, 0 /* delay */, DEFAULT_TINT_ANIMATION_DURATION);
101 }
102 mTransitionPending = false;
103 }
104
Jason Monkaa573e92017-01-27 17:00:29 -0500105 @Override
106 public void appTransitionStarting(long startTime, long duration, boolean forced) {
107 if (mKeyguardMonitor.isKeyguardGoingAway() && !forced) {
108 return;
109 }
Jorim Jaggi40db0292016-06-27 17:58:03 -0700110 if (mTransitionPending && mTintChangePending) {
111 mTintChangePending = false;
112 animateIconTint(mPendingDarkIntensity,
113 Math.max(0, startTime - SystemClock.uptimeMillis()),
114 duration);
115
116 } else if (mTransitionPending) {
117
118 // If we don't have a pending tint change yet, the change might come in the future until
119 // startTime is reached.
120 mTransitionDeferring = true;
121 mTransitionDeferringStartTime = startTime;
122 mTransitionDeferringDuration = duration;
123 mHandler.removeCallbacks(mTransitionDeferringDoneRunnable);
124 mHandler.postAtTime(mTransitionDeferringDoneRunnable, startTime);
125 }
126 mTransitionPending = false;
127 }
128
129 public void setIconsDark(boolean dark, boolean animate) {
130 if (!animate) {
131 setIconTintInternal(dark ? 1.0f : 0.0f);
Jorim Jaggiff46d4c2017-07-17 16:46:00 +0200132 mNextDarkIntensity = dark ? 1.0f : 0.0f;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700133 } 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) {
Jorim Jaggiff46d4c2017-07-17 16:46:00 +0200158 if (mNextDarkIntensity == targetDarkIntensity) {
159 return;
160 }
Jorim Jaggi40db0292016-06-27 17:58:03 -0700161 if (mTintAnimator != null) {
162 mTintAnimator.cancel();
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);
170 mTintAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
171 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}