BackgroundManager.java revision b70539172cdeb5672ed7128f69383d1fc1458ccb
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
1617993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.support.v17.leanback.R;
1717993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.animation.ObjectAnimator;
1817993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.app.Activity;
1917993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.content.Context;
2017993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.content.res.TypedArray;
2117993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.Bitmap;
2217993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.Color;
2317993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.Matrix;
2417993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.BitmapDrawable;
2517993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.ColorDrawable;
2617993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.Drawable;
2717993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.graphics.drawable.LayerDrawable;
2817993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.os.Handler;
2917993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.util.Log;
3017993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.Gravity;
3117993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.LayoutInflater;
3217993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.View;
3317993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.ViewGroup;
3417993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.Window;
3517993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.WindowManager;
3617993c442c26161f684d6c0c6867a746f3148548Craig Stoutimport android.view.animation.LinearInterpolator;
3717993c442c26161f684d6c0c6867a746f3148548Craig Stout
3817993c442c26161f684d6c0c6867a746f3148548Craig Stout/**
3917993c442c26161f684d6c0c6867a746f3148548Craig Stout * Supports background continuity between multiple activities.
4017993c442c26161f684d6c0c6867a746f3148548Craig Stout *
411c33346ba79177e64fe33da70ee73547d7bb15f7Craig Stout * An activity should instantiate a BackgroundManager and {@link #attach}
4217993c442c26161f684d6c0c6867a746f3148548Craig Stout * to the activity's window.  When the activity is started, the background is
4317993c442c26161f684d6c0c6867a746f3148548Craig Stout * initialized to the current background values stored in a continuity service.
4417993c442c26161f684d6c0c6867a746f3148548Craig Stout * The background continuity service is updated as the background is updated.
4517993c442c26161f684d6c0c6867a746f3148548Craig Stout *
4617993c442c26161f684d6c0c6867a746f3148548Craig Stout * At some point, for example when stopped, the activity may release its background
4717993c442c26161f684d6c0c6867a746f3148548Craig Stout * state.  The background may then be resumed, again from the continuity service.
4817993c442c26161f684d6c0c6867a746f3148548Craig Stout *
4917993c442c26161f684d6c0c6867a746f3148548Craig Stout * When the last activity is destroyed, the background state is reset.
5017993c442c26161f684d6c0c6867a746f3148548Craig Stout *
5117993c442c26161f684d6c0c6867a746f3148548Craig Stout * Backgrounds consist of several layers, from back to front:
5217993c442c26161f684d6c0c6867a746f3148548Craig Stout * - the background drawable of the theme
5317993c442c26161f684d6c0c6867a746f3148548Craig Stout * - a solid color (set via setColor)
5417993c442c26161f684d6c0c6867a746f3148548Craig Stout * - two drawables, previous and current (set via setBitmap or setDrawable),
5517993c442c26161f684d6c0c6867a746f3148548Craig Stout *   which may be in transition
5617993c442c26161f684d6c0c6867a746f3148548Craig Stout *
5717993c442c26161f684d6c0c6867a746f3148548Craig Stout * BackgroundManager holds references to potentially large bitmap drawables.
581c33346ba79177e64fe33da70ee73547d7bb15f7Craig Stout * Call {@link #release} to release these references when the activity is not
5917993c442c26161f684d6c0c6867a746f3148548Craig Stout * visible.
6017993c442c26161f684d6c0c6867a746f3148548Craig Stout *
6117993c442c26161f684d6c0c6867a746f3148548Craig Stout * TODO: support for multiple app processes requires a proper android service
6217993c442c26161f684d6c0c6867a746f3148548Craig Stout * instead of the shared memory "service" implemented here. Such a service could
6317993c442c26161f684d6c0c6867a746f3148548Craig Stout * support continuity between fragments of different applications if desired.
6417993c442c26161f684d6c0c6867a746f3148548Craig Stout */
6517993c442c26161f684d6c0c6867a746f3148548Craig Stoutpublic final class BackgroundManager {
6617993c442c26161f684d6c0c6867a746f3148548Craig Stout    private static final String TAG = "BackgroundManager";
6717993c442c26161f684d6c0c6867a746f3148548Craig Stout    private static final boolean DEBUG = false;
6817993c442c26161f684d6c0c6867a746f3148548Craig Stout
6917993c442c26161f684d6c0c6867a746f3148548Craig Stout    private static final int FULL_ALPHA = 255;
7017993c442c26161f684d6c0c6867a746f3148548Craig Stout    private static final int DIM_ALPHA_ON_SOLID = (int) (0.8f * FULL_ALPHA);
7117993c442c26161f684d6c0c6867a746f3148548Craig Stout    private static final int CHANGE_BG_DELAY_MS = 500;
7217993c442c26161f684d6c0c6867a746f3148548Craig Stout    private static final int FADE_DURATION_QUICK = 200;
7317993c442c26161f684d6c0c6867a746f3148548Craig Stout    private static final int FADE_DURATION_SLOW = 1000;
7417993c442c26161f684d6c0c6867a746f3148548Craig Stout
7517993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
7617993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Using a separate window for backgrounds can improve graphics performance by
7717993c442c26161f684d6c0c6867a746f3148548Craig Stout     * leveraging hardware display layers.
7817993c442c26161f684d6c0c6867a746f3148548Craig Stout     * TODO: support a leanback configuration option.
7917993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
8017993c442c26161f684d6c0c6867a746f3148548Craig Stout    private static final boolean USE_SEPARATE_WINDOW = false;
8117993c442c26161f684d6c0c6867a746f3148548Craig Stout
8217993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
8317993c442c26161f684d6c0c6867a746f3148548Craig Stout     * If true, bitmaps will be scaled to the exact display size.
8417993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Small bitmaps will be scaled up, using more memory but improving display quality.
8517993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Large bitmaps will be scaled down to use less memory.
8617993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Introduces an allocation overhead.
8717993c442c26161f684d6c0c6867a746f3148548Craig Stout     * TODO: support a leanback configuration option.
8817993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
8917993c442c26161f684d6c0c6867a746f3148548Craig Stout    private static final boolean SCALE_BITMAPS_TO_FIT = true;
9017993c442c26161f684d6c0c6867a746f3148548Craig Stout
9117993c442c26161f684d6c0c6867a746f3148548Craig Stout    private static final String WINDOW_NAME = "BackgroundManager";
9217993c442c26161f684d6c0c6867a746f3148548Craig Stout
9317993c442c26161f684d6c0c6867a746f3148548Craig Stout    private Context mContext;
9417993c442c26161f684d6c0c6867a746f3148548Craig Stout    private Handler mHandler;
9517993c442c26161f684d6c0c6867a746f3148548Craig Stout    private Window mWindow;
9617993c442c26161f684d6c0c6867a746f3148548Craig Stout    private WindowManager mWindowManager;
9717993c442c26161f684d6c0c6867a746f3148548Craig Stout    private View mBgView;
9817993c442c26161f684d6c0c6867a746f3148548Craig Stout    private BackgroundContinuityService mService;
9917993c442c26161f684d6c0c6867a746f3148548Craig Stout    private int mThemeDrawableResourceId;
10017993c442c26161f684d6c0c6867a746f3148548Craig Stout
10117993c442c26161f684d6c0c6867a746f3148548Craig Stout    private int mHeightPx;
10217993c442c26161f684d6c0c6867a746f3148548Craig Stout    private int mWidthPx;
10317993c442c26161f684d6c0c6867a746f3148548Craig Stout    private Drawable mBackgroundDrawable;
10417993c442c26161f684d6c0c6867a746f3148548Craig Stout    private int mBackgroundColor;
10517993c442c26161f684d6c0c6867a746f3148548Craig Stout    private boolean mAttached;
10617993c442c26161f684d6c0c6867a746f3148548Craig Stout
10717993c442c26161f684d6c0c6867a746f3148548Craig Stout    private class DrawableWrapper {
10817993c442c26161f684d6c0c6867a746f3148548Craig Stout        protected int mAlpha;
10917993c442c26161f684d6c0c6867a746f3148548Craig Stout        protected Drawable mDrawable;
11017993c442c26161f684d6c0c6867a746f3148548Craig Stout        protected ObjectAnimator mAnimator;
11117993c442c26161f684d6c0c6867a746f3148548Craig Stout        protected boolean mAnimationPending;
11217993c442c26161f684d6c0c6867a746f3148548Craig Stout
11317993c442c26161f684d6c0c6867a746f3148548Craig Stout        public DrawableWrapper(Drawable drawable) {
11417993c442c26161f684d6c0c6867a746f3148548Craig Stout            mDrawable = drawable;
11517993c442c26161f684d6c0c6867a746f3148548Craig Stout            setAlpha(FULL_ALPHA);
11617993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
11717993c442c26161f684d6c0c6867a746f3148548Craig Stout
11817993c442c26161f684d6c0c6867a746f3148548Craig Stout        public Drawable getDrawable() {
11917993c442c26161f684d6c0c6867a746f3148548Craig Stout            return mDrawable;
12017993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
12117993c442c26161f684d6c0c6867a746f3148548Craig Stout        public void setAlpha(int alpha) {
12217993c442c26161f684d6c0c6867a746f3148548Craig Stout            mAlpha = alpha;
12317993c442c26161f684d6c0c6867a746f3148548Craig Stout            mDrawable.setAlpha(alpha);
12417993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
12517993c442c26161f684d6c0c6867a746f3148548Craig Stout        public int getAlpha() {
12617993c442c26161f684d6c0c6867a746f3148548Craig Stout            return mAlpha;
12717993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
12817993c442c26161f684d6c0c6867a746f3148548Craig Stout        public void setColor(int color) {
12917993c442c26161f684d6c0c6867a746f3148548Craig Stout            ((ColorDrawable) mDrawable).setColor(color);
13017993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
13117993c442c26161f684d6c0c6867a746f3148548Craig Stout        public void fadeIn(int durationMs, int delayMs) {
13217993c442c26161f684d6c0c6867a746f3148548Craig Stout            fade(durationMs, delayMs, FULL_ALPHA);
13317993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
13417993c442c26161f684d6c0c6867a746f3148548Craig Stout        public void fadeOut(int durationMs) {
13517993c442c26161f684d6c0c6867a746f3148548Craig Stout            fade(durationMs, 0, 0);
13617993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
13717993c442c26161f684d6c0c6867a746f3148548Craig Stout        public void fade(int durationMs, int delayMs, int alpha) {
13817993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (mAnimator != null && mAnimator.isStarted()) {
13917993c442c26161f684d6c0c6867a746f3148548Craig Stout                mAnimator.cancel();
14017993c442c26161f684d6c0c6867a746f3148548Craig Stout            }
14117993c442c26161f684d6c0c6867a746f3148548Craig Stout            mAnimator = ObjectAnimator.ofInt(this, "alpha", alpha);
14217993c442c26161f684d6c0c6867a746f3148548Craig Stout            mAnimator.setInterpolator(new LinearInterpolator());
14317993c442c26161f684d6c0c6867a746f3148548Craig Stout            mAnimator.setDuration(durationMs);
14417993c442c26161f684d6c0c6867a746f3148548Craig Stout            mAnimator.setStartDelay(delayMs);
14517993c442c26161f684d6c0c6867a746f3148548Craig Stout            mAnimationPending = true;
14617993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
14717993c442c26161f684d6c0c6867a746f3148548Craig Stout        public boolean isAnimationPending() {
14817993c442c26161f684d6c0c6867a746f3148548Craig Stout            return mAnimationPending;
14917993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
15017993c442c26161f684d6c0c6867a746f3148548Craig Stout        public boolean isAnimationStarted() {
15117993c442c26161f684d6c0c6867a746f3148548Craig Stout            return mAnimator != null && mAnimator.isStarted();
15217993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
15317993c442c26161f684d6c0c6867a746f3148548Craig Stout        public void startAnimation() {
15417993c442c26161f684d6c0c6867a746f3148548Craig Stout            mAnimator.start();
15517993c442c26161f684d6c0c6867a746f3148548Craig Stout            mAnimationPending = false;
15617993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
15717993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
15817993c442c26161f684d6c0c6867a746f3148548Craig Stout
15917993c442c26161f684d6c0c6867a746f3148548Craig Stout    private LayerDrawable mLayerDrawable;
16017993c442c26161f684d6c0c6867a746f3148548Craig Stout    private DrawableWrapper mLayerWrapper;
16117993c442c26161f684d6c0c6867a746f3148548Craig Stout    private DrawableWrapper mImageInWrapper;
16217993c442c26161f684d6c0c6867a746f3148548Craig Stout    private DrawableWrapper mImageOutWrapper;
16317993c442c26161f684d6c0c6867a746f3148548Craig Stout    private DrawableWrapper mColorWrapper;
16417993c442c26161f684d6c0c6867a746f3148548Craig Stout    private DrawableWrapper mDimWrapper;
16517993c442c26161f684d6c0c6867a746f3148548Craig Stout
16617993c442c26161f684d6c0c6867a746f3148548Craig Stout    private Drawable mThemeDrawable;
16717993c442c26161f684d6c0c6867a746f3148548Craig Stout    private ChangeBackgroundRunnable mChangeRunnable;
16817993c442c26161f684d6c0c6867a746f3148548Craig Stout
16917993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
17017993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Shared memory continuity service.
17117993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
17217993c442c26161f684d6c0c6867a746f3148548Craig Stout    private static class BackgroundContinuityService {
17317993c442c26161f684d6c0c6867a746f3148548Craig Stout        private static final String TAG = "BackgroundContinuityService";
17417993c442c26161f684d6c0c6867a746f3148548Craig Stout        private static boolean DEBUG = BackgroundManager.DEBUG;
17517993c442c26161f684d6c0c6867a746f3148548Craig Stout
17617993c442c26161f684d6c0c6867a746f3148548Craig Stout        private static BackgroundContinuityService sService = new BackgroundContinuityService();
17717993c442c26161f684d6c0c6867a746f3148548Craig Stout
17817993c442c26161f684d6c0c6867a746f3148548Craig Stout        private int mColor;
17917993c442c26161f684d6c0c6867a746f3148548Craig Stout        private Drawable mDrawable;
18017993c442c26161f684d6c0c6867a746f3148548Craig Stout        private int mCount;
18117993c442c26161f684d6c0c6867a746f3148548Craig Stout
18217993c442c26161f684d6c0c6867a746f3148548Craig Stout        private BackgroundContinuityService() {
18317993c442c26161f684d6c0c6867a746f3148548Craig Stout            reset();
18417993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
18517993c442c26161f684d6c0c6867a746f3148548Craig Stout
18617993c442c26161f684d6c0c6867a746f3148548Craig Stout        private void reset() {
18717993c442c26161f684d6c0c6867a746f3148548Craig Stout            mColor = Color.TRANSPARENT;
18817993c442c26161f684d6c0c6867a746f3148548Craig Stout            mDrawable = null;
18917993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
19017993c442c26161f684d6c0c6867a746f3148548Craig Stout
19117993c442c26161f684d6c0c6867a746f3148548Craig Stout        public static BackgroundContinuityService getInstance() {
19217993c442c26161f684d6c0c6867a746f3148548Craig Stout            final int count = sService.mCount++;
19317993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (DEBUG) Log.v(TAG, "Returning instance with new count " + count);
19417993c442c26161f684d6c0c6867a746f3148548Craig Stout            return sService;
19517993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
19617993c442c26161f684d6c0c6867a746f3148548Craig Stout
19717993c442c26161f684d6c0c6867a746f3148548Craig Stout        public void unref() {
19817993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (mCount <= 0) throw new IllegalStateException("Can't unref, count " + mCount);
19917993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (--mCount == 0) {
20017993c442c26161f684d6c0c6867a746f3148548Craig Stout                if (DEBUG) Log.v(TAG, "mCount is zero, resetting");
20117993c442c26161f684d6c0c6867a746f3148548Craig Stout                reset();
20217993c442c26161f684d6c0c6867a746f3148548Craig Stout            }
20317993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
20417993c442c26161f684d6c0c6867a746f3148548Craig Stout        public int getColor() {
20517993c442c26161f684d6c0c6867a746f3148548Craig Stout            return mColor;
20617993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
20717993c442c26161f684d6c0c6867a746f3148548Craig Stout        public Drawable getDrawable() {
20817993c442c26161f684d6c0c6867a746f3148548Craig Stout            return mDrawable;
20917993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
21017993c442c26161f684d6c0c6867a746f3148548Craig Stout        public void setColor(int color) {
21117993c442c26161f684d6c0c6867a746f3148548Craig Stout            mColor = color;
21217993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
21317993c442c26161f684d6c0c6867a746f3148548Craig Stout        public void setDrawable(Drawable drawable) {
21417993c442c26161f684d6c0c6867a746f3148548Craig Stout            mDrawable = drawable;
21517993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
21617993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
21717993c442c26161f684d6c0c6867a746f3148548Craig Stout
21817993c442c26161f684d6c0c6867a746f3148548Craig Stout    private Drawable getThemeDrawable() {
21917993c442c26161f684d6c0c6867a746f3148548Craig Stout        Drawable drawable = null;
22017993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mThemeDrawableResourceId != -1) {
22117993c442c26161f684d6c0c6867a746f3148548Craig Stout            drawable = mContext.getResources().getDrawable(mThemeDrawableResourceId);
22217993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
22317993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (drawable == null) {
22417993c442c26161f684d6c0c6867a746f3148548Craig Stout            drawable = createEmptyDrawable();
22517993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
22617993c442c26161f684d6c0c6867a746f3148548Craig Stout        return drawable;
22717993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
22817993c442c26161f684d6c0c6867a746f3148548Craig Stout
22917993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
23017993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Construct a background manager instance.
23117993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Initial background set from continuity service.
23217993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
23317993c442c26161f684d6c0c6867a746f3148548Craig Stout    public BackgroundManager(Activity activity) {
23417993c442c26161f684d6c0c6867a746f3148548Craig Stout        mContext = activity;
23517993c442c26161f684d6c0c6867a746f3148548Craig Stout        mService = BackgroundContinuityService.getInstance();
23617993c442c26161f684d6c0c6867a746f3148548Craig Stout        mHeightPx = mContext.getResources().getDisplayMetrics().heightPixels;
23717993c442c26161f684d6c0c6867a746f3148548Craig Stout        mWidthPx = mContext.getResources().getDisplayMetrics().widthPixels;
23817993c442c26161f684d6c0c6867a746f3148548Craig Stout        mHandler = new Handler();
23917993c442c26161f684d6c0c6867a746f3148548Craig Stout
24017993c442c26161f684d6c0c6867a746f3148548Craig Stout        TypedArray ta = activity.getTheme().obtainStyledAttributes(new int[] {
24117993c442c26161f684d6c0c6867a746f3148548Craig Stout                android.R.attr.windowBackground });
24217993c442c26161f684d6c0c6867a746f3148548Craig Stout        mThemeDrawableResourceId = ta.getResourceId(0, -1);
24317993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mThemeDrawableResourceId < 0) {
24417993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (DEBUG) Log.v(TAG, "BackgroundManager no window background resource!");
24517993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
24617993c442c26161f684d6c0c6867a746f3148548Craig Stout        ta.recycle();
24717993c442c26161f684d6c0c6867a746f3148548Craig Stout
24817993c442c26161f684d6c0c6867a746f3148548Craig Stout        createFragment(activity);
24917993c442c26161f684d6c0c6867a746f3148548Craig Stout
25017993c442c26161f684d6c0c6867a746f3148548Craig Stout        syncWithService();
25117993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
25217993c442c26161f684d6c0c6867a746f3148548Craig Stout
25317993c442c26161f684d6c0c6867a746f3148548Craig Stout    private void createFragment(Activity activity) {
25417993c442c26161f684d6c0c6867a746f3148548Craig Stout        // Use a fragment to ensure the background manager gets detached properly.
255b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu        BackgroundFragment fragment = (BackgroundFragment) activity.getFragmentManager()
256b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu                .findFragmentByTag(TAG);
257b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu        if (fragment == null) {
258b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu            fragment = new BackgroundFragment();
259b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu            activity.getFragmentManager().beginTransaction().add(fragment, TAG).commit();
260b70539172cdeb5672ed7128f69383d1fc1458ccbDake Gu        }
26117993c442c26161f684d6c0c6867a746f3148548Craig Stout        fragment.setBackgroundManager(this);
26217993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
26317993c442c26161f684d6c0c6867a746f3148548Craig Stout
26417993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
26517993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Updates state from continuity service.
26617993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Typically called when an activity resumes after having done a release.
26717993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
26817993c442c26161f684d6c0c6867a746f3148548Craig Stout    public void resume() {
26917993c442c26161f684d6c0c6867a746f3148548Craig Stout        syncWithService();
27017993c442c26161f684d6c0c6867a746f3148548Craig Stout        updateImmediate();
27117993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
27217993c442c26161f684d6c0c6867a746f3148548Craig Stout
27317993c442c26161f684d6c0c6867a746f3148548Craig Stout    private void syncWithService() {
27417993c442c26161f684d6c0c6867a746f3148548Craig Stout        int color = mService.getColor();
27517993c442c26161f684d6c0c6867a746f3148548Craig Stout        Drawable drawable = mService.getDrawable();
27617993c442c26161f684d6c0c6867a746f3148548Craig Stout
27717993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (DEBUG) Log.v(TAG, "syncWithService color " + Integer.toHexString(color)
27817993c442c26161f684d6c0c6867a746f3148548Craig Stout                + " drawable " + drawable);
27917993c442c26161f684d6c0c6867a746f3148548Craig Stout
28017993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (drawable != null) {
28117993c442c26161f684d6c0c6867a746f3148548Craig Stout            drawable = drawable.getConstantState().newDrawable(mContext.getResources()).mutate();
28217993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
28317993c442c26161f684d6c0c6867a746f3148548Craig Stout
28417993c442c26161f684d6c0c6867a746f3148548Craig Stout        mBackgroundColor = color;
28517993c442c26161f684d6c0c6867a746f3148548Craig Stout        mBackgroundDrawable = drawable;
28617993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
28717993c442c26161f684d6c0c6867a746f3148548Craig Stout
28817993c442c26161f684d6c0c6867a746f3148548Craig Stout    private void lazyInit() {
28917993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mLayerDrawable != null) {
29017993c442c26161f684d6c0c6867a746f3148548Craig Stout            return;
29117993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
29217993c442c26161f684d6c0c6867a746f3148548Craig Stout
29317993c442c26161f684d6c0c6867a746f3148548Craig Stout        mLayerDrawable = (LayerDrawable) mContext.getResources().getDrawable(
29417993c442c26161f684d6c0c6867a746f3148548Craig Stout                R.drawable.lb_background);
29517993c442c26161f684d6c0c6867a746f3148548Craig Stout        mBgView.setBackground(mLayerDrawable);
29617993c442c26161f684d6c0c6867a746f3148548Craig Stout
29717993c442c26161f684d6c0c6867a746f3148548Craig Stout        mLayerDrawable.setDrawableByLayerId(R.id.background_imageout, createEmptyDrawable());
29817993c442c26161f684d6c0c6867a746f3148548Craig Stout
29917993c442c26161f684d6c0c6867a746f3148548Craig Stout        mDimWrapper = new DrawableWrapper(
30017993c442c26161f684d6c0c6867a746f3148548Craig Stout                mLayerDrawable.findDrawableByLayerId(R.id.background_dim));
30117993c442c26161f684d6c0c6867a746f3148548Craig Stout
30217993c442c26161f684d6c0c6867a746f3148548Craig Stout        mLayerWrapper = new DrawableWrapper(mLayerDrawable);
30317993c442c26161f684d6c0c6867a746f3148548Craig Stout
30417993c442c26161f684d6c0c6867a746f3148548Craig Stout        mColorWrapper = new DrawableWrapper(
30517993c442c26161f684d6c0c6867a746f3148548Craig Stout                mLayerDrawable.findDrawableByLayerId(R.id.background_color));
30617993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
30717993c442c26161f684d6c0c6867a746f3148548Craig Stout
30817993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
30917993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Make the background visible on the given window.
31017993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
31117993c442c26161f684d6c0c6867a746f3148548Craig Stout    public void attach(Window window) {
31217993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (USE_SEPARATE_WINDOW) {
31317993c442c26161f684d6c0c6867a746f3148548Craig Stout            attachBehindWindow(window);
31417993c442c26161f684d6c0c6867a746f3148548Craig Stout        } else {
31517993c442c26161f684d6c0c6867a746f3148548Craig Stout            attachToView(window.getDecorView());
31617993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
31717993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
31817993c442c26161f684d6c0c6867a746f3148548Craig Stout
31917993c442c26161f684d6c0c6867a746f3148548Craig Stout    private void attachBehindWindow(Window window) {
32017993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (DEBUG) Log.v(TAG, "attachBehindWindow " + window);
32117993c442c26161f684d6c0c6867a746f3148548Craig Stout        mWindow = window;
32217993c442c26161f684d6c0c6867a746f3148548Craig Stout        mWindowManager = window.getWindowManager();
32317993c442c26161f684d6c0c6867a746f3148548Craig Stout
32417993c442c26161f684d6c0c6867a746f3148548Craig Stout        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
32517993c442c26161f684d6c0c6867a746f3148548Craig Stout                // Media window sits behind the main application window
32617993c442c26161f684d6c0c6867a746f3148548Craig Stout                WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA,
32717993c442c26161f684d6c0c6867a746f3148548Craig Stout                // Avoid default to software format RGBA
32817993c442c26161f684d6c0c6867a746f3148548Craig Stout                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
32917993c442c26161f684d6c0c6867a746f3148548Craig Stout                android.graphics.PixelFormat.TRANSLUCENT);
33017993c442c26161f684d6c0c6867a746f3148548Craig Stout        params.setTitle(WINDOW_NAME);
33117993c442c26161f684d6c0c6867a746f3148548Craig Stout        params.width = ViewGroup.LayoutParams.MATCH_PARENT;
33217993c442c26161f684d6c0c6867a746f3148548Craig Stout        params.height = ViewGroup.LayoutParams.MATCH_PARENT;
33317993c442c26161f684d6c0c6867a746f3148548Craig Stout
33417993c442c26161f684d6c0c6867a746f3148548Craig Stout        View backgroundView = LayoutInflater.from(mContext).inflate(
33517993c442c26161f684d6c0c6867a746f3148548Craig Stout                R.layout.lb_background_window, null);
33617993c442c26161f684d6c0c6867a746f3148548Craig Stout        mWindowManager.addView(backgroundView, params);
33717993c442c26161f684d6c0c6867a746f3148548Craig Stout
33817993c442c26161f684d6c0c6867a746f3148548Craig Stout        attachToView(backgroundView);
33917993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
34017993c442c26161f684d6c0c6867a746f3148548Craig Stout
34117993c442c26161f684d6c0c6867a746f3148548Craig Stout    private void attachToView(View sceneRoot) {
34217993c442c26161f684d6c0c6867a746f3148548Craig Stout        mBgView = sceneRoot;
34317993c442c26161f684d6c0c6867a746f3148548Craig Stout        mAttached = true;
34417993c442c26161f684d6c0c6867a746f3148548Craig Stout        updateImmediate();
34517993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
34617993c442c26161f684d6c0c6867a746f3148548Craig Stout
34717993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
34817993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Releases references to drawables and puts the background manager into
34917993c442c26161f684d6c0c6867a746f3148548Craig Stout     * detached state.
35017993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Called when the associated activity is destroyed.
35117993c442c26161f684d6c0c6867a746f3148548Craig Stout     * @hide
35217993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
35317993c442c26161f684d6c0c6867a746f3148548Craig Stout    void detach() {
35417993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (DEBUG) Log.v(TAG, "detach");
35517993c442c26161f684d6c0c6867a746f3148548Craig Stout        release();
35617993c442c26161f684d6c0c6867a746f3148548Craig Stout
35717993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mWindowManager != null && mBgView != null) {
35817993c442c26161f684d6c0c6867a746f3148548Craig Stout            mWindowManager.removeViewImmediate(mBgView);
35917993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
36017993c442c26161f684d6c0c6867a746f3148548Craig Stout
36117993c442c26161f684d6c0c6867a746f3148548Craig Stout        mWindowManager = null;
36217993c442c26161f684d6c0c6867a746f3148548Craig Stout        mWindow = null;
36317993c442c26161f684d6c0c6867a746f3148548Craig Stout        mBgView = null;
36417993c442c26161f684d6c0c6867a746f3148548Craig Stout        mAttached = false;
36517993c442c26161f684d6c0c6867a746f3148548Craig Stout
36617993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mService != null) {
36717993c442c26161f684d6c0c6867a746f3148548Craig Stout            mService.unref();
36817993c442c26161f684d6c0c6867a746f3148548Craig Stout            mService = null;
36917993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
37017993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
37117993c442c26161f684d6c0c6867a746f3148548Craig Stout
37217993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
37317993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Releases references to drawables.
37417993c442c26161f684d6c0c6867a746f3148548Craig Stout     * May be called to reduce memory overhead when not visible.
37517993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
37617993c442c26161f684d6c0c6867a746f3148548Craig Stout    public void release() {
37717993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (DEBUG) Log.v(TAG, "release");
37817993c442c26161f684d6c0c6867a746f3148548Craig Stout        mLayerDrawable = null;
37917993c442c26161f684d6c0c6867a746f3148548Craig Stout        mLayerWrapper = null;
38017993c442c26161f684d6c0c6867a746f3148548Craig Stout        mImageInWrapper = null;
38117993c442c26161f684d6c0c6867a746f3148548Craig Stout        mImageOutWrapper = null;
38217993c442c26161f684d6c0c6867a746f3148548Craig Stout        mColorWrapper = null;
38317993c442c26161f684d6c0c6867a746f3148548Craig Stout        mDimWrapper = null;
38417993c442c26161f684d6c0c6867a746f3148548Craig Stout        mThemeDrawable = null;
38517993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mChangeRunnable != null) {
38617993c442c26161f684d6c0c6867a746f3148548Craig Stout            mChangeRunnable.cancel();
38717993c442c26161f684d6c0c6867a746f3148548Craig Stout            mChangeRunnable = null;
38817993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
38917993c442c26161f684d6c0c6867a746f3148548Craig Stout        releaseBackgroundBitmap();
39017993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
39117993c442c26161f684d6c0c6867a746f3148548Craig Stout
39217993c442c26161f684d6c0c6867a746f3148548Craig Stout    private void releaseBackgroundBitmap() {
39317993c442c26161f684d6c0c6867a746f3148548Craig Stout        mBackgroundDrawable = null;
39417993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
39517993c442c26161f684d6c0c6867a746f3148548Craig Stout
39617993c442c26161f684d6c0c6867a746f3148548Craig Stout    private void updateImmediate() {
39717993c442c26161f684d6c0c6867a746f3148548Craig Stout        lazyInit();
39817993c442c26161f684d6c0c6867a746f3148548Craig Stout
39917993c442c26161f684d6c0c6867a746f3148548Craig Stout        mColorWrapper.setColor(mBackgroundColor);
40017993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mDimWrapper != null) {
40117993c442c26161f684d6c0c6867a746f3148548Craig Stout            mDimWrapper.setAlpha(mBackgroundColor == Color.TRANSPARENT ? 0 : DIM_ALPHA_ON_SOLID);
40217993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
40317993c442c26161f684d6c0c6867a746f3148548Craig Stout        showWallpaper(mBackgroundColor == Color.TRANSPARENT);
40417993c442c26161f684d6c0c6867a746f3148548Craig Stout
40517993c442c26161f684d6c0c6867a746f3148548Craig Stout        mThemeDrawable = getThemeDrawable();
40617993c442c26161f684d6c0c6867a746f3148548Craig Stout        mLayerDrawable.setDrawableByLayerId(R.id.background_theme, mThemeDrawable);
40717993c442c26161f684d6c0c6867a746f3148548Craig Stout
40817993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mBackgroundDrawable == null) {
40917993c442c26161f684d6c0c6867a746f3148548Craig Stout            mLayerDrawable.setDrawableByLayerId(R.id.background_imagein, createEmptyDrawable());
41017993c442c26161f684d6c0c6867a746f3148548Craig Stout        } else {
41117993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (DEBUG) Log.v(TAG, "Background drawable is available");
41217993c442c26161f684d6c0c6867a746f3148548Craig Stout            mImageInWrapper = new DrawableWrapper(mBackgroundDrawable);
41317993c442c26161f684d6c0c6867a746f3148548Craig Stout            mLayerDrawable.setDrawableByLayerId(R.id.background_imagein, mBackgroundDrawable);
41417993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (mDimWrapper != null) {
41517993c442c26161f684d6c0c6867a746f3148548Craig Stout                mDimWrapper.setAlpha(FULL_ALPHA);
41617993c442c26161f684d6c0c6867a746f3148548Craig Stout            }
41717993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
41817993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
41917993c442c26161f684d6c0c6867a746f3148548Craig Stout
42017993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
42117993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Sets the given color into the background.
42217993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Timing is undefined.
42317993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
42417993c442c26161f684d6c0c6867a746f3148548Craig Stout    public void setColor(int color) {
42517993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (DEBUG) Log.v(TAG, "setColor " + Integer.toHexString(color));
42617993c442c26161f684d6c0c6867a746f3148548Craig Stout
42717993c442c26161f684d6c0c6867a746f3148548Craig Stout        mBackgroundColor = color;
42817993c442c26161f684d6c0c6867a746f3148548Craig Stout        mService.setColor(mBackgroundColor);
42917993c442c26161f684d6c0c6867a746f3148548Craig Stout
43017993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mColorWrapper != null) {
43117993c442c26161f684d6c0c6867a746f3148548Craig Stout            mColorWrapper.setColor(mBackgroundColor);
43217993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
43317993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
43417993c442c26161f684d6c0c6867a746f3148548Craig Stout
43517993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
43617993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Set the given drawable into the background.
43717993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Timing is undefined.
43817993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
43917993c442c26161f684d6c0c6867a746f3148548Craig Stout    public void setDrawable(Drawable drawable) {
44017993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (DEBUG) Log.v(TAG, "setBackgroundDrawable " + drawable);
44117993c442c26161f684d6c0c6867a746f3148548Craig Stout        setDrawableInternal(drawable);
44217993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
44317993c442c26161f684d6c0c6867a746f3148548Craig Stout
44417993c442c26161f684d6c0c6867a746f3148548Craig Stout    private void setDrawableInternal(Drawable drawable) {
44517993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (!mAttached) throw new IllegalStateException("Must attach before setting background drawable");
44617993c442c26161f684d6c0c6867a746f3148548Craig Stout
44717993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mChangeRunnable != null) {
44817993c442c26161f684d6c0c6867a746f3148548Craig Stout            mChangeRunnable.cancel();
44917993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
45017993c442c26161f684d6c0c6867a746f3148548Craig Stout        mChangeRunnable = new ChangeBackgroundRunnable(drawable);
45117993c442c26161f684d6c0c6867a746f3148548Craig Stout
45217993c442c26161f684d6c0c6867a746f3148548Craig Stout        mHandler.postDelayed(mChangeRunnable, CHANGE_BG_DELAY_MS);
45317993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
45417993c442c26161f684d6c0c6867a746f3148548Craig Stout
45517993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
45617993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Set the given bitmap into the background.
45717993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Timing is undefined.
45817993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
45917993c442c26161f684d6c0c6867a746f3148548Craig Stout    public void setBitmap(Bitmap bitmap) {
46017993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (DEBUG) Log.v(TAG, "setBitmap " + bitmap);
46117993c442c26161f684d6c0c6867a746f3148548Craig Stout
46217993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
46317993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (DEBUG) Log.v(TAG, "invalid bitmap width or height");
46417993c442c26161f684d6c0c6867a746f3148548Craig Stout            return;
46517993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
46617993c442c26161f684d6c0c6867a746f3148548Craig Stout
46717993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mBackgroundDrawable instanceof BitmapDrawable &&
46817993c442c26161f684d6c0c6867a746f3148548Craig Stout                ((BitmapDrawable) mBackgroundDrawable).getBitmap() == bitmap) {
46917993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (DEBUG) Log.v(TAG, "same bitmap detected");
47017993c442c26161f684d6c0c6867a746f3148548Craig Stout            mService.setDrawable(mBackgroundDrawable);
47117993c442c26161f684d6c0c6867a746f3148548Craig Stout            return;
47217993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
47317993c442c26161f684d6c0c6867a746f3148548Craig Stout
47417993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (SCALE_BITMAPS_TO_FIT && bitmap.getWidth() != mWidthPx) {
47517993c442c26161f684d6c0c6867a746f3148548Craig Stout            // Scale proportionately to fit width.
47617993c442c26161f684d6c0c6867a746f3148548Craig Stout            final float scale = (float) mWidthPx / (float) bitmap.getWidth();
47717993c442c26161f684d6c0c6867a746f3148548Craig Stout            final int height = (int) (mHeightPx / scale);
47817993c442c26161f684d6c0c6867a746f3148548Craig Stout
47917993c442c26161f684d6c0c6867a746f3148548Craig Stout            Matrix matrix = new Matrix();
48017993c442c26161f684d6c0c6867a746f3148548Craig Stout            matrix.postScale(scale, scale);
48117993c442c26161f684d6c0c6867a746f3148548Craig Stout
48217993c442c26161f684d6c0c6867a746f3148548Craig Stout            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), height, matrix, true);
48317993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (DEBUG) Log.v(TAG, "resized image to " + bitmap.getWidth() + "x" + bitmap.getHeight() + " from height " + height);
48417993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
48517993c442c26161f684d6c0c6867a746f3148548Craig Stout
48617993c442c26161f684d6c0c6867a746f3148548Craig Stout        BitmapDrawable bitmapDrawable = new BitmapDrawable(mContext.getResources(), bitmap);
48717993c442c26161f684d6c0c6867a746f3148548Craig Stout        bitmapDrawable.setGravity(Gravity.CLIP_HORIZONTAL);
48817993c442c26161f684d6c0c6867a746f3148548Craig Stout
48917993c442c26161f684d6c0c6867a746f3148548Craig Stout        setDrawableInternal(bitmapDrawable);
49017993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
49117993c442c26161f684d6c0c6867a746f3148548Craig Stout
49217993c442c26161f684d6c0c6867a746f3148548Craig Stout    private void applyBackgroundChanges() {
49317993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (!mAttached || mLayerWrapper == null) {
49417993c442c26161f684d6c0c6867a746f3148548Craig Stout            return;
49517993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
49617993c442c26161f684d6c0c6867a746f3148548Craig Stout
49717993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (DEBUG) Log.v(TAG, "applyBackgroundChanges drawable " + mBackgroundDrawable);
49817993c442c26161f684d6c0c6867a746f3148548Craig Stout
49917993c442c26161f684d6c0c6867a746f3148548Craig Stout        int dimAlpha = 0;
50017993c442c26161f684d6c0c6867a746f3148548Craig Stout
50117993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mImageOutWrapper != null && mImageOutWrapper.isAnimationPending()) {
50217993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (DEBUG) Log.v(TAG, "mImageOutWrapper animation starting");
50317993c442c26161f684d6c0c6867a746f3148548Craig Stout            mImageOutWrapper.startAnimation();
50417993c442c26161f684d6c0c6867a746f3148548Craig Stout            mImageOutWrapper = null;
50517993c442c26161f684d6c0c6867a746f3148548Craig Stout            dimAlpha = DIM_ALPHA_ON_SOLID;
50617993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
50717993c442c26161f684d6c0c6867a746f3148548Craig Stout
50817993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mImageInWrapper == null && mBackgroundDrawable != null) {
50917993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (DEBUG) Log.v(TAG, "creating new imagein drawable");
51017993c442c26161f684d6c0c6867a746f3148548Craig Stout            mImageInWrapper = new DrawableWrapper(mBackgroundDrawable);
51117993c442c26161f684d6c0c6867a746f3148548Craig Stout            mLayerDrawable.setDrawableByLayerId(R.id.background_imagein, mBackgroundDrawable);
51217993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (mLayerWrapper.isAnimationStarted()) {
51317993c442c26161f684d6c0c6867a746f3148548Craig Stout                mImageInWrapper.setAlpha(mLayerWrapper.getAlpha());
51417993c442c26161f684d6c0c6867a746f3148548Craig Stout            } else {
51517993c442c26161f684d6c0c6867a746f3148548Craig Stout                if (DEBUG) Log.v(TAG, "mImageInWrapper animation starting");
51617993c442c26161f684d6c0c6867a746f3148548Craig Stout                mImageInWrapper.setAlpha(0);
51717993c442c26161f684d6c0c6867a746f3148548Craig Stout                mImageInWrapper.fadeIn(FADE_DURATION_SLOW, 0);
51817993c442c26161f684d6c0c6867a746f3148548Craig Stout                mImageInWrapper.startAnimation();
51917993c442c26161f684d6c0c6867a746f3148548Craig Stout                dimAlpha = FULL_ALPHA;
52017993c442c26161f684d6c0c6867a746f3148548Craig Stout            }
52117993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
52217993c442c26161f684d6c0c6867a746f3148548Craig Stout
52317993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mDimWrapper != null && dimAlpha != 0) {
52417993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (DEBUG) Log.v(TAG, "dimwrapper animation starting to " + dimAlpha);
52517993c442c26161f684d6c0c6867a746f3148548Craig Stout            mDimWrapper.fade(FADE_DURATION_SLOW, 0, dimAlpha);
52617993c442c26161f684d6c0c6867a746f3148548Craig Stout            mDimWrapper.startAnimation();
52717993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
52817993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
52917993c442c26161f684d6c0c6867a746f3148548Craig Stout
53017993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
53117993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Returns the color currently in use by the background.
53217993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
53317993c442c26161f684d6c0c6867a746f3148548Craig Stout    public final int getColor() {
53417993c442c26161f684d6c0c6867a746f3148548Craig Stout        return mBackgroundColor;
53517993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
53617993c442c26161f684d6c0c6867a746f3148548Craig Stout
53717993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
53817993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Returns the {@link Drawable} currently in use by the background.
53917993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
54017993c442c26161f684d6c0c6867a746f3148548Craig Stout    public Drawable getDrawable() {
54117993c442c26161f684d6c0c6867a746f3148548Craig Stout        return mBackgroundDrawable;
54217993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
54317993c442c26161f684d6c0c6867a746f3148548Craig Stout
54417993c442c26161f684d6c0c6867a746f3148548Craig Stout    /**
54517993c442c26161f684d6c0c6867a746f3148548Craig Stout     * Task which changes the background.
54617993c442c26161f684d6c0c6867a746f3148548Craig Stout     */
54717993c442c26161f684d6c0c6867a746f3148548Craig Stout    class ChangeBackgroundRunnable implements Runnable {
54817993c442c26161f684d6c0c6867a746f3148548Craig Stout        private Drawable mDrawable;
54917993c442c26161f684d6c0c6867a746f3148548Craig Stout        private boolean mCancel;
55017993c442c26161f684d6c0c6867a746f3148548Craig Stout
55117993c442c26161f684d6c0c6867a746f3148548Craig Stout        ChangeBackgroundRunnable(Drawable drawable) {
55217993c442c26161f684d6c0c6867a746f3148548Craig Stout            mDrawable = drawable;
55317993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
55417993c442c26161f684d6c0c6867a746f3148548Craig Stout
55517993c442c26161f684d6c0c6867a746f3148548Craig Stout        public void cancel() {
55617993c442c26161f684d6c0c6867a746f3148548Craig Stout            mCancel = true;
55717993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
55817993c442c26161f684d6c0c6867a746f3148548Craig Stout
55917993c442c26161f684d6c0c6867a746f3148548Craig Stout        @Override
56017993c442c26161f684d6c0c6867a746f3148548Craig Stout        public void run() {
56117993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (!mCancel) {
56217993c442c26161f684d6c0c6867a746f3148548Craig Stout                runTask();
56317993c442c26161f684d6c0c6867a746f3148548Craig Stout            }
56417993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
56517993c442c26161f684d6c0c6867a746f3148548Craig Stout
56617993c442c26161f684d6c0c6867a746f3148548Craig Stout        private void runTask() {
56717993c442c26161f684d6c0c6867a746f3148548Craig Stout            boolean newBackground = false;
56817993c442c26161f684d6c0c6867a746f3148548Craig Stout            lazyInit();
56917993c442c26161f684d6c0c6867a746f3148548Craig Stout
57017993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (mDrawable != mBackgroundDrawable) {
57117993c442c26161f684d6c0c6867a746f3148548Craig Stout                newBackground = true;
57217993c442c26161f684d6c0c6867a746f3148548Craig Stout                releaseBackgroundBitmap();
57317993c442c26161f684d6c0c6867a746f3148548Craig Stout
57417993c442c26161f684d6c0c6867a746f3148548Craig Stout                if (mImageInWrapper != null) {
57517993c442c26161f684d6c0c6867a746f3148548Craig Stout                    mImageOutWrapper = new DrawableWrapper(mImageInWrapper.getDrawable());
57617993c442c26161f684d6c0c6867a746f3148548Craig Stout                    mImageOutWrapper.setAlpha(mImageInWrapper.getAlpha());
57717993c442c26161f684d6c0c6867a746f3148548Craig Stout                    mImageOutWrapper.fadeOut(FADE_DURATION_QUICK);
57817993c442c26161f684d6c0c6867a746f3148548Craig Stout
57917993c442c26161f684d6c0c6867a746f3148548Craig Stout                    // Order is important! Setting a drawable "removes" the
58017993c442c26161f684d6c0c6867a746f3148548Craig Stout                    // previous one from the view
58117993c442c26161f684d6c0c6867a746f3148548Craig Stout                    mLayerDrawable.setDrawableByLayerId(R.id.background_imagein, createEmptyDrawable());
58217993c442c26161f684d6c0c6867a746f3148548Craig Stout                    mLayerDrawable.setDrawableByLayerId(R.id.background_imageout,
58317993c442c26161f684d6c0c6867a746f3148548Craig Stout                            mImageOutWrapper.getDrawable());
58417993c442c26161f684d6c0c6867a746f3148548Craig Stout                    mImageInWrapper.setAlpha(0);
58517993c442c26161f684d6c0c6867a746f3148548Craig Stout                    mImageInWrapper = null;
58617993c442c26161f684d6c0c6867a746f3148548Craig Stout                }
58717993c442c26161f684d6c0c6867a746f3148548Craig Stout
58817993c442c26161f684d6c0c6867a746f3148548Craig Stout                mBackgroundDrawable = mDrawable;
58917993c442c26161f684d6c0c6867a746f3148548Craig Stout                mService.setDrawable(mBackgroundDrawable);
59017993c442c26161f684d6c0c6867a746f3148548Craig Stout            }
59117993c442c26161f684d6c0c6867a746f3148548Craig Stout
59217993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (newBackground) {
59317993c442c26161f684d6c0c6867a746f3148548Craig Stout                applyBackgroundChanges();
59417993c442c26161f684d6c0c6867a746f3148548Craig Stout            }
59517993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
59617993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
59717993c442c26161f684d6c0c6867a746f3148548Craig Stout
59817993c442c26161f684d6c0c6867a746f3148548Craig Stout    private Drawable createEmptyDrawable() {
59917993c442c26161f684d6c0c6867a746f3148548Craig Stout        Bitmap bitmap = null;
60017993c442c26161f684d6c0c6867a746f3148548Craig Stout        return new BitmapDrawable(mContext.getResources(), bitmap);
60117993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
60217993c442c26161f684d6c0c6867a746f3148548Craig Stout
60317993c442c26161f684d6c0c6867a746f3148548Craig Stout    private void showWallpaper(boolean show) {
60417993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (mWindow == null) {
60517993c442c26161f684d6c0c6867a746f3148548Craig Stout            return;
60617993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
60717993c442c26161f684d6c0c6867a746f3148548Craig Stout
60817993c442c26161f684d6c0c6867a746f3148548Craig Stout        WindowManager.LayoutParams layoutParams = mWindow.getAttributes();
60917993c442c26161f684d6c0c6867a746f3148548Craig Stout        if (show) {
61017993c442c26161f684d6c0c6867a746f3148548Craig Stout            if ((layoutParams.flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
61117993c442c26161f684d6c0c6867a746f3148548Craig Stout                return;
61217993c442c26161f684d6c0c6867a746f3148548Craig Stout            }
61317993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (DEBUG) Log.v(TAG, "showing wallpaper");
61417993c442c26161f684d6c0c6867a746f3148548Craig Stout            layoutParams.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
61517993c442c26161f684d6c0c6867a746f3148548Craig Stout        } else {
61617993c442c26161f684d6c0c6867a746f3148548Craig Stout            if ((layoutParams.flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) == 0) {
61717993c442c26161f684d6c0c6867a746f3148548Craig Stout                return;
61817993c442c26161f684d6c0c6867a746f3148548Craig Stout            }
61917993c442c26161f684d6c0c6867a746f3148548Craig Stout            if (DEBUG) Log.v(TAG, "hiding wallpaper");
62017993c442c26161f684d6c0c6867a746f3148548Craig Stout            layoutParams.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
62117993c442c26161f684d6c0c6867a746f3148548Craig Stout        }
62217993c442c26161f684d6c0c6867a746f3148548Craig Stout
62317993c442c26161f684d6c0c6867a746f3148548Craig Stout        mWindow.setAttributes(layoutParams);
62417993c442c26161f684d6c0c6867a746f3148548Craig Stout    }
62517993c442c26161f684d6c0c6867a746f3148548Craig Stout}
626