14c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn/*
24c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * Copyright (C) 2009 The Android Open Source Project
34c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn *
44c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
54c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * you may not use this file except in compliance with the License.
64c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * You may obtain a copy of the License at
74c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn *
84c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
94c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn *
104c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
114c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
124c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * See the License for the specific language governing permissions and
144c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * limitations under the License.
154c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn */
164c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
178cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornpackage android.app;
188cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
19bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinskiimport android.content.ContentResolver;
208cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.content.Context;
218cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.content.Intent;
22e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.content.pm.PackageManager;
23e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.content.pm.ResolveInfo;
248cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.content.res.Resources;
258cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.graphics.Bitmap;
268cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.graphics.BitmapFactory;
27b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurkaimport android.graphics.BitmapRegionDecoder;
28284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackbornimport android.graphics.Canvas;
2919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackbornimport android.graphics.ColorFilter;
30b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurkaimport android.graphics.Matrix;
31284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackbornimport android.graphics.Paint;
3219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackbornimport android.graphics.PixelFormat;
3324572375323dee79e3b456af07640ca194fd40bfJeff Brownimport android.graphics.PorterDuff;
3424572375323dee79e3b456af07640ca194fd40bfJeff Brownimport android.graphics.PorterDuffXfermode;
35284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackbornimport android.graphics.Rect;
36b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurkaimport android.graphics.RectF;
378cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.graphics.drawable.BitmapDrawable;
388cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.graphics.drawable.Drawable;
39e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport android.net.Uri;
40284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackbornimport android.os.Bundle;
418cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.os.Handler;
428cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.os.IBinder;
43840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackbornimport android.os.Looper;
44840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackbornimport android.os.Message;
458cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.os.ParcelFileDescriptor;
468cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.os.RemoteException;
478cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.os.ServiceManager;
48284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackbornimport android.util.DisplayMetrics;
497341d7a104b47996445d069a695e155a07184606Dianne Hackbornimport android.util.Log;
50908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackbornimport android.view.WindowManager;
5198365d7663cbd82979a5700faf0050220b01084dJeff Brownimport android.view.WindowManagerGlobal;
528cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
53b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurkaimport java.io.BufferedInputStream;
548cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport java.io.FileOutputStream;
558cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport java.io.IOException;
568cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport java.io.InputStream;
57e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurkaimport java.util.List;
588cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
598b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main/**
608b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main * Provides access to the system wallpaper. With WallpaperManager, you can
618b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main * get the current wallpaper, get the desired dimensions for the wallpaper, set
628b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main * the wallpaper, and more. Get an instance of WallpaperManager with
638b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main * {@link #getInstance(android.content.Context) getInstance()}.
648b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main */
658cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornpublic class WallpaperManager {
668cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    private static String TAG = "WallpaperManager";
678cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    private static boolean DEBUG = false;
68bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen    private float mWallpaperXStep = -1;
69bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen    private float mWallpaperYStep = -1;
708cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
714c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    /**
72e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka     * Activity Action: Show settings for choosing wallpaper. Do not use directly to construct
73e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka     * an intent; instead, use {@link #getCropAndSetWallpaperIntent}.
74e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka     * <p>Input:  {@link Intent#getData} is the URI of the image to crop and set as wallpaper.
75e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka     * <p>Output: RESULT_OK if user decided to crop/set the wallpaper, RESULT_CANCEL otherwise
76bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski     * Activities that support this intent should specify a MIME filter of "image/*"
77e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka     */
78e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka    public static final String ACTION_CROP_AND_SET_WALLPAPER =
79e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka            "android.service.wallpaper.CROP_AND_SET_WALLPAPER";
80e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka
81e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka    /**
824c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn     * Launch an activity for the user to pick the current global live
834c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn     * wallpaper.
844c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn     */
854c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    public static final String ACTION_LIVE_WALLPAPER_CHOOSER
864c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            = "android.service.wallpaper.LIVE_WALLPAPER_CHOOSER";
875a242ec2cf54e1bda69c2451304181ef1bc3e872Adam Cohen
885a242ec2cf54e1bda69c2451304181ef1bc3e872Adam Cohen    /**
897df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn     * Directly launch live wallpaper preview, allowing the user to immediately
907df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn     * confirm to switch to a specific live wallpaper.  You must specify
917df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn     * {@link #EXTRA_LIVE_WALLPAPER_COMPONENT} with the ComponentName of
927df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn     * a live wallpaper component that is to be shown.
937df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn     */
947df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn    public static final String ACTION_CHANGE_LIVE_WALLPAPER
957df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn            = "android.service.wallpaper.CHANGE_LIVE_WALLPAPER";
967df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn
977df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn    /**
987df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn     * Extra in {@link #ACTION_CHANGE_LIVE_WALLPAPER} that specifies the
997df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn     * ComponentName of a live wallpaper that should be shown as a preview,
1007df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn     * for the user to confirm.
1017df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn     */
1027df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn    public static final String EXTRA_LIVE_WALLPAPER_COMPONENT
1037df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn            = "android.service.wallpaper.extra.LIVE_WALLPAPER_COMPONENT";
1047df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn
1057df7d2022d9bebc21a13dcb7ddacaa61f9c2e38eDianne Hackborn    /**
1065a242ec2cf54e1bda69c2451304181ef1bc3e872Adam Cohen     * Manifest entry for activities that respond to {@link Intent#ACTION_SET_WALLPAPER}
1075a242ec2cf54e1bda69c2451304181ef1bc3e872Adam Cohen     * which allows them to provide a custom large icon associated with this action.
1085a242ec2cf54e1bda69c2451304181ef1bc3e872Adam Cohen     */
1095a242ec2cf54e1bda69c2451304181ef1bc3e872Adam Cohen    public static final String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
1105a242ec2cf54e1bda69c2451304181ef1bc3e872Adam Cohen
11123ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn    /**
11223ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn     * Command for {@link #sendWallpaperCommand}: reported by the wallpaper
11323ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn     * host when the user taps on an empty area (not performing an action
11423ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn     * in the host).  The x and y arguments are the location of the tap in
11523ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn     * screen coordinates.
11623ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn     */
11723ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn    public static final String COMMAND_TAP = "android.wallpaper.tap";
11823ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn
11923ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn    /**
12023ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn     * Command for {@link #sendWallpaperCommand}: reported by the wallpaper
1219f3bdfe3eb04723efa07a2d0e6a7709da1191fa5Jeff Brown     * host when the user releases a secondary pointer on an empty area
1229f3bdfe3eb04723efa07a2d0e6a7709da1191fa5Jeff Brown     * (not performing an action in the host).  The x and y arguments are
1239f3bdfe3eb04723efa07a2d0e6a7709da1191fa5Jeff Brown     * the location of the secondary tap in screen coordinates.
1249f3bdfe3eb04723efa07a2d0e6a7709da1191fa5Jeff Brown     */
1259f3bdfe3eb04723efa07a2d0e6a7709da1191fa5Jeff Brown    public static final String COMMAND_SECONDARY_TAP = "android.wallpaper.secondaryTap";
1269f3bdfe3eb04723efa07a2d0e6a7709da1191fa5Jeff Brown
1279f3bdfe3eb04723efa07a2d0e6a7709da1191fa5Jeff Brown    /**
1289f3bdfe3eb04723efa07a2d0e6a7709da1191fa5Jeff Brown     * Command for {@link #sendWallpaperCommand}: reported by the wallpaper
12923ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn     * host when the user drops an object into an area of the host.  The x
13023ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn     * and y arguments are the location of the drop.
13123ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn     */
13223ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn    public static final String COMMAND_DROP = "android.home.drop";
13323ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn
1348cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    private final Context mContext;
1358cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
13619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn    /**
13719382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn     * Special drawable that draws a wallpaper as fast as possible.  Assumes
13819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn     * no scaling or placement off (0,0) of the wallpaper (this should be done
13919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn     * at the time the bitmap is loaded).
14019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn     */
14119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn    static class FastBitmapDrawable extends Drawable {
14219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        private final Bitmap mBitmap;
14319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        private final int mWidth;
14419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        private final int mHeight;
14519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        private int mDrawLeft;
14619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        private int mDrawTop;
147407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        private final Paint mPaint;
14819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
14919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        private FastBitmapDrawable(Bitmap bitmap) {
15019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            mBitmap = bitmap;
15119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            mWidth = bitmap.getWidth();
15219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            mHeight = bitmap.getHeight();
153407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
15419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            setBounds(0, 0, mWidth, mHeight);
155407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
156407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mPaint = new Paint();
157407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
15819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
15919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
16019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        @Override
16119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        public void draw(Canvas canvas) {
162407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            canvas.drawBitmap(mBitmap, mDrawLeft, mDrawTop, mPaint);
16319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
16419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
16519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        @Override
16619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        public int getOpacity() {
16719382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            return PixelFormat.OPAQUE;
16819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
16919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
17019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        @Override
17119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        public void setBounds(int left, int top, int right, int bottom) {
17219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            mDrawLeft = left + (right-left - mWidth) / 2;
17319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            mDrawTop = top + (bottom-top - mHeight) / 2;
17419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
17519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
17619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        @Override
17719382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        public void setAlpha(int alpha) {
178407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            throw new UnsupportedOperationException("Not supported with this drawable");
17919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
18019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
18119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        @Override
18219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        public void setColorFilter(ColorFilter cf) {
183407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            throw new UnsupportedOperationException("Not supported with this drawable");
18419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
18519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
18619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        @Override
18719382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        public void setDither(boolean dither) {
188407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            throw new UnsupportedOperationException("Not supported with this drawable");
18919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
19019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
19119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        @Override
19219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        public void setFilterBitmap(boolean filter) {
193407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            throw new UnsupportedOperationException("Not supported with this drawable");
19419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
19519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
19619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        @Override
19719382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        public int getIntrinsicWidth() {
19819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            return mWidth;
19919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
20019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
20119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        @Override
20219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        public int getIntrinsicHeight() {
20319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            return mHeight;
20419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
20519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
20619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        @Override
20719382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        public int getMinimumWidth() {
20819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            return mWidth;
20919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
21019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
21119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        @Override
21219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        public int getMinimumHeight() {
21319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            return mHeight;
21419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
21519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn    }
21619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
2178cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    static class Globals extends IWallpaperManagerCallback.Stub {
2188cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        private IWallpaperManager mService;
219284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn        private Bitmap mWallpaper;
22019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        private Bitmap mDefaultWallpaper;
2218cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
222840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackborn        private static final int MSG_CLEAR_WALLPAPER = 1;
223840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackborn
2245e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn        private final Handler mHandler;
225840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackborn
2265e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn        Globals(Looper looper) {
2278cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
2288cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            mService = IWallpaperManager.Stub.asInterface(b);
22985644d78894b66fa2903fb012b5122185767d1c5Dianne Hackborn            mHandler = new Handler(looper) {
2305e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn                @Override
2315e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn                public void handleMessage(Message msg) {
2325e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn                    switch (msg.what) {
2335e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn                        case MSG_CLEAR_WALLPAPER:
2345e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn                            synchronized (this) {
2355e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn                                mWallpaper = null;
23619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                                mDefaultWallpaper = null;
2375e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn                            }
2385e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn                            break;
2395e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn                    }
2405e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn                }
2415e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn            };
2428cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        }
2438cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
2448cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        public void onWallpaperChanged() {
2458cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            /* The wallpaper has changed but we shouldn't eagerly load the
2468cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn             * wallpaper as that would be inefficient. Reset the cached wallpaper
2478cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn             * to null so if the user requests the wallpaper again then we'll
2488cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn             * fetch it.
2498cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn             */
250840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackborn            mHandler.sendEmptyMessage(MSG_CLEAR_WALLPAPER);
2518cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        }
252041a0baba7f075ab3aba9c075dd75695a51617e4Adam Cohen
25319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault) {
2548cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            synchronized (this) {
2558cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                if (mWallpaper != null) {
2568cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                    return mWallpaper;
2578cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                }
25819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                if (mDefaultWallpaper != null) {
25919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                    return mDefaultWallpaper;
26019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                }
261c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn                mWallpaper = null;
262c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn                try {
263908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn                    mWallpaper = getCurrentWallpaperLocked(context);
264c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn                } catch (OutOfMemoryError e) {
265c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn                    Log.w(TAG, "No memory load current wallpaper", e);
266c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn                }
267ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                if (returnDefault) {
268ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                    if (mWallpaper == null) {
269ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                        mDefaultWallpaper = getDefaultWallpaperLocked(context);
270ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                        return mDefaultWallpaper;
271ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                    } else {
272ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                        mDefaultWallpaper = null;
273ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                    }
27419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                }
2758cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                return mWallpaper;
2768cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            }
2778cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        }
278ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn
279ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn        public void forgetLoadedWallpaper() {
280ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn            synchronized (this) {
281ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                mWallpaper = null;
282ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn                mDefaultWallpaper = null;
283b9fca9997100f209e98f0559c54c875b9e661e9fMichael Wright                mHandler.removeMessages(MSG_CLEAR_WALLPAPER);
284ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn            }
285ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn        }
286ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn
287908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn        private Bitmap getCurrentWallpaperLocked(Context context) {
2888cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            try {
289284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn                Bundle params = new Bundle();
290284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn                ParcelFileDescriptor fd = mService.getWallpaper(this, params);
2918cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                if (fd != null) {
292284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn                    int width = params.getInt("width", 0);
293284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn                    int height = params.getInt("height", 0);
29424572375323dee79e3b456af07640ca194fd40bfJeff Brown
29524572375323dee79e3b456af07640ca194fd40bfJeff Brown                    try {
29624572375323dee79e3b456af07640ca194fd40bfJeff Brown                        BitmapFactory.Options options = new BitmapFactory.Options();
29724572375323dee79e3b456af07640ca194fd40bfJeff Brown                        Bitmap bm = BitmapFactory.decodeFileDescriptor(
29824572375323dee79e3b456af07640ca194fd40bfJeff Brown                                fd.getFileDescriptor(), null, options);
299908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn                        return generateBitmap(context, bm, width, height);
30024572375323dee79e3b456af07640ca194fd40bfJeff Brown                    } catch (OutOfMemoryError e) {
30124572375323dee79e3b456af07640ca194fd40bfJeff Brown                        Log.w(TAG, "Can't decode file", e);
30224572375323dee79e3b456af07640ca194fd40bfJeff Brown                    } finally {
303284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn                        try {
304284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn                            fd.close();
305284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn                        } catch (IOException e) {
306407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                            // Ignore
307284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn                        }
308284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn                    }
30919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                }
31019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            } catch (RemoteException e) {
311407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                // Ignore
31219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            }
31319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            return null;
31419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
31519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
31619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        private Bitmap getDefaultWallpaperLocked(Context context) {
31719382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            try {
31819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                InputStream is = context.getResources().openRawResource(
31919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                        com.android.internal.R.drawable.default_wallpaper);
32019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                if (is != null) {
32119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                    int width = mService.getWidthHint();
32219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                    int height = mService.getHeightHint();
32324572375323dee79e3b456af07640ca194fd40bfJeff Brown
32424572375323dee79e3b456af07640ca194fd40bfJeff Brown                    try {
32524572375323dee79e3b456af07640ca194fd40bfJeff Brown                        BitmapFactory.Options options = new BitmapFactory.Options();
32624572375323dee79e3b456af07640ca194fd40bfJeff Brown                        Bitmap bm = BitmapFactory.decodeStream(is, null, options);
327908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn                        return generateBitmap(context, bm, width, height);
32824572375323dee79e3b456af07640ca194fd40bfJeff Brown                    } catch (OutOfMemoryError e) {
32924572375323dee79e3b456af07640ca194fd40bfJeff Brown                        Log.w(TAG, "Can't decode stream", e);
33024572375323dee79e3b456af07640ca194fd40bfJeff Brown                    } finally {
33119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                        try {
33219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                            is.close();
33319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn                        } catch (IOException e) {
334407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                            // Ignore
335284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn                        }
336c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn                    }
3378cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                }
3388cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            } catch (RemoteException e) {
339407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                // Ignore
3408cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            }
3418cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            return null;
3428cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        }
3438cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
3448cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
345407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy    private static final Object sSync = new Object[0];
3468cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    private static Globals sGlobals;
3478cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
348840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackborn    static void initGlobals(Looper looper) {
349407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        synchronized (sSync) {
3508cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            if (sGlobals == null) {
3515e802fbb895a0ff4d9be1a72390f51c134a5ba0fDianne Hackborn                sGlobals = new Globals(looper);
3528cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            }
3538cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        }
3548cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
3558cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
3568cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    /*package*/ WallpaperManager(Context context, Handler handler) {
3578cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        mContext = context;
358840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackborn        initGlobals(context.getMainLooper());
3598cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
3608cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
3618cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    /**
3624c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn     * Retrieve a WallpaperManager associated with the given Context.
3634c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn     */
3644c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    public static WallpaperManager getInstance(Context context) {
3654c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        return (WallpaperManager)context.getSystemService(
3664c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                Context.WALLPAPER_SERVICE);
3674c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    }
3684c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
3694c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    /** @hide */
3704c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    public IWallpaperManager getIWallpaperManager() {
371840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackborn        return sGlobals.mService;
3724c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    }
3734c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
3744c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    /**
3758b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * Retrieve the current system wallpaper; if
376b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * no wallpaper is set, the system built-in static wallpaper is returned.
3778b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * This is returned as an
3788b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * abstract Drawable that you can install in a View to display whatever
3798b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * wallpaper the user has currently set.
3808cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
3818cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * @return Returns a Drawable object that will draw the wallpaper.
3828cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     */
3834c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    public Drawable getDrawable() {
38419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
38519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        if (bm != null) {
38619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
38719382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            dr.setDither(false);
38819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            return dr;
38919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
39019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        return null;
3918cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
3928cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
3938cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    /**
394b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * Returns a drawable for the system built-in static wallpaper .
395b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     *
396b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     */
397b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka    public Drawable getBuiltInDrawable() {
398b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        return getBuiltInDrawable(0, 0, false, 0, 0);
399b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka    }
400b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
401b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka    /**
402b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * Returns a drawable for the system built-in static wallpaper. Based on the parameters, the
403b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * drawable can be cropped and scaled
404b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     *
405b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * @param outWidth The width of the returned drawable
406b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * @param outWidth The height of the returned drawable
407b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * @param scaleToFit If true, scale the wallpaper down rather than just cropping it
408b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * @param horizontalAlignment A float value between 0 and 1 specifying where to crop the image;
409b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     *        0 for left-aligned, 0.5 for horizontal center-aligned, and 1 for right-aligned
410b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * @param verticalAlignment A float value between 0 and 1 specifying where to crop the image;
411b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     *        0 for top-aligned, 0.5 for vertical center-aligned, and 1 for bottom-aligned
412b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     *
413b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     */
414b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka    public Drawable getBuiltInDrawable(int outWidth, int outHeight,
415b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            boolean scaleToFit, float horizontalAlignment, float verticalAlignment) {
416b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        if (sGlobals.mService == null) {
417b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            Log.w(TAG, "WallpaperService not running");
418b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            return null;
419b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        }
420b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        Resources resources = mContext.getResources();
421b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        horizontalAlignment = Math.max(0, Math.min(1, horizontalAlignment));
422b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        verticalAlignment = Math.max(0, Math.min(1, verticalAlignment));
423b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
424b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        InputStream is = new BufferedInputStream(
425b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                resources.openRawResource(com.android.internal.R.drawable.default_wallpaper));
426b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
427b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        if (is == null) {
428b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            Log.e(TAG, "default wallpaper input stream is null");
429b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            return null;
430b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        } else {
431b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            if (outWidth <= 0 || outHeight <= 0) {
432b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                Bitmap fullSize = BitmapFactory.decodeStream(is, null, null);
433b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                return new BitmapDrawable(resources, fullSize);
434b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            } else {
435b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                int inWidth;
436b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                int inHeight;
437b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                {
438b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    BitmapFactory.Options options = new BitmapFactory.Options();
439b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    options.inJustDecodeBounds = true;
440b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    BitmapFactory.decodeStream(is, null, options);
441b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    if (options.outWidth != 0 && options.outHeight != 0) {
442b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        inWidth = options.outWidth;
443b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        inHeight = options.outHeight;
444b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    } else {
445b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        Log.e(TAG, "default wallpaper dimensions are 0");
446b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        return null;
447b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    }
448b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                }
449b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
450b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                is = new BufferedInputStream(resources.openRawResource(
451b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        com.android.internal.R.drawable.default_wallpaper));
452b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
453b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                RectF cropRectF;
454b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
455b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                outWidth = Math.min(inWidth, outWidth);
456b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                outHeight = Math.min(inHeight, outHeight);
457b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                if (scaleToFit) {
458b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    cropRectF = getMaxCropRect(inWidth, inHeight, outWidth, outHeight,
459b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        horizontalAlignment, verticalAlignment);
460b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                } else {
461b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    float left = (inWidth - outWidth) * horizontalAlignment;
462b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    float right = left + outWidth;
463b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    float top = (inHeight - outHeight) * verticalAlignment;
464b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    float bottom = top + outHeight;
4650539153e771642096b3698dae5827f035040e2c8Michael Jurka                    cropRectF = new RectF(left, top, right, bottom);
466b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                }
467b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                Rect roundedTrueCrop = new Rect();
468b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                cropRectF.roundOut(roundedTrueCrop);
469b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
470b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) {
471b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    Log.w(TAG, "crop has bad values for full size image");
472b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    return null;
473b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                }
474b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
475b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                // See how much we're reducing the size of the image
476b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / outWidth,
477b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        roundedTrueCrop.height() / outHeight);
478b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
479b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                // Attempt to open a region decoder
480b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                BitmapRegionDecoder decoder = null;
481b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                try {
482b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    decoder = BitmapRegionDecoder.newInstance(is, true);
483b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                } catch (IOException e) {
484b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    Log.w(TAG, "cannot open region decoder for default wallpaper");
485b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                }
486b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
487b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                Bitmap crop = null;
488b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                if (decoder != null) {
489b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    // Do region decoding to get crop bitmap
490b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    BitmapFactory.Options options = new BitmapFactory.Options();
491b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    if (scaleDownSampleSize > 1) {
492b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        options.inSampleSize = scaleDownSampleSize;
493b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    }
494b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    crop = decoder.decodeRegion(roundedTrueCrop, options);
495b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    decoder.recycle();
496b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                }
497b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
498b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                if (crop == null) {
499b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    // BitmapRegionDecoder has failed, try to crop in-memory
500b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    is = new BufferedInputStream(resources.openRawResource(
501b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                            com.android.internal.R.drawable.default_wallpaper));
502b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    Bitmap fullSize = null;
503b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    if (is != null) {
504b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        BitmapFactory.Options options = new BitmapFactory.Options();
505b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        if (scaleDownSampleSize > 1) {
506b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                            options.inSampleSize = scaleDownSampleSize;
507b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        }
508b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        fullSize = BitmapFactory.decodeStream(is, null, options);
509b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    }
510b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    if (fullSize != null) {
511b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left,
512b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                                roundedTrueCrop.top, roundedTrueCrop.width(),
513b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                                roundedTrueCrop.height());
514b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    }
515b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                }
516b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
517b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                if (crop == null) {
518b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    Log.w(TAG, "cannot decode default wallpaper");
519b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    return null;
520b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                }
521b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
522b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                // Scale down if necessary
523b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                if (outWidth > 0 && outHeight > 0 &&
524b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        (crop.getWidth() != outWidth || crop.getHeight() != outHeight)) {
525b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    Matrix m = new Matrix();
526b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    RectF cropRect = new RectF(0, 0, crop.getWidth(), crop.getHeight());
527b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    RectF returnRect = new RectF(0, 0, outWidth, outHeight);
528b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
529b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(),
530b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                            (int) returnRect.height(), Bitmap.Config.ARGB_8888);
531b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    if (tmp != null) {
532b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        Canvas c = new Canvas(tmp);
533b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        Paint p = new Paint();
534b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        p.setFilterBitmap(true);
535b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        c.drawBitmap(crop, m, p);
536b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                        crop = tmp;
537b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                    }
538b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                }
539b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
540b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                return new BitmapDrawable(resources, crop);
541b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            }
542b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        }
543b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka    }
544b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
545b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka    private static RectF getMaxCropRect(int inWidth, int inHeight, int outWidth, int outHeight,
546b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka                float horizontalAlignment, float verticalAlignment) {
547b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        RectF cropRect = new RectF();
548b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        // Get a crop rect that will fit this
549b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        if (inWidth / (float) inHeight > outWidth / (float) outHeight) {
550b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka             cropRect.top = 0;
551b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka             cropRect.bottom = inHeight;
552b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka             float cropWidth = outWidth * (inHeight / (float) outHeight);
553b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka             cropRect.left = (inWidth - cropWidth) * horizontalAlignment;
554b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka             cropRect.right = cropRect.left + cropWidth;
555b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        } else {
556b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            cropRect.left = 0;
557b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            cropRect.right = inWidth;
558b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            float cropHeight = outHeight * (inWidth / (float) outWidth);
559b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            cropRect.top = (inHeight - cropHeight) * verticalAlignment;
560b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka            cropRect.bottom = cropRect.top + cropHeight;
561b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        }
562b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka        return cropRect;
563b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka    }
564b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka
565b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka    /**
5668b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * Retrieve the current system wallpaper; if there is no wallpaper set,
5678b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * a null pointer is returned. This is returned as an
5688cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * abstract Drawable that you can install in a View to display whatever
5698b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * wallpaper the user has currently set.
5708cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
5718cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * @return Returns a Drawable object that will draw the wallpaper or a
5728cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * null pointer if these is none.
5738cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     */
5744c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    public Drawable peekDrawable() {
57519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
57619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        if (bm != null) {
57719382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
57819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            dr.setDither(false);
57919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            return dr;
58019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
58119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        return null;
58219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn    }
58319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
58419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn    /**
5858b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * Like {@link #getDrawable()}, but the returned Drawable has a number
5868b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * of limitations to reduce its overhead as much as possible. It will
5878b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * never scale the wallpaper (only centering it if the requested bounds
5888b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * do match the bitmap bounds, which should not be typical), doesn't
5898b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * allow setting an alpha, color filter, or other attributes, etc.  The
5908b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * bounds of the returned drawable will be initialized to the same bounds
5918b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * as the wallpaper, so normally you will not need to touch it.  The
5928b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * drawable also assumes that it will be used in a context running in
5938b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * the same density as the screen (not in density compatibility mode).
59419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn     *
59519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn     * @return Returns a Drawable object that will draw the wallpaper.
59619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn     */
59719382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn    public Drawable getFastDrawable() {
59819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
59919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        if (bm != null) {
600407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return new FastBitmapDrawable(bm);
60119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
60219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        return null;
60319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn    }
60419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
60519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn    /**
6068b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * Like {@link #getFastDrawable()}, but if there is no wallpaper set,
6078b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * a null pointer is returned.
60819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn     *
60919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn     * @return Returns an optimized Drawable object that will draw the
61019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn     * wallpaper or a null pointer if these is none.
61119382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn     */
61219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn    public Drawable peekFastDrawable() {
61319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
61419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        if (bm != null) {
615407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            return new FastBitmapDrawable(bm);
61619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
61719382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        return null;
6188cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
6198cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
6208cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    /**
621407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy     * Like {@link #getDrawable()} but returns a Bitmap.
622407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy     *
623407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy     * @hide
624407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy     */
625407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy    public Bitmap getBitmap() {
626407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy        return sGlobals.peekWallpaperBitmap(mContext, true);
627407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy    }
628407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy
629407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy    /**
630ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn     * Remove all internal references to the last loaded wallpaper.  Useful
631ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn     * for apps that want to reduce memory usage when they only temporarily
632ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn     * need to have the wallpaper.  After calling, the next request for the
633ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn     * wallpaper will require reloading it again from disk.
634ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn     */
635ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn    public void forgetLoadedWallpaper() {
636ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn        sGlobals.forgetLoadedWallpaper();
637ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn    }
638ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn
639ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn    /**
640eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn     * If the current wallpaper is a live wallpaper component, return the
641eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn     * information about that wallpaper.  Otherwise, if it is a static image,
642eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn     * simply return null.
643eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn     */
644eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn    public WallpaperInfo getWallpaperInfo() {
645eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn        try {
646c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            if (sGlobals.mService == null) {
647c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood                Log.w(TAG, "WallpaperService not running");
648c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood                return null;
649c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            } else {
650c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood                return sGlobals.mService.getWallpaperInfo();
651c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            }
652eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn        } catch (RemoteException e) {
653eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn            return null;
654eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn        }
655eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn    }
656e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka
657e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka    /**
658e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka     * Gets an Intent that will launch an activity that crops the given
659e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka     * image and sets the device's wallpaper. If there is a default HOME activity
660e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka     * that supports cropping wallpapers, it will be preferred as the default.
661930d4e52adcd4acf3d6a7ac224ab2142858d595eYing Wang     * Use this method instead of directly creating a {@link #ACTION_CROP_AND_SET_WALLPAPER}
662e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka     * intent.
663bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski     *
664bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski     * @param imageUri The image URI that will be set in the intent. The must be a content
665bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski     *                 URI and its provider must resolve its type to "image/*"
666bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski     *
667bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski     * @throws IllegalArgumentException if the URI is not a content URI or its MIME type is
668bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski     *         not "image/*"
669e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka     */
670e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka    public Intent getCropAndSetWallpaperIntent(Uri imageUri) {
671bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski        if (!ContentResolver.SCHEME_CONTENT.equals(imageUri.getScheme())) {
672bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski            throw new IllegalArgumentException("Image URI must be of the "
673bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski                    + ContentResolver.SCHEME_CONTENT + " scheme type");
674bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski        }
675bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski
676e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka        final PackageManager packageManager = mContext.getPackageManager();
677e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka        Intent cropAndSetWallpaperIntent =
678e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka                new Intent(ACTION_CROP_AND_SET_WALLPAPER, imageUri);
679e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka        cropAndSetWallpaperIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
680e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka
681e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka        // Find out if the default HOME activity supports CROP_AND_SET_WALLPAPER
682e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka        Intent homeIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME);
683e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka        ResolveInfo resolvedHome = packageManager.resolveActivity(homeIntent,
684e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka                PackageManager.MATCH_DEFAULT_ONLY);
685e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka        if (resolvedHome != null) {
686e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka            cropAndSetWallpaperIntent.setPackage(resolvedHome.activityInfo.packageName);
687e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka
688e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka            List<ResolveInfo> cropAppList = packageManager.queryIntentActivities(
689e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka                    cropAndSetWallpaperIntent, 0);
690e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka            if (cropAppList.size() > 0) {
691e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka                return cropAndSetWallpaperIntent;
692e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka            }
693e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka        }
694e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka
695e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka        // fallback crop activity
696e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka        cropAndSetWallpaperIntent.setPackage("com.android.wallpapercropper");
697bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski        List<ResolveInfo> cropAppList = packageManager.queryIntentActivities(
698bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski                cropAndSetWallpaperIntent, 0);
699bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski        if (cropAppList.size() > 0) {
700bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski            return cropAndSetWallpaperIntent;
701bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski        }
702bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski        // If the URI is not of the right type, or for some reason the system wallpaper
703bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski        // cropper doesn't exist, return null
704bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski        throw new IllegalArgumentException("Cannot use passed URI to set wallpaper; " +
705bba72d13afb024453373077f4f8d21164b63c76dAdam Lesinski            "check that the type returned by ContentProvider matches image/*");
706e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka    }
707e8d1bf7a439450b9979701909164a6baffbe8baeMichael Jurka
708eb034652c2037a47ebfd99779e8383bb8bb528afDianne Hackborn    /**
7098cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * Change the current system wallpaper to the bitmap in the given resource.
7108cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * The resource is opened as a raw data stream and copied into the
7118cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * wallpaper; it must be a valid PNG or JPEG image.  On success, the intent
7128cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast.
7138cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
7149530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
7159530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#SET_WALLPAPER}.
7169530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     *
7178cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * @param resid The bitmap to save.
7188cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
719b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * @throws IOException If an error occurs reverting to the built-in
7208cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * wallpaper.
7218cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     */
7224c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    public void setResource(int resid) throws IOException {
723c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood        if (sGlobals.mService == null) {
724c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            Log.w(TAG, "WallpaperService not running");
725c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            return;
726c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood        }
7278cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        try {
7288cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            Resources resources = mContext.getResources();
7298cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            /* Set the wallpaper to the default values */
730840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackborn            ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(
7318cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                    "res:" + resources.getResourceName(resid));
7328cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            if (fd != null) {
7338cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                FileOutputStream fos = null;
7348cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                try {
7358cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                    fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
7368cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                    setWallpaper(resources.openRawResource(resid), fos);
7378cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                } finally {
7388cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                    if (fos != null) {
7398cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                        fos.close();
7408cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                    }
7418cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                }
7428cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            }
7438cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        } catch (RemoteException e) {
744407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            // Ignore
7458cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        }
7468cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
7478cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
7488cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    /**
7498cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * Change the current system wallpaper to a bitmap.  The given bitmap is
7508cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * converted to a PNG and stored as the wallpaper.  On success, the intent
7518cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast.
7528cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
7539530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
7549530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#SET_WALLPAPER}.
7559530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     *
7568cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * @param bitmap The bitmap to save.
7578cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
758b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * @throws IOException If an error occurs reverting to the built-in
7598cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * wallpaper.
7608cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     */
7614c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    public void setBitmap(Bitmap bitmap) throws IOException {
762c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood        if (sGlobals.mService == null) {
763c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            Log.w(TAG, "WallpaperService not running");
764c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            return;
765c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood        }
7668cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        try {
767840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackborn            ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null);
7688cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            if (fd == null) {
7698cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                return;
7708cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            }
7718cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            FileOutputStream fos = null;
7728cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            try {
7738cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
7748cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
7758cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            } finally {
7768cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                if (fos != null) {
7778cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                    fos.close();
7788cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                }
7798cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            }
7808cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        } catch (RemoteException e) {
781407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            // Ignore
7828cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        }
7838cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
7848cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
7858cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    /**
7868cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * Change the current system wallpaper to a specific byte stream.  The
7878cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * give InputStream is copied into persistent storage and will now be
7888cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * used as the wallpaper.  Currently it must be either a JPEG or PNG
7898cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * image.  On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
7908cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * is broadcast.
7918cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
7929530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
7939530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#SET_WALLPAPER}.
7949530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     *
7958cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * @param data A stream containing the raw data to install as a wallpaper.
7968cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
797b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * @throws IOException If an error occurs reverting to the built-in
7988cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * wallpaper.
7998cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     */
8004c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    public void setStream(InputStream data) throws IOException {
801c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood        if (sGlobals.mService == null) {
802c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            Log.w(TAG, "WallpaperService not running");
803c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            return;
804c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood        }
8058cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        try {
806840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackborn            ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null);
8078cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            if (fd == null) {
8088cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                return;
8098cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            }
8108cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            FileOutputStream fos = null;
8118cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            try {
8128cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
8138cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                setWallpaper(data, fos);
8148cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            } finally {
8158cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                if (fos != null) {
8168cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                    fos.close();
8178cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn                }
8188cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            }
8198cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        } catch (RemoteException e) {
820407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            // Ignore
8218cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        }
8228cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
8238cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
8248cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    private void setWallpaper(InputStream data, FileOutputStream fos)
8258cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            throws IOException {
8268cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        byte[] buffer = new byte[32768];
8278cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        int amt;
8288cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        while ((amt=data.read(buffer)) > 0) {
8298cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            fos.write(buffer, 0, amt);
8308cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        }
8318cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
8328cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
8338cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    /**
8345dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn     * Return whether any users are currently set to use the wallpaper
8355dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn     * with the given resource ID.  That is, their wallpaper has been
8365dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn     * set through {@link #setResource(int)} with the same resource id.
8375dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn     */
8385dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn    public boolean hasResourceWallpaper(int resid) {
8395dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn        if (sGlobals.mService == null) {
8405dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn            Log.w(TAG, "WallpaperService not running");
8415dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn            return false;
8425dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn        }
8435dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn        try {
8445dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn            Resources resources = mContext.getResources();
8455dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn            String name = "res:" + resources.getResourceName(resid);
8465dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn            return sGlobals.mService.hasNamedWallpaper(name);
8475dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn        } catch (RemoteException e) {
8485dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn            return false;
8495dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn        }
8505dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn    }
8515dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn
8525dc5a00e7ebadc085ded7e29feacd17e53698486Dianne Hackborn    /**
8538cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * Returns the desired minimum width for the wallpaper. Callers of
8544c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn     * {@link #setBitmap(android.graphics.Bitmap)} or
8554c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn     * {@link #setStream(java.io.InputStream)} should check this value
8568cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * beforehand to make sure the supplied wallpaper respects the desired
8578cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * minimum width.
8588cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
8598cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * If the returned value is <= 0, the caller should use the width of
8608cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * the default display instead.
8618cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
8628cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * @return The desired minimum width for the wallpaper. This value should
8638cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * be honored by applications that set the wallpaper but it is not
8648cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * mandatory.
8658cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     */
8668cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    public int getDesiredMinimumWidth() {
867c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood        if (sGlobals.mService == null) {
868c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            Log.w(TAG, "WallpaperService not running");
869c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            return 0;
870c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood        }
8718cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        try {
872840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackborn            return sGlobals.mService.getWidthHint();
8738cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        } catch (RemoteException e) {
8748cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            // Shouldn't happen!
8758cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            return 0;
8768cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        }
8778cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
8788cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
8798cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    /**
8808cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * Returns the desired minimum height for the wallpaper. Callers of
8814c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn     * {@link #setBitmap(android.graphics.Bitmap)} or
8824c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn     * {@link #setStream(java.io.InputStream)} should check this value
8838cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * beforehand to make sure the supplied wallpaper respects the desired
8848cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * minimum height.
8858cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
8868cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * If the returned value is <= 0, the caller should use the height of
8878cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * the default display instead.
8888cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
8898cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * @return The desired minimum height for the wallpaper. This value should
8908cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * be honored by applications that set the wallpaper but it is not
8918cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * mandatory.
8928cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     */
8938cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    public int getDesiredMinimumHeight() {
894c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood        if (sGlobals.mService == null) {
895c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            Log.w(TAG, "WallpaperService not running");
896c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            return 0;
897c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood        }
8988cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        try {
899840c3a2b7e29cd75c13418a90cce5e311415c843Dianne Hackborn            return sGlobals.mService.getHeightHint();
9008cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        } catch (RemoteException e) {
9018cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            // Shouldn't happen!
9028cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            return 0;
9038cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        }
9048cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
9058cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn
9068cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    /**
9078cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * For use only by the current home application, to specify the size of
9088cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * wallpaper it would like to use.  This allows such applications to have
9098cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * a virtual wallpaper that is larger than the physical screen, matching
9108cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * the size of their workspace.
911c5bf7584422adca286c1f27a073df925c06f068dDianne Hackborn     *
912c5bf7584422adca286c1f27a073df925c06f068dDianne Hackborn     * <p>Note developers, who don't seem to be reading this.  This is
913c5bf7584422adca286c1f27a073df925c06f068dDianne Hackborn     * for <em>home screens</em> to tell what size wallpaper they would like.
914c5bf7584422adca286c1f27a073df925c06f068dDianne Hackborn     * Nobody else should be calling this!  Certainly not other non-home-screen
915c5bf7584422adca286c1f27a073df925c06f068dDianne Hackborn     * apps that change the wallpaper.  Those apps are supposed to
916c5bf7584422adca286c1f27a073df925c06f068dDianne Hackborn     * <b>retrieve</b> the suggested size so they can construct a wallpaper
917c5bf7584422adca286c1f27a073df925c06f068dDianne Hackborn     * that matches it.
918c5bf7584422adca286c1f27a073df925c06f068dDianne Hackborn     *
9199530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
9209530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#SET_WALLPAPER_HINTS}.
9219530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     *
9228cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * @param minimumWidth Desired minimum width
9238cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * @param minimumHeight Desired minimum height
9248cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     */
9254c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    public void suggestDesiredDimensions(int minimumWidth, int minimumHeight) {
9268cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        try {
927c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            if (sGlobals.mService == null) {
928c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood                Log.w(TAG, "WallpaperService not running");
929c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            } else {
930c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood                sGlobals.mService.setDimensionHints(minimumWidth, minimumHeight);
931c067c9c373e673b2474e8dc2e5a00db274d5e13dMike Lockwood            }
9328cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        } catch (RemoteException e) {
933407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy            // Ignore
9348cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn        }
9358cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
936041a0baba7f075ab3aba9c075dd75695a51617e4Adam Cohen
9378cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    /**
938c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn     * Set the position of the current wallpaper within any larger space, when
939c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn     * that wallpaper is visible behind the given window.  The X and Y offsets
940c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn     * are floating point numbers ranging from 0 to 1, representing where the
941c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn     * wallpaper should be positioned within the screen space.  These only
942c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn     * make sense when the wallpaper is larger than the screen.
943c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn     *
944c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn     * @param windowToken The window who these offsets should be associated
9458b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * with, as returned by {@link android.view.View#getWindowToken()
946c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn     * View.getWindowToken()}.
947bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen     * @param xOffset The offset along the X dimension, from 0 to 1.
948c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn     * @param yOffset The offset along the Y dimension, from 0 to 1.
949c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn     */
950c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn    public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
951791a6331e3ca21e3b6cdbfee62348e45786ca3eaAdam Cohen        try {
952791a6331e3ca21e3b6cdbfee62348e45786ca3eaAdam Cohen            //Log.v(TAG, "Sending new wallpaper offsets from app...");
953f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown            WindowManagerGlobal.getWindowSession().setWallpaperPosition(
954791a6331e3ca21e3b6cdbfee62348e45786ca3eaAdam Cohen                    windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
955791a6331e3ca21e3b6cdbfee62348e45786ca3eaAdam Cohen            //Log.v(TAG, "...app returning after sending offsets!");
956791a6331e3ca21e3b6cdbfee62348e45786ca3eaAdam Cohen        } catch (RemoteException e) {
957791a6331e3ca21e3b6cdbfee62348e45786ca3eaAdam Cohen            // Ignore.
958791a6331e3ca21e3b6cdbfee62348e45786ca3eaAdam Cohen        }
9597580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn    }
960041a0baba7f075ab3aba9c075dd75695a51617e4Adam Cohen
9617580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn    /**
962bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen     * For applications that use multiple virtual screens showing a wallpaper,
963bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen     * specify the step size between virtual screens. For example, if the
96423ef7b4836d66d31430fedee2aac36275bb30d4bDianne Hackborn     * launcher has 3 virtual screens, it would specify an xStep of 0.5,
965bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen     * since the X offset for those screens are 0.0, 0.5 and 1.0
966bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen     * @param xStep The X offset delta from one screen to the next one
967bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen     * @param yStep The Y offset delta from one screen to the next one
968bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen     */
969bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen    public void setWallpaperOffsetSteps(float xStep, float yStep) {
970bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen        mWallpaperXStep = xStep;
971bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen        mWallpaperYStep = yStep;
972bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen    }
973bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen
974bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen    /**
9757580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn     * Send an arbitrary command to the current active wallpaper.
9767580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn     *
9777580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn     * @param windowToken The window who these offsets should be associated
9787580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn     * with, as returned by {@link android.view.View#getWindowToken()
9797580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn     * View.getWindowToken()}.
9807580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn     * @param action Name of the command to perform.  This must be a scoped
9817580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn     * name to avoid collisions, such as "com.mycompany.wallpaper.DOIT".
9827580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn     * @param x Arbitrary integer argument based on command.
9837580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn     * @param y Arbitrary integer argument based on command.
9847580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn     * @param z Arbitrary integer argument based on command.
9857580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn     * @param extras Optional additional information for the command, or null.
9867580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn     */
9877580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn    public void sendWallpaperCommand(IBinder windowToken, String action,
9887580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn            int x, int y, int z, Bundle extras) {
9897580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn        try {
9907580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn            //Log.v(TAG, "Sending new wallpaper offsets from app...");
991f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown            WindowManagerGlobal.getWindowSession().sendWallpaperCommand(
9927580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn                    windowToken, action, x, y, z, extras, false);
9937580493b014a2c7ea883cd291255798dc72ebbffDianne Hackborn            //Log.v(TAG, "...app returning after sending offsets!");
994c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn        } catch (RemoteException e) {
995c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn            // Ignore.
996c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn        }
997c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn    }
998c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn
999c8a0a75e1c61d1ab24bd46a8243041c107e738acDianne Hackborn    /**
100072c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn     * Clear the offsets previously associated with this window through
100172c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn     * {@link #setWallpaperOffsets(IBinder, float, float)}.  This reverts
100272c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn     * the window to its default state, where it does not cause the wallpaper
100372c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn     * to scroll from whatever its last offsets were.
100472c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn     *
100572c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn     * @param windowToken The window who these offsets should be associated
10068b2e000c43f5a93209be269a0b9e08943fad8d3cScott Main     * with, as returned by {@link android.view.View#getWindowToken()
100772c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn     * View.getWindowToken()}.
100872c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn     */
100972c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn    public void clearWallpaperOffsets(IBinder windowToken) {
101072c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn        try {
1011f9e989d5f09e72f5c9a59d713521f37d3fdd93ddJeff Brown            WindowManagerGlobal.getWindowSession().setWallpaperPosition(
1012bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen                    windowToken, -1, -1, -1, -1);
101372c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn        } catch (RemoteException e) {
101472c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn            // Ignore.
101572c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn        }
101672c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn    }
101772c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn
101872c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn    /**
1019b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * Remove any currently set wallpaper, reverting to the system's built-in
10208cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * wallpaper. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
10218cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * is broadcast.
10228cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     *
10239530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * <p>This method requires the caller to hold the permission
10249530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     * {@link android.Manifest.permission#SET_WALLPAPER}.
10259530e3a22d5ffa2019d1a5177b6a441d4d6d048bNicolas Falliere     *
1026b668d0ba7e3c18dd0e9ee9654b4ffdc6c6a8a71fMichael Jurka     * @throws IOException If an error occurs reverting to the built-in
10278cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     * wallpaper.
10288cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn     */
10298cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    public void clear() throws IOException {
10304c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        setResource(com.android.internal.R.drawable.default_wallpaper);
10318cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    }
103219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn
1033908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn    static Bitmap generateBitmap(Context context, Bitmap bm, int width, int height) {
103419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        if (bm == null) {
103524572375323dee79e3b456af07640ca194fd40bfJeff Brown            return null;
103619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
103724572375323dee79e3b456af07640ca194fd40bfJeff Brown
1038908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
1039908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn        DisplayMetrics metrics = new DisplayMetrics();
1040908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn        wm.getDefaultDisplay().getMetrics(metrics);
1041908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn        bm.setDensity(metrics.noncompatDensityDpi);
104224572375323dee79e3b456af07640ca194fd40bfJeff Brown
1043038b737c7561e6a92edcd6267f1299d2602f1920Jeff Brown        if (width <= 0 || height <= 0
1044038b737c7561e6a92edcd6267f1299d2602f1920Jeff Brown                || (bm.getWidth() == width && bm.getHeight() == height)) {
104524572375323dee79e3b456af07640ca194fd40bfJeff Brown            return bm;
104624572375323dee79e3b456af07640ca194fd40bfJeff Brown        }
104724572375323dee79e3b456af07640ca194fd40bfJeff Brown
104819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        // This is the final bitmap we want to return.
104924572375323dee79e3b456af07640ca194fd40bfJeff Brown        try {
105024572375323dee79e3b456af07640ca194fd40bfJeff Brown            Bitmap newbm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
1051908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn            newbm.setDensity(metrics.noncompatDensityDpi);
105224572375323dee79e3b456af07640ca194fd40bfJeff Brown
105324572375323dee79e3b456af07640ca194fd40bfJeff Brown            Canvas c = new Canvas(newbm);
105424572375323dee79e3b456af07640ca194fd40bfJeff Brown            Rect targetRect = new Rect();
105524572375323dee79e3b456af07640ca194fd40bfJeff Brown            targetRect.right = bm.getWidth();
105624572375323dee79e3b456af07640ca194fd40bfJeff Brown            targetRect.bottom = bm.getHeight();
105724572375323dee79e3b456af07640ca194fd40bfJeff Brown
105824572375323dee79e3b456af07640ca194fd40bfJeff Brown            int deltaw = width - targetRect.right;
105924572375323dee79e3b456af07640ca194fd40bfJeff Brown            int deltah = height - targetRect.bottom;
106024572375323dee79e3b456af07640ca194fd40bfJeff Brown
106124572375323dee79e3b456af07640ca194fd40bfJeff Brown            if (deltaw > 0 || deltah > 0) {
106224572375323dee79e3b456af07640ca194fd40bfJeff Brown                // We need to scale up so it covers the entire area.
1063407ec78b828173257b0c5dae221649a4ccd8b058Romain Guy                float scale;
106424572375323dee79e3b456af07640ca194fd40bfJeff Brown                if (deltaw > deltah) {
106524572375323dee79e3b456af07640ca194fd40bfJeff Brown                    scale = width / (float)targetRect.right;
106624572375323dee79e3b456af07640ca194fd40bfJeff Brown                } else {
106724572375323dee79e3b456af07640ca194fd40bfJeff Brown                    scale = height / (float)targetRect.bottom;
106824572375323dee79e3b456af07640ca194fd40bfJeff Brown                }
106924572375323dee79e3b456af07640ca194fd40bfJeff Brown                targetRect.right = (int)(targetRect.right*scale);
107024572375323dee79e3b456af07640ca194fd40bfJeff Brown                targetRect.bottom = (int)(targetRect.bottom*scale);
107124572375323dee79e3b456af07640ca194fd40bfJeff Brown                deltaw = width - targetRect.right;
107224572375323dee79e3b456af07640ca194fd40bfJeff Brown                deltah = height - targetRect.bottom;
107319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn            }
107424572375323dee79e3b456af07640ca194fd40bfJeff Brown
107524572375323dee79e3b456af07640ca194fd40bfJeff Brown            targetRect.offset(deltaw/2, deltah/2);
107624572375323dee79e3b456af07640ca194fd40bfJeff Brown
107724572375323dee79e3b456af07640ca194fd40bfJeff Brown            Paint paint = new Paint();
107824572375323dee79e3b456af07640ca194fd40bfJeff Brown            paint.setFilterBitmap(true);
107924572375323dee79e3b456af07640ca194fd40bfJeff Brown            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
108024572375323dee79e3b456af07640ca194fd40bfJeff Brown            c.drawBitmap(bm, null, targetRect, paint);
108124572375323dee79e3b456af07640ca194fd40bfJeff Brown
108224572375323dee79e3b456af07640ca194fd40bfJeff Brown            bm.recycle();
1083ba39839444532af0ed3766f736582413f6d7a40bDianne Hackborn            c.setBitmap(null);
108424572375323dee79e3b456af07640ca194fd40bfJeff Brown            return newbm;
108524572375323dee79e3b456af07640ca194fd40bfJeff Brown        } catch (OutOfMemoryError e) {
108624572375323dee79e3b456af07640ca194fd40bfJeff Brown            Log.w(TAG, "Can't generate default bitmap", e);
108724572375323dee79e3b456af07640ca194fd40bfJeff Brown            return bm;
108819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn        }
108919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn    }
10908cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn}
1091