blob: ed71e5708ce1fd801c15bc5e5877e10cbd87aa2a [file] [log] [blame]
John Spurlocke932e302013-08-12 10:16:29 -04001/*
2 * Copyright (C) 2013 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.app.ActivityManager;
John Spurlock42197262013-10-21 09:32:25 -040020import android.content.Context;
John Spurlocke932e302013-08-12 10:16:29 -040021import android.content.res.Resources;
John Spurlock42197262013-10-21 09:32:25 -040022import android.graphics.Canvas;
23import android.graphics.Color;
24import android.graphics.ColorFilter;
Yorke Lee1b268cb2016-02-25 17:58:33 -080025import android.graphics.Paint;
John Spurlock42197262013-10-21 09:32:25 -040026import android.graphics.PixelFormat;
Yorke Lee1b268cb2016-02-25 17:58:33 -080027import android.graphics.PorterDuff;
28import android.graphics.PorterDuffColorFilter;
John Spurlock42197262013-10-21 09:32:25 -040029import android.graphics.Rect;
Yorke Lee1b268cb2016-02-25 17:58:33 -080030import android.graphics.PorterDuff.Mode;
John Spurlocke932e302013-08-12 10:16:29 -040031import android.graphics.drawable.Drawable;
John Spurlock42197262013-10-21 09:32:25 -040032import android.os.SystemClock;
John Spurlock27735a42013-08-14 17:57:38 -040033import android.util.Log;
John Spurlocke932e302013-08-12 10:16:29 -040034import android.view.View;
35
Winsonc0d70582016-01-29 10:24:39 -080036import com.android.systemui.Interpolators;
John Spurlocke932e302013-08-12 10:16:29 -040037import com.android.systemui.R;
38
39public class BarTransitions {
John Spurlock27735a42013-08-14 17:57:38 -040040 private static final boolean DEBUG = false;
John Spurlocke631b412013-09-18 16:33:57 -040041 private static final boolean DEBUG_COLORS = false;
John Spurlocke932e302013-08-12 10:16:29 -040042
John Spurlockfd0e6c02014-01-14 14:51:23 -050043 public static final boolean HIGH_END = ActivityManager.isHighEndGfx();
44
John Spurlock3b139a92013-08-17 17:18:08 -040045 public static final int MODE_OPAQUE = 0;
John Spurlock89835dd2013-08-16 15:06:51 -040046 public static final int MODE_SEMI_TRANSPARENT = 1;
John Spurlockbd957402013-10-03 11:38:39 -040047 public static final int MODE_TRANSLUCENT = 2;
John Spurlock7edfbca2013-09-14 11:58:55 -040048 public static final int MODE_LIGHTS_OUT = 3;
Adrian Roosea562512014-05-05 13:33:03 +020049 public static final int MODE_TRANSPARENT = 4;
John Spurlock0ff62e02014-07-22 16:15:08 -040050 public static final int MODE_WARNING = 5;
Adrian Roosc0f0a742014-10-28 16:39:56 +010051 public static final int MODE_LIGHTS_OUT_TRANSPARENT = 6;
John Spurlock7edfbca2013-09-14 11:58:55 -040052
John Spurlocke631b412013-09-18 16:33:57 -040053 public static final int LIGHTS_IN_DURATION = 250;
54 public static final int LIGHTS_OUT_DURATION = 750;
55 public static final int BACKGROUND_DURATION = 200;
John Spurlocke932e302013-08-12 10:16:29 -040056
John Spurlock27735a42013-08-14 17:57:38 -040057 private final String mTag;
John Spurlocke631b412013-09-18 16:33:57 -040058 private final View mView;
John Spurlock42197262013-10-21 09:32:25 -040059 private final BarBackgroundDrawable mBarBackground;
John Spurlocke631b412013-09-18 16:33:57 -040060
John Spurlocke932e302013-08-12 10:16:29 -040061 private int mMode;
Yorke Lee1b268cb2016-02-25 17:58:33 -080062 private boolean mAlwaysOpaque = false;
John Spurlock3b139a92013-08-17 17:18:08 -040063
John Spurlock7057d2c2013-10-02 10:00:37 -040064 public BarTransitions(View view, int gradientResourceId) {
John Spurlocke631b412013-09-18 16:33:57 -040065 mTag = "BarTransitions." + view.getClass().getSimpleName();
66 mView = view;
John Spurlock42197262013-10-21 09:32:25 -040067 mBarBackground = new BarBackgroundDrawable(mView.getContext(), gradientResourceId);
John Spurlockfd0e6c02014-01-14 14:51:23 -050068 if (HIGH_END) {
John Spurlock42197262013-10-21 09:32:25 -040069 mView.setBackground(mBarBackground);
John Spurlocke631b412013-09-18 16:33:57 -040070 }
71 }
72
John Spurlockb77edbf2013-08-21 21:04:12 -040073 public int getMode() {
74 return mMode;
75 }
76
Yorke Lee1b268cb2016-02-25 17:58:33 -080077 /**
78 * @param alwaysOpaque if {@code true}, the bar's background will always be opaque, regardless
79 * of what mode it is currently set to.
80 */
81 public void setAlwaysOpaque(boolean alwaysOpaque) {
82 mAlwaysOpaque = alwaysOpaque;
83 }
84
85 public boolean isAlwaysOpaque() {
86 // Low-end devices do not support translucent modes, fallback to opaque
87 return !HIGH_END || mAlwaysOpaque;
88 }
89
John Spurlock3b139a92013-08-17 17:18:08 -040090 public void transitionTo(int mode, boolean animate) {
Yorke Lee1b268cb2016-02-25 17:58:33 -080091 if (isAlwaysOpaque() && (mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT
Adrian Roosea562512014-05-05 13:33:03 +020092 || mode == MODE_TRANSPARENT)) {
John Spurlockfd0e6c02014-01-14 14:51:23 -050093 mode = MODE_OPAQUE;
94 }
Yorke Lee1b268cb2016-02-25 17:58:33 -080095 if (isAlwaysOpaque() && (mode == MODE_LIGHTS_OUT_TRANSPARENT)) {
Adrian Roosc0f0a742014-10-28 16:39:56 +010096 mode = MODE_LIGHTS_OUT;
97 }
John Spurlock89835dd2013-08-16 15:06:51 -040098 if (mMode == mode) return;
99 int oldMode = mMode;
John Spurlocke932e302013-08-12 10:16:29 -0400100 mMode = mode;
John Spurlocke631b412013-09-18 16:33:57 -0400101 if (DEBUG) Log.d(mTag, String.format("%s -> %s animate=%s",
102 modeToString(oldMode), modeToString(mode), animate));
John Spurlockfd0e6c02014-01-14 14:51:23 -0500103 onTransition(oldMode, mMode, animate);
John Spurlock89835dd2013-08-16 15:06:51 -0400104 }
105
John Spurlock3b139a92013-08-17 17:18:08 -0400106 protected void onTransition(int oldMode, int newMode, boolean animate) {
John Spurlockfd0e6c02014-01-14 14:51:23 -0500107 if (HIGH_END) {
108 applyModeBackground(oldMode, newMode, animate);
109 }
John Spurlocke631b412013-09-18 16:33:57 -0400110 }
111
112 protected void applyModeBackground(int oldMode, int newMode, boolean animate) {
John Spurlock42197262013-10-21 09:32:25 -0400113 if (DEBUG) Log.d(mTag, String.format("applyModeBackground oldMode=%s newMode=%s animate=%s",
114 modeToString(oldMode), modeToString(newMode), animate));
115 mBarBackground.applyModeBackground(oldMode, newMode, animate);
John Spurlocke932e302013-08-12 10:16:29 -0400116 }
John Spurlock27735a42013-08-14 17:57:38 -0400117
118 public static String modeToString(int mode) {
John Spurlock3b139a92013-08-17 17:18:08 -0400119 if (mode == MODE_OPAQUE) return "MODE_OPAQUE";
John Spurlock89835dd2013-08-16 15:06:51 -0400120 if (mode == MODE_SEMI_TRANSPARENT) return "MODE_SEMI_TRANSPARENT";
John Spurlockbd957402013-10-03 11:38:39 -0400121 if (mode == MODE_TRANSLUCENT) return "MODE_TRANSLUCENT";
John Spurlock7edfbca2013-09-14 11:58:55 -0400122 if (mode == MODE_LIGHTS_OUT) return "MODE_LIGHTS_OUT";
Adrian Roosea562512014-05-05 13:33:03 +0200123 if (mode == MODE_TRANSPARENT) return "MODE_TRANSPARENT";
John Spurlock0ff62e02014-07-22 16:15:08 -0400124 if (mode == MODE_WARNING) return "MODE_WARNING";
Adrian Roosc0f0a742014-10-28 16:39:56 +0100125 if (mode == MODE_LIGHTS_OUT_TRANSPARENT) return "MODE_LIGHTS_OUT_TRANSPARENT";
John Spurlock27735a42013-08-14 17:57:38 -0400126 throw new IllegalArgumentException("Unknown mode " + mode);
127 }
John Spurlock42197262013-10-21 09:32:25 -0400128
129 public void finishAnimations() {
130 mBarBackground.finishAnimation();
131 }
132
Adrian Roosc0f0a742014-10-28 16:39:56 +0100133 protected boolean isLightsOut(int mode) {
134 return mode == MODE_LIGHTS_OUT || mode == MODE_LIGHTS_OUT_TRANSPARENT;
135 }
136
John Spurlock42197262013-10-21 09:32:25 -0400137 private static class BarBackgroundDrawable extends Drawable {
138 private final int mOpaque;
139 private final int mSemiTransparent;
Adrian Roosea562512014-05-05 13:33:03 +0200140 private final int mTransparent;
John Spurlock0ff62e02014-07-22 16:15:08 -0400141 private final int mWarning;
John Spurlock42197262013-10-21 09:32:25 -0400142 private final Drawable mGradient;
John Spurlock42197262013-10-21 09:32:25 -0400143
144 private int mMode = -1;
145 private boolean mAnimating;
146 private long mStartTime;
147 private long mEndTime;
148
149 private int mGradientAlpha;
150 private int mColor;
Yorke Lee1b268cb2016-02-25 17:58:33 -0800151 private PorterDuffColorFilter mTintFilter;
152 private Paint mPaint = new Paint();
John Spurlock42197262013-10-21 09:32:25 -0400153
154 private int mGradientAlphaStart;
155 private int mColorStart;
156
Yorke Lee1b268cb2016-02-25 17:58:33 -0800157
John Spurlock42197262013-10-21 09:32:25 -0400158 public BarBackgroundDrawable(Context context, int gradientResourceId) {
159 final Resources res = context.getResources();
160 if (DEBUG_COLORS) {
161 mOpaque = 0xff0000ff;
162 mSemiTransparent = 0x7f0000ff;
Adrian Roosea562512014-05-05 13:33:03 +0200163 mTransparent = 0x2f0000ff;
John Spurlock0ff62e02014-07-22 16:15:08 -0400164 mWarning = 0xffff0000;
John Spurlock42197262013-10-21 09:32:25 -0400165 } else {
Alan Viverette4a357cd2015-03-18 18:37:18 -0700166 mOpaque = context.getColor(R.color.system_bar_background_opaque);
Jorim Jaggi4fa78922015-11-30 17:13:56 -0800167 mSemiTransparent = context.getColor(
168 com.android.internal.R.color.system_bar_background_semi_transparent);
Alan Viverette4a357cd2015-03-18 18:37:18 -0700169 mTransparent = context.getColor(R.color.system_bar_background_transparent);
170 mWarning = context.getColor(com.android.internal.R.color.battery_saver_mode_color);
John Spurlock42197262013-10-21 09:32:25 -0400171 }
Alan Viverette4a357cd2015-03-18 18:37:18 -0700172 mGradient = context.getDrawable(gradientResourceId);
John Spurlock42197262013-10-21 09:32:25 -0400173 }
174
175 @Override
176 public void setAlpha(int alpha) {
177 // noop
178 }
179
180 @Override
Chris Craikbd3bfc52015-03-02 10:43:29 -0800181 public void setColorFilter(ColorFilter colorFilter) {
John Spurlock42197262013-10-21 09:32:25 -0400182 // noop
183 }
184
185 @Override
Yorke Lee1b268cb2016-02-25 17:58:33 -0800186 public void setTint(int color) {
187 if (mTintFilter == null) {
188 mTintFilter = new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN);
189 } else {
190 mTintFilter.setColor(color);
191 }
192 invalidateSelf();
193 }
194
195 @Override
196 public void setTintMode(Mode tintMode) {
197 if (mTintFilter == null) {
198 mTintFilter = new PorterDuffColorFilter(0, tintMode);
199 } else {
200 mTintFilter.setMode(tintMode);
201 }
202 invalidateSelf();
203 }
204
205 @Override
John Spurlock42197262013-10-21 09:32:25 -0400206 protected void onBoundsChange(Rect bounds) {
207 super.onBoundsChange(bounds);
208 mGradient.setBounds(bounds);
209 }
210
211 public void applyModeBackground(int oldMode, int newMode, boolean animate) {
212 if (mMode == newMode) return;
213 mMode = newMode;
214 mAnimating = animate;
215 if (animate) {
216 long now = SystemClock.elapsedRealtime();
217 mStartTime = now;
218 mEndTime = now + BACKGROUND_DURATION;
219 mGradientAlphaStart = mGradientAlpha;
220 mColorStart = mColor;
221 }
222 invalidateSelf();
223 }
224
225 @Override
226 public int getOpacity() {
227 return PixelFormat.TRANSLUCENT;
228 }
229
230 public void finishAnimation() {
231 if (mAnimating) {
232 mAnimating = false;
233 invalidateSelf();
234 }
235 }
236
237 @Override
238 public void draw(Canvas canvas) {
239 int targetGradientAlpha = 0, targetColor = 0;
John Spurlock0ff62e02014-07-22 16:15:08 -0400240 if (mMode == MODE_WARNING) {
241 targetColor = mWarning;
242 } else if (mMode == MODE_TRANSLUCENT) {
Adrian Roosea562512014-05-05 13:33:03 +0200243 targetColor = mSemiTransparent;
John Spurlock42197262013-10-21 09:32:25 -0400244 } else if (mMode == MODE_SEMI_TRANSPARENT) {
245 targetColor = mSemiTransparent;
Adrian Roosc0f0a742014-10-28 16:39:56 +0100246 } else if (mMode == MODE_TRANSPARENT || mMode == MODE_LIGHTS_OUT_TRANSPARENT) {
Adrian Roosea562512014-05-05 13:33:03 +0200247 targetColor = mTransparent;
John Spurlock42197262013-10-21 09:32:25 -0400248 } else {
249 targetColor = mOpaque;
250 }
Yorke Lee1b268cb2016-02-25 17:58:33 -0800251
John Spurlock42197262013-10-21 09:32:25 -0400252 if (!mAnimating) {
253 mColor = targetColor;
254 mGradientAlpha = targetGradientAlpha;
255 } else {
256 final long now = SystemClock.elapsedRealtime();
257 if (now >= mEndTime) {
258 mAnimating = false;
259 mColor = targetColor;
260 mGradientAlpha = targetGradientAlpha;
261 } else {
262 final float t = (now - mStartTime) / (float)(mEndTime - mStartTime);
Selim Cinekc18010f2016-01-20 13:41:30 -0800263 final float v = Math.max(0, Math.min(
264 Interpolators.LINEAR.getInterpolation(t), 1));
John Spurlock42197262013-10-21 09:32:25 -0400265 mGradientAlpha = (int)(v * targetGradientAlpha + mGradientAlphaStart * (1 - v));
266 mColor = Color.argb(
267 (int)(v * Color.alpha(targetColor) + Color.alpha(mColorStart) * (1 - v)),
268 (int)(v * Color.red(targetColor) + Color.red(mColorStart) * (1 - v)),
269 (int)(v * Color.green(targetColor) + Color.green(mColorStart) * (1 - v)),
270 (int)(v * Color.blue(targetColor) + Color.blue(mColorStart) * (1 - v)));
271 }
272 }
273 if (mGradientAlpha > 0) {
274 mGradient.setAlpha(mGradientAlpha);
275 mGradient.draw(canvas);
276 }
277 if (Color.alpha(mColor) > 0) {
Yorke Lee1b268cb2016-02-25 17:58:33 -0800278 mPaint.setColor(mColor);
279 if (mTintFilter != null) {
280 mPaint.setColorFilter(mTintFilter);
281 }
282 canvas.drawPaint(mPaint);
John Spurlock42197262013-10-21 09:32:25 -0400283 }
284 if (mAnimating) {
285 invalidateSelf(); // keep going
286 }
287 }
288 }
John Spurlocke932e302013-08-12 10:16:29 -0400289}