165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/*
265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project
365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License");
565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License.
665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at
765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *      http://www.apache.org/licenses/LICENSE-2.0
965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software
1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS,
1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and
1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License.
1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.widget;
1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Context;
2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent.ShortcutIconResource;
2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.graphics.Bitmap;
2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.Uri;
2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.text.TextUtils;
2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.util.UriUtils;
2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/**
2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Options for loading bitmap resources from different sources and for scaling to an appropriate
2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * resolution.
3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * @see BitmapWorkerTask
3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepublic class BitmapWorkerOptions {
3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /** Max image size handled by android.graphics */
3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    static final int MAX_IMAGE_DIMENSION_PX = 2048;
3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /** flag to force disable memory cache */
3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final int CACHE_FLAG_MEM_DISABLED = 1;
4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /** TODO support disk cache options */
4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static final int CACHE_FLAG_DISK_DISABLED = 2;
4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private ShortcutIconResource mIconResource;
4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private Uri mResourceUri;
4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mWidth;
4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mHeight;
4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private Context mContext;
4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private int mCacheFlag;
5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private Bitmap.Config mBitmapConfig;
5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private String mKey;
5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Builds options for a bitmap worker task.
5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static class Builder {
5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private String mPackageName;
6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private String mResourceName;
6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private Uri mResourceUri;
6265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private int mWidth;
6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private int mHeight;
656e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler        private final Context mContext;
6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private int mCacheFlag;
6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        private Bitmap.Config mBitmapConfig;
6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Builder(Context context) {
7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mWidth = MAX_IMAGE_DIMENSION_PX;
7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mHeight = MAX_IMAGE_DIMENSION_PX;
7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mContext = context.getApplicationContext();
7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mCacheFlag = 0;
7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mBitmapConfig = null;
7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public BitmapWorkerOptions build() {
7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            BitmapWorkerOptions options = new BitmapWorkerOptions();
7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (!TextUtils.isEmpty(mPackageName)) {
8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                options.mIconResource = new ShortcutIconResource();
8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                options.mIconResource.packageName = mPackageName;
8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                options.mIconResource.resourceName = mResourceName;
8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            final int largestDim = Math.max(mWidth, mHeight);
8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (largestDim > MAX_IMAGE_DIMENSION_PX) {
8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                double scale = (double) MAX_IMAGE_DIMENSION_PX / largestDim;
8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mWidth *= scale;
9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mHeight *= scale;
9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            options.mResourceUri = mResourceUri;
9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            options.mWidth = mWidth;
9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            options.mHeight = mHeight;
9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            options.mContext = mContext;
9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            options.mCacheFlag = mCacheFlag;
9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            options.mBitmapConfig = mBitmapConfig;
9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (options.mIconResource == null && options.mResourceUri == null) {
10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                throw new RuntimeException("Both Icon and ResourceUri are null");
10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return options;
10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Builder resource(String packageName, String resourceName) {
10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mPackageName = packageName;
10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mResourceName = resourceName;
10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return this;
10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Builder resource(ShortcutIconResource iconResource) {
11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mPackageName = iconResource.packageName;
11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mResourceName = iconResource.resourceName;
11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return this;
11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Builder resource(Uri resourceUri) {
11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mResourceUri = resourceUri;
11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return this;
12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Builder width(int width) {
12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (width > 0) {
12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mWidth = width;
12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                throw new IllegalArgumentException("Can't set width to " + width);
12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return this;
12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Builder height(int height) {
13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (height > 0) {
13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                mHeight = height;
13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                throw new IllegalArgumentException("Can't set height to " + height);
13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return this;
13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Builder cacheFlag(int flag) {
14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mCacheFlag = flag;
14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return this;
14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        public Builder bitmapConfig(Bitmap.Config config) {
14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mBitmapConfig = config;
14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return this;
14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
15365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Private constructor.
15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * <p>
15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Use a {@link Builder} to create.
15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private BitmapWorkerOptions() {
15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public ShortcutIconResource getIconResource() {
16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mIconResource;
16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public Uri getResourceUri() {
16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mResourceUri;
16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public int getWidth() {
16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mWidth;
17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public int getHeight() {
17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mHeight;
17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public Context getContext() {
17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mContext;
17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public boolean isFromResource() {
18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return getIconResource() != null ||
18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                UriUtils.isAndroidResourceUri(getResourceUri())
18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                || UriUtils.isShortcutIconResourceUri(getResourceUri());
18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Combination of CACHE_FLAG_MEM_DISABLED and CACHE_FLAG_DISK_DISABLED,
18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * 0 for fully cache enabled
18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public int getCacheFlag() {
19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mCacheFlag;
19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public boolean isMemCacheEnabled() {
19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return (mCacheFlag & CACHE_FLAG_MEM_DISABLED) == 0;
19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public boolean isDiskCacheEnabled() {
19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return (mCacheFlag & CACHE_FLAG_DISK_DISABLED) == 0;
20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
20265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @return  preferred Bitmap config to decode bitmap, null for auto detect.
20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Use {@link Builder#bitmapConfig(android.graphics.Bitmap.Config)} to change it.
20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public Bitmap.Config getBitmapConfig() {
20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mBitmapConfig;
20865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public String getCacheKey() {
21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mKey == null) {
21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            mKey = mIconResource != null ? mIconResource.packageName + "/"
21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    + mIconResource.resourceName : mResourceUri.toString();
21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mKey;
21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    @Override
21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public String toString() {
22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (mIconResource == null) {
22165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return "URI: " + mResourceUri;
22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return "PackageName: " + mIconResource.packageName + " Resource: " + mIconResource
22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    + " URI: " + mResourceUri;
22565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
22665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane}
228