1 /* 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 17 package com.android.systemui.statusbar.phone; 18 19 import android.animation.TimeInterpolator; 20 import android.app.ActivityManager; 21 import android.content.Context; 22 import android.content.res.Resources; 23 import android.graphics.Canvas; 24 import android.graphics.Color; 25 import android.graphics.ColorFilter; 26 import android.graphics.PixelFormat; 27 import android.graphics.Rect; 28 import android.graphics.drawable.Drawable; 29 import android.os.SystemClock; 30 import android.util.Log; 31 import android.view.View; 32 import android.view.animation.LinearInterpolator; 33 34 import com.android.systemui.R; 35 36 public class BarTransitions { 37 private static final boolean DEBUG = false; 38 private static final boolean DEBUG_COLORS = false; 39 40 public static final boolean HIGH_END = ActivityManager.isHighEndGfx(); 41 42 public static final int MODE_OPAQUE = 0; 43 public static final int MODE_SEMI_TRANSPARENT = 1; 44 public static final int MODE_TRANSLUCENT = 2; 45 public static final int MODE_LIGHTS_OUT = 3; 46 public static final int MODE_TRANSPARENT = 4; 47 public static final int MODE_WARNING = 5; 48 public static final int MODE_LIGHTS_OUT_TRANSPARENT = 6; 49 50 public static final int LIGHTS_IN_DURATION = 250; 51 public static final int LIGHTS_OUT_DURATION = 750; 52 public static final int BACKGROUND_DURATION = 200; 53 54 private final String mTag; 55 private final View mView; 56 private final BarBackgroundDrawable mBarBackground; 57 58 private int mMode; 59 BarTransitions(View view, int gradientResourceId)60 public BarTransitions(View view, int gradientResourceId) { 61 mTag = "BarTransitions." + view.getClass().getSimpleName(); 62 mView = view; 63 mBarBackground = new BarBackgroundDrawable(mView.getContext(), gradientResourceId); 64 if (HIGH_END) { 65 mView.setBackground(mBarBackground); 66 } 67 } 68 getMode()69 public int getMode() { 70 return mMode; 71 } 72 transitionTo(int mode, boolean animate)73 public void transitionTo(int mode, boolean animate) { 74 // low-end devices do not support translucent modes, fallback to opaque 75 if (!HIGH_END && (mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT 76 || mode == MODE_TRANSPARENT)) { 77 mode = MODE_OPAQUE; 78 } 79 if (!HIGH_END && (mode == MODE_LIGHTS_OUT_TRANSPARENT)) { 80 mode = MODE_LIGHTS_OUT; 81 } 82 if (mMode == mode) return; 83 int oldMode = mMode; 84 mMode = mode; 85 if (DEBUG) Log.d(mTag, String.format("%s -> %s animate=%s", 86 modeToString(oldMode), modeToString(mode), animate)); 87 onTransition(oldMode, mMode, animate); 88 } 89 onTransition(int oldMode, int newMode, boolean animate)90 protected void onTransition(int oldMode, int newMode, boolean animate) { 91 if (HIGH_END) { 92 applyModeBackground(oldMode, newMode, animate); 93 } 94 } 95 applyModeBackground(int oldMode, int newMode, boolean animate)96 protected void applyModeBackground(int oldMode, int newMode, boolean animate) { 97 if (DEBUG) Log.d(mTag, String.format("applyModeBackground oldMode=%s newMode=%s animate=%s", 98 modeToString(oldMode), modeToString(newMode), animate)); 99 mBarBackground.applyModeBackground(oldMode, newMode, animate); 100 } 101 modeToString(int mode)102 public static String modeToString(int mode) { 103 if (mode == MODE_OPAQUE) return "MODE_OPAQUE"; 104 if (mode == MODE_SEMI_TRANSPARENT) return "MODE_SEMI_TRANSPARENT"; 105 if (mode == MODE_TRANSLUCENT) return "MODE_TRANSLUCENT"; 106 if (mode == MODE_LIGHTS_OUT) return "MODE_LIGHTS_OUT"; 107 if (mode == MODE_TRANSPARENT) return "MODE_TRANSPARENT"; 108 if (mode == MODE_WARNING) return "MODE_WARNING"; 109 if (mode == MODE_LIGHTS_OUT_TRANSPARENT) return "MODE_LIGHTS_OUT_TRANSPARENT"; 110 throw new IllegalArgumentException("Unknown mode " + mode); 111 } 112 finishAnimations()113 public void finishAnimations() { 114 mBarBackground.finishAnimation(); 115 } 116 isLightsOut(int mode)117 protected boolean isLightsOut(int mode) { 118 return mode == MODE_LIGHTS_OUT || mode == MODE_LIGHTS_OUT_TRANSPARENT; 119 } 120 121 private static class BarBackgroundDrawable extends Drawable { 122 private final int mOpaque; 123 private final int mSemiTransparent; 124 private final int mTransparent; 125 private final int mWarning; 126 private final Drawable mGradient; 127 private final TimeInterpolator mInterpolator; 128 129 private int mMode = -1; 130 private boolean mAnimating; 131 private long mStartTime; 132 private long mEndTime; 133 134 private int mGradientAlpha; 135 private int mColor; 136 137 private int mGradientAlphaStart; 138 private int mColorStart; 139 BarBackgroundDrawable(Context context, int gradientResourceId)140 public BarBackgroundDrawable(Context context, int gradientResourceId) { 141 final Resources res = context.getResources(); 142 if (DEBUG_COLORS) { 143 mOpaque = 0xff0000ff; 144 mSemiTransparent = 0x7f0000ff; 145 mTransparent = 0x2f0000ff; 146 mWarning = 0xffff0000; 147 } else { 148 mOpaque = context.getColor(R.color.system_bar_background_opaque); 149 mSemiTransparent = context.getColor(R.color.system_bar_background_semi_transparent); 150 mTransparent = context.getColor(R.color.system_bar_background_transparent); 151 mWarning = context.getColor(com.android.internal.R.color.battery_saver_mode_color); 152 } 153 mGradient = context.getDrawable(gradientResourceId); 154 mInterpolator = new LinearInterpolator(); 155 } 156 157 @Override setAlpha(int alpha)158 public void setAlpha(int alpha) { 159 // noop 160 } 161 162 @Override setColorFilter(ColorFilter colorFilter)163 public void setColorFilter(ColorFilter colorFilter) { 164 // noop 165 } 166 167 @Override onBoundsChange(Rect bounds)168 protected void onBoundsChange(Rect bounds) { 169 super.onBoundsChange(bounds); 170 mGradient.setBounds(bounds); 171 } 172 applyModeBackground(int oldMode, int newMode, boolean animate)173 public void applyModeBackground(int oldMode, int newMode, boolean animate) { 174 if (mMode == newMode) return; 175 mMode = newMode; 176 mAnimating = animate; 177 if (animate) { 178 long now = SystemClock.elapsedRealtime(); 179 mStartTime = now; 180 mEndTime = now + BACKGROUND_DURATION; 181 mGradientAlphaStart = mGradientAlpha; 182 mColorStart = mColor; 183 } 184 invalidateSelf(); 185 } 186 187 @Override getOpacity()188 public int getOpacity() { 189 return PixelFormat.TRANSLUCENT; 190 } 191 finishAnimation()192 public void finishAnimation() { 193 if (mAnimating) { 194 mAnimating = false; 195 invalidateSelf(); 196 } 197 } 198 199 @Override draw(Canvas canvas)200 public void draw(Canvas canvas) { 201 int targetGradientAlpha = 0, targetColor = 0; 202 if (mMode == MODE_WARNING) { 203 targetColor = mWarning; 204 } else if (mMode == MODE_TRANSLUCENT) { 205 targetColor = mSemiTransparent; 206 } else if (mMode == MODE_SEMI_TRANSPARENT) { 207 targetColor = mSemiTransparent; 208 } else if (mMode == MODE_TRANSPARENT || mMode == MODE_LIGHTS_OUT_TRANSPARENT) { 209 targetColor = mTransparent; 210 } else { 211 targetColor = mOpaque; 212 } 213 if (!mAnimating) { 214 mColor = targetColor; 215 mGradientAlpha = targetGradientAlpha; 216 } else { 217 final long now = SystemClock.elapsedRealtime(); 218 if (now >= mEndTime) { 219 mAnimating = false; 220 mColor = targetColor; 221 mGradientAlpha = targetGradientAlpha; 222 } else { 223 final float t = (now - mStartTime) / (float)(mEndTime - mStartTime); 224 final float v = Math.max(0, Math.min(mInterpolator.getInterpolation(t), 1)); 225 mGradientAlpha = (int)(v * targetGradientAlpha + mGradientAlphaStart * (1 - v)); 226 mColor = Color.argb( 227 (int)(v * Color.alpha(targetColor) + Color.alpha(mColorStart) * (1 - v)), 228 (int)(v * Color.red(targetColor) + Color.red(mColorStart) * (1 - v)), 229 (int)(v * Color.green(targetColor) + Color.green(mColorStart) * (1 - v)), 230 (int)(v * Color.blue(targetColor) + Color.blue(mColorStart) * (1 - v))); 231 } 232 } 233 if (mGradientAlpha > 0) { 234 mGradient.setAlpha(mGradientAlpha); 235 mGradient.draw(canvas); 236 } 237 if (Color.alpha(mColor) > 0) { 238 canvas.drawColor(mColor); 239 } 240 if (mAnimating) { 241 invalidateSelf(); // keep going 242 } 243 } 244 } 245 } 246