blob: 3ff11d271f8c2f553f97e668999303a36476abb7 [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;
John Spurlockd06aa572014-09-10 10:40:49 -040022import android.content.Context;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020023import android.graphics.Color;
24import android.graphics.drawable.ColorDrawable;
John Spurlockbf370992014-06-17 13:58:31 -040025import android.util.Log;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020026import android.view.View;
27import android.view.ViewTreeObserver;
Jorim Jaggi76a16232014-08-08 17:00:47 +020028import android.view.animation.AnimationUtils;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020029import android.view.animation.DecelerateInterpolator;
30import android.view.animation.Interpolator;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020031
John Spurlockbf370992014-06-17 13:58:31 -040032import com.android.systemui.R;
33
Jorim Jaggiecc798e2014-05-26 18:14:37 +020034/**
35 * Controls both the scrim behind the notifications and in front of the notifications (when a
36 * security method gets shown).
37 */
38public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
John Spurlockbf370992014-06-17 13:58:31 -040039 private static final String TAG = "ScrimController";
John Spurlockd06aa572014-09-10 10:40:49 -040040 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
Jorim Jaggiecc798e2014-05-26 18:14:37 +020041
John Spurlock8b12f222014-09-09 11:54:11 -040042 public static final long ANIMATION_DURATION = 220;
43
Jorim Jaggiecc798e2014-05-26 18:14:37 +020044 private static final float SCRIM_BEHIND_ALPHA = 0.62f;
Jorim Jaggi76a16232014-08-08 17:00:47 +020045 private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.55f;
46 private static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020047 private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
John Spurlockbf370992014-06-17 13:58:31 -040048 private static final int TAG_KEY_ANIM = R.id.scrim;
49
Jorim Jaggiecc798e2014-05-26 18:14:37 +020050 private final View mScrimBehind;
51 private final View mScrimInFront;
52 private final UnlockMethodCache mUnlockMethodCache;
John Spurlockd06aa572014-09-10 10:40:49 -040053 private final DozeParameters mDozeParameters;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020054
55 private boolean mKeyguardShowing;
56 private float mFraction;
57
58 private boolean mDarkenWhileDragging;
59 private boolean mBouncerShowing;
60 private boolean mAnimateChange;
61 private boolean mUpdatePending;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +020062 private boolean mExpanding;
Jorim Jaggie29b2db2014-05-30 23:17:03 +020063 private boolean mAnimateKeyguardFadingOut;
64 private long mDurationOverride = -1;
65 private long mAnimationDelay;
66 private Runnable mOnAnimationFinished;
67 private boolean mAnimationStarted;
John Spurlockbf370992014-06-17 13:58:31 -040068 private boolean mDozing;
John Spurlockd06aa572014-09-10 10:40:49 -040069 private long mPulseEndTime;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020070 private final Interpolator mInterpolator = new DecelerateInterpolator();
Jorim Jaggi76a16232014-08-08 17:00:47 +020071 private final Interpolator mLinearOutSlowInInterpolator;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020072
73 public ScrimController(View scrimBehind, View scrimInFront) {
74 mScrimBehind = scrimBehind;
75 mScrimInFront = scrimInFront;
John Spurlockd06aa572014-09-10 10:40:49 -040076 final Context context = scrimBehind.getContext();
77 mUnlockMethodCache = UnlockMethodCache.getInstance(context);
78 mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
Jorim Jaggi76a16232014-08-08 17:00:47 +020079 android.R.interpolator.linear_out_slow_in);
John Spurlockd06aa572014-09-10 10:40:49 -040080 mDozeParameters = new DozeParameters(context);
Jorim Jaggiecc798e2014-05-26 18:14:37 +020081 }
82
83 public void setKeyguardShowing(boolean showing) {
84 mKeyguardShowing = showing;
85 scheduleUpdate();
86 }
87
88 public void onTrackingStarted() {
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +020089 mExpanding = true;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020090 mDarkenWhileDragging = !mUnlockMethodCache.isMethodInsecure();
91 }
92
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +020093 public void onExpandingFinished() {
94 mExpanding = false;
95 }
96
Jorim Jaggiecc798e2014-05-26 18:14:37 +020097 public void setPanelExpansion(float fraction) {
Jorim Jaggi93439da2014-06-30 23:53:39 +020098 if (mFraction != fraction) {
99 mFraction = fraction;
100 scheduleUpdate();
101 }
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200102 }
103
104 public void setBouncerShowing(boolean showing) {
105 mBouncerShowing = showing;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200106 mAnimateChange = !mExpanding;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200107 scheduleUpdate();
108 }
109
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200110 public void animateKeyguardFadingOut(long delay, long duration, Runnable onAnimationFinished) {
111 mAnimateKeyguardFadingOut = true;
112 mDurationOverride = duration;
113 mAnimationDelay = delay;
114 mAnimateChange = true;
115 mOnAnimationFinished = onAnimationFinished;
116 scheduleUpdate();
117 }
118
Jorim Jaggidbc3dce2014-08-01 01:16:36 +0200119 public void animateGoingToFullShade(long delay, long duration) {
120 mDurationOverride = duration;
121 mAnimationDelay = delay;
122 mAnimateChange = true;
123 scheduleUpdate();
124 }
125
John Spurlockbf370992014-06-17 13:58:31 -0400126 public void setDozing(boolean dozing) {
127 if (mDozing == dozing) return;
128 mDozing = dozing;
129 if (!mDozing) {
John Spurlockcb566aa2014-08-03 22:58:28 -0400130 cancelPulsing();
John Spurlock8b12f222014-09-09 11:54:11 -0400131 mAnimateChange = true;
John Spurlock190d0262014-09-14 15:39:13 -0400132 } else {
133 mAnimateChange = false;
John Spurlockbf370992014-06-17 13:58:31 -0400134 }
135 scheduleUpdate();
136 }
137
John Spurlockd06aa572014-09-10 10:40:49 -0400138 /** When dozing, fade screen contents in and out using the front scrim. */
John Spurlock190d0262014-09-14 15:39:13 -0400139 public long pulse() {
John Spurlockbf370992014-06-17 13:58:31 -0400140 if (!mDozing) return 0;
John Spurlockd06aa572014-09-10 10:40:49 -0400141 final long now = System.currentTimeMillis();
John Spurlock190d0262014-09-14 15:39:13 -0400142 if (DEBUG) Log.d(TAG, "pulse mPulseEndTime=" + mPulseEndTime + " now=" + now);
John Spurlockd06aa572014-09-10 10:40:49 -0400143 if (mPulseEndTime != 0 && mPulseEndTime > now) return mPulseEndTime - now;
John Spurlock190d0262014-09-14 15:39:13 -0400144 mScrimInFront.post(mPulseIn);
145 mPulseEndTime = now + mDozeParameters.getPulseDuration();
John Spurlockd06aa572014-09-10 10:40:49 -0400146 return mPulseEndTime - now;
147 }
148
149 public boolean isPulsing() {
150 return mDozing && mPulseEndTime != 0;
John Spurlockbf370992014-06-17 13:58:31 -0400151 }
152
John Spurlockcb566aa2014-08-03 22:58:28 -0400153 private void cancelPulsing() {
John Spurlockd06aa572014-09-10 10:40:49 -0400154 if (DEBUG) Log.d(TAG, "Cancel pulsing");
John Spurlockcb566aa2014-08-03 22:58:28 -0400155 mScrimInFront.removeCallbacks(mPulseIn);
156 mScrimInFront.removeCallbacks(mPulseOut);
John Spurlockd06aa572014-09-10 10:40:49 -0400157 mPulseEndTime = 0;
John Spurlockbf370992014-06-17 13:58:31 -0400158 }
159
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200160 private void scheduleUpdate() {
161 if (mUpdatePending) return;
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200162
163 // Make sure that a frame gets scheduled.
164 mScrimBehind.invalidate();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200165 mScrimBehind.getViewTreeObserver().addOnPreDrawListener(this);
166 mUpdatePending = true;
167 }
168
169 private void updateScrims() {
Selim Cinekbaa23272014-07-08 18:01:07 +0200170 if (mAnimateKeyguardFadingOut) {
171 setScrimInFrontColor(0f);
172 setScrimBehindColor(0f);
John Spurlock8b12f222014-09-09 11:54:11 -0400173 } else if (!mKeyguardShowing && !mBouncerShowing) {
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200174 updateScrimNormal();
175 setScrimInFrontColor(0);
176 } else {
177 updateScrimKeyguard();
178 }
179 mAnimateChange = false;
180 }
181
182 private void updateScrimKeyguard() {
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200183 if (mExpanding && mDarkenWhileDragging) {
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200184 float behindFraction = Math.max(0, Math.min(mFraction, 1));
185 float fraction = 1 - behindFraction;
Jorim Jaggi76a16232014-08-08 17:00:47 +0200186 fraction = (float) Math.pow(fraction, 0.8f);
187 behindFraction = (float) Math.pow(behindFraction, 0.8f);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200188 setScrimInFrontColor(fraction * SCRIM_IN_FRONT_ALPHA);
189 setScrimBehindColor(behindFraction * SCRIM_BEHIND_ALPHA_KEYGUARD);
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200190 } else if (mBouncerShowing) {
191 setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA);
192 setScrimBehindColor(0f);
John Spurlockbf370992014-06-17 13:58:31 -0400193 } else if (mDozing) {
194 setScrimInFrontColor(1);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200195 } else {
Jorim Jaggi76a16232014-08-08 17:00:47 +0200196 float fraction = Math.max(0, Math.min(mFraction, 1));
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200197 setScrimInFrontColor(0f);
Jorim Jaggi76a16232014-08-08 17:00:47 +0200198 setScrimBehindColor(fraction
199 * (SCRIM_BEHIND_ALPHA_KEYGUARD - SCRIM_BEHIND_ALPHA_UNLOCKING)
200 + SCRIM_BEHIND_ALPHA_UNLOCKING);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200201 }
202 }
203
204 private void updateScrimNormal() {
205 float frac = mFraction;
206 // let's start this 20% of the way down the screen
207 frac = frac * 1.2f - 0.2f;
208 if (frac <= 0) {
209 setScrimBehindColor(0);
210 } else {
211 // woo, special effects
212 final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
213 setScrimBehindColor(k * SCRIM_BEHIND_ALPHA);
214 }
215 }
216
217 private void setScrimBehindColor(float alpha) {
218 setScrimColor(mScrimBehind, alpha);
219 }
220
221 private void setScrimInFrontColor(float alpha) {
222 setScrimColor(mScrimInFront, alpha);
223 if (alpha == 0f) {
224 mScrimInFront.setClickable(false);
225 } else {
226
John Spurlock8b12f222014-09-09 11:54:11 -0400227 // Eat touch events (unless dozing).
228 mScrimInFront.setClickable(!mDozing);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200229 }
230 }
231
232 private void setScrimColor(View scrim, float alpha) {
233 int color = Color.argb((int) (alpha * 255), 0, 0, 0);
234 if (mAnimateChange) {
235 startScrimAnimation(scrim, color);
236 } else {
237 scrim.setBackgroundColor(color);
238 }
239 }
240
241 private void startScrimAnimation(final View scrim, int targetColor) {
242 int current = getBackgroundAlpha(scrim);
243 int target = Color.alpha(targetColor);
244 if (current == targetColor) {
245 return;
246 }
John Spurlockbf370992014-06-17 13:58:31 -0400247 Object runningAnim = scrim.getTag(TAG_KEY_ANIM);
248 if (runningAnim instanceof ValueAnimator) {
249 ((ValueAnimator) runningAnim).cancel();
250 }
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200251 ValueAnimator anim = ValueAnimator.ofInt(current, target);
252 anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
253 @Override
254 public void onAnimationUpdate(ValueAnimator animation) {
255 int value = (int) animation.getAnimatedValue();
256 scrim.setBackgroundColor(Color.argb(value, 0, 0, 0));
257 }
258 });
Jorim Jaggi76a16232014-08-08 17:00:47 +0200259 anim.setInterpolator(mAnimateKeyguardFadingOut
260 ? mLinearOutSlowInInterpolator
261 : mInterpolator);
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200262 anim.setStartDelay(mAnimationDelay);
263 anim.setDuration(mDurationOverride != -1 ? mDurationOverride : ANIMATION_DURATION);
264 anim.addListener(new AnimatorListenerAdapter() {
265
266 @Override
267 public void onAnimationEnd(Animator animation) {
268 if (mOnAnimationFinished != null) {
269 mOnAnimationFinished.run();
270 mOnAnimationFinished = null;
271 }
John Spurlockbf370992014-06-17 13:58:31 -0400272 scrim.setTag(TAG_KEY_ANIM, null);
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200273 }
274 });
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200275 anim.start();
John Spurlockbf370992014-06-17 13:58:31 -0400276 scrim.setTag(TAG_KEY_ANIM, anim);
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200277 mAnimationStarted = true;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200278 }
279
280 private int getBackgroundAlpha(View scrim) {
281 if (scrim.getBackground() instanceof ColorDrawable) {
282 ColorDrawable drawable = (ColorDrawable) scrim.getBackground();
283 return Color.alpha(drawable.getColor());
284 } else {
285 return 0;
286 }
287 }
288
289 @Override
290 public boolean onPreDraw() {
291 mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this);
292 mUpdatePending = false;
293 updateScrims();
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200294 mAnimateKeyguardFadingOut = false;
295 mDurationOverride = -1;
296 mAnimationDelay = 0;
297
298 // Make sure that we always call the listener even if we didn't start an animation.
299 if (!mAnimationStarted && mOnAnimationFinished != null) {
300 mOnAnimationFinished.run();
301 mOnAnimationFinished = null;
302 }
303 mAnimationStarted = false;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200304 return true;
305 }
John Spurlockbf370992014-06-17 13:58:31 -0400306
John Spurlockcb566aa2014-08-03 22:58:28 -0400307 private final Runnable mPulseIn = new Runnable() {
John Spurlockbf370992014-06-17 13:58:31 -0400308 @Override
309 public void run() {
John Spurlockd06aa572014-09-10 10:40:49 -0400310 if (DEBUG) Log.d(TAG, "Pulse in, mDozing=" + mDozing);
311 if (!mDozing) return;
312 mDurationOverride = mDozeParameters.getPulseInDuration();
John Spurlockbf370992014-06-17 13:58:31 -0400313 mAnimationDelay = 0;
314 mAnimateChange = true;
John Spurlockcb566aa2014-08-03 22:58:28 -0400315 mOnAnimationFinished = mPulseInFinished;
John Spurlockbf370992014-06-17 13:58:31 -0400316 setScrimColor(mScrimInFront, 0);
317 }
318 };
319
John Spurlockcb566aa2014-08-03 22:58:28 -0400320 private final Runnable mPulseInFinished = new Runnable() {
John Spurlockbf370992014-06-17 13:58:31 -0400321 @Override
322 public void run() {
John Spurlockcb566aa2014-08-03 22:58:28 -0400323 if (DEBUG) Log.d(TAG, "Pulse in finished, mDozing=" + mDozing);
John Spurlockbf370992014-06-17 13:58:31 -0400324 if (!mDozing) return;
John Spurlockd06aa572014-09-10 10:40:49 -0400325 mScrimInFront.postDelayed(mPulseOut, mDozeParameters.getPulseVisibleDuration());
John Spurlockbf370992014-06-17 13:58:31 -0400326 }
327 };
328
John Spurlockcb566aa2014-08-03 22:58:28 -0400329 private final Runnable mPulseOut = new Runnable() {
John Spurlockbf370992014-06-17 13:58:31 -0400330 @Override
331 public void run() {
John Spurlockcb566aa2014-08-03 22:58:28 -0400332 if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
John Spurlockbf370992014-06-17 13:58:31 -0400333 if (!mDozing) return;
John Spurlockd06aa572014-09-10 10:40:49 -0400334 mDurationOverride = mDozeParameters.getPulseOutDuration();
John Spurlockbf370992014-06-17 13:58:31 -0400335 mAnimationDelay = 0;
336 mAnimateChange = true;
John Spurlockcb566aa2014-08-03 22:58:28 -0400337 mOnAnimationFinished = mPulseOutFinished;
John Spurlockbf370992014-06-17 13:58:31 -0400338 setScrimColor(mScrimInFront, 1);
339 }
340 };
341
John Spurlockcb566aa2014-08-03 22:58:28 -0400342 private final Runnable mPulseOutFinished = new Runnable() {
John Spurlockbf370992014-06-17 13:58:31 -0400343 @Override
344 public void run() {
John Spurlockd06aa572014-09-10 10:40:49 -0400345 if (DEBUG) Log.d(TAG, "Pulse out finished");
346 mPulseEndTime = 0;
John Spurlockbf370992014-06-17 13:58:31 -0400347 }
348 };
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200349}