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 1870acb0c19be3831a2080e4f902324de16bfbf62eTor Norbyeimport android.support.annotation.ColorInt; 19d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stoutimport android.graphics.PixelFormat; 20f684b94c5f316e9735abc298e00c3f61642b821eCraig Stoutimport android.graphics.PorterDuff; 21f684b94c5f316e9735abc298e00c3f61642b821eCraig Stoutimport android.graphics.PorterDuffColorFilter; 2217993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.support.v17.leanback.R; 233d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stoutimport android.animation.Animator; 247e22f555da71f49a32420965817c760522b95963Craig Stoutimport android.animation.ValueAnimator; 2517993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.app.Activity; 2617993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.content.Context; 277f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stoutimport android.content.res.Resources; 2817993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.content.res.TypedArray; 2917993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.Bitmap; 307f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stoutimport android.graphics.Canvas; 3117993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.Color; 327f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stoutimport android.graphics.ColorFilter; 3317993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.Matrix; 347f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stoutimport android.graphics.Paint; 3517993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.ColorDrawable; 3617993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.Drawable; 3717993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.LayerDrawable; 3817993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.os.Handler; 392590c39739945451f80dcf8667709b93293fc8bcCraig Stoutimport android.support.v17.leanback.widget.BackgroundHelper; 400f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stoutimport android.support.v4.view.animation.FastOutLinearInInterpolator; 4117993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.util.Log; 4217993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.LayoutInflater; 4317993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.View; 4417993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.ViewGroup; 4517993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.Window; 4617993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.WindowManager; 477e22f555da71f49a32420965817c760522b95963Craig Stoutimport android.view.animation.Interpolator; 480f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stoutimport android.view.animation.AnimationUtils; 49fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Guimport android.support.v4.app.FragmentActivity; 5060c3b420827d0520509387f1abe3e3d8168e2279Dake Guimport android.support.v4.content.ContextCompat; 5117993c442c26161f684d6c0c6867a746f3148548Craig Stout 5217993c442c26161f684d6c0c6867a746f3148548Craig Stout/** 53146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Supports background image continuity between multiple Activities. 5417993c442c26161f684d6c0c6867a746f3148548Craig Stout * 55146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>An Activity should instantiate a BackgroundManager and {@link #attach} 56146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * to the Activity's window. When the Activity is started, the background is 5717993c442c26161f684d6c0c6867a746f3148548Craig Stout * initialized to the current background values stored in a continuity service. 5817993c442c26161f684d6c0c6867a746f3148548Craig Stout * The background continuity service is updated as the background is updated. 5917993c442c26161f684d6c0c6867a746f3148548Craig Stout * 60146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>At some point, for example when it is stopped, the Activity may release 61146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * its background state. 622e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout * 63146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>When an Activity is resumed, if the BackgroundManager has not been 64146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * released, the continuity service is updated from the BackgroundManager state. 65146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * If the BackgroundManager was released, the BackgroundManager inherits the 66146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * current state from the continuity service. 6717993c442c26161f684d6c0c6867a746f3148548Craig Stout * 68146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>When the last Activity is destroyed, the background state is reset. 6917993c442c26161f684d6c0c6867a746f3148548Craig Stout * 70146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>Backgrounds consist of several layers, from back to front: 71146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <ul> 72146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <li>the background Drawable of the theme</li> 73146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <li>a solid color (set via {@link #setColor})</li> 74146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <li>two Drawables, previous and current (set via {@link #setBitmap} or 75146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * {@link #setDrawable}), which may be in transition</li> 76146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * </ul> 7717993c442c26161f684d6c0c6867a746f3148548Craig Stout * 78146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>BackgroundManager holds references to potentially large bitmap Drawables. 79146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Call {@link #release} to release these references when the Activity is not 8017993c442c26161f684d6c0c6867a746f3148548Craig Stout * visible. 8117993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 82146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn// TODO: support for multiple app processes requires a proper android service 83146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn// instead of the shared memory "service" implemented here. Such a service could 84146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn// support continuity between fragments of different applications if desired. 8517993c442c26161f684d6c0c6867a746f3148548Craig Stoutpublic final class BackgroundManager { 86f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 87f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout interface FragmentStateQueriable { 88f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout public boolean isResumed(); 89f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 90f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 9117993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final String TAG = "BackgroundManager"; 9217993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final boolean DEBUG = false; 9317993c442c26161f684d6c0c6867a746f3148548Craig Stout 9417993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final int FULL_ALPHA = 255; 9517993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final int DIM_ALPHA_ON_SOLID = (int) (0.8f * FULL_ALPHA); 9617993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final int CHANGE_BG_DELAY_MS = 500; 973d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout private static final int FADE_DURATION = 500; 9817993c442c26161f684d6c0c6867a746f3148548Craig Stout 9917993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 10017993c442c26161f684d6c0c6867a746f3148548Craig Stout * Using a separate window for backgrounds can improve graphics performance by 10117993c442c26161f684d6c0c6867a746f3148548Craig Stout * leveraging hardware display layers. 10217993c442c26161f684d6c0c6867a746f3148548Craig Stout * TODO: support a leanback configuration option. 10317993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 10417993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final boolean USE_SEPARATE_WINDOW = false; 10517993c442c26161f684d6c0c6867a746f3148548Craig Stout 10617993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final String WINDOW_NAME = "BackgroundManager"; 1077f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu private static final String FRAGMENT_TAG = BackgroundManager.class.getCanonicalName(); 10817993c442c26161f684d6c0c6867a746f3148548Craig Stout 10917993c442c26161f684d6c0c6867a746f3148548Craig Stout private Context mContext; 11017993c442c26161f684d6c0c6867a746f3148548Craig Stout private Handler mHandler; 11117993c442c26161f684d6c0c6867a746f3148548Craig Stout private Window mWindow; 11217993c442c26161f684d6c0c6867a746f3148548Craig Stout private WindowManager mWindowManager; 11317993c442c26161f684d6c0c6867a746f3148548Craig Stout private View mBgView; 11417993c442c26161f684d6c0c6867a746f3148548Craig Stout private BackgroundContinuityService mService; 11517993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mThemeDrawableResourceId; 116f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private FragmentStateQueriable mFragmentState; 11717993c442c26161f684d6c0c6867a746f3148548Craig Stout 11817993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mHeightPx; 11917993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mWidthPx; 12017993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable mBackgroundDrawable; 12117993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mBackgroundColor; 12217993c442c26161f684d6c0c6867a746f3148548Craig Stout private boolean mAttached; 1230f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private long mLastSetTime; 1240f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 1250f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final Interpolator mAccelerateInterpolator; 1260f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final Interpolator mDecelerateInterpolator; 1270f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final ValueAnimator mAnimator; 1280f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final ValueAnimator mDimAnimator; 12917993c442c26161f684d6c0c6867a746f3148548Craig Stout 1307f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout private static class BitmapDrawable extends Drawable { 1317f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1323d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout static class ConstantState extends Drawable.ConstantState { 1333d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout Bitmap mBitmap; 1343d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout Matrix mMatrix; 1353d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout Paint mPaint; 1363d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 1373d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 1383d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public Drawable newDrawable() { 1393d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout return new BitmapDrawable(null, mBitmap, mMatrix); 1403d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 1413d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 1423d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 1433d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public int getChangingConfigurations() { 1443d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout return 0; 1453d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 1463d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 1473d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 1483d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout private ConstantState mState = new ConstantState(); 1497f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1507f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout BitmapDrawable(Resources resources, Bitmap bitmap) { 1517f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout this(resources, bitmap, null); 1527f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1537f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1547f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout BitmapDrawable(Resources resources, Bitmap bitmap, Matrix matrix) { 1553d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mBitmap = bitmap; 1563d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mMatrix = matrix != null ? matrix : new Matrix(); 1573d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mPaint = new Paint(); 1583d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mPaint.setFilterBitmap(true); 1597f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1607f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1617f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout Bitmap getBitmap() { 1623d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout return mState.mBitmap; 1637f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1647f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1657f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout @Override 1667f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout public void draw(Canvas canvas) { 1673d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (mState.mBitmap == null) { 1687f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return; 1697f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 170f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (mState.mPaint.getAlpha() < FULL_ALPHA && mState.mPaint.getColorFilter() != null) { 171f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout throw new IllegalStateException("Can't draw with translucent alpha and color filter"); 172f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 1733d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout canvas.drawBitmap(mState.mBitmap, mState.mMatrix, mState.mPaint); 1747f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1757f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1767f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout @Override 1777f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout public int getOpacity() { 178d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return android.graphics.PixelFormat.TRANSLUCENT; 1797f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1807f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1817f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout @Override 1827f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout public void setAlpha(int alpha) { 1833d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (mState.mPaint.getAlpha() != alpha) { 1843d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mPaint.setAlpha(alpha); 1857f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout invalidateSelf(); 1867f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1877f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1887f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 189f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout /** 190f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * Does not invalidateSelf to avoid recursion issues. 191f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * Caller must ensure appropriate invalidation. 192f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout */ 1937f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout @Override 1947f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout public void setColorFilter(ColorFilter cf) { 195f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mState.mPaint.setColorFilter(cf); 196f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 197f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 198f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout public ColorFilter getColorFilter() { 199f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout return mState.mPaint.getColorFilter(); 2007f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 2013d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 2023d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 2033d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public ConstantState getConstantState() { 2043d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout return mState; 2053d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 2067f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 2077f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 2087f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout private static class DrawableWrapper { 209d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private int mAlpha = FULL_ALPHA; 210d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private Drawable mDrawable; 211f36902ae811a12506f54faa261cb653f45a27612Craig Stout private ColorFilter mColorFilter; 2127e22f555da71f49a32420965817c760522b95963Craig Stout 21317993c442c26161f684d6c0c6867a746f3148548Craig Stout public DrawableWrapper(Drawable drawable) { 21417993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable = drawable; 215d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout updateAlpha(); 216f36902ae811a12506f54faa261cb653f45a27612Craig Stout updateColorFilter(); 217d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 218d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public DrawableWrapper(DrawableWrapper wrapper, Drawable drawable) { 219d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mDrawable = drawable; 220d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mAlpha = wrapper.getAlpha(); 221d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout updateAlpha(); 222f36902ae811a12506f54faa261cb653f45a27612Craig Stout mColorFilter = wrapper.getColorFilter(); 223f36902ae811a12506f54faa261cb653f45a27612Craig Stout updateColorFilter(); 22417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 225f36902ae811a12506f54faa261cb653f45a27612Craig Stout 22617993c442c26161f684d6c0c6867a746f3148548Craig Stout public Drawable getDrawable() { 22717993c442c26161f684d6c0c6867a746f3148548Craig Stout return mDrawable; 22817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 22917993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setAlpha(int alpha) { 23017993c442c26161f684d6c0c6867a746f3148548Craig Stout mAlpha = alpha; 231d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout updateAlpha(); 23217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 23317993c442c26161f684d6c0c6867a746f3148548Craig Stout public int getAlpha() { 23417993c442c26161f684d6c0c6867a746f3148548Craig Stout return mAlpha; 23517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 236d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private void updateAlpha() { 237d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mDrawable.setAlpha(mAlpha); 238d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 239f36902ae811a12506f54faa261cb653f45a27612Craig Stout 240f36902ae811a12506f54faa261cb653f45a27612Craig Stout public ColorFilter getColorFilter() { 241f36902ae811a12506f54faa261cb653f45a27612Craig Stout return mColorFilter; 242f36902ae811a12506f54faa261cb653f45a27612Craig Stout } 243f36902ae811a12506f54faa261cb653f45a27612Craig Stout public void setColorFilter(ColorFilter colorFilter) { 244f36902ae811a12506f54faa261cb653f45a27612Craig Stout mColorFilter = colorFilter; 245f36902ae811a12506f54faa261cb653f45a27612Craig Stout updateColorFilter(); 246f36902ae811a12506f54faa261cb653f45a27612Craig Stout } 247f36902ae811a12506f54faa261cb653f45a27612Craig Stout private void updateColorFilter() { 248f36902ae811a12506f54faa261cb653f45a27612Craig Stout mDrawable.setColorFilter(mColorFilter); 249f36902ae811a12506f54faa261cb653f45a27612Craig Stout } 250f36902ae811a12506f54faa261cb653f45a27612Craig Stout 25117993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setColor(int color) { 25217993c442c26161f684d6c0c6867a746f3148548Craig Stout ((ColorDrawable) mDrawable).setColor(color); 25317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 25417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 25517993c442c26161f684d6c0c6867a746f3148548Craig Stout 256f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout static class TranslucentLayerDrawable extends LayerDrawable { 257d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private DrawableWrapper[] mWrapper; 258d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private Paint mPaint = new Paint(); 259d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 260d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public TranslucentLayerDrawable(Drawable[] drawables) { 261d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout super(drawables); 262d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout int count = drawables.length; 263d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mWrapper = new DrawableWrapper[count]; 264d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout for (int i = 0; i < count; i++) { 265d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mWrapper[i] = new DrawableWrapper(drawables[i]); 266d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 267d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 268d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 269d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout @Override 270d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public void setAlpha(int alpha) { 271d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (mPaint.getAlpha() != alpha) { 272f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout int previousAlpha = mPaint.getAlpha(); 273d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mPaint.setAlpha(alpha); 274d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout invalidateSelf(); 275f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout onAlphaChanged(previousAlpha, alpha); 276d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 277d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 278d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 2792590c39739945451f80dcf8667709b93293fc8bcCraig Stout // Queried by system transitions 2802590c39739945451f80dcf8667709b93293fc8bcCraig Stout public int getAlpha() { 2812590c39739945451f80dcf8667709b93293fc8bcCraig Stout return mPaint.getAlpha(); 2822590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 2832590c39739945451f80dcf8667709b93293fc8bcCraig Stout 284f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout protected void onAlphaChanged(int oldAlpha, int newAlpha) { 285f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 286f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 287d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout @Override 288d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public Drawable mutate() { 289d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout Drawable drawable = super.mutate(); 290d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout int count = getNumberOfLayers(); 291d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout for (int i = 0; i < count; i++) { 292d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (mWrapper[i] != null) { 293d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mWrapper[i] = new DrawableWrapper(mWrapper[i], getDrawable(i)); 294d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 295d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 296f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout invalidateSelf(); 297d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return drawable; 298d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 299d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 300d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout @Override 301d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public int getOpacity() { 302d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return PixelFormat.TRANSLUCENT; 303d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 304d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 305d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout @Override 306d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public boolean setDrawableByLayerId(int id, Drawable drawable) { 307d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return updateDrawable(id, drawable) != null; 308d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 309d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 310d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public DrawableWrapper updateDrawable(int id, Drawable drawable) { 311d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout super.setDrawableByLayerId(id, drawable); 312d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout for (int i = 0; i < getNumberOfLayers(); i++) { 313d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (getId(i) == id) { 314d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mWrapper[i] = new DrawableWrapper(drawable); 315f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // Must come after mWrapper was updated so it can be seen by updateColorFilter 316f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout invalidateSelf(); 317d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return mWrapper[i]; 318d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 319d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 320d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return null; 321d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 322d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 323d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public void clearDrawable(int id, Context context) { 324d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout for (int i = 0; i < getNumberOfLayers(); i++) { 325d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (getId(i) == id) { 326d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mWrapper[i] = null; 327d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout super.setDrawableByLayerId(id, createEmptyDrawable(context)); 328d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout break; 329d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 330d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 331d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 332d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 333d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public DrawableWrapper findWrapperById(int id) { 334d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout for (int i = 0; i < getNumberOfLayers(); i++) { 335d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (getId(i) == id) { 336d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return mWrapper[i]; 337d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 338d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 339d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return null; 340d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 341d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 342d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout @Override 343d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public void draw(Canvas canvas) { 344d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (mPaint.getAlpha() < FULL_ALPHA) { 345d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), 346d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mPaint, Canvas.ALL_SAVE_FLAG); 347d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 348d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout super.draw(canvas); 349d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (mPaint.getAlpha() < FULL_ALPHA) { 350d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout canvas.restore(); 351d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 352d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 353d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 354d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 355f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout /** 356f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * Optimizes drawing when the dim drawable is an alpha-only color and imagein is opaque. 357f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * When the layer drawable is translucent (activity transition) then we can avoid the slow 358f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * saveLayer/restore draw path. 359f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout */ 360f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private class OptimizedTranslucentLayerDrawable extends TranslucentLayerDrawable { 361f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private PorterDuffColorFilter mColorFilter; 362f36902ae811a12506f54faa261cb653f45a27612Craig Stout private boolean mUpdatingColorFilter; 363f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 364f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout public OptimizedTranslucentLayerDrawable(Drawable[] drawables) { 365f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout super(drawables); 366f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 367f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 368f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout @Override 369f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout protected void onAlphaChanged(int oldAlpha, int newAlpha) { 370f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (newAlpha == FULL_ALPHA && oldAlpha < FULL_ALPHA) { 371f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "transition complete"); 372f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout postChangeRunnable(); 373f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 374f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 375f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 376f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout @Override 377f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout public void invalidateSelf() { 378f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout super.invalidateSelf(); 379f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout updateColorFilter(); 380f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 381f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 382f36902ae811a12506f54faa261cb653f45a27612Craig Stout @Override 383f36902ae811a12506f54faa261cb653f45a27612Craig Stout public void invalidateDrawable(Drawable who) { 384f36902ae811a12506f54faa261cb653f45a27612Craig Stout if (!mUpdatingColorFilter) { 385f36902ae811a12506f54faa261cb653f45a27612Craig Stout invalidateSelf(); 386f36902ae811a12506f54faa261cb653f45a27612Craig Stout } 387f36902ae811a12506f54faa261cb653f45a27612Craig Stout } 388f36902ae811a12506f54faa261cb653f45a27612Craig Stout 389f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private void updateColorFilter() { 390f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout DrawableWrapper dimWrapper = findWrapperById(R.id.background_dim); 391f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout DrawableWrapper imageInWrapper = findWrapperById(R.id.background_imagein); 392f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout DrawableWrapper imageOutWrapper = findWrapperById(R.id.background_imageout); 393f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 394f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mColorFilter = null; 395f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (imageInWrapper != null && imageInWrapper.getAlpha() == FULL_ALPHA && 396f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout dimWrapper.getDrawable() instanceof ColorDrawable) { 397f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout int dimColor = ((ColorDrawable) dimWrapper.getDrawable()).getColor(); 398f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (Color.red(dimColor) == 0 && 399f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout Color.green(dimColor) == 0 && 400f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout Color.blue(dimColor) == 0) { 401f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout int dimAlpha = 255 - Color.alpha(dimColor); 402f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout int color = Color.argb(getAlpha(), dimAlpha, dimAlpha, dimAlpha); 403f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mColorFilter = new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY); 404f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 405f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 406f36902ae811a12506f54faa261cb653f45a27612Craig Stout mUpdatingColorFilter = true; 407f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (imageInWrapper != null) { 408f36902ae811a12506f54faa261cb653f45a27612Craig Stout imageInWrapper.setColorFilter(mColorFilter); 409f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 410f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (imageOutWrapper != null) { 411f36902ae811a12506f54faa261cb653f45a27612Craig Stout imageOutWrapper.setColorFilter(null); 412f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 413f36902ae811a12506f54faa261cb653f45a27612Craig Stout mUpdatingColorFilter = false; 414f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 415f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 416f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout @Override 417f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout public void draw(Canvas canvas) { 418f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout DrawableWrapper imageInWrapper = findWrapperById(R.id.background_imagein); 419f36902ae811a12506f54faa261cb653f45a27612Craig Stout if (imageInWrapper != null && imageInWrapper.getDrawable() != null && 420f36902ae811a12506f54faa261cb653f45a27612Craig Stout imageInWrapper.getColorFilter() != null) { 421f36902ae811a12506f54faa261cb653f45a27612Craig Stout imageInWrapper.getDrawable().draw(canvas); 422f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } else { 423f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout super.draw(canvas); 424f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 425f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 426f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 427f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 428f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private TranslucentLayerDrawable createOptimizedTranslucentLayerDrawable( 429f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout LayerDrawable layerDrawable) { 430f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout int numChildren = layerDrawable.getNumberOfLayers(); 431f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout Drawable[] drawables = new Drawable[numChildren]; 432f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout for (int i = 0; i < numChildren; i++) { 433f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout drawables[i] = layerDrawable.getDrawable(i); 434f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 435f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout TranslucentLayerDrawable result = new OptimizedTranslucentLayerDrawable(drawables); 436f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout for (int i = 0; i < numChildren; i++) { 437f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout result.setId(i, layerDrawable.getId(i)); 438f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 439f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout return result; 440f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 441f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 442d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private TranslucentLayerDrawable mLayerDrawable; 4430f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private Drawable mDimDrawable; 44417993c442c26161f684d6c0c6867a746f3148548Craig Stout private ChangeBackgroundRunnable mChangeRunnable; 445f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private boolean mChangeRunnablePending; 44617993c442c26161f684d6c0c6867a746f3148548Craig Stout 4470f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final Animator.AnimatorListener mAnimationListener = new Animator.AnimatorListener() { 448f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout final Runnable mRunnable = new Runnable() { 449f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout @Override 450f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout public void run() { 451f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout postChangeRunnable(); 452f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 453f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout }; 454f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 4550f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout @Override 4560f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void onAnimationStart(Animator animation) { 4570f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4580f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout @Override 4590f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void onAnimationRepeat(Animator animation) { 4600f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4610f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout @Override 4620f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void onAnimationEnd(Animator animation) { 463f988bc054a2e0ccefacd8c76cbcf47a1ab88e6b1Craig Stout if (mLayerDrawable != null) { 464f988bc054a2e0ccefacd8c76cbcf47a1ab88e6b1Craig Stout mLayerDrawable.clearDrawable(R.id.background_imageout, mContext); 465f988bc054a2e0ccefacd8c76cbcf47a1ab88e6b1Craig Stout } 466f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mHandler.post(mRunnable); 4670f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4680f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout @Override 4690f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void onAnimationCancel(Animator animation) { 4700f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4710f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout }; 4720f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 4730f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final ValueAnimator.AnimatorUpdateListener mAnimationUpdateListener = 4740f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout new ValueAnimator.AnimatorUpdateListener() { 4750f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout @Override 4760f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void onAnimationUpdate(ValueAnimator animation) { 4770f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout int fadeInAlpha = (Integer) animation.getAnimatedValue(); 4782590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper imageInWrapper = getImageInWrapper(); 4792590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (imageInWrapper != null) { 4802590c39739945451f80dcf8667709b93293fc8bcCraig Stout imageInWrapper.setAlpha(fadeInAlpha); 4812590c39739945451f80dcf8667709b93293fc8bcCraig Stout } else { 4822590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper imageOutWrapper = getImageOutWrapper(); 4832590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (imageOutWrapper != null) { 4842590c39739945451f80dcf8667709b93293fc8bcCraig Stout imageOutWrapper.setAlpha(255 - fadeInAlpha); 4852590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 4860f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4870f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4880f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout }; 4890f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 4900f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final ValueAnimator.AnimatorUpdateListener mDimUpdateListener = 4910f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout new ValueAnimator.AnimatorUpdateListener() { 4920f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout @Override 4930f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void onAnimationUpdate(ValueAnimator animation) { 4942590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper dimWrapper = getDimWrapper(); 4952590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (dimWrapper != null) { 4962590c39739945451f80dcf8667709b93293fc8bcCraig Stout dimWrapper.setAlpha((Integer) animation.getAnimatedValue()); 4970f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4980f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4990f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout }; 5000f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 50117993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 50217993c442c26161f684d6c0c6867a746f3148548Craig Stout * Shared memory continuity service. 50317993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 50417993c442c26161f684d6c0c6867a746f3148548Craig Stout private static class BackgroundContinuityService { 50517993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final String TAG = "BackgroundContinuityService"; 50617993c442c26161f684d6c0c6867a746f3148548Craig Stout private static boolean DEBUG = BackgroundManager.DEBUG; 50717993c442c26161f684d6c0c6867a746f3148548Craig Stout 50817993c442c26161f684d6c0c6867a746f3148548Craig Stout private static BackgroundContinuityService sService = new BackgroundContinuityService(); 50917993c442c26161f684d6c0c6867a746f3148548Craig Stout 51017993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mColor; 51117993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable mDrawable; 51217993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mCount; 51317993c442c26161f684d6c0c6867a746f3148548Craig Stout 51460c3b420827d0520509387f1abe3e3d8168e2279Dake Gu /** Single cache of theme drawable */ 51560c3b420827d0520509387f1abe3e3d8168e2279Dake Gu private int mLastThemeDrawableId; 516363191eb688c10be4f8ffe10c41da1664168d1feCraig Stout private WeakReference<Drawable.ConstantState> mLastThemeDrawableState; 51760c3b420827d0520509387f1abe3e3d8168e2279Dake Gu 51817993c442c26161f684d6c0c6867a746f3148548Craig Stout private BackgroundContinuityService() { 51917993c442c26161f684d6c0c6867a746f3148548Craig Stout reset(); 52017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 52117993c442c26161f684d6c0c6867a746f3148548Craig Stout 52217993c442c26161f684d6c0c6867a746f3148548Craig Stout private void reset() { 52317993c442c26161f684d6c0c6867a746f3148548Craig Stout mColor = Color.TRANSPARENT; 52417993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable = null; 52517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 52617993c442c26161f684d6c0c6867a746f3148548Craig Stout 52717993c442c26161f684d6c0c6867a746f3148548Craig Stout public static BackgroundContinuityService getInstance() { 52817993c442c26161f684d6c0c6867a746f3148548Craig Stout final int count = sService.mCount++; 52917993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "Returning instance with new count " + count); 53017993c442c26161f684d6c0c6867a746f3148548Craig Stout return sService; 53117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 53217993c442c26161f684d6c0c6867a746f3148548Craig Stout 53317993c442c26161f684d6c0c6867a746f3148548Craig Stout public void unref() { 53417993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mCount <= 0) throw new IllegalStateException("Can't unref, count " + mCount); 53517993c442c26161f684d6c0c6867a746f3148548Craig Stout if (--mCount == 0) { 53617993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "mCount is zero, resetting"); 53717993c442c26161f684d6c0c6867a746f3148548Craig Stout reset(); 53817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 53917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 54017993c442c26161f684d6c0c6867a746f3148548Craig Stout public int getColor() { 54117993c442c26161f684d6c0c6867a746f3148548Craig Stout return mColor; 54217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 54317993c442c26161f684d6c0c6867a746f3148548Craig Stout public Drawable getDrawable() { 54417993c442c26161f684d6c0c6867a746f3148548Craig Stout return mDrawable; 54517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 54617993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setColor(int color) { 54717993c442c26161f684d6c0c6867a746f3148548Craig Stout mColor = color; 54817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 54917993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setDrawable(Drawable drawable) { 55017993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable = drawable; 55117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 55260c3b420827d0520509387f1abe3e3d8168e2279Dake Gu public Drawable getThemeDrawable(Context context, int themeDrawableId) { 55360c3b420827d0520509387f1abe3e3d8168e2279Dake Gu Drawable drawable = null; 554363191eb688c10be4f8ffe10c41da1664168d1feCraig Stout if (mLastThemeDrawableState != null && mLastThemeDrawableId == themeDrawableId) { 555363191eb688c10be4f8ffe10c41da1664168d1feCraig Stout Drawable.ConstantState drawableState = mLastThemeDrawableState.get(); 556363191eb688c10be4f8ffe10c41da1664168d1feCraig Stout if (DEBUG) Log.v(TAG, "got cached theme drawable state " + drawableState); 557363191eb688c10be4f8ffe10c41da1664168d1feCraig Stout if (drawableState != null) { 558363191eb688c10be4f8ffe10c41da1664168d1feCraig Stout drawable = drawableState.newDrawable(); 559363191eb688c10be4f8ffe10c41da1664168d1feCraig Stout } 56060c3b420827d0520509387f1abe3e3d8168e2279Dake Gu } 56160c3b420827d0520509387f1abe3e3d8168e2279Dake Gu if (drawable == null) { 56260c3b420827d0520509387f1abe3e3d8168e2279Dake Gu drawable = ContextCompat.getDrawable(context, themeDrawableId); 563363191eb688c10be4f8ffe10c41da1664168d1feCraig Stout if (DEBUG) Log.v(TAG, "loaded theme drawable " + drawable); 564363191eb688c10be4f8ffe10c41da1664168d1feCraig Stout mLastThemeDrawableState = new WeakReference<Drawable.ConstantState>( 565363191eb688c10be4f8ffe10c41da1664168d1feCraig Stout drawable.getConstantState()); 56660c3b420827d0520509387f1abe3e3d8168e2279Dake Gu mLastThemeDrawableId = themeDrawableId; 56760c3b420827d0520509387f1abe3e3d8168e2279Dake Gu } 568459af78be7413b944e2ff0a6f231a8b7b5de3aadCraig Stout // No mutate required because this drawable is never manipulated. 569459af78be7413b944e2ff0a6f231a8b7b5de3aadCraig Stout return drawable; 57060c3b420827d0520509387f1abe3e3d8168e2279Dake Gu } 57117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 57217993c442c26161f684d6c0c6867a746f3148548Craig Stout 57317993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable getThemeDrawable() { 57417993c442c26161f684d6c0c6867a746f3148548Craig Stout Drawable drawable = null; 57517993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mThemeDrawableResourceId != -1) { 57660c3b420827d0520509387f1abe3e3d8168e2279Dake Gu drawable = mService.getThemeDrawable(mContext, mThemeDrawableResourceId); 57717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 57817993c442c26161f684d6c0c6867a746f3148548Craig Stout if (drawable == null) { 579d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout drawable = createEmptyDrawable(mContext); 58017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 58117993c442c26161f684d6c0c6867a746f3148548Craig Stout return drawable; 58217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 58317993c442c26161f684d6c0c6867a746f3148548Craig Stout 58417993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 585a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Returns the BackgroundManager associated with the given Activity. 5867f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu * <p> 587146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * The BackgroundManager will be created on-demand for each individual 588146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Activity. Subsequent calls will return the same BackgroundManager created 589146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * for this Activity. 5907f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu */ 5917f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu public static BackgroundManager getInstance(Activity activity) { 592fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu if (activity instanceof FragmentActivity) { 593fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu return getSupportInstance((FragmentActivity) activity); 594fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 5957f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu BackgroundFragment fragment = (BackgroundFragment) activity.getFragmentManager() 5967f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu .findFragmentByTag(FRAGMENT_TAG); 5977f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu if (fragment != null) { 5987f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu BackgroundManager manager = fragment.getBackgroundManager(); 5997f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu if (manager != null) { 6007f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu return manager; 6017f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } 6027f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu // manager is null: this is a fragment restored by FragmentManager, 6037f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu // fall through to create a BackgroundManager attach to it. 6047f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } 605fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu return new BackgroundManager(activity, false); 606fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 607fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu 608fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu private static BackgroundManager getSupportInstance(FragmentActivity activity) { 609fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu BackgroundSupportFragment fragment = (BackgroundSupportFragment) activity 610fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu .getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG); 611fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu if (fragment != null) { 612fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu BackgroundManager manager = fragment.getBackgroundManager(); 613fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu if (manager != null) { 614fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu return manager; 615fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 616fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu // manager is null: this is a fragment restored by FragmentManager, 617fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu // fall through to create a BackgroundManager attach to it. 618fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 619fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu return new BackgroundManager(activity, true); 6207f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } 6217f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu 622fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu private BackgroundManager(Activity activity, boolean isSupportFragmentActivity) { 62317993c442c26161f684d6c0c6867a746f3148548Craig Stout mContext = activity; 62417993c442c26161f684d6c0c6867a746f3148548Craig Stout mService = BackgroundContinuityService.getInstance(); 62517993c442c26161f684d6c0c6867a746f3148548Craig Stout mHeightPx = mContext.getResources().getDisplayMetrics().heightPixels; 62617993c442c26161f684d6c0c6867a746f3148548Craig Stout mWidthPx = mContext.getResources().getDisplayMetrics().widthPixels; 62717993c442c26161f684d6c0c6867a746f3148548Craig Stout mHandler = new Handler(); 62817993c442c26161f684d6c0c6867a746f3148548Craig Stout 6290f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout Interpolator defaultInterpolator = new FastOutLinearInInterpolator(); 6300f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAccelerateInterpolator = AnimationUtils.loadInterpolator(mContext, 6310f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout android.R.anim.accelerate_interpolator); 6320f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDecelerateInterpolator = AnimationUtils.loadInterpolator(mContext, 6330f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout android.R.anim.decelerate_interpolator); 6340f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 6350f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAnimator = ValueAnimator.ofInt(0, FULL_ALPHA); 6360f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAnimator.addListener(mAnimationListener); 6370f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAnimator.addUpdateListener(mAnimationUpdateListener); 6380f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAnimator.setInterpolator(defaultInterpolator); 6390f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 6400f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimAnimator = new ValueAnimator(); 6410f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimAnimator.addUpdateListener(mDimUpdateListener); 6420f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 64317993c442c26161f684d6c0c6867a746f3148548Craig Stout TypedArray ta = activity.getTheme().obtainStyledAttributes(new int[] { 64417993c442c26161f684d6c0c6867a746f3148548Craig Stout android.R.attr.windowBackground }); 64517993c442c26161f684d6c0c6867a746f3148548Craig Stout mThemeDrawableResourceId = ta.getResourceId(0, -1); 64617993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mThemeDrawableResourceId < 0) { 64717993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "BackgroundManager no window background resource!"); 64817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 64917993c442c26161f684d6c0c6867a746f3148548Craig Stout ta.recycle(); 65017993c442c26161f684d6c0c6867a746f3148548Craig Stout 651fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu if (isSupportFragmentActivity) { 652fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu createSupportFragment((FragmentActivity) activity); 653fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } else { 654fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu createFragment(activity); 655fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 65617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 65717993c442c26161f684d6c0c6867a746f3148548Craig Stout 65817993c442c26161f684d6c0c6867a746f3148548Craig Stout private void createFragment(Activity activity) { 65917993c442c26161f684d6c0c6867a746f3148548Craig Stout // Use a fragment to ensure the background manager gets detached properly. 660b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu BackgroundFragment fragment = (BackgroundFragment) activity.getFragmentManager() 6617f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu .findFragmentByTag(FRAGMENT_TAG); 662b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu if (fragment == null) { 663b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu fragment = new BackgroundFragment(); 6647f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu activity.getFragmentManager().beginTransaction().add(fragment, FRAGMENT_TAG).commit(); 6657f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } else { 6667f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu if (fragment.getBackgroundManager() != null) { 6677f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu throw new IllegalStateException("Created duplicated BackgroundManager for same " + 6687f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu "activity, please use getInstance() instead"); 6697f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } 670b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu } 67117993c442c26161f684d6c0c6867a746f3148548Craig Stout fragment.setBackgroundManager(this); 672f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mFragmentState = fragment; 67317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 67417993c442c26161f684d6c0c6867a746f3148548Craig Stout 675fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu private void createSupportFragment(FragmentActivity activity) { 676fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu // Use a fragment to ensure the background manager gets detached properly. 677fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu BackgroundSupportFragment fragment = (BackgroundSupportFragment) activity 678fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu .getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG); 679fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu if (fragment == null) { 680fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu fragment = new BackgroundSupportFragment(); 681fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu activity.getSupportFragmentManager().beginTransaction().add(fragment, FRAGMENT_TAG) 682fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu .commit(); 683fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } else { 684fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu if (fragment.getBackgroundManager() != null) { 685fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu throw new IllegalStateException("Created duplicated BackgroundManager for same " + 686fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu "activity, please use getInstance() instead"); 687fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 688fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 689fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu fragment.setBackgroundManager(this); 690f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mFragmentState = fragment; 691fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 692fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu 6932590c39739945451f80dcf8667709b93293fc8bcCraig Stout private DrawableWrapper getImageInWrapper() { 6942590c39739945451f80dcf8667709b93293fc8bcCraig Stout return mLayerDrawable == null ? null : 6952590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.findWrapperById(R.id.background_imagein); 6962590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 6972590c39739945451f80dcf8667709b93293fc8bcCraig Stout 6982590c39739945451f80dcf8667709b93293fc8bcCraig Stout private DrawableWrapper getImageOutWrapper() { 6992590c39739945451f80dcf8667709b93293fc8bcCraig Stout return mLayerDrawable == null ? null : 7002590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.findWrapperById(R.id.background_imageout); 7012590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 7022590c39739945451f80dcf8667709b93293fc8bcCraig Stout 7032590c39739945451f80dcf8667709b93293fc8bcCraig Stout private DrawableWrapper getDimWrapper() { 7042590c39739945451f80dcf8667709b93293fc8bcCraig Stout return mLayerDrawable == null ? null : 7052590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.findWrapperById(R.id.background_dim); 7062590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 7072590c39739945451f80dcf8667709b93293fc8bcCraig Stout 7082590c39739945451f80dcf8667709b93293fc8bcCraig Stout private DrawableWrapper getColorWrapper() { 7092590c39739945451f80dcf8667709b93293fc8bcCraig Stout return mLayerDrawable == null ? null : 7102590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.findWrapperById(R.id.background_color); 7112590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 7122590c39739945451f80dcf8667709b93293fc8bcCraig Stout 71317993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 714f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * Synchronizes state when the owning Activity is started. 715f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * At that point the view becomes visible. 71617993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 717f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout void onActivityStart() { 7182e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout if (mService == null) { 7192e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout return; 7202e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout } 7212e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout if (mLayerDrawable == null) { 722f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "onActivityStart " + this + 7233d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout " released state, syncing with service"); 7242e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout syncWithService(); 7252e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout } else { 726f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "onActivityStart " + this + " updating service color " 7272e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout + mBackgroundColor + " drawable " + mBackgroundDrawable); 7282e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mService.setColor(mBackgroundColor); 7292e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mService.setDrawable(mBackgroundDrawable); 7302e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout } 73117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 73217993c442c26161f684d6c0c6867a746f3148548Craig Stout 733f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout void onResume() { 734f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "onResume " + this); 735f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout postChangeRunnable(); 736f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 737f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 73817993c442c26161f684d6c0c6867a746f3148548Craig Stout private void syncWithService() { 73917993c442c26161f684d6c0c6867a746f3148548Craig Stout int color = mService.getColor(); 74017993c442c26161f684d6c0c6867a746f3148548Craig Stout Drawable drawable = mService.getDrawable(); 74117993c442c26161f684d6c0c6867a746f3148548Craig Stout 74217993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "syncWithService color " + Integer.toHexString(color) 74317993c442c26161f684d6c0c6867a746f3148548Craig Stout + " drawable " + drawable); 74417993c442c26161f684d6c0c6867a746f3148548Craig Stout 74517993c442c26161f684d6c0c6867a746f3148548Craig Stout mBackgroundColor = color; 7463d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mBackgroundDrawable = drawable == null ? null : 7473d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout drawable.getConstantState().newDrawable().mutate(); 7482e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout 7492e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout updateImmediate(); 75017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 75117993c442c26161f684d6c0c6867a746f3148548Craig Stout 75217993c442c26161f684d6c0c6867a746f3148548Craig Stout private void lazyInit() { 75317993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mLayerDrawable != null) { 75417993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 75517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 75617993c442c26161f684d6c0c6867a746f3148548Craig Stout 757d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout LayerDrawable layerDrawable = (LayerDrawable) 758d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout ContextCompat.getDrawable(mContext, R.drawable.lb_background).mutate(); 759f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mLayerDrawable = createOptimizedTranslucentLayerDrawable(layerDrawable); 7602590c39739945451f80dcf8667709b93293fc8bcCraig Stout BackgroundHelper.setBackgroundPreservingAlpha(mBgView, mLayerDrawable); 76117993c442c26161f684d6c0c6867a746f3148548Craig Stout 762d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.clearDrawable(R.id.background_imageout, mContext); 763d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.updateDrawable(R.id.background_theme, getThemeDrawable()); 764c149abce7f8a46f7c54211b5f97c5cd9ee729357Dake Gu 7650f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout updateDimWrapper(); 7660f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 7670f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 7680f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private void updateDimWrapper() { 7690f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout if (mDimDrawable == null) { 7700f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimDrawable = getDefaultDimLayer(); 7710f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 772d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout Drawable dimDrawable = mDimDrawable.getConstantState().newDrawable( 773d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mContext.getResources()).mutate(); 7742590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (mLayerDrawable != null) { 7752590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.updateDrawable(R.id.background_dim, dimDrawable); 7762590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 77717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 77817993c442c26161f684d6c0c6867a746f3148548Craig Stout 77917993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 780a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Makes the background visible on the given Window. The background manager must be attached 7810f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout * when the background is set. 78217993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 78317993c442c26161f684d6c0c6867a746f3148548Craig Stout public void attach(Window window) { 78417993c442c26161f684d6c0c6867a746f3148548Craig Stout if (USE_SEPARATE_WINDOW) { 78517993c442c26161f684d6c0c6867a746f3148548Craig Stout attachBehindWindow(window); 78617993c442c26161f684d6c0c6867a746f3148548Craig Stout } else { 78717993c442c26161f684d6c0c6867a746f3148548Craig Stout attachToView(window.getDecorView()); 78817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 78917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 79017993c442c26161f684d6c0c6867a746f3148548Craig Stout 791459af78be7413b944e2ff0a6f231a8b7b5de3aadCraig Stout /** 792459af78be7413b944e2ff0a6f231a8b7b5de3aadCraig Stout * Sets the resource id for the drawable to be shown when there is no background set. 793459af78be7413b944e2ff0a6f231a8b7b5de3aadCraig Stout * Overrides the window background drawable from the theme. This should 794459af78be7413b944e2ff0a6f231a8b7b5de3aadCraig Stout * be called before attaching. 795459af78be7413b944e2ff0a6f231a8b7b5de3aadCraig Stout */ 796459af78be7413b944e2ff0a6f231a8b7b5de3aadCraig Stout public void setThemeDrawableResourceId(int resourceId) { 797459af78be7413b944e2ff0a6f231a8b7b5de3aadCraig Stout mThemeDrawableResourceId = resourceId; 798459af78be7413b944e2ff0a6f231a8b7b5de3aadCraig Stout } 799459af78be7413b944e2ff0a6f231a8b7b5de3aadCraig Stout 80017993c442c26161f684d6c0c6867a746f3148548Craig Stout private void attachBehindWindow(Window window) { 80117993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "attachBehindWindow " + window); 80217993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindow = window; 80317993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindowManager = window.getWindowManager(); 80417993c442c26161f684d6c0c6867a746f3148548Craig Stout 80517993c442c26161f684d6c0c6867a746f3148548Craig Stout WindowManager.LayoutParams params = new WindowManager.LayoutParams( 80617993c442c26161f684d6c0c6867a746f3148548Craig Stout // Media window sits behind the main application window 80717993c442c26161f684d6c0c6867a746f3148548Craig Stout WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA, 80817993c442c26161f684d6c0c6867a746f3148548Craig Stout // Avoid default to software format RGBA 80917993c442c26161f684d6c0c6867a746f3148548Craig Stout WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, 81017993c442c26161f684d6c0c6867a746f3148548Craig Stout android.graphics.PixelFormat.TRANSLUCENT); 81117993c442c26161f684d6c0c6867a746f3148548Craig Stout params.setTitle(WINDOW_NAME); 81217993c442c26161f684d6c0c6867a746f3148548Craig Stout params.width = ViewGroup.LayoutParams.MATCH_PARENT; 81317993c442c26161f684d6c0c6867a746f3148548Craig Stout params.height = ViewGroup.LayoutParams.MATCH_PARENT; 81417993c442c26161f684d6c0c6867a746f3148548Craig Stout 81517993c442c26161f684d6c0c6867a746f3148548Craig Stout View backgroundView = LayoutInflater.from(mContext).inflate( 81617993c442c26161f684d6c0c6867a746f3148548Craig Stout R.layout.lb_background_window, null); 81717993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindowManager.addView(backgroundView, params); 81817993c442c26161f684d6c0c6867a746f3148548Craig Stout 81917993c442c26161f684d6c0c6867a746f3148548Craig Stout attachToView(backgroundView); 82017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 82117993c442c26161f684d6c0c6867a746f3148548Craig Stout 82217993c442c26161f684d6c0c6867a746f3148548Craig Stout private void attachToView(View sceneRoot) { 82317993c442c26161f684d6c0c6867a746f3148548Craig Stout mBgView = sceneRoot; 82417993c442c26161f684d6c0c6867a746f3148548Craig Stout mAttached = true; 8252e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout syncWithService(); 82617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 82717993c442c26161f684d6c0c6867a746f3148548Craig Stout 82817993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 8290f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout * Returns true if the background manager is currently attached; false otherwise. 8300f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout */ 8310f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public boolean isAttached() { 8320f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout return mAttached; 8330f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 8340f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 8350f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout /** 836146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Release references to Drawables and put the BackgroundManager into the 837146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * detached state. Called when the associated Activity is destroyed. 83817993c442c26161f684d6c0c6867a746f3148548Craig Stout * @hide 83917993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 84017993c442c26161f684d6c0c6867a746f3148548Craig Stout void detach() { 8413d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (DEBUG) Log.v(TAG, "detach " + this); 84217993c442c26161f684d6c0c6867a746f3148548Craig Stout release(); 84317993c442c26161f684d6c0c6867a746f3148548Craig Stout 84417993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mWindowManager != null && mBgView != null) { 84517993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindowManager.removeViewImmediate(mBgView); 84617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 84717993c442c26161f684d6c0c6867a746f3148548Craig Stout 84817993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindowManager = null; 84917993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindow = null; 85017993c442c26161f684d6c0c6867a746f3148548Craig Stout mBgView = null; 85117993c442c26161f684d6c0c6867a746f3148548Craig Stout mAttached = false; 85217993c442c26161f684d6c0c6867a746f3148548Craig Stout 85317993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mService != null) { 85417993c442c26161f684d6c0c6867a746f3148548Craig Stout mService.unref(); 85517993c442c26161f684d6c0c6867a746f3148548Craig Stout mService = null; 85617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 85717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 85817993c442c26161f684d6c0c6867a746f3148548Craig Stout 85917993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 860146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Release references to Drawables. Typically called to reduce memory 861146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * overhead when not visible. 8622e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout * <p> 863f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * When an Activity is started, if the BackgroundManager has not been 864146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * released, the continuity service is updated from the BackgroundManager 865146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * state. If the BackgroundManager was released, the BackgroundManager 866146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * inherits the current state from the continuity service. 86717993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 86817993c442c26161f684d6c0c6867a746f3148548Craig Stout public void release() { 8693d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (DEBUG) Log.v(TAG, "release " + this); 8702e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout if (mLayerDrawable != null) { 871d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.clearDrawable(R.id.background_imagein, mContext); 872d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.clearDrawable(R.id.background_imageout, mContext); 873d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.clearDrawable(R.id.background_theme, mContext); 8742e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mLayerDrawable = null; 8752e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout } 87617993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mChangeRunnable != null) { 8770f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mHandler.removeCallbacks(mChangeRunnable); 87817993c442c26161f684d6c0c6867a746f3148548Craig Stout mChangeRunnable = null; 87917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 88017993c442c26161f684d6c0c6867a746f3148548Craig Stout releaseBackgroundBitmap(); 88117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 88217993c442c26161f684d6c0c6867a746f3148548Craig Stout 88317993c442c26161f684d6c0c6867a746f3148548Craig Stout private void releaseBackgroundBitmap() { 88417993c442c26161f684d6c0c6867a746f3148548Craig Stout mBackgroundDrawable = null; 88517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 88617993c442c26161f684d6c0c6867a746f3148548Craig Stout 887f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private void setBackgroundDrawable(Drawable drawable) { 888f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mBackgroundDrawable = drawable; 889f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mService.setDrawable(mBackgroundDrawable); 890f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 891f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 8920f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout /** 8930f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout * Sets the drawable used as a dim layer. 8940f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout */ 8950f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void setDimLayer(Drawable drawable) { 8960f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimDrawable = drawable; 8970f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout updateDimWrapper(); 8980f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 8990f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 9000f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout /** 9010f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout * Returns the drawable used as a dim layer. 9020f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout */ 9030f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public Drawable getDimLayer() { 9040f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout return mDimDrawable; 9050f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 9060f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 9070f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout /** 9080f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout * Returns the default drawable used as a dim layer. 9090f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout */ 9100f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public Drawable getDefaultDimLayer() { 9110f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout return ContextCompat.getDrawable(mContext, R.color.lb_background_protection); 9120f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 9130f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 914f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private void postChangeRunnable() { 915f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (mChangeRunnable == null || !mChangeRunnablePending) { 916f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout return; 917f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 918f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 919f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // Postpone a pending change runnable until: no existing change animation in progress && 920f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // activity is resumed (in the foreground) && layerdrawable fully opaque. 921f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // If the layerdrawable is translucent then an activity transition is in progress 922f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // and we want to use the optimized drawing path for performance reasons (see 923f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // OptimizedTranslucentLayerDrawable). 924f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (mAnimator.isStarted()) { 925f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "animation in progress"); 926f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } else if (!mFragmentState.isResumed()) { 927f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "not resumed"); 928f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } else if (mLayerDrawable.getAlpha() < FULL_ALPHA) { 929f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "in transition, alpha " + mLayerDrawable.getAlpha()); 930f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } else { 931f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout long delayMs = getRunnableDelay(); 932f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "posting runnable delayMs " + delayMs); 933f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mLastSetTime = System.currentTimeMillis(); 934f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mHandler.postDelayed(mChangeRunnable, delayMs); 935f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mChangeRunnablePending = false; 936f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 937f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 938f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 93917993c442c26161f684d6c0c6867a746f3148548Craig Stout private void updateImmediate() { 94017993c442c26161f684d6c0c6867a746f3148548Craig Stout lazyInit(); 94117993c442c26161f684d6c0c6867a746f3148548Craig Stout 9422590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper colorWrapper = getColorWrapper(); 9432590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (colorWrapper != null) { 9442590c39739945451f80dcf8667709b93293fc8bcCraig Stout colorWrapper.setColor(mBackgroundColor); 9452590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 9462590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper dimWrapper = getDimWrapper(); 9472590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (dimWrapper != null) { 9482590c39739945451f80dcf8667709b93293fc8bcCraig Stout dimWrapper.setAlpha(mBackgroundColor == Color.TRANSPARENT ? 0 : DIM_ALPHA_ON_SOLID); 94917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 95017993c442c26161f684d6c0c6867a746f3148548Craig Stout showWallpaper(mBackgroundColor == Color.TRANSPARENT); 95117993c442c26161f684d6c0c6867a746f3148548Craig Stout 95217993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mBackgroundDrawable == null) { 953d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.clearDrawable(R.id.background_imagein, mContext); 95417993c442c26161f684d6c0c6867a746f3148548Craig Stout } else { 95517993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "Background drawable is available"); 9562590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.updateDrawable( 957d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout R.id.background_imagein, mBackgroundDrawable); 9582590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (dimWrapper != null) { 9592590c39739945451f80dcf8667709b93293fc8bcCraig Stout dimWrapper.setAlpha(FULL_ALPHA); 96017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 96117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 96217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 96317993c442c26161f684d6c0c6867a746f3148548Craig Stout 96417993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 965a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Sets the background to the given color. The timing for when this becomes 966146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * visible in the app is undefined and may take place after a small delay. 96717993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 96870acb0c19be3831a2080e4f902324de16bfbf62eTor Norbye public void setColor(@ColorInt int color) { 96917993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "setColor " + Integer.toHexString(color)); 97017993c442c26161f684d6c0c6867a746f3148548Craig Stout 97117993c442c26161f684d6c0c6867a746f3148548Craig Stout mBackgroundColor = color; 97217993c442c26161f684d6c0c6867a746f3148548Craig Stout mService.setColor(mBackgroundColor); 97317993c442c26161f684d6c0c6867a746f3148548Craig Stout 9742590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper colorWrapper = getColorWrapper(); 9752590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (colorWrapper != null) { 9762590c39739945451f80dcf8667709b93293fc8bcCraig Stout colorWrapper.setColor(mBackgroundColor); 97717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 97817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 97917993c442c26161f684d6c0c6867a746f3148548Craig Stout 98017993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 981a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Sets the given drawable into the background. The provided Drawable will be 9825a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * used unmodified as the background, without any scaling or cropping 9835a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * applied to it. The timing for when this becomes visible in the app is 9845a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * undefined and may take place after a small delay. 98517993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 98617993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setDrawable(Drawable drawable) { 98717993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "setBackgroundDrawable " + drawable); 98817993c442c26161f684d6c0c6867a746f3148548Craig Stout setDrawableInternal(drawable); 98917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 99017993c442c26161f684d6c0c6867a746f3148548Craig Stout 99117993c442c26161f684d6c0c6867a746f3148548Craig Stout private void setDrawableInternal(Drawable drawable) { 9925a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (!mAttached) { 9935a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima throw new IllegalStateException("Must attach before setting background drawable"); 9945a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 99517993c442c26161f684d6c0c6867a746f3148548Craig Stout 99617993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mChangeRunnable != null) { 997d6019d141130ae4811b78e37286faf93d5944fd9Craig Stout if (sameDrawable(drawable, mChangeRunnable.mDrawable)) { 9980f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout if (DEBUG) Log.v(TAG, "new drawable same as pending"); 999d6019d141130ae4811b78e37286faf93d5944fd9Craig Stout return; 1000d6019d141130ae4811b78e37286faf93d5944fd9Craig Stout } 10010f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mHandler.removeCallbacks(mChangeRunnable); 1002f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mChangeRunnable = null; 100317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 1004d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 1005f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // If layer drawable is null then the activity hasn't started yet. 1006f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // If the layer drawable alpha is zero then the activity transition hasn't started yet. 1007f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // In these cases we can update the background immediately and let activity transition 1008f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // fade it in. 1009f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (mLayerDrawable == null || mLayerDrawable.getAlpha() == 0) { 1010f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "setDrawableInternal null or alpha is zero"); 1011f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout setBackgroundDrawable(drawable); 1012d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout updateImmediate(); 1013d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return; 1014d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 1015d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 101617993c442c26161f684d6c0c6867a746f3148548Craig Stout mChangeRunnable = new ChangeBackgroundRunnable(drawable); 1017f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mChangeRunnablePending = true; 101817993c442c26161f684d6c0c6867a746f3148548Craig Stout 1019f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout postChangeRunnable(); 102017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 102117993c442c26161f684d6c0c6867a746f3148548Craig Stout 10220f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private long getRunnableDelay() { 10230f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout return Math.max(0, mLastSetTime + CHANGE_BG_DELAY_MS - System.currentTimeMillis()); 10240f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 10250f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 102617993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 1027a00bada00bff4a58436a39472ab14ccb7a8f619dCraig Stout * Sets the given bitmap into the background. When using setBitmap to set the 10285a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * background, the provided bitmap will be scaled and cropped to correctly 10295a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * fit within the dimensions of the view. The timing for when this becomes 1030146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * visible in the app is undefined and may take place after a small delay. 103117993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 103217993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setBitmap(Bitmap bitmap) { 10335a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (DEBUG) { 10345a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima Log.v(TAG, "setBitmap " + bitmap); 10355a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 10365a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima 10375a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (bitmap == null) { 10385a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima setDrawableInternal(null); 10395a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima return; 10405a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 104117993c442c26161f684d6c0c6867a746f3148548Craig Stout 104217993c442c26161f684d6c0c6867a746f3148548Craig Stout if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) { 10435a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (DEBUG) { 10445a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima Log.v(TAG, "invalid bitmap width or height"); 10455a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 104617993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 104717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 104817993c442c26161f684d6c0c6867a746f3148548Craig Stout 10497f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout Matrix matrix = null; 105017993c442c26161f684d6c0c6867a746f3148548Craig Stout 10517f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if ((bitmap.getWidth() != mWidthPx || bitmap.getHeight() != mHeightPx)) { 10525a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima int dwidth = bitmap.getWidth(); 10535a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima int dheight = bitmap.getHeight(); 10545a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima float scale; 10555a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima 10567f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout // Scale proportionately to fit width and height. 10575a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (dwidth * mHeightPx > mWidthPx * dheight) { 10585a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima scale = (float) mHeightPx / (float) dheight; 10595a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } else { 10605a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima scale = (float) mWidthPx / (float) dwidth; 10615a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 10625a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima 10635a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima int subX = Math.min((int) (mWidthPx / scale), dwidth); 10647f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout int dx = Math.max(0, (dwidth - subX) / 2); 10655a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima 10667f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout matrix = new Matrix(); 10677f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout matrix.setScale(scale, scale); 10687f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout matrix.preTranslate(-dx, 0); 10697f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 10707f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (DEBUG) Log.v(TAG, "original image size " + bitmap.getWidth() + "x" + bitmap.getHeight() + 10717f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout " scale " + scale + " dx " + dx); 107217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 107317993c442c26161f684d6c0c6867a746f3148548Craig Stout 10747f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout BitmapDrawable bitmapDrawable = new BitmapDrawable(mContext.getResources(), bitmap, matrix); 107517993c442c26161f684d6c0c6867a746f3148548Craig Stout 107617993c442c26161f684d6c0c6867a746f3148548Craig Stout setDrawableInternal(bitmapDrawable); 107717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 107817993c442c26161f684d6c0c6867a746f3148548Craig Stout 107917993c442c26161f684d6c0c6867a746f3148548Craig Stout private void applyBackgroundChanges() { 1080d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (!mAttached) { 108117993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 108217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 108317993c442c26161f684d6c0c6867a746f3148548Craig Stout 108417993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "applyBackgroundChanges drawable " + mBackgroundDrawable); 108517993c442c26161f684d6c0c6867a746f3148548Craig Stout 10860f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout int dimAlpha = -1; 108717993c442c26161f684d6c0c6867a746f3148548Craig Stout 10882590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (getImageOutWrapper() != null) { 10890f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout dimAlpha = mBackgroundColor == Color.TRANSPARENT ? 0 : DIM_ALPHA_ON_SOLID; 109017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 109117993c442c26161f684d6c0c6867a746f3148548Craig Stout 10922590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper imageInWrapper = getImageInWrapper(); 10932590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (imageInWrapper == null && mBackgroundDrawable != null) { 109417993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "creating new imagein drawable"); 10952590c39739945451f80dcf8667709b93293fc8bcCraig Stout imageInWrapper = mLayerDrawable.updateDrawable( 1096d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout R.id.background_imagein, mBackgroundDrawable); 10972590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (DEBUG) Log.v(TAG, "imageInWrapper animation starting"); 10982590c39739945451f80dcf8667709b93293fc8bcCraig Stout imageInWrapper.setAlpha(0); 10992e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout dimAlpha = FULL_ALPHA; 110017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 110117993c442c26161f684d6c0c6867a746f3148548Craig Stout 11020f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAnimator.setDuration(FADE_DURATION); 11030f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAnimator.start(); 11040f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 11052590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper dimWrapper = getDimWrapper(); 11062590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (dimWrapper != null && dimAlpha >= 0) { 110717993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "dimwrapper animation starting to " + dimAlpha); 11080f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimAnimator.cancel(); 11092590c39739945451f80dcf8667709b93293fc8bcCraig Stout mDimAnimator.setIntValues(dimWrapper.getAlpha(), dimAlpha); 11100f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimAnimator.setDuration(FADE_DURATION); 11110f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimAnimator.setInterpolator( 11120f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout dimAlpha == FULL_ALPHA ? mDecelerateInterpolator : mAccelerateInterpolator); 11130f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimAnimator.start(); 111417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 111517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 111617993c442c26161f684d6c0c6867a746f3148548Craig Stout 111717993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 1118146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Returns the current background color. 111917993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 112070acb0c19be3831a2080e4f902324de16bfbf62eTor Norbye @ColorInt 112117993c442c26161f684d6c0c6867a746f3148548Craig Stout public final int getColor() { 112217993c442c26161f684d6c0c6867a746f3148548Craig Stout return mBackgroundColor; 112317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 112417993c442c26161f684d6c0c6867a746f3148548Craig Stout 112517993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 1126146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Returns the current background {@link Drawable}. 112717993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 112817993c442c26161f684d6c0c6867a746f3148548Craig Stout public Drawable getDrawable() { 112917993c442c26161f684d6c0c6867a746f3148548Craig Stout return mBackgroundDrawable; 113017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 113117993c442c26161f684d6c0c6867a746f3148548Craig Stout 11327f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout private boolean sameDrawable(Drawable first, Drawable second) { 11337f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (first == null || second == null) { 11347f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return false; 11357f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 11367f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (first == second) { 11377f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return true; 11387f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 11397f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (first instanceof BitmapDrawable && second instanceof BitmapDrawable) { 11407f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (((BitmapDrawable) first).getBitmap().sameAs(((BitmapDrawable) second).getBitmap())) { 11417f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return true; 11427f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 11437f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 11447f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return false; 11457f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 11467f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 114717993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 114817993c442c26161f684d6c0c6867a746f3148548Craig Stout * Task which changes the background. 114917993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 115017993c442c26161f684d6c0c6867a746f3148548Craig Stout class ChangeBackgroundRunnable implements Runnable { 115117993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable mDrawable; 115217993c442c26161f684d6c0c6867a746f3148548Craig Stout 115317993c442c26161f684d6c0c6867a746f3148548Craig Stout ChangeBackgroundRunnable(Drawable drawable) { 115417993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable = drawable; 115517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 115617993c442c26161f684d6c0c6867a746f3148548Craig Stout 115717993c442c26161f684d6c0c6867a746f3148548Craig Stout @Override 115817993c442c26161f684d6c0c6867a746f3148548Craig Stout public void run() { 11590f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout runTask(); 11600f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mChangeRunnable = null; 116117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 116217993c442c26161f684d6c0c6867a746f3148548Craig Stout 116317993c442c26161f684d6c0c6867a746f3148548Craig Stout private void runTask() { 1164d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (mLayerDrawable == null) { 1165d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (DEBUG) Log.v(TAG, "runTask while released - should not happen"); 1166d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return; 1167d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 116817993c442c26161f684d6c0c6867a746f3148548Craig Stout 11697f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (sameDrawable(mDrawable, mBackgroundDrawable)) { 11700f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout if (DEBUG) Log.v(TAG, "new drawable same as current"); 11712e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout return; 117217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 117317993c442c26161f684d6c0c6867a746f3148548Craig Stout 11742e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout releaseBackgroundBitmap(); 11752e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout 11762590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper imageInWrapper = getImageInWrapper(); 11772590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (imageInWrapper != null) { 11780f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout if (DEBUG) Log.v(TAG, "moving image in to image out"); 11792e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout // Order is important! Setting a drawable "removes" the 11802e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout // previous one from the view 1181d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.clearDrawable(R.id.background_imagein, mContext); 11822590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.updateDrawable(R.id.background_imageout, 11832590c39739945451f80dcf8667709b93293fc8bcCraig Stout imageInWrapper.getDrawable()); 118417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 11852e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout 1186f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout setBackgroundDrawable(mDrawable); 11872e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout applyBackgroundChanges(); 118817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 118917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 119017993c442c26161f684d6c0c6867a746f3148548Craig Stout 1191d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private static Drawable createEmptyDrawable(Context context) { 119217993c442c26161f684d6c0c6867a746f3148548Craig Stout Bitmap bitmap = null; 1193d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return new BitmapDrawable(context.getResources(), bitmap); 119417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 119517993c442c26161f684d6c0c6867a746f3148548Craig Stout 119617993c442c26161f684d6c0c6867a746f3148548Craig Stout private void showWallpaper(boolean show) { 119717993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mWindow == null) { 119817993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 119917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 120017993c442c26161f684d6c0c6867a746f3148548Craig Stout 120117993c442c26161f684d6c0c6867a746f3148548Craig Stout WindowManager.LayoutParams layoutParams = mWindow.getAttributes(); 120217993c442c26161f684d6c0c6867a746f3148548Craig Stout if (show) { 120317993c442c26161f684d6c0c6867a746f3148548Craig Stout if ((layoutParams.flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 120417993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 120517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 120617993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "showing wallpaper"); 120717993c442c26161f684d6c0c6867a746f3148548Craig Stout layoutParams.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 120817993c442c26161f684d6c0c6867a746f3148548Craig Stout } else { 120917993c442c26161f684d6c0c6867a746f3148548Craig Stout if ((layoutParams.flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) == 0) { 121017993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 121117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 121217993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "hiding wallpaper"); 121317993c442c26161f684d6c0c6867a746f3148548Craig Stout layoutParams.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 121417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 121517993c442c26161f684d6c0c6867a746f3148548Craig Stout 121617993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindow.setAttributes(layoutParams); 121717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 121817993c442c26161f684d6c0c6867a746f3148548Craig Stout} 1219