BackgroundManager.java revision 60c3b420827d0520509387f1abe3e3d8168e2279
117993c442c26161f684d6c0c6867a746f3148548Craig Stout/* 217993c442c26161f684d6c0c6867a746f3148548Craig Stout * Copyright (C) 2014 The Android Open Source Project 317993c442c26161f684d6c0c6867a746f3148548Craig Stout * 417993c442c26161f684d6c0c6867a746f3148548Craig Stout * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 517993c442c26161f684d6c0c6867a746f3148548Craig Stout * in compliance with the License. You may obtain a copy of the License at 617993c442c26161f684d6c0c6867a746f3148548Craig Stout * 717993c442c26161f684d6c0c6867a746f3148548Craig Stout * http://www.apache.org/licenses/LICENSE-2.0 817993c442c26161f684d6c0c6867a746f3148548Craig Stout * 917993c442c26161f684d6c0c6867a746f3148548Craig Stout * Unless required by applicable law or agreed to in writing, software distributed under the License 1017993c442c26161f684d6c0c6867a746f3148548Craig Stout * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 1117993c442c26161f684d6c0c6867a746f3148548Craig Stout * or implied. See the License for the specific language governing permissions and limitations under 1217993c442c26161f684d6c0c6867a746f3148548Craig Stout * the License. 1317993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 1417993c442c26161f684d6c0c6867a746f3148548Craig Stoutpackage android.support.v17.leanback.app; 1517993c442c26161f684d6c0c6867a746f3148548Craig Stout 1660c3b420827d0520509387f1abe3e3d8168e2279Dake Guimport java.lang.ref.WeakReference; 1760c3b420827d0520509387f1abe3e3d8168e2279Dake Gu 1817993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.support.v17.leanback.R; 193d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stoutimport android.animation.Animator; 207e22f555da71f49a32420965817c760522b95963Craig Stoutimport android.animation.ValueAnimator; 2117993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.app.Activity; 2217993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.content.Context; 237f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stoutimport android.content.res.Resources; 2417993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.content.res.TypedArray; 2517993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.Bitmap; 267f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stoutimport android.graphics.Canvas; 2717993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.Color; 287f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stoutimport android.graphics.ColorFilter; 2917993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.Matrix; 307f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stoutimport android.graphics.Paint; 3117993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.ColorDrawable; 3217993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.Drawable; 3317993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.LayerDrawable; 3417993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.os.Handler; 3517993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.util.Log; 3617993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.LayoutInflater; 3717993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.View; 3817993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.ViewGroup; 3917993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.Window; 4017993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.WindowManager; 417e22f555da71f49a32420965817c760522b95963Craig Stoutimport android.view.animation.Interpolator; 4217993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.animation.LinearInterpolator; 4360c3b420827d0520509387f1abe3e3d8168e2279Dake Guimport android.support.v4.content.ContextCompat; 4417993c442c26161f684d6c0c6867a746f3148548Craig Stout 4517993c442c26161f684d6c0c6867a746f3148548Craig Stout/** 46146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Supports background image continuity between multiple Activities. 4717993c442c26161f684d6c0c6867a746f3148548Craig Stout * 48146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>An Activity should instantiate a BackgroundManager and {@link #attach} 49146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * to the Activity's window. When the Activity is started, the background is 5017993c442c26161f684d6c0c6867a746f3148548Craig Stout * initialized to the current background values stored in a continuity service. 5117993c442c26161f684d6c0c6867a746f3148548Craig Stout * The background continuity service is updated as the background is updated. 5217993c442c26161f684d6c0c6867a746f3148548Craig Stout * 53146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>At some point, for example when it is stopped, the Activity may release 54146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * its background state. 552e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout * 56146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>When an Activity is resumed, if the BackgroundManager has not been 57146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * released, the continuity service is updated from the BackgroundManager state. 58146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * If the BackgroundManager was released, the BackgroundManager inherits the 59146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * current state from the continuity service. 6017993c442c26161f684d6c0c6867a746f3148548Craig Stout * 61146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>When the last Activity is destroyed, the background state is reset. 6217993c442c26161f684d6c0c6867a746f3148548Craig Stout * 63146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>Backgrounds consist of several layers, from back to front: 64146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <ul> 65146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <li>the background Drawable of the theme</li> 66146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <li>a solid color (set via {@link #setColor})</li> 67146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <li>two Drawables, previous and current (set via {@link #setBitmap} or 68146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * {@link #setDrawable}), which may be in transition</li> 69146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * </ul> 7017993c442c26161f684d6c0c6867a746f3148548Craig Stout * 71146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>BackgroundManager holds references to potentially large bitmap Drawables. 72146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Call {@link #release} to release these references when the Activity is not 7317993c442c26161f684d6c0c6867a746f3148548Craig Stout * visible. 7417993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 75146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn// TODO: support for multiple app processes requires a proper android service 76146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn// instead of the shared memory "service" implemented here. Such a service could 77146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn// support continuity between fragments of different applications if desired. 7817993c442c26161f684d6c0c6867a746f3148548Craig Stoutpublic final class BackgroundManager { 7917993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final String TAG = "BackgroundManager"; 8017993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final boolean DEBUG = false; 8117993c442c26161f684d6c0c6867a746f3148548Craig Stout 8217993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final int FULL_ALPHA = 255; 8317993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final int DIM_ALPHA_ON_SOLID = (int) (0.8f * FULL_ALPHA); 8417993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final int CHANGE_BG_DELAY_MS = 500; 853d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout private static final int FADE_DURATION = 500; 8617993c442c26161f684d6c0c6867a746f3148548Craig Stout 8717993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 8817993c442c26161f684d6c0c6867a746f3148548Craig Stout * Using a separate window for backgrounds can improve graphics performance by 8917993c442c26161f684d6c0c6867a746f3148548Craig Stout * leveraging hardware display layers. 9017993c442c26161f684d6c0c6867a746f3148548Craig Stout * TODO: support a leanback configuration option. 9117993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 9217993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final boolean USE_SEPARATE_WINDOW = false; 9317993c442c26161f684d6c0c6867a746f3148548Craig Stout 9417993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final String WINDOW_NAME = "BackgroundManager"; 957f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu private static final String FRAGMENT_TAG = BackgroundManager.class.getCanonicalName(); 9617993c442c26161f684d6c0c6867a746f3148548Craig Stout 9717993c442c26161f684d6c0c6867a746f3148548Craig Stout private Context mContext; 9817993c442c26161f684d6c0c6867a746f3148548Craig Stout private Handler mHandler; 9917993c442c26161f684d6c0c6867a746f3148548Craig Stout private Window mWindow; 10017993c442c26161f684d6c0c6867a746f3148548Craig Stout private WindowManager mWindowManager; 10117993c442c26161f684d6c0c6867a746f3148548Craig Stout private View mBgView; 10217993c442c26161f684d6c0c6867a746f3148548Craig Stout private BackgroundContinuityService mService; 10317993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mThemeDrawableResourceId; 10417993c442c26161f684d6c0c6867a746f3148548Craig Stout 10517993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mHeightPx; 10617993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mWidthPx; 10717993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable mBackgroundDrawable; 10817993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mBackgroundColor; 10917993c442c26161f684d6c0c6867a746f3148548Craig Stout private boolean mAttached; 11017993c442c26161f684d6c0c6867a746f3148548Craig Stout 1117f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout private static class BitmapDrawable extends Drawable { 1127f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1133d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout static class ConstantState extends Drawable.ConstantState { 1143d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout Bitmap mBitmap; 1153d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout Matrix mMatrix; 1163d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout Paint mPaint; 1173d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 1183d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 1193d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public Drawable newDrawable() { 1203d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout return new BitmapDrawable(null, mBitmap, mMatrix); 1213d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 1223d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 1233d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 1243d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public int getChangingConfigurations() { 1253d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout return 0; 1263d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 1273d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 1283d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 1293d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout private ConstantState mState = new ConstantState(); 1307f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1317f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout BitmapDrawable(Resources resources, Bitmap bitmap) { 1327f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout this(resources, bitmap, null); 1337f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1347f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1357f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout BitmapDrawable(Resources resources, Bitmap bitmap, Matrix matrix) { 1363d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mBitmap = bitmap; 1373d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mMatrix = matrix != null ? matrix : new Matrix(); 1383d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mPaint = new Paint(); 1393d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mPaint.setFilterBitmap(true); 1407f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1417f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1427f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout Bitmap getBitmap() { 1433d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout return mState.mBitmap; 1447f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1457f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1467f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout @Override 1477f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout public void draw(Canvas canvas) { 1483d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (mState.mBitmap == null) { 1497f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return; 1507f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1513d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout canvas.drawBitmap(mState.mBitmap, mState.mMatrix, mState.mPaint); 1527f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1537f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1547f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout @Override 1557f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout public int getOpacity() { 1567f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return android.graphics.PixelFormat.OPAQUE; 1577f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1587f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1597f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout @Override 1607f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout public void setAlpha(int alpha) { 1613d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (mState.mPaint.getAlpha() != alpha) { 1623d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mPaint.setAlpha(alpha); 1637f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout invalidateSelf(); 1647f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1657f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1667f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1677f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout @Override 1687f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout public void setColorFilter(ColorFilter cf) { 1697f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout // Abstract in Drawable, not implemented 1707f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1713d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 1723d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 1733d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public ConstantState getConstantState() { 1743d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout return mState; 1753d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 1767f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1777f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1787f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout private static class DrawableWrapper { 17917993c442c26161f684d6c0c6867a746f3148548Craig Stout protected int mAlpha; 18017993c442c26161f684d6c0c6867a746f3148548Craig Stout protected Drawable mDrawable; 1817e22f555da71f49a32420965817c760522b95963Craig Stout protected ValueAnimator mAnimator; 18217993c442c26161f684d6c0c6867a746f3148548Craig Stout protected boolean mAnimationPending; 18317993c442c26161f684d6c0c6867a746f3148548Craig Stout 1847e22f555da71f49a32420965817c760522b95963Craig Stout private final Interpolator mInterpolator = new LinearInterpolator(); 1857e22f555da71f49a32420965817c760522b95963Craig Stout private final ValueAnimator.AnimatorUpdateListener mAnimationUpdateListener = 1867e22f555da71f49a32420965817c760522b95963Craig Stout new ValueAnimator.AnimatorUpdateListener() { 1877e22f555da71f49a32420965817c760522b95963Craig Stout @Override 1887e22f555da71f49a32420965817c760522b95963Craig Stout public void onAnimationUpdate(ValueAnimator animation) { 1897e22f555da71f49a32420965817c760522b95963Craig Stout setAlpha((Integer) animation.getAnimatedValue()); 1907e22f555da71f49a32420965817c760522b95963Craig Stout } 1917e22f555da71f49a32420965817c760522b95963Craig Stout }; 1927e22f555da71f49a32420965817c760522b95963Craig Stout 19317993c442c26161f684d6c0c6867a746f3148548Craig Stout public DrawableWrapper(Drawable drawable) { 19417993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable = drawable; 19517993c442c26161f684d6c0c6867a746f3148548Craig Stout setAlpha(FULL_ALPHA); 19617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 19717993c442c26161f684d6c0c6867a746f3148548Craig Stout 19817993c442c26161f684d6c0c6867a746f3148548Craig Stout public Drawable getDrawable() { 19917993c442c26161f684d6c0c6867a746f3148548Craig Stout return mDrawable; 20017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 20117993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setAlpha(int alpha) { 20217993c442c26161f684d6c0c6867a746f3148548Craig Stout mAlpha = alpha; 20317993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable.setAlpha(alpha); 20417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 20517993c442c26161f684d6c0c6867a746f3148548Craig Stout public int getAlpha() { 20617993c442c26161f684d6c0c6867a746f3148548Craig Stout return mAlpha; 20717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 20817993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setColor(int color) { 20917993c442c26161f684d6c0c6867a746f3148548Craig Stout ((ColorDrawable) mDrawable).setColor(color); 21017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 21117993c442c26161f684d6c0c6867a746f3148548Craig Stout public void fadeIn(int durationMs, int delayMs) { 21217993c442c26161f684d6c0c6867a746f3148548Craig Stout fade(durationMs, delayMs, FULL_ALPHA); 21317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 21417993c442c26161f684d6c0c6867a746f3148548Craig Stout public void fadeOut(int durationMs) { 21517993c442c26161f684d6c0c6867a746f3148548Craig Stout fade(durationMs, 0, 0); 21617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 21717993c442c26161f684d6c0c6867a746f3148548Craig Stout public void fade(int durationMs, int delayMs, int alpha) { 21817993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mAnimator != null && mAnimator.isStarted()) { 21917993c442c26161f684d6c0c6867a746f3148548Craig Stout mAnimator.cancel(); 22017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 2217e22f555da71f49a32420965817c760522b95963Craig Stout mAnimator = ValueAnimator.ofInt(getAlpha(), alpha); 2227e22f555da71f49a32420965817c760522b95963Craig Stout mAnimator.addUpdateListener(mAnimationUpdateListener); 2237e22f555da71f49a32420965817c760522b95963Craig Stout mAnimator.setInterpolator(mInterpolator); 22417993c442c26161f684d6c0c6867a746f3148548Craig Stout mAnimator.setDuration(durationMs); 22517993c442c26161f684d6c0c6867a746f3148548Craig Stout mAnimator.setStartDelay(delayMs); 22617993c442c26161f684d6c0c6867a746f3148548Craig Stout mAnimationPending = true; 22717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 22817993c442c26161f684d6c0c6867a746f3148548Craig Stout public boolean isAnimationPending() { 22917993c442c26161f684d6c0c6867a746f3148548Craig Stout return mAnimationPending; 23017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 23117993c442c26161f684d6c0c6867a746f3148548Craig Stout public boolean isAnimationStarted() { 23217993c442c26161f684d6c0c6867a746f3148548Craig Stout return mAnimator != null && mAnimator.isStarted(); 23317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 23417993c442c26161f684d6c0c6867a746f3148548Craig Stout public void startAnimation() { 2353d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout startAnimation(null); 2363d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 2373d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public void startAnimation(Animator.AnimatorListener listener) { 2383d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (listener != null) { 2393d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mAnimator.addListener(listener); 2403d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 24117993c442c26161f684d6c0c6867a746f3148548Craig Stout mAnimator.start(); 24217993c442c26161f684d6c0c6867a746f3148548Craig Stout mAnimationPending = false; 24317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 24417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 24517993c442c26161f684d6c0c6867a746f3148548Craig Stout 24617993c442c26161f684d6c0c6867a746f3148548Craig Stout private LayerDrawable mLayerDrawable; 24717993c442c26161f684d6c0c6867a746f3148548Craig Stout private DrawableWrapper mLayerWrapper; 24817993c442c26161f684d6c0c6867a746f3148548Craig Stout private DrawableWrapper mImageInWrapper; 24917993c442c26161f684d6c0c6867a746f3148548Craig Stout private DrawableWrapper mImageOutWrapper; 25017993c442c26161f684d6c0c6867a746f3148548Craig Stout private DrawableWrapper mColorWrapper; 25117993c442c26161f684d6c0c6867a746f3148548Craig Stout private DrawableWrapper mDimWrapper; 25217993c442c26161f684d6c0c6867a746f3148548Craig Stout 25317993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable mThemeDrawable; 25417993c442c26161f684d6c0c6867a746f3148548Craig Stout private ChangeBackgroundRunnable mChangeRunnable; 25517993c442c26161f684d6c0c6867a746f3148548Craig Stout 25617993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 25717993c442c26161f684d6c0c6867a746f3148548Craig Stout * Shared memory continuity service. 25817993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 25917993c442c26161f684d6c0c6867a746f3148548Craig Stout private static class BackgroundContinuityService { 26017993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final String TAG = "BackgroundContinuityService"; 26117993c442c26161f684d6c0c6867a746f3148548Craig Stout private static boolean DEBUG = BackgroundManager.DEBUG; 26217993c442c26161f684d6c0c6867a746f3148548Craig Stout 26317993c442c26161f684d6c0c6867a746f3148548Craig Stout private static BackgroundContinuityService sService = new BackgroundContinuityService(); 26417993c442c26161f684d6c0c6867a746f3148548Craig Stout 26517993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mColor; 26617993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable mDrawable; 26717993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mCount; 26817993c442c26161f684d6c0c6867a746f3148548Craig Stout 26960c3b420827d0520509387f1abe3e3d8168e2279Dake Gu /** Single cache of theme drawable */ 27060c3b420827d0520509387f1abe3e3d8168e2279Dake Gu private int mLastThemeDrawableId; 27160c3b420827d0520509387f1abe3e3d8168e2279Dake Gu private WeakReference<Drawable> mLastThemeDrawable; 27260c3b420827d0520509387f1abe3e3d8168e2279Dake Gu 27317993c442c26161f684d6c0c6867a746f3148548Craig Stout private BackgroundContinuityService() { 27417993c442c26161f684d6c0c6867a746f3148548Craig Stout reset(); 27517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 27617993c442c26161f684d6c0c6867a746f3148548Craig Stout 27717993c442c26161f684d6c0c6867a746f3148548Craig Stout private void reset() { 27817993c442c26161f684d6c0c6867a746f3148548Craig Stout mColor = Color.TRANSPARENT; 27917993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable = null; 28017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 28117993c442c26161f684d6c0c6867a746f3148548Craig Stout 28217993c442c26161f684d6c0c6867a746f3148548Craig Stout public static BackgroundContinuityService getInstance() { 28317993c442c26161f684d6c0c6867a746f3148548Craig Stout final int count = sService.mCount++; 28417993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "Returning instance with new count " + count); 28517993c442c26161f684d6c0c6867a746f3148548Craig Stout return sService; 28617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 28717993c442c26161f684d6c0c6867a746f3148548Craig Stout 28817993c442c26161f684d6c0c6867a746f3148548Craig Stout public void unref() { 28917993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mCount <= 0) throw new IllegalStateException("Can't unref, count " + mCount); 29017993c442c26161f684d6c0c6867a746f3148548Craig Stout if (--mCount == 0) { 29117993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "mCount is zero, resetting"); 29217993c442c26161f684d6c0c6867a746f3148548Craig Stout reset(); 29317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 29417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 29517993c442c26161f684d6c0c6867a746f3148548Craig Stout public int getColor() { 29617993c442c26161f684d6c0c6867a746f3148548Craig Stout return mColor; 29717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 29817993c442c26161f684d6c0c6867a746f3148548Craig Stout public Drawable getDrawable() { 29917993c442c26161f684d6c0c6867a746f3148548Craig Stout return mDrawable; 30017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 30117993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setColor(int color) { 30217993c442c26161f684d6c0c6867a746f3148548Craig Stout mColor = color; 30317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 30417993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setDrawable(Drawable drawable) { 30517993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable = drawable; 30617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 30760c3b420827d0520509387f1abe3e3d8168e2279Dake Gu public Drawable getThemeDrawable(Context context, int themeDrawableId) { 30860c3b420827d0520509387f1abe3e3d8168e2279Dake Gu Drawable drawable = null; 30960c3b420827d0520509387f1abe3e3d8168e2279Dake Gu if (mLastThemeDrawable != null && mLastThemeDrawableId == themeDrawableId) { 31060c3b420827d0520509387f1abe3e3d8168e2279Dake Gu drawable = mLastThemeDrawable.get(); 31160c3b420827d0520509387f1abe3e3d8168e2279Dake Gu } 31260c3b420827d0520509387f1abe3e3d8168e2279Dake Gu if (drawable == null) { 31360c3b420827d0520509387f1abe3e3d8168e2279Dake Gu drawable = ContextCompat.getDrawable(context, themeDrawableId); 31460c3b420827d0520509387f1abe3e3d8168e2279Dake Gu mLastThemeDrawable = new WeakReference<Drawable>(drawable); 31560c3b420827d0520509387f1abe3e3d8168e2279Dake Gu mLastThemeDrawableId = themeDrawableId; 31660c3b420827d0520509387f1abe3e3d8168e2279Dake Gu } 31760c3b420827d0520509387f1abe3e3d8168e2279Dake Gu return drawable.getConstantState().newDrawable(context.getResources()).mutate(); 31860c3b420827d0520509387f1abe3e3d8168e2279Dake Gu } 31917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 32017993c442c26161f684d6c0c6867a746f3148548Craig Stout 32117993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable getThemeDrawable() { 32217993c442c26161f684d6c0c6867a746f3148548Craig Stout Drawable drawable = null; 32317993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mThemeDrawableResourceId != -1) { 32460c3b420827d0520509387f1abe3e3d8168e2279Dake Gu drawable = mService.getThemeDrawable(mContext, mThemeDrawableResourceId); 32517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 32617993c442c26161f684d6c0c6867a746f3148548Craig Stout if (drawable == null) { 32717993c442c26161f684d6c0c6867a746f3148548Craig Stout drawable = createEmptyDrawable(); 32817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 32917993c442c26161f684d6c0c6867a746f3148548Craig Stout return drawable; 33017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 33117993c442c26161f684d6c0c6867a746f3148548Craig Stout 33217993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 333146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Get the BackgroundManager associated with the Activity. 3347f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu * <p> 335146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * The BackgroundManager will be created on-demand for each individual 336146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Activity. Subsequent calls will return the same BackgroundManager created 337146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * for this Activity. 3387f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu */ 3397f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu public static BackgroundManager getInstance(Activity activity) { 3407f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu BackgroundFragment fragment = (BackgroundFragment) activity.getFragmentManager() 3417f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu .findFragmentByTag(FRAGMENT_TAG); 3427f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu if (fragment != null) { 3437f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu BackgroundManager manager = fragment.getBackgroundManager(); 3447f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu if (manager != null) { 3457f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu return manager; 3467f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } 3477f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu // manager is null: this is a fragment restored by FragmentManager, 3487f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu // fall through to create a BackgroundManager attach to it. 3497f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } 3507f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu return new BackgroundManager(activity); 3517f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } 3527f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu 353497a47f2ab7fdc8490191b02caa9a68f884d9ac0Tim Kilbourn private BackgroundManager(Activity activity) { 35417993c442c26161f684d6c0c6867a746f3148548Craig Stout mContext = activity; 35517993c442c26161f684d6c0c6867a746f3148548Craig Stout mService = BackgroundContinuityService.getInstance(); 35617993c442c26161f684d6c0c6867a746f3148548Craig Stout mHeightPx = mContext.getResources().getDisplayMetrics().heightPixels; 35717993c442c26161f684d6c0c6867a746f3148548Craig Stout mWidthPx = mContext.getResources().getDisplayMetrics().widthPixels; 35817993c442c26161f684d6c0c6867a746f3148548Craig Stout mHandler = new Handler(); 35917993c442c26161f684d6c0c6867a746f3148548Craig Stout 36017993c442c26161f684d6c0c6867a746f3148548Craig Stout TypedArray ta = activity.getTheme().obtainStyledAttributes(new int[] { 36117993c442c26161f684d6c0c6867a746f3148548Craig Stout android.R.attr.windowBackground }); 36217993c442c26161f684d6c0c6867a746f3148548Craig Stout mThemeDrawableResourceId = ta.getResourceId(0, -1); 36317993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mThemeDrawableResourceId < 0) { 36417993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "BackgroundManager no window background resource!"); 36517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 36617993c442c26161f684d6c0c6867a746f3148548Craig Stout ta.recycle(); 36717993c442c26161f684d6c0c6867a746f3148548Craig Stout 36817993c442c26161f684d6c0c6867a746f3148548Craig Stout createFragment(activity); 36917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 37017993c442c26161f684d6c0c6867a746f3148548Craig Stout 37117993c442c26161f684d6c0c6867a746f3148548Craig Stout private void createFragment(Activity activity) { 37217993c442c26161f684d6c0c6867a746f3148548Craig Stout // Use a fragment to ensure the background manager gets detached properly. 373b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu BackgroundFragment fragment = (BackgroundFragment) activity.getFragmentManager() 3747f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu .findFragmentByTag(FRAGMENT_TAG); 375b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu if (fragment == null) { 376b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu fragment = new BackgroundFragment(); 3777f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu activity.getFragmentManager().beginTransaction().add(fragment, FRAGMENT_TAG).commit(); 3787f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } else { 3797f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu if (fragment.getBackgroundManager() != null) { 3807f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu throw new IllegalStateException("Created duplicated BackgroundManager for same " + 3817f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu "activity, please use getInstance() instead"); 3827f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } 383b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu } 38417993c442c26161f684d6c0c6867a746f3148548Craig Stout fragment.setBackgroundManager(this); 38517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 38617993c442c26161f684d6c0c6867a746f3148548Craig Stout 38717993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 388146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Synchronizes state when the owning Activity is resumed. 38917993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 3902e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout void onActivityResume() { 3912e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout if (mService == null) { 3922e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout return; 3932e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout } 3942e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout if (mLayerDrawable == null) { 3953d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (DEBUG) Log.v(TAG, "onActivityResume " + this + 3963d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout " released state, syncing with service"); 3972e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout syncWithService(); 3982e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout } else { 3993d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (DEBUG) Log.v(TAG, "onActivityResume " + this + " updating service color " 4002e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout + mBackgroundColor + " drawable " + mBackgroundDrawable); 4012e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mService.setColor(mBackgroundColor); 4022e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mService.setDrawable(mBackgroundDrawable); 4032e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout } 40417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 40517993c442c26161f684d6c0c6867a746f3148548Craig Stout 40617993c442c26161f684d6c0c6867a746f3148548Craig Stout private void syncWithService() { 40717993c442c26161f684d6c0c6867a746f3148548Craig Stout int color = mService.getColor(); 40817993c442c26161f684d6c0c6867a746f3148548Craig Stout Drawable drawable = mService.getDrawable(); 40917993c442c26161f684d6c0c6867a746f3148548Craig Stout 41017993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "syncWithService color " + Integer.toHexString(color) 41117993c442c26161f684d6c0c6867a746f3148548Craig Stout + " drawable " + drawable); 41217993c442c26161f684d6c0c6867a746f3148548Craig Stout 41317993c442c26161f684d6c0c6867a746f3148548Craig Stout mBackgroundColor = color; 4143d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mBackgroundDrawable = drawable == null ? null : 4153d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout drawable.getConstantState().newDrawable().mutate(); 4162e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout 4172e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout updateImmediate(); 41817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 41917993c442c26161f684d6c0c6867a746f3148548Craig Stout 42017993c442c26161f684d6c0c6867a746f3148548Craig Stout private void lazyInit() { 42117993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mLayerDrawable != null) { 42217993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 42317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 42417993c442c26161f684d6c0c6867a746f3148548Craig Stout 42560c3b420827d0520509387f1abe3e3d8168e2279Dake Gu mLayerDrawable = (LayerDrawable) ContextCompat.getDrawable(mContext, 4260eb4595e6a4d6e9ebc9f5b8065e0c787d45a0f70David Saxton R.drawable.lb_background).mutate(); 42717993c442c26161f684d6c0c6867a746f3148548Craig Stout mBgView.setBackground(mLayerDrawable); 42817993c442c26161f684d6c0c6867a746f3148548Craig Stout 42917993c442c26161f684d6c0c6867a746f3148548Craig Stout mLayerDrawable.setDrawableByLayerId(R.id.background_imageout, createEmptyDrawable()); 43017993c442c26161f684d6c0c6867a746f3148548Craig Stout 43117993c442c26161f684d6c0c6867a746f3148548Craig Stout mDimWrapper = new DrawableWrapper( 43217993c442c26161f684d6c0c6867a746f3148548Craig Stout mLayerDrawable.findDrawableByLayerId(R.id.background_dim)); 43317993c442c26161f684d6c0c6867a746f3148548Craig Stout 43417993c442c26161f684d6c0c6867a746f3148548Craig Stout mLayerWrapper = new DrawableWrapper(mLayerDrawable); 43517993c442c26161f684d6c0c6867a746f3148548Craig Stout 43617993c442c26161f684d6c0c6867a746f3148548Craig Stout mColorWrapper = new DrawableWrapper( 43717993c442c26161f684d6c0c6867a746f3148548Craig Stout mLayerDrawable.findDrawableByLayerId(R.id.background_color)); 43817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 43917993c442c26161f684d6c0c6867a746f3148548Craig Stout 44017993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 441146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Make the background visible on the given Window. 44217993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 44317993c442c26161f684d6c0c6867a746f3148548Craig Stout public void attach(Window window) { 44417993c442c26161f684d6c0c6867a746f3148548Craig Stout if (USE_SEPARATE_WINDOW) { 44517993c442c26161f684d6c0c6867a746f3148548Craig Stout attachBehindWindow(window); 44617993c442c26161f684d6c0c6867a746f3148548Craig Stout } else { 44717993c442c26161f684d6c0c6867a746f3148548Craig Stout attachToView(window.getDecorView()); 44817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 44917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 45017993c442c26161f684d6c0c6867a746f3148548Craig Stout 45117993c442c26161f684d6c0c6867a746f3148548Craig Stout private void attachBehindWindow(Window window) { 45217993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "attachBehindWindow " + window); 45317993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindow = window; 45417993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindowManager = window.getWindowManager(); 45517993c442c26161f684d6c0c6867a746f3148548Craig Stout 45617993c442c26161f684d6c0c6867a746f3148548Craig Stout WindowManager.LayoutParams params = new WindowManager.LayoutParams( 45717993c442c26161f684d6c0c6867a746f3148548Craig Stout // Media window sits behind the main application window 45817993c442c26161f684d6c0c6867a746f3148548Craig Stout WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA, 45917993c442c26161f684d6c0c6867a746f3148548Craig Stout // Avoid default to software format RGBA 46017993c442c26161f684d6c0c6867a746f3148548Craig Stout WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, 46117993c442c26161f684d6c0c6867a746f3148548Craig Stout android.graphics.PixelFormat.TRANSLUCENT); 46217993c442c26161f684d6c0c6867a746f3148548Craig Stout params.setTitle(WINDOW_NAME); 46317993c442c26161f684d6c0c6867a746f3148548Craig Stout params.width = ViewGroup.LayoutParams.MATCH_PARENT; 46417993c442c26161f684d6c0c6867a746f3148548Craig Stout params.height = ViewGroup.LayoutParams.MATCH_PARENT; 46517993c442c26161f684d6c0c6867a746f3148548Craig Stout 46617993c442c26161f684d6c0c6867a746f3148548Craig Stout View backgroundView = LayoutInflater.from(mContext).inflate( 46717993c442c26161f684d6c0c6867a746f3148548Craig Stout R.layout.lb_background_window, null); 46817993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindowManager.addView(backgroundView, params); 46917993c442c26161f684d6c0c6867a746f3148548Craig Stout 47017993c442c26161f684d6c0c6867a746f3148548Craig Stout attachToView(backgroundView); 47117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 47217993c442c26161f684d6c0c6867a746f3148548Craig Stout 47317993c442c26161f684d6c0c6867a746f3148548Craig Stout private void attachToView(View sceneRoot) { 47417993c442c26161f684d6c0c6867a746f3148548Craig Stout mBgView = sceneRoot; 47517993c442c26161f684d6c0c6867a746f3148548Craig Stout mAttached = true; 4762e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout syncWithService(); 47717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 47817993c442c26161f684d6c0c6867a746f3148548Craig Stout 47917993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 480146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Release references to Drawables and put the BackgroundManager into the 481146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * detached state. Called when the associated Activity is destroyed. 48217993c442c26161f684d6c0c6867a746f3148548Craig Stout * @hide 48317993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 48417993c442c26161f684d6c0c6867a746f3148548Craig Stout void detach() { 4853d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (DEBUG) Log.v(TAG, "detach " + this); 48617993c442c26161f684d6c0c6867a746f3148548Craig Stout release(); 48717993c442c26161f684d6c0c6867a746f3148548Craig Stout 48817993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mWindowManager != null && mBgView != null) { 48917993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindowManager.removeViewImmediate(mBgView); 49017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 49117993c442c26161f684d6c0c6867a746f3148548Craig Stout 49217993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindowManager = null; 49317993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindow = null; 49417993c442c26161f684d6c0c6867a746f3148548Craig Stout mBgView = null; 49517993c442c26161f684d6c0c6867a746f3148548Craig Stout mAttached = false; 49617993c442c26161f684d6c0c6867a746f3148548Craig Stout 49717993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mService != null) { 49817993c442c26161f684d6c0c6867a746f3148548Craig Stout mService.unref(); 49917993c442c26161f684d6c0c6867a746f3148548Craig Stout mService = null; 50017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 50117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 50217993c442c26161f684d6c0c6867a746f3148548Craig Stout 50317993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 504146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Release references to Drawables. Typically called to reduce memory 505146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * overhead when not visible. 5062e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout * <p> 507146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * When an Activity is resumed, if the BackgroundManager has not been 508146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * released, the continuity service is updated from the BackgroundManager 509146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * state. If the BackgroundManager was released, the BackgroundManager 510146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * inherits the current state from the continuity service. 51117993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 51217993c442c26161f684d6c0c6867a746f3148548Craig Stout public void release() { 5133d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (DEBUG) Log.v(TAG, "release " + this); 5142e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout if (mLayerDrawable != null) { 5152e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mLayerDrawable.setDrawableByLayerId(R.id.background_imagein, createEmptyDrawable()); 5162e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mLayerDrawable.setDrawableByLayerId(R.id.background_imageout, createEmptyDrawable()); 5172e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mLayerDrawable = null; 5182e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout } 51917993c442c26161f684d6c0c6867a746f3148548Craig Stout mLayerWrapper = null; 52017993c442c26161f684d6c0c6867a746f3148548Craig Stout mImageInWrapper = null; 52117993c442c26161f684d6c0c6867a746f3148548Craig Stout mImageOutWrapper = null; 52217993c442c26161f684d6c0c6867a746f3148548Craig Stout mColorWrapper = null; 52317993c442c26161f684d6c0c6867a746f3148548Craig Stout mDimWrapper = null; 52417993c442c26161f684d6c0c6867a746f3148548Craig Stout mThemeDrawable = null; 52517993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mChangeRunnable != null) { 52617993c442c26161f684d6c0c6867a746f3148548Craig Stout mChangeRunnable.cancel(); 52717993c442c26161f684d6c0c6867a746f3148548Craig Stout mChangeRunnable = null; 52817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 52917993c442c26161f684d6c0c6867a746f3148548Craig Stout releaseBackgroundBitmap(); 53017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 53117993c442c26161f684d6c0c6867a746f3148548Craig Stout 53217993c442c26161f684d6c0c6867a746f3148548Craig Stout private void releaseBackgroundBitmap() { 53317993c442c26161f684d6c0c6867a746f3148548Craig Stout mBackgroundDrawable = null; 53417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 53517993c442c26161f684d6c0c6867a746f3148548Craig Stout 53617993c442c26161f684d6c0c6867a746f3148548Craig Stout private void updateImmediate() { 53717993c442c26161f684d6c0c6867a746f3148548Craig Stout lazyInit(); 53817993c442c26161f684d6c0c6867a746f3148548Craig Stout 53917993c442c26161f684d6c0c6867a746f3148548Craig Stout mColorWrapper.setColor(mBackgroundColor); 54017993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mDimWrapper != null) { 54117993c442c26161f684d6c0c6867a746f3148548Craig Stout mDimWrapper.setAlpha(mBackgroundColor == Color.TRANSPARENT ? 0 : DIM_ALPHA_ON_SOLID); 54217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 54317993c442c26161f684d6c0c6867a746f3148548Craig Stout showWallpaper(mBackgroundColor == Color.TRANSPARENT); 54417993c442c26161f684d6c0c6867a746f3148548Craig Stout 54517993c442c26161f684d6c0c6867a746f3148548Craig Stout mThemeDrawable = getThemeDrawable(); 54617993c442c26161f684d6c0c6867a746f3148548Craig Stout mLayerDrawable.setDrawableByLayerId(R.id.background_theme, mThemeDrawable); 54717993c442c26161f684d6c0c6867a746f3148548Craig Stout 54817993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mBackgroundDrawable == null) { 54917993c442c26161f684d6c0c6867a746f3148548Craig Stout mLayerDrawable.setDrawableByLayerId(R.id.background_imagein, createEmptyDrawable()); 55017993c442c26161f684d6c0c6867a746f3148548Craig Stout } else { 55117993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "Background drawable is available"); 55217993c442c26161f684d6c0c6867a746f3148548Craig Stout mImageInWrapper = new DrawableWrapper(mBackgroundDrawable); 55317993c442c26161f684d6c0c6867a746f3148548Craig Stout mLayerDrawable.setDrawableByLayerId(R.id.background_imagein, mBackgroundDrawable); 55417993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mDimWrapper != null) { 55517993c442c26161f684d6c0c6867a746f3148548Craig Stout mDimWrapper.setAlpha(FULL_ALPHA); 55617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 55717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 55817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 55917993c442c26161f684d6c0c6867a746f3148548Craig Stout 56017993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 561146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Set the background to the given color. The timing for when this becomes 562146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * visible in the app is undefined and may take place after a small delay. 56317993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 56417993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setColor(int color) { 56517993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "setColor " + Integer.toHexString(color)); 56617993c442c26161f684d6c0c6867a746f3148548Craig Stout 56717993c442c26161f684d6c0c6867a746f3148548Craig Stout mBackgroundColor = color; 56817993c442c26161f684d6c0c6867a746f3148548Craig Stout mService.setColor(mBackgroundColor); 56917993c442c26161f684d6c0c6867a746f3148548Craig Stout 57017993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mColorWrapper != null) { 57117993c442c26161f684d6c0c6867a746f3148548Craig Stout mColorWrapper.setColor(mBackgroundColor); 57217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 57317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 57417993c442c26161f684d6c0c6867a746f3148548Craig Stout 57517993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 5765a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * Set the given drawable into the background. The provided Drawable will be 5775a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * used unmodified as the background, without any scaling or cropping 5785a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * applied to it. The timing for when this becomes visible in the app is 5795a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * undefined and may take place after a small delay. 58017993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 58117993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setDrawable(Drawable drawable) { 58217993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "setBackgroundDrawable " + drawable); 58317993c442c26161f684d6c0c6867a746f3148548Craig Stout setDrawableInternal(drawable); 58417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 58517993c442c26161f684d6c0c6867a746f3148548Craig Stout 58617993c442c26161f684d6c0c6867a746f3148548Craig Stout private void setDrawableInternal(Drawable drawable) { 5875a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (!mAttached) { 5885a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima throw new IllegalStateException("Must attach before setting background drawable"); 5895a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 59017993c442c26161f684d6c0c6867a746f3148548Craig Stout 59117993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mChangeRunnable != null) { 592d6019d141130ae4811b78e37286faf93d5944fd9Craig Stout if (sameDrawable(drawable, mChangeRunnable.mDrawable)) { 593d6019d141130ae4811b78e37286faf93d5944fd9Craig Stout if (DEBUG) Log.v(TAG, "setting same drawable"); 594d6019d141130ae4811b78e37286faf93d5944fd9Craig Stout return; 595d6019d141130ae4811b78e37286faf93d5944fd9Craig Stout } 59617993c442c26161f684d6c0c6867a746f3148548Craig Stout mChangeRunnable.cancel(); 59717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 59817993c442c26161f684d6c0c6867a746f3148548Craig Stout mChangeRunnable = new ChangeBackgroundRunnable(drawable); 59917993c442c26161f684d6c0c6867a746f3148548Craig Stout 6003d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (mImageInWrapper != null && mImageInWrapper.isAnimationStarted()) { 6013d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (DEBUG) Log.v(TAG, "animation in progress"); 6023d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } else { 6033d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mHandler.postDelayed(mChangeRunnable, CHANGE_BG_DELAY_MS); 6043d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 60517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 60617993c442c26161f684d6c0c6867a746f3148548Craig Stout 60717993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 6085a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * Set the given bitmap into the background. When using setBitmap to set the 6095a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * background, the provided bitmap will be scaled and cropped to correctly 6105a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * fit within the dimensions of the view. The timing for when this becomes 611146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * visible in the app is undefined and may take place after a small delay. 61217993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 61317993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setBitmap(Bitmap bitmap) { 6145a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (DEBUG) { 6155a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima Log.v(TAG, "setBitmap " + bitmap); 6165a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 6175a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima 6185a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (bitmap == null) { 6195a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima setDrawableInternal(null); 6205a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima return; 6215a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 62217993c442c26161f684d6c0c6867a746f3148548Craig Stout 62317993c442c26161f684d6c0c6867a746f3148548Craig Stout if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) { 6245a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (DEBUG) { 6255a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima Log.v(TAG, "invalid bitmap width or height"); 6265a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 62717993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 62817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 62917993c442c26161f684d6c0c6867a746f3148548Craig Stout 6307f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout Matrix matrix = null; 63117993c442c26161f684d6c0c6867a746f3148548Craig Stout 6327f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if ((bitmap.getWidth() != mWidthPx || bitmap.getHeight() != mHeightPx)) { 6335a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima int dwidth = bitmap.getWidth(); 6345a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima int dheight = bitmap.getHeight(); 6355a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima float scale; 6365a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima 6377f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout // Scale proportionately to fit width and height. 6385a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (dwidth * mHeightPx > mWidthPx * dheight) { 6395a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima scale = (float) mHeightPx / (float) dheight; 6405a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } else { 6415a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima scale = (float) mWidthPx / (float) dwidth; 6425a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 6435a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima 6445a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima int subX = Math.min((int) (mWidthPx / scale), dwidth); 6457f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout int dx = Math.max(0, (dwidth - subX) / 2); 6465a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima 6477f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout matrix = new Matrix(); 6487f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout matrix.setScale(scale, scale); 6497f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout matrix.preTranslate(-dx, 0); 6507f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 6517f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (DEBUG) Log.v(TAG, "original image size " + bitmap.getWidth() + "x" + bitmap.getHeight() + 6527f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout " scale " + scale + " dx " + dx); 65317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 65417993c442c26161f684d6c0c6867a746f3148548Craig Stout 6557f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout BitmapDrawable bitmapDrawable = new BitmapDrawable(mContext.getResources(), bitmap, matrix); 65617993c442c26161f684d6c0c6867a746f3148548Craig Stout 65717993c442c26161f684d6c0c6867a746f3148548Craig Stout setDrawableInternal(bitmapDrawable); 65817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 65917993c442c26161f684d6c0c6867a746f3148548Craig Stout 66017993c442c26161f684d6c0c6867a746f3148548Craig Stout private void applyBackgroundChanges() { 66117993c442c26161f684d6c0c6867a746f3148548Craig Stout if (!mAttached || mLayerWrapper == null) { 66217993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 66317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 66417993c442c26161f684d6c0c6867a746f3148548Craig Stout 66517993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "applyBackgroundChanges drawable " + mBackgroundDrawable); 66617993c442c26161f684d6c0c6867a746f3148548Craig Stout 66717993c442c26161f684d6c0c6867a746f3148548Craig Stout int dimAlpha = 0; 66817993c442c26161f684d6c0c6867a746f3148548Craig Stout 66917993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mImageOutWrapper != null && mImageOutWrapper.isAnimationPending()) { 67017993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "mImageOutWrapper animation starting"); 67117993c442c26161f684d6c0c6867a746f3148548Craig Stout mImageOutWrapper.startAnimation(); 67217993c442c26161f684d6c0c6867a746f3148548Craig Stout mImageOutWrapper = null; 67317993c442c26161f684d6c0c6867a746f3148548Craig Stout dimAlpha = DIM_ALPHA_ON_SOLID; 67417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 67517993c442c26161f684d6c0c6867a746f3148548Craig Stout 67617993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mImageInWrapper == null && mBackgroundDrawable != null) { 67717993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "creating new imagein drawable"); 67817993c442c26161f684d6c0c6867a746f3148548Craig Stout mImageInWrapper = new DrawableWrapper(mBackgroundDrawable); 67917993c442c26161f684d6c0c6867a746f3148548Craig Stout mLayerDrawable.setDrawableByLayerId(R.id.background_imagein, mBackgroundDrawable); 6802e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout if (DEBUG) Log.v(TAG, "mImageInWrapper animation starting"); 6812e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mImageInWrapper.setAlpha(0); 6823d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mImageInWrapper.fadeIn(FADE_DURATION, 0); 6833d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mImageInWrapper.startAnimation(mImageInListener); 6842e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout dimAlpha = FULL_ALPHA; 68517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 68617993c442c26161f684d6c0c6867a746f3148548Craig Stout 68717993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mDimWrapper != null && dimAlpha != 0) { 68817993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "dimwrapper animation starting to " + dimAlpha); 6893d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mDimWrapper.fade(FADE_DURATION, 0, dimAlpha); 69017993c442c26161f684d6c0c6867a746f3148548Craig Stout mDimWrapper.startAnimation(); 69117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 69217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 69317993c442c26161f684d6c0c6867a746f3148548Craig Stout 6943d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout private final Animator.AnimatorListener mImageInListener = new Animator.AnimatorListener() { 6953d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 6963d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public void onAnimationStart(Animator animation) { 6973d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 6983d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 6993d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public void onAnimationRepeat(Animator animation) { 7003d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 7013d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 7023d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public void onAnimationEnd(Animator animation) { 7033d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (mChangeRunnable != null) { 7043d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (DEBUG) Log.v(TAG, "animation ended, found change runnable"); 7053d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mChangeRunnable.run(); 7063d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 7073d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 7083d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 7093d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public void onAnimationCancel(Animator animation) { 7103d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 7113d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout }; 7123d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 71317993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 714146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Returns the current background color. 71517993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 71617993c442c26161f684d6c0c6867a746f3148548Craig Stout public final int getColor() { 71717993c442c26161f684d6c0c6867a746f3148548Craig Stout return mBackgroundColor; 71817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 71917993c442c26161f684d6c0c6867a746f3148548Craig Stout 72017993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 721146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Returns the current background {@link Drawable}. 72217993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 72317993c442c26161f684d6c0c6867a746f3148548Craig Stout public Drawable getDrawable() { 72417993c442c26161f684d6c0c6867a746f3148548Craig Stout return mBackgroundDrawable; 72517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 72617993c442c26161f684d6c0c6867a746f3148548Craig Stout 7277f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout private boolean sameDrawable(Drawable first, Drawable second) { 7287f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (first == null || second == null) { 7297f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return false; 7307f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 7317f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (first == second) { 7327f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return true; 7337f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 7347f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (first instanceof BitmapDrawable && second instanceof BitmapDrawable) { 7357f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (((BitmapDrawable) first).getBitmap().sameAs(((BitmapDrawable) second).getBitmap())) { 7367f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return true; 7377f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 7387f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 7397f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return false; 7407f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 7417f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 74217993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 74317993c442c26161f684d6c0c6867a746f3148548Craig Stout * Task which changes the background. 74417993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 74517993c442c26161f684d6c0c6867a746f3148548Craig Stout class ChangeBackgroundRunnable implements Runnable { 74617993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable mDrawable; 74717993c442c26161f684d6c0c6867a746f3148548Craig Stout private boolean mCancel; 74817993c442c26161f684d6c0c6867a746f3148548Craig Stout 74917993c442c26161f684d6c0c6867a746f3148548Craig Stout ChangeBackgroundRunnable(Drawable drawable) { 75017993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable = drawable; 75117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 75217993c442c26161f684d6c0c6867a746f3148548Craig Stout 75317993c442c26161f684d6c0c6867a746f3148548Craig Stout public void cancel() { 75417993c442c26161f684d6c0c6867a746f3148548Craig Stout mCancel = true; 75517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 75617993c442c26161f684d6c0c6867a746f3148548Craig Stout 75717993c442c26161f684d6c0c6867a746f3148548Craig Stout @Override 75817993c442c26161f684d6c0c6867a746f3148548Craig Stout public void run() { 75917993c442c26161f684d6c0c6867a746f3148548Craig Stout if (!mCancel) { 76017993c442c26161f684d6c0c6867a746f3148548Craig Stout runTask(); 76117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 76217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 76317993c442c26161f684d6c0c6867a746f3148548Craig Stout 76417993c442c26161f684d6c0c6867a746f3148548Craig Stout private void runTask() { 76517993c442c26161f684d6c0c6867a746f3148548Craig Stout lazyInit(); 76617993c442c26161f684d6c0c6867a746f3148548Craig Stout 7677f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (sameDrawable(mDrawable, mBackgroundDrawable)) { 7687f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (DEBUG) Log.v(TAG, "same bitmap detected"); 7692e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout return; 77017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 77117993c442c26161f684d6c0c6867a746f3148548Craig Stout 7722e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout releaseBackgroundBitmap(); 7732e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout 7742e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout if (mImageInWrapper != null) { 7752e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mImageOutWrapper = new DrawableWrapper(mImageInWrapper.getDrawable()); 7762e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mImageOutWrapper.setAlpha(mImageInWrapper.getAlpha()); 7773d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mImageOutWrapper.fadeOut(FADE_DURATION); 7782e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout 7792e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout // Order is important! Setting a drawable "removes" the 7802e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout // previous one from the view 7812e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mLayerDrawable.setDrawableByLayerId(R.id.background_imagein, createEmptyDrawable()); 7822e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mLayerDrawable.setDrawableByLayerId(R.id.background_imageout, 7832e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mImageOutWrapper.getDrawable()); 7842e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mImageInWrapper.setAlpha(0); 7852e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mImageInWrapper = null; 78617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 7872e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout 7882e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mBackgroundDrawable = mDrawable; 7892e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mService.setDrawable(mBackgroundDrawable); 7902e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout 7912e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout applyBackgroundChanges(); 7923d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 7933d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mChangeRunnable = null; 79417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 79517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 79617993c442c26161f684d6c0c6867a746f3148548Craig Stout 79717993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable createEmptyDrawable() { 79817993c442c26161f684d6c0c6867a746f3148548Craig Stout Bitmap bitmap = null; 79917993c442c26161f684d6c0c6867a746f3148548Craig Stout return new BitmapDrawable(mContext.getResources(), bitmap); 80017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 80117993c442c26161f684d6c0c6867a746f3148548Craig Stout 80217993c442c26161f684d6c0c6867a746f3148548Craig Stout private void showWallpaper(boolean show) { 80317993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mWindow == null) { 80417993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 80517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 80617993c442c26161f684d6c0c6867a746f3148548Craig Stout 80717993c442c26161f684d6c0c6867a746f3148548Craig Stout WindowManager.LayoutParams layoutParams = mWindow.getAttributes(); 80817993c442c26161f684d6c0c6867a746f3148548Craig Stout if (show) { 80917993c442c26161f684d6c0c6867a746f3148548Craig Stout if ((layoutParams.flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 81017993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 81117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 81217993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "showing wallpaper"); 81317993c442c26161f684d6c0c6867a746f3148548Craig Stout layoutParams.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 81417993c442c26161f684d6c0c6867a746f3148548Craig Stout } else { 81517993c442c26161f684d6c0c6867a746f3148548Craig Stout if ((layoutParams.flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) == 0) { 81617993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 81717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 81817993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "hiding wallpaper"); 81917993c442c26161f684d6c0c6867a746f3148548Craig Stout layoutParams.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 82017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 82117993c442c26161f684d6c0c6867a746f3148548Craig Stout 82217993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindow.setAttributes(layoutParams); 82317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 82417993c442c26161f684d6c0c6867a746f3148548Craig Stout} 825