blob: cbd66aa949a9a5fc466094b2c3b71ffd9ea1dc58 [file] [log] [blame]
Jorim Jaggiecc798e2014-05-26 18:14:37 +02001/*
2 * Copyright (C) 2014 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.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.ValueAnimator;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020022import android.graphics.Color;
23import android.graphics.drawable.ColorDrawable;
John Spurlockbf370992014-06-17 13:58:31 -040024import android.util.Log;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020025import android.view.View;
26import android.view.ViewTreeObserver;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020027import android.view.animation.DecelerateInterpolator;
28import android.view.animation.Interpolator;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020029
John Spurlockbf370992014-06-17 13:58:31 -040030import com.android.systemui.R;
31
Jorim Jaggiecc798e2014-05-26 18:14:37 +020032/**
33 * Controls both the scrim behind the notifications and in front of the notifications (when a
34 * security method gets shown).
35 */
36public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
John Spurlockbf370992014-06-17 13:58:31 -040037 private static final String TAG = "ScrimController";
38 private static final boolean DEBUG = false;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020039
40 private static final float SCRIM_BEHIND_ALPHA = 0.62f;
41 private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.5f;
42 private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
43 private static final long ANIMATION_DURATION = 220;
John Spurlockbf370992014-06-17 13:58:31 -040044 private static final int TAG_KEY_ANIM = R.id.scrim;
45
John Spurlockcb566aa2014-08-03 22:58:28 -040046 private static final long PULSE_IN_ANIMATION_DURATION = 1000;
47 private static final long PULSE_VISIBLE_DURATION = 2000;
48 private static final long PULSE_OUT_ANIMATION_DURATION = 1000;
49 private static final long PULSE_INVISIBLE_DURATION = 1000;
50 private static final long PULSE_DURATION = PULSE_IN_ANIMATION_DURATION
51 + PULSE_VISIBLE_DURATION + PULSE_OUT_ANIMATION_DURATION + PULSE_INVISIBLE_DURATION;
52 private static final long PRE_PULSE_DELAY = 1000;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020053
54 private final View mScrimBehind;
55 private final View mScrimInFront;
56 private final UnlockMethodCache mUnlockMethodCache;
57
58 private boolean mKeyguardShowing;
59 private float mFraction;
60
61 private boolean mDarkenWhileDragging;
62 private boolean mBouncerShowing;
63 private boolean mAnimateChange;
64 private boolean mUpdatePending;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +020065 private boolean mExpanding;
Jorim Jaggie29b2db2014-05-30 23:17:03 +020066 private boolean mAnimateKeyguardFadingOut;
67 private long mDurationOverride = -1;
68 private long mAnimationDelay;
69 private Runnable mOnAnimationFinished;
70 private boolean mAnimationStarted;
John Spurlockbf370992014-06-17 13:58:31 -040071 private boolean mDozing;
John Spurlockcb566aa2014-08-03 22:58:28 -040072 private int mPulsesRemaining;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020073 private final Interpolator mInterpolator = new DecelerateInterpolator();
74
75 public ScrimController(View scrimBehind, View scrimInFront) {
76 mScrimBehind = scrimBehind;
77 mScrimInFront = scrimInFront;
78 mUnlockMethodCache = UnlockMethodCache.getInstance(scrimBehind.getContext());
79 }
80
81 public void setKeyguardShowing(boolean showing) {
82 mKeyguardShowing = showing;
83 scheduleUpdate();
84 }
85
86 public void onTrackingStarted() {
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +020087 mExpanding = true;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020088 mDarkenWhileDragging = !mUnlockMethodCache.isMethodInsecure();
89 }
90
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +020091 public void onExpandingFinished() {
92 mExpanding = false;
93 }
94
Jorim Jaggiecc798e2014-05-26 18:14:37 +020095 public void setPanelExpansion(float fraction) {
Jorim Jaggi93439da2014-06-30 23:53:39 +020096 if (mFraction != fraction) {
97 mFraction = fraction;
98 scheduleUpdate();
99 }
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200100 }
101
102 public void setBouncerShowing(boolean showing) {
103 mBouncerShowing = showing;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200104 mAnimateChange = !mExpanding;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200105 scheduleUpdate();
106 }
107
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200108 public void animateKeyguardFadingOut(long delay, long duration, Runnable onAnimationFinished) {
109 mAnimateKeyguardFadingOut = true;
110 mDurationOverride = duration;
111 mAnimationDelay = delay;
112 mAnimateChange = true;
113 mOnAnimationFinished = onAnimationFinished;
114 scheduleUpdate();
115 }
116
Jorim Jaggidbc3dce2014-08-01 01:16:36 +0200117 public void animateGoingToFullShade(long delay, long duration) {
118 mDurationOverride = duration;
119 mAnimationDelay = delay;
120 mAnimateChange = true;
121 scheduleUpdate();
122 }
123
John Spurlockbf370992014-06-17 13:58:31 -0400124 public void setDozing(boolean dozing) {
125 if (mDozing == dozing) return;
126 mDozing = dozing;
127 if (!mDozing) {
John Spurlockcb566aa2014-08-03 22:58:28 -0400128 cancelPulsing();
John Spurlockbf370992014-06-17 13:58:31 -0400129 }
130 scheduleUpdate();
131 }
132
133 /** When dozing, fade screen contents in and out a few times using the front scrim. */
John Spurlockcb566aa2014-08-03 22:58:28 -0400134 public long pulse(int pulses) {
John Spurlockbf370992014-06-17 13:58:31 -0400135 if (!mDozing) return 0;
John Spurlockcb566aa2014-08-03 22:58:28 -0400136 mPulsesRemaining = Math.max(pulses, mPulsesRemaining);
137 mScrimInFront.postDelayed(mPulseIn, PRE_PULSE_DELAY);
138 return PRE_PULSE_DELAY + mPulsesRemaining * PULSE_DURATION;
John Spurlockbf370992014-06-17 13:58:31 -0400139 }
140
John Spurlockcb566aa2014-08-03 22:58:28 -0400141 private void cancelPulsing() {
142 mPulsesRemaining = 0;
143 mScrimInFront.removeCallbacks(mPulseIn);
144 mScrimInFront.removeCallbacks(mPulseOut);
John Spurlockbf370992014-06-17 13:58:31 -0400145 }
146
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200147 private void scheduleUpdate() {
148 if (mUpdatePending) return;
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200149
150 // Make sure that a frame gets scheduled.
151 mScrimBehind.invalidate();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200152 mScrimBehind.getViewTreeObserver().addOnPreDrawListener(this);
153 mUpdatePending = true;
154 }
155
156 private void updateScrims() {
Selim Cinekbaa23272014-07-08 18:01:07 +0200157 if (mAnimateKeyguardFadingOut) {
158 setScrimInFrontColor(0f);
159 setScrimBehindColor(0f);
160 }else if (!mKeyguardShowing && !mBouncerShowing) {
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200161 updateScrimNormal();
162 setScrimInFrontColor(0);
163 } else {
164 updateScrimKeyguard();
165 }
166 mAnimateChange = false;
167 }
168
169 private void updateScrimKeyguard() {
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200170 if (mExpanding && mDarkenWhileDragging) {
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200171 float behindFraction = Math.max(0, Math.min(mFraction, 1));
172 float fraction = 1 - behindFraction;
173 setScrimInFrontColor(fraction * SCRIM_IN_FRONT_ALPHA);
174 setScrimBehindColor(behindFraction * SCRIM_BEHIND_ALPHA_KEYGUARD);
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200175 } else if (mBouncerShowing) {
176 setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA);
177 setScrimBehindColor(0f);
John Spurlockbf370992014-06-17 13:58:31 -0400178 } else if (mDozing) {
179 setScrimInFrontColor(1);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200180 } else {
181 setScrimInFrontColor(0f);
182 setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD);
183 }
184 }
185
186 private void updateScrimNormal() {
187 float frac = mFraction;
188 // let's start this 20% of the way down the screen
189 frac = frac * 1.2f - 0.2f;
190 if (frac <= 0) {
191 setScrimBehindColor(0);
192 } else {
193 // woo, special effects
194 final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
195 setScrimBehindColor(k * SCRIM_BEHIND_ALPHA);
196 }
197 }
198
199 private void setScrimBehindColor(float alpha) {
200 setScrimColor(mScrimBehind, alpha);
201 }
202
203 private void setScrimInFrontColor(float alpha) {
204 setScrimColor(mScrimInFront, alpha);
205 if (alpha == 0f) {
206 mScrimInFront.setClickable(false);
207 } else {
208
209 // Eat touch events.
210 mScrimInFront.setClickable(true);
211 }
212 }
213
214 private void setScrimColor(View scrim, float alpha) {
215 int color = Color.argb((int) (alpha * 255), 0, 0, 0);
216 if (mAnimateChange) {
217 startScrimAnimation(scrim, color);
218 } else {
219 scrim.setBackgroundColor(color);
220 }
221 }
222
223 private void startScrimAnimation(final View scrim, int targetColor) {
224 int current = getBackgroundAlpha(scrim);
225 int target = Color.alpha(targetColor);
226 if (current == targetColor) {
227 return;
228 }
John Spurlockbf370992014-06-17 13:58:31 -0400229 Object runningAnim = scrim.getTag(TAG_KEY_ANIM);
230 if (runningAnim instanceof ValueAnimator) {
231 ((ValueAnimator) runningAnim).cancel();
232 }
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200233 ValueAnimator anim = ValueAnimator.ofInt(current, target);
234 anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
235 @Override
236 public void onAnimationUpdate(ValueAnimator animation) {
237 int value = (int) animation.getAnimatedValue();
238 scrim.setBackgroundColor(Color.argb(value, 0, 0, 0));
239 }
240 });
241 anim.setInterpolator(mInterpolator);
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200242 anim.setStartDelay(mAnimationDelay);
243 anim.setDuration(mDurationOverride != -1 ? mDurationOverride : ANIMATION_DURATION);
244 anim.addListener(new AnimatorListenerAdapter() {
245
246 @Override
247 public void onAnimationEnd(Animator animation) {
248 if (mOnAnimationFinished != null) {
249 mOnAnimationFinished.run();
250 mOnAnimationFinished = null;
251 }
John Spurlockbf370992014-06-17 13:58:31 -0400252 scrim.setTag(TAG_KEY_ANIM, null);
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200253 }
254 });
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200255 anim.start();
John Spurlockbf370992014-06-17 13:58:31 -0400256 scrim.setTag(TAG_KEY_ANIM, anim);
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200257 mAnimationStarted = true;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200258 }
259
260 private int getBackgroundAlpha(View scrim) {
261 if (scrim.getBackground() instanceof ColorDrawable) {
262 ColorDrawable drawable = (ColorDrawable) scrim.getBackground();
263 return Color.alpha(drawable.getColor());
264 } else {
265 return 0;
266 }
267 }
268
269 @Override
270 public boolean onPreDraw() {
271 mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this);
272 mUpdatePending = false;
273 updateScrims();
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200274 mAnimateKeyguardFadingOut = false;
275 mDurationOverride = -1;
276 mAnimationDelay = 0;
277
278 // Make sure that we always call the listener even if we didn't start an animation.
279 if (!mAnimationStarted && mOnAnimationFinished != null) {
280 mOnAnimationFinished.run();
281 mOnAnimationFinished = null;
282 }
283 mAnimationStarted = false;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200284 return true;
285 }
John Spurlockbf370992014-06-17 13:58:31 -0400286
John Spurlockcb566aa2014-08-03 22:58:28 -0400287 private final Runnable mPulseIn = new Runnable() {
John Spurlockbf370992014-06-17 13:58:31 -0400288 @Override
289 public void run() {
John Spurlockcb566aa2014-08-03 22:58:28 -0400290 if (DEBUG) Log.d(TAG, "Pulse in, mDozing=" + mDozing
291 + " mPulsesRemaining=" + mPulsesRemaining);
292 if (!mDozing || mPulsesRemaining == 0) return;
293 mPulsesRemaining--;
294 mDurationOverride = PULSE_IN_ANIMATION_DURATION;
John Spurlockbf370992014-06-17 13:58:31 -0400295 mAnimationDelay = 0;
296 mAnimateChange = true;
John Spurlockcb566aa2014-08-03 22:58:28 -0400297 mOnAnimationFinished = mPulseInFinished;
John Spurlockbf370992014-06-17 13:58:31 -0400298 setScrimColor(mScrimInFront, 0);
299 }
300 };
301
John Spurlockcb566aa2014-08-03 22:58:28 -0400302 private final Runnable mPulseInFinished = new Runnable() {
John Spurlockbf370992014-06-17 13:58:31 -0400303 @Override
304 public void run() {
John Spurlockcb566aa2014-08-03 22:58:28 -0400305 if (DEBUG) Log.d(TAG, "Pulse in finished, mDozing=" + mDozing);
John Spurlockbf370992014-06-17 13:58:31 -0400306 if (!mDozing) return;
John Spurlockcb566aa2014-08-03 22:58:28 -0400307 mScrimInFront.postDelayed(mPulseOut, PULSE_VISIBLE_DURATION);
John Spurlockbf370992014-06-17 13:58:31 -0400308 }
309 };
310
John Spurlockcb566aa2014-08-03 22:58:28 -0400311 private final Runnable mPulseOut = new Runnable() {
John Spurlockbf370992014-06-17 13:58:31 -0400312 @Override
313 public void run() {
John Spurlockcb566aa2014-08-03 22:58:28 -0400314 if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
John Spurlockbf370992014-06-17 13:58:31 -0400315 if (!mDozing) return;
John Spurlockcb566aa2014-08-03 22:58:28 -0400316 mDurationOverride = PULSE_OUT_ANIMATION_DURATION;
John Spurlockbf370992014-06-17 13:58:31 -0400317 mAnimationDelay = 0;
318 mAnimateChange = true;
John Spurlockcb566aa2014-08-03 22:58:28 -0400319 mOnAnimationFinished = mPulseOutFinished;
John Spurlockbf370992014-06-17 13:58:31 -0400320 setScrimColor(mScrimInFront, 1);
321 }
322 };
323
John Spurlockcb566aa2014-08-03 22:58:28 -0400324 private final Runnable mPulseOutFinished = new Runnable() {
John Spurlockbf370992014-06-17 13:58:31 -0400325 @Override
326 public void run() {
John Spurlockcb566aa2014-08-03 22:58:28 -0400327 if (DEBUG) Log.d(TAG, "Pulse out finished, mPulsesRemaining=" + mPulsesRemaining);
328 if (mPulsesRemaining > 0) {
329 mScrimInFront.postDelayed(mPulseIn, PULSE_INVISIBLE_DURATION);
John Spurlockbf370992014-06-17 13:58:31 -0400330 }
331 }
332 };
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200333}