BackgroundManager.java revision f684b94c5f316e9735abc298e00c3f61642b821e
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 18d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stoutimport android.graphics.PixelFormat; 19f684b94c5f316e9735abc298e00c3f61642b821eCraig Stoutimport android.graphics.PorterDuff; 20f684b94c5f316e9735abc298e00c3f61642b821eCraig Stoutimport android.graphics.PorterDuffColorFilter; 2117993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.support.v17.leanback.R; 223d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stoutimport android.animation.Animator; 237e22f555da71f49a32420965817c760522b95963Craig Stoutimport android.animation.ValueAnimator; 2417993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.app.Activity; 2517993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.content.Context; 267f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stoutimport android.content.res.Resources; 2717993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.content.res.TypedArray; 2817993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.Bitmap; 297f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stoutimport android.graphics.Canvas; 3017993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.Color; 317f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stoutimport android.graphics.ColorFilter; 3217993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.Matrix; 337f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stoutimport android.graphics.Paint; 3417993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.ColorDrawable; 3517993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.Drawable; 3617993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.LayerDrawable; 3717993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.os.Handler; 382590c39739945451f80dcf8667709b93293fc8bcCraig Stoutimport android.support.v17.leanback.widget.BackgroundHelper; 390f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stoutimport android.support.v4.view.animation.FastOutLinearInInterpolator; 4017993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.util.Log; 4117993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.LayoutInflater; 4217993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.View; 4317993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.ViewGroup; 4417993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.Window; 4517993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.WindowManager; 467e22f555da71f49a32420965817c760522b95963Craig Stoutimport android.view.animation.Interpolator; 470f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stoutimport android.view.animation.AnimationUtils; 48fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Guimport android.support.v4.app.FragmentActivity; 4960c3b420827d0520509387f1abe3e3d8168e2279Dake Guimport android.support.v4.content.ContextCompat; 5017993c442c26161f684d6c0c6867a746f3148548Craig Stout 5117993c442c26161f684d6c0c6867a746f3148548Craig Stout/** 52146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Supports background image continuity between multiple Activities. 5317993c442c26161f684d6c0c6867a746f3148548Craig Stout * 54146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>An Activity should instantiate a BackgroundManager and {@link #attach} 55146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * to the Activity's window. When the Activity is started, the background is 5617993c442c26161f684d6c0c6867a746f3148548Craig Stout * initialized to the current background values stored in a continuity service. 5717993c442c26161f684d6c0c6867a746f3148548Craig Stout * The background continuity service is updated as the background is updated. 5817993c442c26161f684d6c0c6867a746f3148548Craig Stout * 59146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>At some point, for example when it is stopped, the Activity may release 60146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * its background state. 612e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout * 62146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>When an Activity is resumed, if the BackgroundManager has not been 63146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * released, the continuity service is updated from the BackgroundManager state. 64146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * If the BackgroundManager was released, the BackgroundManager inherits the 65146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * current state from the continuity service. 6617993c442c26161f684d6c0c6867a746f3148548Craig Stout * 67146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>When the last Activity is destroyed, the background state is reset. 6817993c442c26161f684d6c0c6867a746f3148548Craig Stout * 69146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>Backgrounds consist of several layers, from back to front: 70146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <ul> 71146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <li>the background Drawable of the theme</li> 72146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <li>a solid color (set via {@link #setColor})</li> 73146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <li>two Drawables, previous and current (set via {@link #setBitmap} or 74146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * {@link #setDrawable}), which may be in transition</li> 75146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * </ul> 7617993c442c26161f684d6c0c6867a746f3148548Craig Stout * 77146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * <p>BackgroundManager holds references to potentially large bitmap Drawables. 78146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Call {@link #release} to release these references when the Activity is not 7917993c442c26161f684d6c0c6867a746f3148548Craig Stout * visible. 8017993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 81146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn// TODO: support for multiple app processes requires a proper android service 82146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn// instead of the shared memory "service" implemented here. Such a service could 83146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn// support continuity between fragments of different applications if desired. 8417993c442c26161f684d6c0c6867a746f3148548Craig Stoutpublic final class BackgroundManager { 85f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 86f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout interface FragmentStateQueriable { 87f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout public boolean isResumed(); 88f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 89f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 9017993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final String TAG = "BackgroundManager"; 9117993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final boolean DEBUG = false; 9217993c442c26161f684d6c0c6867a746f3148548Craig Stout 9317993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final int FULL_ALPHA = 255; 9417993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final int DIM_ALPHA_ON_SOLID = (int) (0.8f * FULL_ALPHA); 9517993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final int CHANGE_BG_DELAY_MS = 500; 963d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout private static final int FADE_DURATION = 500; 9717993c442c26161f684d6c0c6867a746f3148548Craig Stout 9817993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 9917993c442c26161f684d6c0c6867a746f3148548Craig Stout * Using a separate window for backgrounds can improve graphics performance by 10017993c442c26161f684d6c0c6867a746f3148548Craig Stout * leveraging hardware display layers. 10117993c442c26161f684d6c0c6867a746f3148548Craig Stout * TODO: support a leanback configuration option. 10217993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 10317993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final boolean USE_SEPARATE_WINDOW = false; 10417993c442c26161f684d6c0c6867a746f3148548Craig Stout 10517993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final String WINDOW_NAME = "BackgroundManager"; 1067f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu private static final String FRAGMENT_TAG = BackgroundManager.class.getCanonicalName(); 10717993c442c26161f684d6c0c6867a746f3148548Craig Stout 10817993c442c26161f684d6c0c6867a746f3148548Craig Stout private Context mContext; 10917993c442c26161f684d6c0c6867a746f3148548Craig Stout private Handler mHandler; 11017993c442c26161f684d6c0c6867a746f3148548Craig Stout private Window mWindow; 11117993c442c26161f684d6c0c6867a746f3148548Craig Stout private WindowManager mWindowManager; 11217993c442c26161f684d6c0c6867a746f3148548Craig Stout private View mBgView; 11317993c442c26161f684d6c0c6867a746f3148548Craig Stout private BackgroundContinuityService mService; 11417993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mThemeDrawableResourceId; 115f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private FragmentStateQueriable mFragmentState; 11617993c442c26161f684d6c0c6867a746f3148548Craig Stout 11717993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mHeightPx; 11817993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mWidthPx; 11917993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable mBackgroundDrawable; 12017993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mBackgroundColor; 12117993c442c26161f684d6c0c6867a746f3148548Craig Stout private boolean mAttached; 1220f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private long mLastSetTime; 1230f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 1240f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final Interpolator mAccelerateInterpolator; 1250f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final Interpolator mDecelerateInterpolator; 1260f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final ValueAnimator mAnimator; 1270f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final ValueAnimator mDimAnimator; 12817993c442c26161f684d6c0c6867a746f3148548Craig Stout 1297f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout private static class BitmapDrawable extends Drawable { 1307f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1313d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout static class ConstantState extends Drawable.ConstantState { 1323d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout Bitmap mBitmap; 1333d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout Matrix mMatrix; 1343d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout Paint mPaint; 1353d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 1363d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 1373d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public Drawable newDrawable() { 1383d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout return new BitmapDrawable(null, mBitmap, mMatrix); 1393d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 1403d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 1413d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 1423d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public int getChangingConfigurations() { 1433d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout return 0; 1443d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 1453d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 1463d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 1473d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout private ConstantState mState = new ConstantState(); 1487f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1497f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout BitmapDrawable(Resources resources, Bitmap bitmap) { 1507f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout this(resources, bitmap, null); 1517f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1527f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1537f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout BitmapDrawable(Resources resources, Bitmap bitmap, Matrix matrix) { 1543d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mBitmap = bitmap; 1553d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mMatrix = matrix != null ? matrix : new Matrix(); 1563d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mPaint = new Paint(); 1573d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mPaint.setFilterBitmap(true); 1587f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1597f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1607f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout Bitmap getBitmap() { 1613d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout return mState.mBitmap; 1627f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1637f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1647f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout @Override 1657f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout public void draw(Canvas canvas) { 1663d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (mState.mBitmap == null) { 1677f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return; 1687f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 169f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (mState.mPaint.getAlpha() < FULL_ALPHA && mState.mPaint.getColorFilter() != null) { 170f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout throw new IllegalStateException("Can't draw with translucent alpha and color filter"); 171f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 1723d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout canvas.drawBitmap(mState.mBitmap, mState.mMatrix, mState.mPaint); 1737f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1747f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1757f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout @Override 1767f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout public int getOpacity() { 177d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return android.graphics.PixelFormat.TRANSLUCENT; 1787f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1797f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 1807f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout @Override 1817f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout public void setAlpha(int alpha) { 1823d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (mState.mPaint.getAlpha() != alpha) { 1833d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mState.mPaint.setAlpha(alpha); 1847f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout invalidateSelf(); 1857f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1867f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 1877f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 188f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout /** 189f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * Does not invalidateSelf to avoid recursion issues. 190f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * Caller must ensure appropriate invalidation. 191f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout */ 1927f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout @Override 1937f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout public void setColorFilter(ColorFilter cf) { 194f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mState.mPaint.setColorFilter(cf); 195f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 196f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 197f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout public ColorFilter getColorFilter() { 198f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout return mState.mPaint.getColorFilter(); 1997f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 2003d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout 2013d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout @Override 2023d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout public ConstantState getConstantState() { 2033d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout return mState; 2043d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout } 2057f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 2067f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 2077f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout private static class DrawableWrapper { 208d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private int mAlpha = FULL_ALPHA; 209d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private Drawable mDrawable; 2107e22f555da71f49a32420965817c760522b95963Craig Stout 21117993c442c26161f684d6c0c6867a746f3148548Craig Stout public DrawableWrapper(Drawable drawable) { 21217993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable = drawable; 213d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout updateAlpha(); 214d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 215d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public DrawableWrapper(DrawableWrapper wrapper, Drawable drawable) { 216d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mDrawable = drawable; 217d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mAlpha = wrapper.getAlpha(); 218d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout updateAlpha(); 21917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 22017993c442c26161f684d6c0c6867a746f3148548Craig Stout public Drawable getDrawable() { 22117993c442c26161f684d6c0c6867a746f3148548Craig Stout return mDrawable; 22217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 22317993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setAlpha(int alpha) { 22417993c442c26161f684d6c0c6867a746f3148548Craig Stout mAlpha = alpha; 225d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout updateAlpha(); 22617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 22717993c442c26161f684d6c0c6867a746f3148548Craig Stout public int getAlpha() { 22817993c442c26161f684d6c0c6867a746f3148548Craig Stout return mAlpha; 22917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 230d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private void updateAlpha() { 231d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mDrawable.setAlpha(mAlpha); 232d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 23317993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setColor(int color) { 23417993c442c26161f684d6c0c6867a746f3148548Craig Stout ((ColorDrawable) mDrawable).setColor(color); 23517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 23617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 23717993c442c26161f684d6c0c6867a746f3148548Craig Stout 238f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout static class TranslucentLayerDrawable extends LayerDrawable { 239d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private DrawableWrapper[] mWrapper; 240d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private Paint mPaint = new Paint(); 241d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 242d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public TranslucentLayerDrawable(Drawable[] drawables) { 243d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout super(drawables); 244d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout int count = drawables.length; 245d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mWrapper = new DrawableWrapper[count]; 246d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout for (int i = 0; i < count; i++) { 247d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mWrapper[i] = new DrawableWrapper(drawables[i]); 248d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 249d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 250d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 251d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout @Override 252d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public void setAlpha(int alpha) { 253d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (mPaint.getAlpha() != alpha) { 254f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout int previousAlpha = mPaint.getAlpha(); 255d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mPaint.setAlpha(alpha); 256d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout invalidateSelf(); 257f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout onAlphaChanged(previousAlpha, alpha); 258d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 259d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 260d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 2612590c39739945451f80dcf8667709b93293fc8bcCraig Stout // Queried by system transitions 2622590c39739945451f80dcf8667709b93293fc8bcCraig Stout public int getAlpha() { 2632590c39739945451f80dcf8667709b93293fc8bcCraig Stout return mPaint.getAlpha(); 2642590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 2652590c39739945451f80dcf8667709b93293fc8bcCraig Stout 266f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout protected void onAlphaChanged(int oldAlpha, int newAlpha) { 267f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 268f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 269d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout @Override 270d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public Drawable mutate() { 271d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout Drawable drawable = super.mutate(); 272d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout int count = getNumberOfLayers(); 273d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout for (int i = 0; i < count; i++) { 274d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (mWrapper[i] != null) { 275d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mWrapper[i] = new DrawableWrapper(mWrapper[i], getDrawable(i)); 276d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 277d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 278f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout invalidateSelf(); 279d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return drawable; 280d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 281d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 282d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout @Override 283d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public int getOpacity() { 284d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return PixelFormat.TRANSLUCENT; 285d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 286d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 287d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout @Override 288d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public boolean setDrawableByLayerId(int id, Drawable drawable) { 289d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return updateDrawable(id, drawable) != null; 290d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 291d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 292d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public DrawableWrapper updateDrawable(int id, Drawable drawable) { 293d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout super.setDrawableByLayerId(id, drawable); 294d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout for (int i = 0; i < getNumberOfLayers(); i++) { 295d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (getId(i) == id) { 296d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mWrapper[i] = new DrawableWrapper(drawable); 297f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // Must come after mWrapper was updated so it can be seen by updateColorFilter 298f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout invalidateSelf(); 299d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return mWrapper[i]; 300d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 301d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 302d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return null; 303d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 304d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 305d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public void clearDrawable(int id, Context context) { 306d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout for (int i = 0; i < getNumberOfLayers(); i++) { 307d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (getId(i) == id) { 308d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mWrapper[i] = null; 309d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout super.setDrawableByLayerId(id, createEmptyDrawable(context)); 310d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout break; 311d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 312d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 313d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 314d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 315d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public DrawableWrapper findWrapperById(int id) { 316d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout for (int i = 0; i < getNumberOfLayers(); i++) { 317d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (getId(i) == id) { 318d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return mWrapper[i]; 319d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 320d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 321d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return null; 322d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 323d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 324d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout @Override 325d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout public void draw(Canvas canvas) { 326d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (mPaint.getAlpha() < FULL_ALPHA) { 327d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), 328d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mPaint, Canvas.ALL_SAVE_FLAG); 329d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 330d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout super.draw(canvas); 331d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (mPaint.getAlpha() < FULL_ALPHA) { 332d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout canvas.restore(); 333d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 334d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 335d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 336d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 337f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout /** 338f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * Optimizes drawing when the dim drawable is an alpha-only color and imagein is opaque. 339f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * When the layer drawable is translucent (activity transition) then we can avoid the slow 340f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * saveLayer/restore draw path. 341f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout */ 342f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private class OptimizedTranslucentLayerDrawable extends TranslucentLayerDrawable { 343f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private PorterDuffColorFilter mColorFilter; 344f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 345f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout public OptimizedTranslucentLayerDrawable(Drawable[] drawables) { 346f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout super(drawables); 347f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 348f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 349f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout @Override 350f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout protected void onAlphaChanged(int oldAlpha, int newAlpha) { 351f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (newAlpha == FULL_ALPHA && oldAlpha < FULL_ALPHA) { 352f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "transition complete"); 353f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout postChangeRunnable(); 354f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 355f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 356f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 357f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout @Override 358f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout public void invalidateSelf() { 359f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout super.invalidateSelf(); 360f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout updateColorFilter(); 361f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 362f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 363f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private void updateColorFilter() { 364f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout DrawableWrapper dimWrapper = findWrapperById(R.id.background_dim); 365f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout DrawableWrapper imageInWrapper = findWrapperById(R.id.background_imagein); 366f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout DrawableWrapper imageOutWrapper = findWrapperById(R.id.background_imageout); 367f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 368f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mColorFilter = null; 369f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (imageInWrapper != null && imageInWrapper.getAlpha() == FULL_ALPHA && 370f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout dimWrapper.getDrawable() instanceof ColorDrawable) { 371f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout int dimColor = ((ColorDrawable) dimWrapper.getDrawable()).getColor(); 372f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (Color.red(dimColor) == 0 && 373f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout Color.green(dimColor) == 0 && 374f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout Color.blue(dimColor) == 0) { 375f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout int dimAlpha = 255 - Color.alpha(dimColor); 376f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout int color = Color.argb(getAlpha(), dimAlpha, dimAlpha, dimAlpha); 377f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mColorFilter = new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY); 378f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 379f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 380f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (imageInWrapper != null) { 381f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout imageInWrapper.getDrawable().setColorFilter(mColorFilter); 382f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 383f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (imageOutWrapper != null) { 384f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout imageOutWrapper.getDrawable().setColorFilter(null); 385f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 386f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 387f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 388f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout @Override 389f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout public void draw(Canvas canvas) { 390f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout DrawableWrapper imageInWrapper = findWrapperById(R.id.background_imagein); 391f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout BitmapDrawable drawable = imageInWrapper == null ? null : 392f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout (BitmapDrawable) imageInWrapper.getDrawable(); 393f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (drawable != null && drawable.getColorFilter() != null) { 394f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout drawable.draw(canvas); 395f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } else { 396f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout super.draw(canvas); 397f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 398f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 399f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 400f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 401f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private TranslucentLayerDrawable createOptimizedTranslucentLayerDrawable( 402f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout LayerDrawable layerDrawable) { 403f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout int numChildren = layerDrawable.getNumberOfLayers(); 404f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout Drawable[] drawables = new Drawable[numChildren]; 405f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout for (int i = 0; i < numChildren; i++) { 406f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout drawables[i] = layerDrawable.getDrawable(i); 407f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 408f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout TranslucentLayerDrawable result = new OptimizedTranslucentLayerDrawable(drawables); 409f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout for (int i = 0; i < numChildren; i++) { 410f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout result.setId(i, layerDrawable.getId(i)); 411f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 412f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout return result; 413f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 414f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 415d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private TranslucentLayerDrawable mLayerDrawable; 4160f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private Drawable mDimDrawable; 41717993c442c26161f684d6c0c6867a746f3148548Craig Stout private ChangeBackgroundRunnable mChangeRunnable; 418f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private boolean mChangeRunnablePending; 41917993c442c26161f684d6c0c6867a746f3148548Craig Stout 4200f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final Animator.AnimatorListener mAnimationListener = new Animator.AnimatorListener() { 421f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout final Runnable mRunnable = new Runnable() { 422f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout @Override 423f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout public void run() { 424f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout postChangeRunnable(); 425f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 426f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout }; 427f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 4280f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout @Override 4290f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void onAnimationStart(Animator animation) { 4300f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4310f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout @Override 4320f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void onAnimationRepeat(Animator animation) { 4330f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4340f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout @Override 4350f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void onAnimationEnd(Animator animation) { 436f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mLayerDrawable.clearDrawable(R.id.background_imageout, mContext); 437f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mHandler.post(mRunnable); 4380f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4390f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout @Override 4400f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void onAnimationCancel(Animator animation) { 4410f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4420f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout }; 4430f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 4440f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final ValueAnimator.AnimatorUpdateListener mAnimationUpdateListener = 4450f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout new ValueAnimator.AnimatorUpdateListener() { 4460f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout @Override 4470f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void onAnimationUpdate(ValueAnimator animation) { 4480f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout int fadeInAlpha = (Integer) animation.getAnimatedValue(); 4492590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper imageInWrapper = getImageInWrapper(); 4502590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (imageInWrapper != null) { 4512590c39739945451f80dcf8667709b93293fc8bcCraig Stout imageInWrapper.setAlpha(fadeInAlpha); 4522590c39739945451f80dcf8667709b93293fc8bcCraig Stout } else { 4532590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper imageOutWrapper = getImageOutWrapper(); 4542590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (imageOutWrapper != null) { 4552590c39739945451f80dcf8667709b93293fc8bcCraig Stout imageOutWrapper.setAlpha(255 - fadeInAlpha); 4562590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 4570f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4580f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4590f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout }; 4600f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 4610f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private final ValueAnimator.AnimatorUpdateListener mDimUpdateListener = 4620f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout new ValueAnimator.AnimatorUpdateListener() { 4630f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout @Override 4640f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void onAnimationUpdate(ValueAnimator animation) { 4652590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper dimWrapper = getDimWrapper(); 4662590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (dimWrapper != null) { 4672590c39739945451f80dcf8667709b93293fc8bcCraig Stout dimWrapper.setAlpha((Integer) animation.getAnimatedValue()); 4680f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4690f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 4700f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout }; 4710f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 47217993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 47317993c442c26161f684d6c0c6867a746f3148548Craig Stout * Shared memory continuity service. 47417993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 47517993c442c26161f684d6c0c6867a746f3148548Craig Stout private static class BackgroundContinuityService { 47617993c442c26161f684d6c0c6867a746f3148548Craig Stout private static final String TAG = "BackgroundContinuityService"; 47717993c442c26161f684d6c0c6867a746f3148548Craig Stout private static boolean DEBUG = BackgroundManager.DEBUG; 47817993c442c26161f684d6c0c6867a746f3148548Craig Stout 47917993c442c26161f684d6c0c6867a746f3148548Craig Stout private static BackgroundContinuityService sService = new BackgroundContinuityService(); 48017993c442c26161f684d6c0c6867a746f3148548Craig Stout 48117993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mColor; 48217993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable mDrawable; 48317993c442c26161f684d6c0c6867a746f3148548Craig Stout private int mCount; 48417993c442c26161f684d6c0c6867a746f3148548Craig Stout 48560c3b420827d0520509387f1abe3e3d8168e2279Dake Gu /** Single cache of theme drawable */ 48660c3b420827d0520509387f1abe3e3d8168e2279Dake Gu private int mLastThemeDrawableId; 48760c3b420827d0520509387f1abe3e3d8168e2279Dake Gu private WeakReference<Drawable> mLastThemeDrawable; 48860c3b420827d0520509387f1abe3e3d8168e2279Dake Gu 48917993c442c26161f684d6c0c6867a746f3148548Craig Stout private BackgroundContinuityService() { 49017993c442c26161f684d6c0c6867a746f3148548Craig Stout reset(); 49117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 49217993c442c26161f684d6c0c6867a746f3148548Craig Stout 49317993c442c26161f684d6c0c6867a746f3148548Craig Stout private void reset() { 49417993c442c26161f684d6c0c6867a746f3148548Craig Stout mColor = Color.TRANSPARENT; 49517993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable = null; 49617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 49717993c442c26161f684d6c0c6867a746f3148548Craig Stout 49817993c442c26161f684d6c0c6867a746f3148548Craig Stout public static BackgroundContinuityService getInstance() { 49917993c442c26161f684d6c0c6867a746f3148548Craig Stout final int count = sService.mCount++; 50017993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "Returning instance with new count " + count); 50117993c442c26161f684d6c0c6867a746f3148548Craig Stout return sService; 50217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 50317993c442c26161f684d6c0c6867a746f3148548Craig Stout 50417993c442c26161f684d6c0c6867a746f3148548Craig Stout public void unref() { 50517993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mCount <= 0) throw new IllegalStateException("Can't unref, count " + mCount); 50617993c442c26161f684d6c0c6867a746f3148548Craig Stout if (--mCount == 0) { 50717993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "mCount is zero, resetting"); 50817993c442c26161f684d6c0c6867a746f3148548Craig Stout reset(); 50917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 51017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 51117993c442c26161f684d6c0c6867a746f3148548Craig Stout public int getColor() { 51217993c442c26161f684d6c0c6867a746f3148548Craig Stout return mColor; 51317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 51417993c442c26161f684d6c0c6867a746f3148548Craig Stout public Drawable getDrawable() { 51517993c442c26161f684d6c0c6867a746f3148548Craig Stout return mDrawable; 51617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 51717993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setColor(int color) { 51817993c442c26161f684d6c0c6867a746f3148548Craig Stout mColor = color; 51917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 52017993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setDrawable(Drawable drawable) { 52117993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable = drawable; 52217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 52360c3b420827d0520509387f1abe3e3d8168e2279Dake Gu public Drawable getThemeDrawable(Context context, int themeDrawableId) { 52460c3b420827d0520509387f1abe3e3d8168e2279Dake Gu Drawable drawable = null; 52560c3b420827d0520509387f1abe3e3d8168e2279Dake Gu if (mLastThemeDrawable != null && mLastThemeDrawableId == themeDrawableId) { 52660c3b420827d0520509387f1abe3e3d8168e2279Dake Gu drawable = mLastThemeDrawable.get(); 52760c3b420827d0520509387f1abe3e3d8168e2279Dake Gu } 52860c3b420827d0520509387f1abe3e3d8168e2279Dake Gu if (drawable == null) { 52960c3b420827d0520509387f1abe3e3d8168e2279Dake Gu drawable = ContextCompat.getDrawable(context, themeDrawableId); 53060c3b420827d0520509387f1abe3e3d8168e2279Dake Gu mLastThemeDrawable = new WeakReference<Drawable>(drawable); 53160c3b420827d0520509387f1abe3e3d8168e2279Dake Gu mLastThemeDrawableId = themeDrawableId; 53260c3b420827d0520509387f1abe3e3d8168e2279Dake Gu } 53360c3b420827d0520509387f1abe3e3d8168e2279Dake Gu return drawable.getConstantState().newDrawable(context.getResources()).mutate(); 53460c3b420827d0520509387f1abe3e3d8168e2279Dake Gu } 53517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 53617993c442c26161f684d6c0c6867a746f3148548Craig Stout 53717993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable getThemeDrawable() { 53817993c442c26161f684d6c0c6867a746f3148548Craig Stout Drawable drawable = null; 53917993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mThemeDrawableResourceId != -1) { 54060c3b420827d0520509387f1abe3e3d8168e2279Dake Gu drawable = mService.getThemeDrawable(mContext, mThemeDrawableResourceId); 54117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 54217993c442c26161f684d6c0c6867a746f3148548Craig Stout if (drawable == null) { 543d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout drawable = createEmptyDrawable(mContext); 54417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 54517993c442c26161f684d6c0c6867a746f3148548Craig Stout return drawable; 54617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 54717993c442c26161f684d6c0c6867a746f3148548Craig Stout 54817993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 549146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Get the BackgroundManager associated with the Activity. 5507f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu * <p> 551146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * The BackgroundManager will be created on-demand for each individual 552146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Activity. Subsequent calls will return the same BackgroundManager created 553146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * for this Activity. 5547f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu */ 5557f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu public static BackgroundManager getInstance(Activity activity) { 556fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu if (activity instanceof FragmentActivity) { 557fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu return getSupportInstance((FragmentActivity) activity); 558fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 5597f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu BackgroundFragment fragment = (BackgroundFragment) activity.getFragmentManager() 5607f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu .findFragmentByTag(FRAGMENT_TAG); 5617f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu if (fragment != null) { 5627f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu BackgroundManager manager = fragment.getBackgroundManager(); 5637f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu if (manager != null) { 5647f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu return manager; 5657f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } 5667f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu // manager is null: this is a fragment restored by FragmentManager, 5677f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu // fall through to create a BackgroundManager attach to it. 5687f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } 569fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu return new BackgroundManager(activity, false); 570fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 571fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu 572fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu private static BackgroundManager getSupportInstance(FragmentActivity activity) { 573fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu BackgroundSupportFragment fragment = (BackgroundSupportFragment) activity 574fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu .getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG); 575fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu if (fragment != null) { 576fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu BackgroundManager manager = fragment.getBackgroundManager(); 577fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu if (manager != null) { 578fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu return manager; 579fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 580fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu // manager is null: this is a fragment restored by FragmentManager, 581fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu // fall through to create a BackgroundManager attach to it. 582fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 583fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu return new BackgroundManager(activity, true); 5847f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } 5857f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu 586fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu private BackgroundManager(Activity activity, boolean isSupportFragmentActivity) { 58717993c442c26161f684d6c0c6867a746f3148548Craig Stout mContext = activity; 58817993c442c26161f684d6c0c6867a746f3148548Craig Stout mService = BackgroundContinuityService.getInstance(); 58917993c442c26161f684d6c0c6867a746f3148548Craig Stout mHeightPx = mContext.getResources().getDisplayMetrics().heightPixels; 59017993c442c26161f684d6c0c6867a746f3148548Craig Stout mWidthPx = mContext.getResources().getDisplayMetrics().widthPixels; 59117993c442c26161f684d6c0c6867a746f3148548Craig Stout mHandler = new Handler(); 59217993c442c26161f684d6c0c6867a746f3148548Craig Stout 5930f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout Interpolator defaultInterpolator = new FastOutLinearInInterpolator(); 5940f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAccelerateInterpolator = AnimationUtils.loadInterpolator(mContext, 5950f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout android.R.anim.accelerate_interpolator); 5960f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDecelerateInterpolator = AnimationUtils.loadInterpolator(mContext, 5970f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout android.R.anim.decelerate_interpolator); 5980f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 5990f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAnimator = ValueAnimator.ofInt(0, FULL_ALPHA); 6000f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAnimator.addListener(mAnimationListener); 6010f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAnimator.addUpdateListener(mAnimationUpdateListener); 6020f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAnimator.setInterpolator(defaultInterpolator); 6030f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 6040f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimAnimator = new ValueAnimator(); 6050f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimAnimator.addUpdateListener(mDimUpdateListener); 6060f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 60717993c442c26161f684d6c0c6867a746f3148548Craig Stout TypedArray ta = activity.getTheme().obtainStyledAttributes(new int[] { 60817993c442c26161f684d6c0c6867a746f3148548Craig Stout android.R.attr.windowBackground }); 60917993c442c26161f684d6c0c6867a746f3148548Craig Stout mThemeDrawableResourceId = ta.getResourceId(0, -1); 61017993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mThemeDrawableResourceId < 0) { 61117993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "BackgroundManager no window background resource!"); 61217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 61317993c442c26161f684d6c0c6867a746f3148548Craig Stout ta.recycle(); 61417993c442c26161f684d6c0c6867a746f3148548Craig Stout 615fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu if (isSupportFragmentActivity) { 616fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu createSupportFragment((FragmentActivity) activity); 617fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } else { 618fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu createFragment(activity); 619fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 62017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 62117993c442c26161f684d6c0c6867a746f3148548Craig Stout 62217993c442c26161f684d6c0c6867a746f3148548Craig Stout private void createFragment(Activity activity) { 62317993c442c26161f684d6c0c6867a746f3148548Craig Stout // Use a fragment to ensure the background manager gets detached properly. 624b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu BackgroundFragment fragment = (BackgroundFragment) activity.getFragmentManager() 6257f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu .findFragmentByTag(FRAGMENT_TAG); 626b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu if (fragment == null) { 627b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu fragment = new BackgroundFragment(); 6287f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu activity.getFragmentManager().beginTransaction().add(fragment, FRAGMENT_TAG).commit(); 6297f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } else { 6307f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu if (fragment.getBackgroundManager() != null) { 6317f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu throw new IllegalStateException("Created duplicated BackgroundManager for same " + 6327f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu "activity, please use getInstance() instead"); 6337f0ed3452a3378c851217cd300950ba2e03f2649Dake Gu } 634b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu } 63517993c442c26161f684d6c0c6867a746f3148548Craig Stout fragment.setBackgroundManager(this); 636f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mFragmentState = fragment; 63717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 63817993c442c26161f684d6c0c6867a746f3148548Craig Stout 639fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu private void createSupportFragment(FragmentActivity activity) { 640fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu // Use a fragment to ensure the background manager gets detached properly. 641fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu BackgroundSupportFragment fragment = (BackgroundSupportFragment) activity 642fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu .getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG); 643fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu if (fragment == null) { 644fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu fragment = new BackgroundSupportFragment(); 645fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu activity.getSupportFragmentManager().beginTransaction().add(fragment, FRAGMENT_TAG) 646fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu .commit(); 647fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } else { 648fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu if (fragment.getBackgroundManager() != null) { 649fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu throw new IllegalStateException("Created duplicated BackgroundManager for same " + 650fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu "activity, please use getInstance() instead"); 651fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 652fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 653fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu fragment.setBackgroundManager(this); 654f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mFragmentState = fragment; 655fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu } 656fa9f41f8f5408b6e3931f1ab81f586a47cc2d975Dake Gu 6572590c39739945451f80dcf8667709b93293fc8bcCraig Stout private DrawableWrapper getImageInWrapper() { 6582590c39739945451f80dcf8667709b93293fc8bcCraig Stout return mLayerDrawable == null ? null : 6592590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.findWrapperById(R.id.background_imagein); 6602590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 6612590c39739945451f80dcf8667709b93293fc8bcCraig Stout 6622590c39739945451f80dcf8667709b93293fc8bcCraig Stout private DrawableWrapper getImageOutWrapper() { 6632590c39739945451f80dcf8667709b93293fc8bcCraig Stout return mLayerDrawable == null ? null : 6642590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.findWrapperById(R.id.background_imageout); 6652590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 6662590c39739945451f80dcf8667709b93293fc8bcCraig Stout 6672590c39739945451f80dcf8667709b93293fc8bcCraig Stout private DrawableWrapper getDimWrapper() { 6682590c39739945451f80dcf8667709b93293fc8bcCraig Stout return mLayerDrawable == null ? null : 6692590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.findWrapperById(R.id.background_dim); 6702590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 6712590c39739945451f80dcf8667709b93293fc8bcCraig Stout 6722590c39739945451f80dcf8667709b93293fc8bcCraig Stout private DrawableWrapper getColorWrapper() { 6732590c39739945451f80dcf8667709b93293fc8bcCraig Stout return mLayerDrawable == null ? null : 6742590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.findWrapperById(R.id.background_color); 6752590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 6762590c39739945451f80dcf8667709b93293fc8bcCraig Stout 67717993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 678f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * Synchronizes state when the owning Activity is started. 679f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * At that point the view becomes visible. 68017993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 681f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout void onActivityStart() { 6822e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout if (mService == null) { 6832e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout return; 6842e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout } 6852e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout if (mLayerDrawable == null) { 686f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "onActivityStart " + this + 6873d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout " released state, syncing with service"); 6882e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout syncWithService(); 6892e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout } else { 690f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "onActivityStart " + this + " updating service color " 6912e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout + mBackgroundColor + " drawable " + mBackgroundDrawable); 6922e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mService.setColor(mBackgroundColor); 6932e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mService.setDrawable(mBackgroundDrawable); 6942e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout } 69517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 69617993c442c26161f684d6c0c6867a746f3148548Craig Stout 697f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout void onResume() { 698f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "onResume " + this); 699f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout postChangeRunnable(); 700f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 701f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 70217993c442c26161f684d6c0c6867a746f3148548Craig Stout private void syncWithService() { 70317993c442c26161f684d6c0c6867a746f3148548Craig Stout int color = mService.getColor(); 70417993c442c26161f684d6c0c6867a746f3148548Craig Stout Drawable drawable = mService.getDrawable(); 70517993c442c26161f684d6c0c6867a746f3148548Craig Stout 70617993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "syncWithService color " + Integer.toHexString(color) 70717993c442c26161f684d6c0c6867a746f3148548Craig Stout + " drawable " + drawable); 70817993c442c26161f684d6c0c6867a746f3148548Craig Stout 70917993c442c26161f684d6c0c6867a746f3148548Craig Stout mBackgroundColor = color; 7103d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout mBackgroundDrawable = drawable == null ? null : 7113d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout drawable.getConstantState().newDrawable().mutate(); 7122e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout 7132e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout updateImmediate(); 71417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 71517993c442c26161f684d6c0c6867a746f3148548Craig Stout 71617993c442c26161f684d6c0c6867a746f3148548Craig Stout private void lazyInit() { 71717993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mLayerDrawable != null) { 71817993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 71917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 72017993c442c26161f684d6c0c6867a746f3148548Craig Stout 721d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout LayerDrawable layerDrawable = (LayerDrawable) 722d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout ContextCompat.getDrawable(mContext, R.drawable.lb_background).mutate(); 723f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mLayerDrawable = createOptimizedTranslucentLayerDrawable(layerDrawable); 7242590c39739945451f80dcf8667709b93293fc8bcCraig Stout BackgroundHelper.setBackgroundPreservingAlpha(mBgView, mLayerDrawable); 72517993c442c26161f684d6c0c6867a746f3148548Craig Stout 726d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.clearDrawable(R.id.background_imageout, mContext); 727d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.updateDrawable(R.id.background_theme, getThemeDrawable()); 728c149abce7f8a46f7c54211b5f97c5cd9ee729357Dake Gu 7290f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout updateDimWrapper(); 7300f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 7310f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 7320f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private void updateDimWrapper() { 7330f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout if (mDimDrawable == null) { 7340f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimDrawable = getDefaultDimLayer(); 7350f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 736d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout Drawable dimDrawable = mDimDrawable.getConstantState().newDrawable( 737d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mContext.getResources()).mutate(); 7382590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (mLayerDrawable != null) { 7392590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.updateDrawable(R.id.background_dim, dimDrawable); 7402590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 74117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 74217993c442c26161f684d6c0c6867a746f3148548Craig Stout 74317993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 7440f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout * Make the background visible on the given Window. The background manager must be attached 7450f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout * when the background is set. 74617993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 74717993c442c26161f684d6c0c6867a746f3148548Craig Stout public void attach(Window window) { 74817993c442c26161f684d6c0c6867a746f3148548Craig Stout if (USE_SEPARATE_WINDOW) { 74917993c442c26161f684d6c0c6867a746f3148548Craig Stout attachBehindWindow(window); 75017993c442c26161f684d6c0c6867a746f3148548Craig Stout } else { 75117993c442c26161f684d6c0c6867a746f3148548Craig Stout attachToView(window.getDecorView()); 75217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 75317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 75417993c442c26161f684d6c0c6867a746f3148548Craig Stout 75517993c442c26161f684d6c0c6867a746f3148548Craig Stout private void attachBehindWindow(Window window) { 75617993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "attachBehindWindow " + window); 75717993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindow = window; 75817993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindowManager = window.getWindowManager(); 75917993c442c26161f684d6c0c6867a746f3148548Craig Stout 76017993c442c26161f684d6c0c6867a746f3148548Craig Stout WindowManager.LayoutParams params = new WindowManager.LayoutParams( 76117993c442c26161f684d6c0c6867a746f3148548Craig Stout // Media window sits behind the main application window 76217993c442c26161f684d6c0c6867a746f3148548Craig Stout WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA, 76317993c442c26161f684d6c0c6867a746f3148548Craig Stout // Avoid default to software format RGBA 76417993c442c26161f684d6c0c6867a746f3148548Craig Stout WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, 76517993c442c26161f684d6c0c6867a746f3148548Craig Stout android.graphics.PixelFormat.TRANSLUCENT); 76617993c442c26161f684d6c0c6867a746f3148548Craig Stout params.setTitle(WINDOW_NAME); 76717993c442c26161f684d6c0c6867a746f3148548Craig Stout params.width = ViewGroup.LayoutParams.MATCH_PARENT; 76817993c442c26161f684d6c0c6867a746f3148548Craig Stout params.height = ViewGroup.LayoutParams.MATCH_PARENT; 76917993c442c26161f684d6c0c6867a746f3148548Craig Stout 77017993c442c26161f684d6c0c6867a746f3148548Craig Stout View backgroundView = LayoutInflater.from(mContext).inflate( 77117993c442c26161f684d6c0c6867a746f3148548Craig Stout R.layout.lb_background_window, null); 77217993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindowManager.addView(backgroundView, params); 77317993c442c26161f684d6c0c6867a746f3148548Craig Stout 77417993c442c26161f684d6c0c6867a746f3148548Craig Stout attachToView(backgroundView); 77517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 77617993c442c26161f684d6c0c6867a746f3148548Craig Stout 77717993c442c26161f684d6c0c6867a746f3148548Craig Stout private void attachToView(View sceneRoot) { 77817993c442c26161f684d6c0c6867a746f3148548Craig Stout mBgView = sceneRoot; 77917993c442c26161f684d6c0c6867a746f3148548Craig Stout mAttached = true; 7802e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout syncWithService(); 78117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 78217993c442c26161f684d6c0c6867a746f3148548Craig Stout 78317993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 7840f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout * Returns true if the background manager is currently attached; false otherwise. 7850f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout */ 7860f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public boolean isAttached() { 7870f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout return mAttached; 7880f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 7890f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 7900f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout /** 791146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Release references to Drawables and put the BackgroundManager into the 792146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * detached state. Called when the associated Activity is destroyed. 79317993c442c26161f684d6c0c6867a746f3148548Craig Stout * @hide 79417993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 79517993c442c26161f684d6c0c6867a746f3148548Craig Stout void detach() { 7963d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (DEBUG) Log.v(TAG, "detach " + this); 79717993c442c26161f684d6c0c6867a746f3148548Craig Stout release(); 79817993c442c26161f684d6c0c6867a746f3148548Craig Stout 79917993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mWindowManager != null && mBgView != null) { 80017993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindowManager.removeViewImmediate(mBgView); 80117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 80217993c442c26161f684d6c0c6867a746f3148548Craig Stout 80317993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindowManager = null; 80417993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindow = null; 80517993c442c26161f684d6c0c6867a746f3148548Craig Stout mBgView = null; 80617993c442c26161f684d6c0c6867a746f3148548Craig Stout mAttached = false; 80717993c442c26161f684d6c0c6867a746f3148548Craig Stout 80817993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mService != null) { 80917993c442c26161f684d6c0c6867a746f3148548Craig Stout mService.unref(); 81017993c442c26161f684d6c0c6867a746f3148548Craig Stout mService = null; 81117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 81217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 81317993c442c26161f684d6c0c6867a746f3148548Craig Stout 81417993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 815146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Release references to Drawables. Typically called to reduce memory 816146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * overhead when not visible. 8172e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout * <p> 818f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout * When an Activity is started, if the BackgroundManager has not been 819146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * released, the continuity service is updated from the BackgroundManager 820146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * state. If the BackgroundManager was released, the BackgroundManager 821146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * inherits the current state from the continuity service. 82217993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 82317993c442c26161f684d6c0c6867a746f3148548Craig Stout public void release() { 8243d9d8cbaa9086f3ca2f486233fa3051e614a99edCraig Stout if (DEBUG) Log.v(TAG, "release " + this); 8252e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout if (mLayerDrawable != null) { 826d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.clearDrawable(R.id.background_imagein, mContext); 827d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.clearDrawable(R.id.background_imageout, mContext); 828d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.clearDrawable(R.id.background_theme, mContext); 8292e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout mLayerDrawable = null; 8302e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout } 83117993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mChangeRunnable != null) { 8320f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mHandler.removeCallbacks(mChangeRunnable); 83317993c442c26161f684d6c0c6867a746f3148548Craig Stout mChangeRunnable = null; 83417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 83517993c442c26161f684d6c0c6867a746f3148548Craig Stout releaseBackgroundBitmap(); 83617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 83717993c442c26161f684d6c0c6867a746f3148548Craig Stout 83817993c442c26161f684d6c0c6867a746f3148548Craig Stout private void releaseBackgroundBitmap() { 83917993c442c26161f684d6c0c6867a746f3148548Craig Stout mBackgroundDrawable = null; 84017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 84117993c442c26161f684d6c0c6867a746f3148548Craig Stout 842f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private void setBackgroundDrawable(Drawable drawable) { 843f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mBackgroundDrawable = drawable; 844f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mService.setDrawable(mBackgroundDrawable); 845f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 846f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 8470f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout /** 8480f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout * Sets the drawable used as a dim layer. 8490f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout */ 8500f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public void setDimLayer(Drawable drawable) { 8510f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimDrawable = drawable; 8520f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout updateDimWrapper(); 8530f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 8540f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 8550f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout /** 8560f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout * Returns the drawable used as a dim layer. 8570f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout */ 8580f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public Drawable getDimLayer() { 8590f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout return mDimDrawable; 8600f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 8610f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 8620f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout /** 8630f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout * Returns the default drawable used as a dim layer. 8640f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout */ 8650f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout public Drawable getDefaultDimLayer() { 8660f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout return ContextCompat.getDrawable(mContext, R.color.lb_background_protection); 8670f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 8680f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 869f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout private void postChangeRunnable() { 870f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (mChangeRunnable == null || !mChangeRunnablePending) { 871f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout return; 872f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 873f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 874f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // Postpone a pending change runnable until: no existing change animation in progress && 875f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // activity is resumed (in the foreground) && layerdrawable fully opaque. 876f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // If the layerdrawable is translucent then an activity transition is in progress 877f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // and we want to use the optimized drawing path for performance reasons (see 878f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // OptimizedTranslucentLayerDrawable). 879f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (mAnimator.isStarted()) { 880f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "animation in progress"); 881f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } else if (!mFragmentState.isResumed()) { 882f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "not resumed"); 883f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } else if (mLayerDrawable.getAlpha() < FULL_ALPHA) { 884f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "in transition, alpha " + mLayerDrawable.getAlpha()); 885f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } else { 886f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout long delayMs = getRunnableDelay(); 887f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "posting runnable delayMs " + delayMs); 888f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mLastSetTime = System.currentTimeMillis(); 889f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mHandler.postDelayed(mChangeRunnable, delayMs); 890f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mChangeRunnablePending = false; 891f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 892f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout } 893f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout 89417993c442c26161f684d6c0c6867a746f3148548Craig Stout private void updateImmediate() { 89517993c442c26161f684d6c0c6867a746f3148548Craig Stout lazyInit(); 89617993c442c26161f684d6c0c6867a746f3148548Craig Stout 8972590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper colorWrapper = getColorWrapper(); 8982590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (colorWrapper != null) { 8992590c39739945451f80dcf8667709b93293fc8bcCraig Stout colorWrapper.setColor(mBackgroundColor); 9002590c39739945451f80dcf8667709b93293fc8bcCraig Stout } 9012590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper dimWrapper = getDimWrapper(); 9022590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (dimWrapper != null) { 9032590c39739945451f80dcf8667709b93293fc8bcCraig Stout dimWrapper.setAlpha(mBackgroundColor == Color.TRANSPARENT ? 0 : DIM_ALPHA_ON_SOLID); 90417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 90517993c442c26161f684d6c0c6867a746f3148548Craig Stout showWallpaper(mBackgroundColor == Color.TRANSPARENT); 90617993c442c26161f684d6c0c6867a746f3148548Craig Stout 90717993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mBackgroundDrawable == null) { 908d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.clearDrawable(R.id.background_imagein, mContext); 90917993c442c26161f684d6c0c6867a746f3148548Craig Stout } else { 91017993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "Background drawable is available"); 9112590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.updateDrawable( 912d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout R.id.background_imagein, mBackgroundDrawable); 9132590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (dimWrapper != null) { 9142590c39739945451f80dcf8667709b93293fc8bcCraig Stout dimWrapper.setAlpha(FULL_ALPHA); 91517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 91617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 91717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 91817993c442c26161f684d6c0c6867a746f3148548Craig Stout 91917993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 920146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Set the background to the given color. The timing for when this becomes 921146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * visible in the app is undefined and may take place after a small delay. 92217993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 92317993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setColor(int color) { 92417993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "setColor " + Integer.toHexString(color)); 92517993c442c26161f684d6c0c6867a746f3148548Craig Stout 92617993c442c26161f684d6c0c6867a746f3148548Craig Stout mBackgroundColor = color; 92717993c442c26161f684d6c0c6867a746f3148548Craig Stout mService.setColor(mBackgroundColor); 92817993c442c26161f684d6c0c6867a746f3148548Craig Stout 9292590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper colorWrapper = getColorWrapper(); 9302590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (colorWrapper != null) { 9312590c39739945451f80dcf8667709b93293fc8bcCraig Stout colorWrapper.setColor(mBackgroundColor); 93217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 93317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 93417993c442c26161f684d6c0c6867a746f3148548Craig Stout 93517993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 9365a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * Set the given drawable into the background. The provided Drawable will be 9375a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * used unmodified as the background, without any scaling or cropping 9385a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * applied to it. The timing for when this becomes visible in the app is 9395a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * undefined and may take place after a small delay. 94017993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 94117993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setDrawable(Drawable drawable) { 94217993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "setBackgroundDrawable " + drawable); 94317993c442c26161f684d6c0c6867a746f3148548Craig Stout setDrawableInternal(drawable); 94417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 94517993c442c26161f684d6c0c6867a746f3148548Craig Stout 94617993c442c26161f684d6c0c6867a746f3148548Craig Stout private void setDrawableInternal(Drawable drawable) { 9475a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (!mAttached) { 9485a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima throw new IllegalStateException("Must attach before setting background drawable"); 9495a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 95017993c442c26161f684d6c0c6867a746f3148548Craig Stout 95117993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mChangeRunnable != null) { 952d6019d141130ae4811b78e37286faf93d5944fd9Craig Stout if (sameDrawable(drawable, mChangeRunnable.mDrawable)) { 9530f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout if (DEBUG) Log.v(TAG, "new drawable same as pending"); 954d6019d141130ae4811b78e37286faf93d5944fd9Craig Stout return; 955d6019d141130ae4811b78e37286faf93d5944fd9Craig Stout } 9560f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mHandler.removeCallbacks(mChangeRunnable); 957f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mChangeRunnable = null; 95817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 959d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 960f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // If layer drawable is null then the activity hasn't started yet. 961f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // If the layer drawable alpha is zero then the activity transition hasn't started yet. 962f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // In these cases we can update the background immediately and let activity transition 963f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout // fade it in. 964f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (mLayerDrawable == null || mLayerDrawable.getAlpha() == 0) { 965f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout if (DEBUG) Log.v(TAG, "setDrawableInternal null or alpha is zero"); 966f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout setBackgroundDrawable(drawable); 967d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout updateImmediate(); 968d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return; 969d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 970d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout 97117993c442c26161f684d6c0c6867a746f3148548Craig Stout mChangeRunnable = new ChangeBackgroundRunnable(drawable); 972f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout mChangeRunnablePending = true; 97317993c442c26161f684d6c0c6867a746f3148548Craig Stout 974f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout postChangeRunnable(); 97517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 97617993c442c26161f684d6c0c6867a746f3148548Craig Stout 9770f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout private long getRunnableDelay() { 9780f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout return Math.max(0, mLastSetTime + CHANGE_BG_DELAY_MS - System.currentTimeMillis()); 9790f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout } 9800f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 98117993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 9825a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * Set the given bitmap into the background. When using setBitmap to set the 9835a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * background, the provided bitmap will be scaled and cropped to correctly 9845a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima * fit within the dimensions of the view. The timing for when this becomes 985146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * visible in the app is undefined and may take place after a small delay. 98617993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 98717993c442c26161f684d6c0c6867a746f3148548Craig Stout public void setBitmap(Bitmap bitmap) { 9885a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (DEBUG) { 9895a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima Log.v(TAG, "setBitmap " + bitmap); 9905a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 9915a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima 9925a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (bitmap == null) { 9935a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima setDrawableInternal(null); 9945a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima return; 9955a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 99617993c442c26161f684d6c0c6867a746f3148548Craig Stout 99717993c442c26161f684d6c0c6867a746f3148548Craig Stout if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) { 9985a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (DEBUG) { 9995a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima Log.v(TAG, "invalid bitmap width or height"); 10005a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 100117993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 100217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 100317993c442c26161f684d6c0c6867a746f3148548Craig Stout 10047f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout Matrix matrix = null; 100517993c442c26161f684d6c0c6867a746f3148548Craig Stout 10067f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if ((bitmap.getWidth() != mWidthPx || bitmap.getHeight() != mHeightPx)) { 10075a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima int dwidth = bitmap.getWidth(); 10085a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima int dheight = bitmap.getHeight(); 10095a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima float scale; 10105a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima 10117f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout // Scale proportionately to fit width and height. 10125a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima if (dwidth * mHeightPx > mWidthPx * dheight) { 10135a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima scale = (float) mHeightPx / (float) dheight; 10145a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } else { 10155a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima scale = (float) mWidthPx / (float) dwidth; 10165a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima } 10175a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima 10185a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima int subX = Math.min((int) (mWidthPx / scale), dwidth); 10197f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout int dx = Math.max(0, (dwidth - subX) / 2); 10205a8a7c929e07e3a3d17b2e5466785d271eee7657Jose Lima 10217f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout matrix = new Matrix(); 10227f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout matrix.setScale(scale, scale); 10237f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout matrix.preTranslate(-dx, 0); 10247f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 10257f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (DEBUG) Log.v(TAG, "original image size " + bitmap.getWidth() + "x" + bitmap.getHeight() + 10267f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout " scale " + scale + " dx " + dx); 102717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 102817993c442c26161f684d6c0c6867a746f3148548Craig Stout 10297f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout BitmapDrawable bitmapDrawable = new BitmapDrawable(mContext.getResources(), bitmap, matrix); 103017993c442c26161f684d6c0c6867a746f3148548Craig Stout 103117993c442c26161f684d6c0c6867a746f3148548Craig Stout setDrawableInternal(bitmapDrawable); 103217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 103317993c442c26161f684d6c0c6867a746f3148548Craig Stout 103417993c442c26161f684d6c0c6867a746f3148548Craig Stout private void applyBackgroundChanges() { 1035d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (!mAttached) { 103617993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 103717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 103817993c442c26161f684d6c0c6867a746f3148548Craig Stout 103917993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "applyBackgroundChanges drawable " + mBackgroundDrawable); 104017993c442c26161f684d6c0c6867a746f3148548Craig Stout 10410f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout int dimAlpha = -1; 104217993c442c26161f684d6c0c6867a746f3148548Craig Stout 10432590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (getImageOutWrapper() != null) { 10440f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout dimAlpha = mBackgroundColor == Color.TRANSPARENT ? 0 : DIM_ALPHA_ON_SOLID; 104517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 104617993c442c26161f684d6c0c6867a746f3148548Craig Stout 10472590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper imageInWrapper = getImageInWrapper(); 10482590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (imageInWrapper == null && mBackgroundDrawable != null) { 104917993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "creating new imagein drawable"); 10502590c39739945451f80dcf8667709b93293fc8bcCraig Stout imageInWrapper = mLayerDrawable.updateDrawable( 1051d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout R.id.background_imagein, mBackgroundDrawable); 10522590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (DEBUG) Log.v(TAG, "imageInWrapper animation starting"); 10532590c39739945451f80dcf8667709b93293fc8bcCraig Stout imageInWrapper.setAlpha(0); 10542e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout dimAlpha = FULL_ALPHA; 105517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 105617993c442c26161f684d6c0c6867a746f3148548Craig Stout 10570f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAnimator.setDuration(FADE_DURATION); 10580f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mAnimator.start(); 10590f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout 10602590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper dimWrapper = getDimWrapper(); 10612590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (dimWrapper != null && dimAlpha >= 0) { 106217993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "dimwrapper animation starting to " + dimAlpha); 10630f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimAnimator.cancel(); 10642590c39739945451f80dcf8667709b93293fc8bcCraig Stout mDimAnimator.setIntValues(dimWrapper.getAlpha(), dimAlpha); 10650f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimAnimator.setDuration(FADE_DURATION); 10660f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimAnimator.setInterpolator( 10670f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout dimAlpha == FULL_ALPHA ? mDecelerateInterpolator : mAccelerateInterpolator); 10680f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mDimAnimator.start(); 106917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 107017993c442c26161f684d6c0c6867a746f3148548Craig Stout } 107117993c442c26161f684d6c0c6867a746f3148548Craig Stout 107217993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 1073146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Returns the current background color. 107417993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 107517993c442c26161f684d6c0c6867a746f3148548Craig Stout public final int getColor() { 107617993c442c26161f684d6c0c6867a746f3148548Craig Stout return mBackgroundColor; 107717993c442c26161f684d6c0c6867a746f3148548Craig Stout } 107817993c442c26161f684d6c0c6867a746f3148548Craig Stout 107917993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 1080146a2a07c0e9750c2bdd5bd434197c2f46fea662Tim Kilbourn * Returns the current background {@link Drawable}. 108117993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 108217993c442c26161f684d6c0c6867a746f3148548Craig Stout public Drawable getDrawable() { 108317993c442c26161f684d6c0c6867a746f3148548Craig Stout return mBackgroundDrawable; 108417993c442c26161f684d6c0c6867a746f3148548Craig Stout } 108517993c442c26161f684d6c0c6867a746f3148548Craig Stout 10867f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout private boolean sameDrawable(Drawable first, Drawable second) { 10877f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (first == null || second == null) { 10887f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return false; 10897f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 10907f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (first == second) { 10917f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return true; 10927f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 10937f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (first instanceof BitmapDrawable && second instanceof BitmapDrawable) { 10947f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (((BitmapDrawable) first).getBitmap().sameAs(((BitmapDrawable) second).getBitmap())) { 10957f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return true; 10967f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 10977f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 10987f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout return false; 10997f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout } 11007f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout 110117993c442c26161f684d6c0c6867a746f3148548Craig Stout /** 110217993c442c26161f684d6c0c6867a746f3148548Craig Stout * Task which changes the background. 110317993c442c26161f684d6c0c6867a746f3148548Craig Stout */ 110417993c442c26161f684d6c0c6867a746f3148548Craig Stout class ChangeBackgroundRunnable implements Runnable { 110517993c442c26161f684d6c0c6867a746f3148548Craig Stout private Drawable mDrawable; 110617993c442c26161f684d6c0c6867a746f3148548Craig Stout 110717993c442c26161f684d6c0c6867a746f3148548Craig Stout ChangeBackgroundRunnable(Drawable drawable) { 110817993c442c26161f684d6c0c6867a746f3148548Craig Stout mDrawable = drawable; 110917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 111017993c442c26161f684d6c0c6867a746f3148548Craig Stout 111117993c442c26161f684d6c0c6867a746f3148548Craig Stout @Override 111217993c442c26161f684d6c0c6867a746f3148548Craig Stout public void run() { 11130f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout runTask(); 11140f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout mChangeRunnable = null; 111517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 111617993c442c26161f684d6c0c6867a746f3148548Craig Stout 111717993c442c26161f684d6c0c6867a746f3148548Craig Stout private void runTask() { 1118d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (mLayerDrawable == null) { 1119d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout if (DEBUG) Log.v(TAG, "runTask while released - should not happen"); 1120d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return; 1121d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout } 112217993c442c26161f684d6c0c6867a746f3148548Craig Stout 11237f85292289f235c50740c3180fdbcb4bb2bf9703Craig Stout if (sameDrawable(mDrawable, mBackgroundDrawable)) { 11240f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout if (DEBUG) Log.v(TAG, "new drawable same as current"); 11252e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout return; 112617993c442c26161f684d6c0c6867a746f3148548Craig Stout } 112717993c442c26161f684d6c0c6867a746f3148548Craig Stout 11282e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout releaseBackgroundBitmap(); 11292e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout 11302590c39739945451f80dcf8667709b93293fc8bcCraig Stout DrawableWrapper imageInWrapper = getImageInWrapper(); 11312590c39739945451f80dcf8667709b93293fc8bcCraig Stout if (imageInWrapper != null) { 11320f82bdd768ca56c4d14fa96afe8ff0355360148bCraig Stout if (DEBUG) Log.v(TAG, "moving image in to image out"); 11332e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout // Order is important! Setting a drawable "removes" the 11342e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout // previous one from the view 1135d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout mLayerDrawable.clearDrawable(R.id.background_imagein, mContext); 11362590c39739945451f80dcf8667709b93293fc8bcCraig Stout mLayerDrawable.updateDrawable(R.id.background_imageout, 11372590c39739945451f80dcf8667709b93293fc8bcCraig Stout imageInWrapper.getDrawable()); 113817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 11392e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout 1140f684b94c5f316e9735abc298e00c3f61642b821eCraig Stout setBackgroundDrawable(mDrawable); 11412e2e91a93f6d03108a73e7b4a05d289589957a0eCraig Stout applyBackgroundChanges(); 114217993c442c26161f684d6c0c6867a746f3148548Craig Stout } 114317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 114417993c442c26161f684d6c0c6867a746f3148548Craig Stout 1145d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout private static Drawable createEmptyDrawable(Context context) { 114617993c442c26161f684d6c0c6867a746f3148548Craig Stout Bitmap bitmap = null; 1147d6c1bec6bd003158e79da4c945ee57f915336e12Craig Stout return new BitmapDrawable(context.getResources(), bitmap); 114817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 114917993c442c26161f684d6c0c6867a746f3148548Craig Stout 115017993c442c26161f684d6c0c6867a746f3148548Craig Stout private void showWallpaper(boolean show) { 115117993c442c26161f684d6c0c6867a746f3148548Craig Stout if (mWindow == null) { 115217993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 115317993c442c26161f684d6c0c6867a746f3148548Craig Stout } 115417993c442c26161f684d6c0c6867a746f3148548Craig Stout 115517993c442c26161f684d6c0c6867a746f3148548Craig Stout WindowManager.LayoutParams layoutParams = mWindow.getAttributes(); 115617993c442c26161f684d6c0c6867a746f3148548Craig Stout if (show) { 115717993c442c26161f684d6c0c6867a746f3148548Craig Stout if ((layoutParams.flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { 115817993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 115917993c442c26161f684d6c0c6867a746f3148548Craig Stout } 116017993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "showing wallpaper"); 116117993c442c26161f684d6c0c6867a746f3148548Craig Stout layoutParams.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 116217993c442c26161f684d6c0c6867a746f3148548Craig Stout } else { 116317993c442c26161f684d6c0c6867a746f3148548Craig Stout if ((layoutParams.flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) == 0) { 116417993c442c26161f684d6c0c6867a746f3148548Craig Stout return; 116517993c442c26161f684d6c0c6867a746f3148548Craig Stout } 116617993c442c26161f684d6c0c6867a746f3148548Craig Stout if (DEBUG) Log.v(TAG, "hiding wallpaper"); 116717993c442c26161f684d6c0c6867a746f3148548Craig Stout layoutParams.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 116817993c442c26161f684d6c0c6867a746f3148548Craig Stout } 116917993c442c26161f684d6c0c6867a746f3148548Craig Stout 117017993c442c26161f684d6c0c6867a746f3148548Craig Stout mWindow.setAttributes(layoutParams); 117117993c442c26161f684d6c0c6867a746f3148548Craig Stout } 117217993c442c26161f684d6c0c6867a746f3148548Craig Stout} 1173