blob: ddb03e7fac68697f5bd172779f67e3f772791899 [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;
John Spurlock813552c2014-09-19 08:30:21 -040033import com.android.systemui.doze.DozeLog;
John Spurlockbf370992014-06-17 13:58:31 -040034
Jorim Jaggiecc798e2014-05-26 18:14:37 +020035/**
36 * Controls both the scrim behind the notifications and in front of the notifications (when a
37 * security method gets shown).
38 */
39public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
John Spurlockbf370992014-06-17 13:58:31 -040040 private static final String TAG = "ScrimController";
John Spurlockd06aa572014-09-10 10:40:49 -040041 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
Jorim Jaggiecc798e2014-05-26 18:14:37 +020042
John Spurlock8b12f222014-09-09 11:54:11 -040043 public static final long ANIMATION_DURATION = 220;
44
Jorim Jaggiecc798e2014-05-26 18:14:37 +020045 private static final float SCRIM_BEHIND_ALPHA = 0.62f;
Jorim Jaggi76a16232014-08-08 17:00:47 +020046 private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.55f;
47 private static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020048 private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
John Spurlockbf370992014-06-17 13:58:31 -040049 private static final int TAG_KEY_ANIM = R.id.scrim;
50
Jorim Jaggiecc798e2014-05-26 18:14:37 +020051 private final View mScrimBehind;
52 private final View mScrimInFront;
53 private final UnlockMethodCache mUnlockMethodCache;
John Spurlockd06aa572014-09-10 10:40:49 -040054 private final DozeParameters mDozeParameters;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020055
56 private boolean mKeyguardShowing;
57 private float mFraction;
58
59 private boolean mDarkenWhileDragging;
60 private boolean mBouncerShowing;
61 private boolean mAnimateChange;
62 private boolean mUpdatePending;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +020063 private boolean mExpanding;
Jorim Jaggie29b2db2014-05-30 23:17:03 +020064 private boolean mAnimateKeyguardFadingOut;
65 private long mDurationOverride = -1;
66 private long mAnimationDelay;
67 private Runnable mOnAnimationFinished;
68 private boolean mAnimationStarted;
John Spurlockbf370992014-06-17 13:58:31 -040069 private boolean mDozing;
John Spurlockd06aa572014-09-10 10:40:49 -040070 private long mPulseEndTime;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020071 private final Interpolator mInterpolator = new DecelerateInterpolator();
Jorim Jaggi76a16232014-08-08 17:00:47 +020072 private final Interpolator mLinearOutSlowInInterpolator;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020073
74 public ScrimController(View scrimBehind, View scrimInFront) {
75 mScrimBehind = scrimBehind;
76 mScrimInFront = scrimInFront;
John Spurlockd06aa572014-09-10 10:40:49 -040077 final Context context = scrimBehind.getContext();
78 mUnlockMethodCache = UnlockMethodCache.getInstance(context);
79 mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
Jorim Jaggi76a16232014-08-08 17:00:47 +020080 android.R.interpolator.linear_out_slow_in);
John Spurlockd06aa572014-09-10 10:40:49 -040081 mDozeParameters = new DozeParameters(context);
Jorim Jaggiecc798e2014-05-26 18:14:37 +020082 }
83
84 public void setKeyguardShowing(boolean showing) {
85 mKeyguardShowing = showing;
86 scheduleUpdate();
87 }
88
89 public void onTrackingStarted() {
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +020090 mExpanding = true;
Jorim Jaggiecc798e2014-05-26 18:14:37 +020091 mDarkenWhileDragging = !mUnlockMethodCache.isMethodInsecure();
92 }
93
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +020094 public void onExpandingFinished() {
95 mExpanding = false;
96 }
97
Jorim Jaggiecc798e2014-05-26 18:14:37 +020098 public void setPanelExpansion(float fraction) {
Jorim Jaggi93439da2014-06-30 23:53:39 +020099 if (mFraction != fraction) {
100 mFraction = fraction;
101 scheduleUpdate();
102 }
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200103 }
104
105 public void setBouncerShowing(boolean showing) {
106 mBouncerShowing = showing;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200107 mAnimateChange = !mExpanding;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200108 scheduleUpdate();
109 }
110
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200111 public void animateKeyguardFadingOut(long delay, long duration, Runnable onAnimationFinished) {
112 mAnimateKeyguardFadingOut = true;
113 mDurationOverride = duration;
114 mAnimationDelay = delay;
115 mAnimateChange = true;
116 mOnAnimationFinished = onAnimationFinished;
117 scheduleUpdate();
118 }
119
Jorim Jaggidbc3dce2014-08-01 01:16:36 +0200120 public void animateGoingToFullShade(long delay, long duration) {
121 mDurationOverride = duration;
122 mAnimationDelay = delay;
123 mAnimateChange = true;
124 scheduleUpdate();
125 }
126
John Spurlockbf370992014-06-17 13:58:31 -0400127 public void setDozing(boolean dozing) {
128 if (mDozing == dozing) return;
129 mDozing = dozing;
130 if (!mDozing) {
John Spurlockcb566aa2014-08-03 22:58:28 -0400131 cancelPulsing();
John Spurlock8b12f222014-09-09 11:54:11 -0400132 mAnimateChange = true;
John Spurlock190d0262014-09-14 15:39:13 -0400133 } else {
134 mAnimateChange = false;
John Spurlockbf370992014-06-17 13:58:31 -0400135 }
136 scheduleUpdate();
137 }
138
John Spurlockd06aa572014-09-10 10:40:49 -0400139 /** When dozing, fade screen contents in and out using the front scrim. */
John Spurlock190d0262014-09-14 15:39:13 -0400140 public long pulse() {
John Spurlockbf370992014-06-17 13:58:31 -0400141 if (!mDozing) return 0;
John Spurlockd06aa572014-09-10 10:40:49 -0400142 final long now = System.currentTimeMillis();
John Spurlock190d0262014-09-14 15:39:13 -0400143 if (DEBUG) Log.d(TAG, "pulse mPulseEndTime=" + mPulseEndTime + " now=" + now);
John Spurlockd06aa572014-09-10 10:40:49 -0400144 if (mPulseEndTime != 0 && mPulseEndTime > now) return mPulseEndTime - now;
John Spurlock190d0262014-09-14 15:39:13 -0400145 mScrimInFront.post(mPulseIn);
146 mPulseEndTime = now + mDozeParameters.getPulseDuration();
John Spurlockd06aa572014-09-10 10:40:49 -0400147 return mPulseEndTime - now;
148 }
149
150 public boolean isPulsing() {
151 return mDozing && mPulseEndTime != 0;
John Spurlockbf370992014-06-17 13:58:31 -0400152 }
153
John Spurlockcb566aa2014-08-03 22:58:28 -0400154 private void cancelPulsing() {
John Spurlockd06aa572014-09-10 10:40:49 -0400155 if (DEBUG) Log.d(TAG, "Cancel pulsing");
John Spurlockcb566aa2014-08-03 22:58:28 -0400156 mScrimInFront.removeCallbacks(mPulseIn);
157 mScrimInFront.removeCallbacks(mPulseOut);
John Spurlockd06aa572014-09-10 10:40:49 -0400158 mPulseEndTime = 0;
John Spurlockbf370992014-06-17 13:58:31 -0400159 }
160
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200161 private void scheduleUpdate() {
162 if (mUpdatePending) return;
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200163
164 // Make sure that a frame gets scheduled.
165 mScrimBehind.invalidate();
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200166 mScrimBehind.getViewTreeObserver().addOnPreDrawListener(this);
167 mUpdatePending = true;
168 }
169
170 private void updateScrims() {
Selim Cinekbaa23272014-07-08 18:01:07 +0200171 if (mAnimateKeyguardFadingOut) {
172 setScrimInFrontColor(0f);
173 setScrimBehindColor(0f);
John Spurlock8b12f222014-09-09 11:54:11 -0400174 } else if (!mKeyguardShowing && !mBouncerShowing) {
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200175 updateScrimNormal();
176 setScrimInFrontColor(0);
177 } else {
178 updateScrimKeyguard();
179 }
180 mAnimateChange = false;
181 }
182
183 private void updateScrimKeyguard() {
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200184 if (mExpanding && mDarkenWhileDragging) {
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200185 float behindFraction = Math.max(0, Math.min(mFraction, 1));
186 float fraction = 1 - behindFraction;
Jorim Jaggi76a16232014-08-08 17:00:47 +0200187 fraction = (float) Math.pow(fraction, 0.8f);
188 behindFraction = (float) Math.pow(behindFraction, 0.8f);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200189 setScrimInFrontColor(fraction * SCRIM_IN_FRONT_ALPHA);
190 setScrimBehindColor(behindFraction * SCRIM_BEHIND_ALPHA_KEYGUARD);
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200191 } else if (mBouncerShowing) {
192 setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA);
193 setScrimBehindColor(0f);
John Spurlockbf370992014-06-17 13:58:31 -0400194 } else if (mDozing) {
195 setScrimInFrontColor(1);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200196 } else {
Jorim Jaggi76a16232014-08-08 17:00:47 +0200197 float fraction = Math.max(0, Math.min(mFraction, 1));
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200198 setScrimInFrontColor(0f);
Jorim Jaggi76a16232014-08-08 17:00:47 +0200199 setScrimBehindColor(fraction
200 * (SCRIM_BEHIND_ALPHA_KEYGUARD - SCRIM_BEHIND_ALPHA_UNLOCKING)
201 + SCRIM_BEHIND_ALPHA_UNLOCKING);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200202 }
203 }
204
205 private void updateScrimNormal() {
206 float frac = mFraction;
207 // let's start this 20% of the way down the screen
208 frac = frac * 1.2f - 0.2f;
209 if (frac <= 0) {
210 setScrimBehindColor(0);
211 } else {
212 // woo, special effects
213 final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
214 setScrimBehindColor(k * SCRIM_BEHIND_ALPHA);
215 }
216 }
217
218 private void setScrimBehindColor(float alpha) {
219 setScrimColor(mScrimBehind, alpha);
220 }
221
222 private void setScrimInFrontColor(float alpha) {
223 setScrimColor(mScrimInFront, alpha);
224 if (alpha == 0f) {
225 mScrimInFront.setClickable(false);
226 } else {
227
John Spurlock8b12f222014-09-09 11:54:11 -0400228 // Eat touch events (unless dozing).
229 mScrimInFront.setClickable(!mDozing);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200230 }
231 }
232
233 private void setScrimColor(View scrim, float alpha) {
234 int color = Color.argb((int) (alpha * 255), 0, 0, 0);
235 if (mAnimateChange) {
236 startScrimAnimation(scrim, color);
237 } else {
238 scrim.setBackgroundColor(color);
239 }
240 }
241
242 private void startScrimAnimation(final View scrim, int targetColor) {
243 int current = getBackgroundAlpha(scrim);
244 int target = Color.alpha(targetColor);
245 if (current == targetColor) {
246 return;
247 }
John Spurlockbf370992014-06-17 13:58:31 -0400248 Object runningAnim = scrim.getTag(TAG_KEY_ANIM);
249 if (runningAnim instanceof ValueAnimator) {
250 ((ValueAnimator) runningAnim).cancel();
251 }
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200252 ValueAnimator anim = ValueAnimator.ofInt(current, target);
253 anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
254 @Override
255 public void onAnimationUpdate(ValueAnimator animation) {
256 int value = (int) animation.getAnimatedValue();
257 scrim.setBackgroundColor(Color.argb(value, 0, 0, 0));
258 }
259 });
Jorim Jaggi76a16232014-08-08 17:00:47 +0200260 anim.setInterpolator(mAnimateKeyguardFadingOut
261 ? mLinearOutSlowInInterpolator
262 : mInterpolator);
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200263 anim.setStartDelay(mAnimationDelay);
264 anim.setDuration(mDurationOverride != -1 ? mDurationOverride : ANIMATION_DURATION);
265 anim.addListener(new AnimatorListenerAdapter() {
266
267 @Override
268 public void onAnimationEnd(Animator animation) {
269 if (mOnAnimationFinished != null) {
270 mOnAnimationFinished.run();
271 mOnAnimationFinished = null;
272 }
John Spurlockbf370992014-06-17 13:58:31 -0400273 scrim.setTag(TAG_KEY_ANIM, null);
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200274 }
275 });
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200276 anim.start();
John Spurlockbf370992014-06-17 13:58:31 -0400277 scrim.setTag(TAG_KEY_ANIM, anim);
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200278 mAnimationStarted = true;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200279 }
280
281 private int getBackgroundAlpha(View scrim) {
282 if (scrim.getBackground() instanceof ColorDrawable) {
283 ColorDrawable drawable = (ColorDrawable) scrim.getBackground();
284 return Color.alpha(drawable.getColor());
285 } else {
286 return 0;
287 }
288 }
289
290 @Override
291 public boolean onPreDraw() {
292 mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this);
293 mUpdatePending = false;
294 updateScrims();
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200295 mAnimateKeyguardFadingOut = false;
296 mDurationOverride = -1;
297 mAnimationDelay = 0;
298
299 // Make sure that we always call the listener even if we didn't start an animation.
300 if (!mAnimationStarted && mOnAnimationFinished != null) {
301 mOnAnimationFinished.run();
302 mOnAnimationFinished = null;
303 }
304 mAnimationStarted = false;
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200305 return true;
306 }
John Spurlockbf370992014-06-17 13:58:31 -0400307
John Spurlockcb566aa2014-08-03 22:58:28 -0400308 private final Runnable mPulseIn = new Runnable() {
John Spurlockbf370992014-06-17 13:58:31 -0400309 @Override
310 public void run() {
John Spurlockd06aa572014-09-10 10:40:49 -0400311 if (DEBUG) Log.d(TAG, "Pulse in, mDozing=" + mDozing);
312 if (!mDozing) return;
John Spurlock813552c2014-09-19 08:30:21 -0400313 DozeLog.tracePulseStart();
John Spurlockd06aa572014-09-10 10:40:49 -0400314 mDurationOverride = mDozeParameters.getPulseInDuration();
John Spurlockbf370992014-06-17 13:58:31 -0400315 mAnimationDelay = 0;
316 mAnimateChange = true;
John Spurlockcb566aa2014-08-03 22:58:28 -0400317 mOnAnimationFinished = mPulseInFinished;
John Spurlockbf370992014-06-17 13:58:31 -0400318 setScrimColor(mScrimInFront, 0);
319 }
320 };
321
John Spurlockcb566aa2014-08-03 22:58:28 -0400322 private final Runnable mPulseInFinished = new Runnable() {
John Spurlockbf370992014-06-17 13:58:31 -0400323 @Override
324 public void run() {
John Spurlockcb566aa2014-08-03 22:58:28 -0400325 if (DEBUG) Log.d(TAG, "Pulse in finished, mDozing=" + mDozing);
John Spurlockbf370992014-06-17 13:58:31 -0400326 if (!mDozing) return;
John Spurlockd06aa572014-09-10 10:40:49 -0400327 mScrimInFront.postDelayed(mPulseOut, mDozeParameters.getPulseVisibleDuration());
John Spurlockbf370992014-06-17 13:58:31 -0400328 }
329 };
330
John Spurlockcb566aa2014-08-03 22:58:28 -0400331 private final Runnable mPulseOut = new Runnable() {
John Spurlockbf370992014-06-17 13:58:31 -0400332 @Override
333 public void run() {
John Spurlockcb566aa2014-08-03 22:58:28 -0400334 if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
John Spurlockbf370992014-06-17 13:58:31 -0400335 if (!mDozing) return;
John Spurlockd06aa572014-09-10 10:40:49 -0400336 mDurationOverride = mDozeParameters.getPulseOutDuration();
John Spurlockbf370992014-06-17 13:58:31 -0400337 mAnimationDelay = 0;
338 mAnimateChange = true;
John Spurlockcb566aa2014-08-03 22:58:28 -0400339 mOnAnimationFinished = mPulseOutFinished;
John Spurlockbf370992014-06-17 13:58:31 -0400340 setScrimColor(mScrimInFront, 1);
341 }
342 };
343
John Spurlockcb566aa2014-08-03 22:58:28 -0400344 private final Runnable mPulseOutFinished = new Runnable() {
John Spurlockbf370992014-06-17 13:58:31 -0400345 @Override
346 public void run() {
John Spurlockd06aa572014-09-10 10:40:49 -0400347 if (DEBUG) Log.d(TAG, "Pulse out finished");
John Spurlock813552c2014-09-19 08:30:21 -0400348 DozeLog.tracePulseFinish();
John Spurlockd06aa572014-09-10 10:40:49 -0400349 mPulseEndTime = 0;
John Spurlockbf370992014-06-17 13:58:31 -0400350 }
351 };
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200352}