blob: e6e0f350e74b7ec43dfe9b20b1b7832c55fac60c [file] [log] [blame]
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070017package android.app;
18
Adam Lesinskibba72d12013-10-11 18:10:56 -070019import android.content.ContentResolver;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070020import android.content.Context;
21import android.content.Intent;
Michael Jurkae8d1bf72013-09-09 15:58:54 +020022import android.content.pm.PackageManager;
23import android.content.pm.ResolveInfo;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070024import android.content.res.Resources;
25import android.graphics.Bitmap;
26import android.graphics.BitmapFactory;
Michael Jurkab668d0b2013-10-04 15:11:05 -070027import android.graphics.BitmapRegionDecoder;
Dianne Hackborn284ac932009-08-28 10:34:25 -070028import android.graphics.Canvas;
Dianne Hackborn19382ac2009-09-11 21:13:37 -070029import android.graphics.ColorFilter;
Michael Jurkab668d0b2013-10-04 15:11:05 -070030import android.graphics.Matrix;
Dianne Hackborn284ac932009-08-28 10:34:25 -070031import android.graphics.Paint;
Dianne Hackborn19382ac2009-09-11 21:13:37 -070032import android.graphics.PixelFormat;
Jeff Brown24572372011-06-09 19:05:15 -070033import android.graphics.PorterDuff;
34import android.graphics.PorterDuffXfermode;
Dianne Hackborn284ac932009-08-28 10:34:25 -070035import android.graphics.Rect;
Michael Jurkab668d0b2013-10-04 15:11:05 -070036import android.graphics.RectF;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070037import android.graphics.drawable.BitmapDrawable;
38import android.graphics.drawable.Drawable;
Michael Jurkae8d1bf72013-09-09 15:58:54 +020039import android.net.Uri;
Dianne Hackborn284ac932009-08-28 10:34:25 -070040import android.os.Bundle;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070041import android.os.Handler;
42import android.os.IBinder;
Dianne Hackborn840c3a22009-09-02 17:35:17 -070043import android.os.Looper;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070044import android.os.ParcelFileDescriptor;
45import android.os.RemoteException;
46import android.os.ServiceManager;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070047import android.util.Log;
Jeff Brown98365d72012-08-19 20:30:52 -070048import android.view.WindowManagerGlobal;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070049
Michael Jurkab668d0b2013-10-04 15:11:05 -070050import java.io.BufferedInputStream;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070051import java.io.FileOutputStream;
52import java.io.IOException;
53import java.io.InputStream;
Michael Jurkae8d1bf72013-09-09 15:58:54 +020054import java.util.List;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070055
Scott Main8b2e0002009-09-29 18:17:31 -070056/**
57 * Provides access to the system wallpaper. With WallpaperManager, you can
58 * get the current wallpaper, get the desired dimensions for the wallpaper, set
59 * the wallpaper, and more. Get an instance of WallpaperManager with
60 * {@link #getInstance(android.content.Context) getInstance()}.
61 */
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070062public class WallpaperManager {
63 private static String TAG = "WallpaperManager";
64 private static boolean DEBUG = false;
Marco Nelissenbf6956b2009-11-09 15:21:13 -080065 private float mWallpaperXStep = -1;
66 private float mWallpaperYStep = -1;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -070067
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070068 /**
Michael Jurkae8d1bf72013-09-09 15:58:54 +020069 * Activity Action: Show settings for choosing wallpaper. Do not use directly to construct
70 * an intent; instead, use {@link #getCropAndSetWallpaperIntent}.
71 * <p>Input: {@link Intent#getData} is the URI of the image to crop and set as wallpaper.
72 * <p>Output: RESULT_OK if user decided to crop/set the wallpaper, RESULT_CANCEL otherwise
Adam Lesinskibba72d12013-10-11 18:10:56 -070073 * Activities that support this intent should specify a MIME filter of "image/*"
Michael Jurkae8d1bf72013-09-09 15:58:54 +020074 */
75 public static final String ACTION_CROP_AND_SET_WALLPAPER =
76 "android.service.wallpaper.CROP_AND_SET_WALLPAPER";
77
78 /**
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070079 * Launch an activity for the user to pick the current global live
80 * wallpaper.
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070081 */
82 public static final String ACTION_LIVE_WALLPAPER_CHOOSER
83 = "android.service.wallpaper.LIVE_WALLPAPER_CHOOSER";
Adam Cohen5a242ec2010-12-07 21:07:07 -080084
85 /**
Dianne Hackborn7df7d202012-04-19 18:00:04 -070086 * Directly launch live wallpaper preview, allowing the user to immediately
87 * confirm to switch to a specific live wallpaper. You must specify
88 * {@link #EXTRA_LIVE_WALLPAPER_COMPONENT} with the ComponentName of
89 * a live wallpaper component that is to be shown.
90 */
91 public static final String ACTION_CHANGE_LIVE_WALLPAPER
92 = "android.service.wallpaper.CHANGE_LIVE_WALLPAPER";
93
94 /**
95 * Extra in {@link #ACTION_CHANGE_LIVE_WALLPAPER} that specifies the
96 * ComponentName of a live wallpaper that should be shown as a preview,
97 * for the user to confirm.
98 */
99 public static final String EXTRA_LIVE_WALLPAPER_COMPONENT
100 = "android.service.wallpaper.extra.LIVE_WALLPAPER_COMPONENT";
101
102 /**
Adam Cohen5a242ec2010-12-07 21:07:07 -0800103 * Manifest entry for activities that respond to {@link Intent#ACTION_SET_WALLPAPER}
104 * which allows them to provide a custom large icon associated with this action.
105 */
106 public static final String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
107
Dianne Hackborn23ef7b42009-11-18 18:20:39 -0800108 /**
109 * Command for {@link #sendWallpaperCommand}: reported by the wallpaper
110 * host when the user taps on an empty area (not performing an action
111 * in the host). The x and y arguments are the location of the tap in
112 * screen coordinates.
113 */
114 public static final String COMMAND_TAP = "android.wallpaper.tap";
115
116 /**
117 * Command for {@link #sendWallpaperCommand}: reported by the wallpaper
Jeff Brown9f3bdfe2010-10-13 06:01:27 -0700118 * host when the user releases a secondary pointer on an empty area
119 * (not performing an action in the host). The x and y arguments are
120 * the location of the secondary tap in screen coordinates.
121 */
122 public static final String COMMAND_SECONDARY_TAP = "android.wallpaper.secondaryTap";
123
124 /**
125 * Command for {@link #sendWallpaperCommand}: reported by the wallpaper
Dianne Hackborn23ef7b42009-11-18 18:20:39 -0800126 * host when the user drops an object into an area of the host. The x
127 * and y arguments are the location of the drop.
128 */
129 public static final String COMMAND_DROP = "android.home.drop";
130
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700131 private final Context mContext;
132
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700133 /**
134 * Special drawable that draws a wallpaper as fast as possible. Assumes
135 * no scaling or placement off (0,0) of the wallpaper (this should be done
136 * at the time the bitmap is loaded).
137 */
138 static class FastBitmapDrawable extends Drawable {
139 private final Bitmap mBitmap;
140 private final int mWidth;
141 private final int mHeight;
142 private int mDrawLeft;
143 private int mDrawTop;
Romain Guy407ec782011-08-24 17:06:58 -0700144 private final Paint mPaint;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700145
146 private FastBitmapDrawable(Bitmap bitmap) {
147 mBitmap = bitmap;
148 mWidth = bitmap.getWidth();
149 mHeight = bitmap.getHeight();
Romain Guy407ec782011-08-24 17:06:58 -0700150
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700151 setBounds(0, 0, mWidth, mHeight);
Romain Guy407ec782011-08-24 17:06:58 -0700152
153 mPaint = new Paint();
154 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700155 }
156
157 @Override
158 public void draw(Canvas canvas) {
Romain Guy407ec782011-08-24 17:06:58 -0700159 canvas.drawBitmap(mBitmap, mDrawLeft, mDrawTop, mPaint);
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700160 }
161
162 @Override
163 public int getOpacity() {
164 return PixelFormat.OPAQUE;
165 }
166
167 @Override
168 public void setBounds(int left, int top, int right, int bottom) {
169 mDrawLeft = left + (right-left - mWidth) / 2;
170 mDrawTop = top + (bottom-top - mHeight) / 2;
171 }
172
173 @Override
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700174 public void setAlpha(int alpha) {
Romain Guy407ec782011-08-24 17:06:58 -0700175 throw new UnsupportedOperationException("Not supported with this drawable");
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700176 }
177
178 @Override
179 public void setColorFilter(ColorFilter cf) {
Romain Guy407ec782011-08-24 17:06:58 -0700180 throw new UnsupportedOperationException("Not supported with this drawable");
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700181 }
182
183 @Override
184 public void setDither(boolean dither) {
Romain Guy407ec782011-08-24 17:06:58 -0700185 throw new UnsupportedOperationException("Not supported with this drawable");
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700186 }
187
188 @Override
189 public void setFilterBitmap(boolean filter) {
Romain Guy407ec782011-08-24 17:06:58 -0700190 throw new UnsupportedOperationException("Not supported with this drawable");
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700191 }
192
193 @Override
194 public int getIntrinsicWidth() {
195 return mWidth;
196 }
197
198 @Override
199 public int getIntrinsicHeight() {
200 return mHeight;
201 }
202
203 @Override
204 public int getMinimumWidth() {
205 return mWidth;
206 }
207
208 @Override
209 public int getMinimumHeight() {
210 return mHeight;
211 }
212 }
213
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700214 static class Globals extends IWallpaperManagerCallback.Stub {
215 private IWallpaperManager mService;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700216 private Bitmap mWallpaper;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700217 private Bitmap mDefaultWallpaper;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700218
Dianne Hackborn840c3a22009-09-02 17:35:17 -0700219 private static final int MSG_CLEAR_WALLPAPER = 1;
220
Dianne Hackborn5e802fb2009-09-02 21:50:50 -0700221 Globals(Looper looper) {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700222 IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
223 mService = IWallpaperManager.Stub.asInterface(b);
224 }
225
226 public void onWallpaperChanged() {
227 /* The wallpaper has changed but we shouldn't eagerly load the
228 * wallpaper as that would be inefficient. Reset the cached wallpaper
229 * to null so if the user requests the wallpaper again then we'll
230 * fetch it.
231 */
Michael Wright6762a442013-10-15 14:43:32 -0700232 synchronized (this) {
233 mWallpaper = null;
234 mDefaultWallpaper = null;
235 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700236 }
Adam Cohen041a0ba2011-11-09 20:10:27 -0800237
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700238 public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault) {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700239 synchronized (this) {
240 if (mWallpaper != null) {
241 return mWallpaper;
242 }
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700243 if (mDefaultWallpaper != null) {
244 return mDefaultWallpaper;
245 }
Dianne Hackbornc9dbbe22009-11-11 22:50:37 -0800246 mWallpaper = null;
247 try {
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700248 mWallpaper = getCurrentWallpaperLocked(context);
Dianne Hackbornc9dbbe22009-11-11 22:50:37 -0800249 } catch (OutOfMemoryError e) {
250 Log.w(TAG, "No memory load current wallpaper", e);
251 }
Dianne Hackbornba398392011-08-01 16:11:57 -0700252 if (returnDefault) {
253 if (mWallpaper == null) {
254 mDefaultWallpaper = getDefaultWallpaperLocked(context);
255 return mDefaultWallpaper;
256 } else {
257 mDefaultWallpaper = null;
258 }
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700259 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700260 return mWallpaper;
261 }
262 }
Dianne Hackbornba398392011-08-01 16:11:57 -0700263
264 public void forgetLoadedWallpaper() {
265 synchronized (this) {
266 mWallpaper = null;
267 mDefaultWallpaper = null;
268 }
269 }
270
Dianne Hackborn908aecc2012-07-31 16:37:34 -0700271 private Bitmap getCurrentWallpaperLocked(Context context) {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700272 try {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700273 Bundle params = new Bundle();
274 ParcelFileDescriptor fd = mService.getWallpaper(this, params);
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700275 if (fd != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700276 int width = params.getInt("width", 0);
277 int height = params.getInt("height", 0);
Jeff Brown24572372011-06-09 19:05:15 -0700278
279 try {
280 BitmapFactory.Options options = new BitmapFactory.Options();
Michael Jurka824a4b52013-12-18 17:10:16 +0100281 return BitmapFactory.decodeFileDescriptor(
Jeff Brown24572372011-06-09 19:05:15 -0700282 fd.getFileDescriptor(), null, options);
Jeff Brown24572372011-06-09 19:05:15 -0700283 } catch (OutOfMemoryError e) {
284 Log.w(TAG, "Can't decode file", e);
285 } finally {
Dianne Hackborn284ac932009-08-28 10:34:25 -0700286 try {
287 fd.close();
288 } catch (IOException e) {
Romain Guy407ec782011-08-24 17:06:58 -0700289 // Ignore
Dianne Hackborn284ac932009-08-28 10:34:25 -0700290 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700291 }
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700292 }
293 } catch (RemoteException e) {
Romain Guy407ec782011-08-24 17:06:58 -0700294 // Ignore
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700295 }
296 return null;
297 }
298
299 private Bitmap getDefaultWallpaperLocked(Context context) {
300 try {
301 InputStream is = context.getResources().openRawResource(
302 com.android.internal.R.drawable.default_wallpaper);
303 if (is != null) {
304 int width = mService.getWidthHint();
305 int height = mService.getHeightHint();
Jeff Brown24572372011-06-09 19:05:15 -0700306
307 try {
308 BitmapFactory.Options options = new BitmapFactory.Options();
Michael Jurka824a4b52013-12-18 17:10:16 +0100309 return BitmapFactory.decodeStream(is, null, options);
Jeff Brown24572372011-06-09 19:05:15 -0700310 } catch (OutOfMemoryError e) {
311 Log.w(TAG, "Can't decode stream", e);
312 } finally {
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700313 try {
314 is.close();
315 } catch (IOException e) {
Romain Guy407ec782011-08-24 17:06:58 -0700316 // Ignore
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700317 }
Dianne Hackbornc9dbbe22009-11-11 22:50:37 -0800318 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700319 }
320 } catch (RemoteException e) {
Romain Guy407ec782011-08-24 17:06:58 -0700321 // Ignore
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700322 }
323 return null;
324 }
325 }
326
Romain Guy407ec782011-08-24 17:06:58 -0700327 private static final Object sSync = new Object[0];
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700328 private static Globals sGlobals;
329
Dianne Hackborn840c3a22009-09-02 17:35:17 -0700330 static void initGlobals(Looper looper) {
Romain Guy407ec782011-08-24 17:06:58 -0700331 synchronized (sSync) {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700332 if (sGlobals == null) {
Dianne Hackborn5e802fb2009-09-02 21:50:50 -0700333 sGlobals = new Globals(looper);
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700334 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700335 }
336 }
337
338 /*package*/ WallpaperManager(Context context, Handler handler) {
339 mContext = context;
Dianne Hackborn840c3a22009-09-02 17:35:17 -0700340 initGlobals(context.getMainLooper());
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700341 }
342
343 /**
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700344 * Retrieve a WallpaperManager associated with the given Context.
345 */
346 public static WallpaperManager getInstance(Context context) {
347 return (WallpaperManager)context.getSystemService(
348 Context.WALLPAPER_SERVICE);
349 }
350
351 /** @hide */
352 public IWallpaperManager getIWallpaperManager() {
Dianne Hackborn840c3a22009-09-02 17:35:17 -0700353 return sGlobals.mService;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700354 }
355
356 /**
Scott Main8b2e0002009-09-29 18:17:31 -0700357 * Retrieve the current system wallpaper; if
Michael Jurkab668d0b2013-10-04 15:11:05 -0700358 * no wallpaper is set, the system built-in static wallpaper is returned.
Scott Main8b2e0002009-09-29 18:17:31 -0700359 * This is returned as an
360 * abstract Drawable that you can install in a View to display whatever
361 * wallpaper the user has currently set.
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700362 *
363 * @return Returns a Drawable object that will draw the wallpaper.
364 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700365 public Drawable getDrawable() {
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700366 Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
367 if (bm != null) {
368 Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
369 dr.setDither(false);
370 return dr;
371 }
372 return null;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700373 }
374
375 /**
Michael Jurkab668d0b2013-10-04 15:11:05 -0700376 * Returns a drawable for the system built-in static wallpaper .
377 *
378 */
379 public Drawable getBuiltInDrawable() {
380 return getBuiltInDrawable(0, 0, false, 0, 0);
381 }
382
383 /**
384 * Returns a drawable for the system built-in static wallpaper. Based on the parameters, the
385 * drawable can be cropped and scaled
386 *
387 * @param outWidth The width of the returned drawable
388 * @param outWidth The height of the returned drawable
389 * @param scaleToFit If true, scale the wallpaper down rather than just cropping it
390 * @param horizontalAlignment A float value between 0 and 1 specifying where to crop the image;
391 * 0 for left-aligned, 0.5 for horizontal center-aligned, and 1 for right-aligned
392 * @param verticalAlignment A float value between 0 and 1 specifying where to crop the image;
393 * 0 for top-aligned, 0.5 for vertical center-aligned, and 1 for bottom-aligned
394 *
395 */
396 public Drawable getBuiltInDrawable(int outWidth, int outHeight,
397 boolean scaleToFit, float horizontalAlignment, float verticalAlignment) {
398 if (sGlobals.mService == null) {
399 Log.w(TAG, "WallpaperService not running");
400 return null;
401 }
402 Resources resources = mContext.getResources();
403 horizontalAlignment = Math.max(0, Math.min(1, horizontalAlignment));
404 verticalAlignment = Math.max(0, Math.min(1, verticalAlignment));
405
406 InputStream is = new BufferedInputStream(
407 resources.openRawResource(com.android.internal.R.drawable.default_wallpaper));
408
409 if (is == null) {
410 Log.e(TAG, "default wallpaper input stream is null");
411 return null;
412 } else {
413 if (outWidth <= 0 || outHeight <= 0) {
414 Bitmap fullSize = BitmapFactory.decodeStream(is, null, null);
415 return new BitmapDrawable(resources, fullSize);
416 } else {
417 int inWidth;
418 int inHeight;
419 {
420 BitmapFactory.Options options = new BitmapFactory.Options();
421 options.inJustDecodeBounds = true;
422 BitmapFactory.decodeStream(is, null, options);
423 if (options.outWidth != 0 && options.outHeight != 0) {
424 inWidth = options.outWidth;
425 inHeight = options.outHeight;
426 } else {
427 Log.e(TAG, "default wallpaper dimensions are 0");
428 return null;
429 }
430 }
431
432 is = new BufferedInputStream(resources.openRawResource(
433 com.android.internal.R.drawable.default_wallpaper));
434
435 RectF cropRectF;
436
437 outWidth = Math.min(inWidth, outWidth);
438 outHeight = Math.min(inHeight, outHeight);
439 if (scaleToFit) {
440 cropRectF = getMaxCropRect(inWidth, inHeight, outWidth, outHeight,
441 horizontalAlignment, verticalAlignment);
442 } else {
443 float left = (inWidth - outWidth) * horizontalAlignment;
444 float right = left + outWidth;
445 float top = (inHeight - outHeight) * verticalAlignment;
446 float bottom = top + outHeight;
Michael Jurka05391532013-10-14 20:44:42 -0700447 cropRectF = new RectF(left, top, right, bottom);
Michael Jurkab668d0b2013-10-04 15:11:05 -0700448 }
449 Rect roundedTrueCrop = new Rect();
450 cropRectF.roundOut(roundedTrueCrop);
451
452 if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) {
453 Log.w(TAG, "crop has bad values for full size image");
454 return null;
455 }
456
457 // See how much we're reducing the size of the image
458 int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / outWidth,
459 roundedTrueCrop.height() / outHeight);
460
461 // Attempt to open a region decoder
462 BitmapRegionDecoder decoder = null;
463 try {
464 decoder = BitmapRegionDecoder.newInstance(is, true);
465 } catch (IOException e) {
466 Log.w(TAG, "cannot open region decoder for default wallpaper");
467 }
468
469 Bitmap crop = null;
470 if (decoder != null) {
471 // Do region decoding to get crop bitmap
472 BitmapFactory.Options options = new BitmapFactory.Options();
473 if (scaleDownSampleSize > 1) {
474 options.inSampleSize = scaleDownSampleSize;
475 }
476 crop = decoder.decodeRegion(roundedTrueCrop, options);
477 decoder.recycle();
478 }
479
480 if (crop == null) {
481 // BitmapRegionDecoder has failed, try to crop in-memory
482 is = new BufferedInputStream(resources.openRawResource(
483 com.android.internal.R.drawable.default_wallpaper));
484 Bitmap fullSize = null;
485 if (is != null) {
486 BitmapFactory.Options options = new BitmapFactory.Options();
487 if (scaleDownSampleSize > 1) {
488 options.inSampleSize = scaleDownSampleSize;
489 }
490 fullSize = BitmapFactory.decodeStream(is, null, options);
491 }
492 if (fullSize != null) {
493 crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left,
494 roundedTrueCrop.top, roundedTrueCrop.width(),
495 roundedTrueCrop.height());
496 }
497 }
498
499 if (crop == null) {
500 Log.w(TAG, "cannot decode default wallpaper");
501 return null;
502 }
503
504 // Scale down if necessary
505 if (outWidth > 0 && outHeight > 0 &&
506 (crop.getWidth() != outWidth || crop.getHeight() != outHeight)) {
507 Matrix m = new Matrix();
508 RectF cropRect = new RectF(0, 0, crop.getWidth(), crop.getHeight());
509 RectF returnRect = new RectF(0, 0, outWidth, outHeight);
510 m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
511 Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(),
512 (int) returnRect.height(), Bitmap.Config.ARGB_8888);
513 if (tmp != null) {
514 Canvas c = new Canvas(tmp);
515 Paint p = new Paint();
516 p.setFilterBitmap(true);
517 c.drawBitmap(crop, m, p);
518 crop = tmp;
519 }
520 }
521
522 return new BitmapDrawable(resources, crop);
523 }
524 }
525 }
526
527 private static RectF getMaxCropRect(int inWidth, int inHeight, int outWidth, int outHeight,
528 float horizontalAlignment, float verticalAlignment) {
529 RectF cropRect = new RectF();
530 // Get a crop rect that will fit this
531 if (inWidth / (float) inHeight > outWidth / (float) outHeight) {
532 cropRect.top = 0;
533 cropRect.bottom = inHeight;
534 float cropWidth = outWidth * (inHeight / (float) outHeight);
535 cropRect.left = (inWidth - cropWidth) * horizontalAlignment;
536 cropRect.right = cropRect.left + cropWidth;
537 } else {
538 cropRect.left = 0;
539 cropRect.right = inWidth;
540 float cropHeight = outHeight * (inWidth / (float) outWidth);
541 cropRect.top = (inHeight - cropHeight) * verticalAlignment;
542 cropRect.bottom = cropRect.top + cropHeight;
543 }
544 return cropRect;
545 }
546
547 /**
Scott Main8b2e0002009-09-29 18:17:31 -0700548 * Retrieve the current system wallpaper; if there is no wallpaper set,
549 * a null pointer is returned. This is returned as an
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700550 * abstract Drawable that you can install in a View to display whatever
Scott Main8b2e0002009-09-29 18:17:31 -0700551 * wallpaper the user has currently set.
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700552 *
553 * @return Returns a Drawable object that will draw the wallpaper or a
554 * null pointer if these is none.
555 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700556 public Drawable peekDrawable() {
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700557 Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
558 if (bm != null) {
559 Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
560 dr.setDither(false);
561 return dr;
562 }
563 return null;
564 }
565
566 /**
Scott Main8b2e0002009-09-29 18:17:31 -0700567 * Like {@link #getDrawable()}, but the returned Drawable has a number
568 * of limitations to reduce its overhead as much as possible. It will
569 * never scale the wallpaper (only centering it if the requested bounds
570 * do match the bitmap bounds, which should not be typical), doesn't
571 * allow setting an alpha, color filter, or other attributes, etc. The
572 * bounds of the returned drawable will be initialized to the same bounds
573 * as the wallpaper, so normally you will not need to touch it. The
574 * drawable also assumes that it will be used in a context running in
575 * the same density as the screen (not in density compatibility mode).
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700576 *
577 * @return Returns a Drawable object that will draw the wallpaper.
578 */
579 public Drawable getFastDrawable() {
580 Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
581 if (bm != null) {
Romain Guy407ec782011-08-24 17:06:58 -0700582 return new FastBitmapDrawable(bm);
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700583 }
584 return null;
585 }
586
587 /**
Scott Main8b2e0002009-09-29 18:17:31 -0700588 * Like {@link #getFastDrawable()}, but if there is no wallpaper set,
589 * a null pointer is returned.
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700590 *
591 * @return Returns an optimized Drawable object that will draw the
592 * wallpaper or a null pointer if these is none.
593 */
594 public Drawable peekFastDrawable() {
595 Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
596 if (bm != null) {
Romain Guy407ec782011-08-24 17:06:58 -0700597 return new FastBitmapDrawable(bm);
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700598 }
599 return null;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700600 }
601
602 /**
Romain Guy407ec782011-08-24 17:06:58 -0700603 * Like {@link #getDrawable()} but returns a Bitmap.
604 *
605 * @hide
606 */
607 public Bitmap getBitmap() {
608 return sGlobals.peekWallpaperBitmap(mContext, true);
609 }
610
611 /**
Dianne Hackbornba398392011-08-01 16:11:57 -0700612 * Remove all internal references to the last loaded wallpaper. Useful
613 * for apps that want to reduce memory usage when they only temporarily
614 * need to have the wallpaper. After calling, the next request for the
615 * wallpaper will require reloading it again from disk.
616 */
617 public void forgetLoadedWallpaper() {
618 sGlobals.forgetLoadedWallpaper();
619 }
620
621 /**
Dianne Hackborneb034652009-09-07 00:49:58 -0700622 * If the current wallpaper is a live wallpaper component, return the
623 * information about that wallpaper. Otherwise, if it is a static image,
624 * simply return null.
Dianne Hackborneb034652009-09-07 00:49:58 -0700625 */
626 public WallpaperInfo getWallpaperInfo() {
627 try {
Mike Lockwoodc067c9c2011-10-31 12:50:12 -0400628 if (sGlobals.mService == null) {
629 Log.w(TAG, "WallpaperService not running");
630 return null;
631 } else {
632 return sGlobals.mService.getWallpaperInfo();
633 }
Dianne Hackborneb034652009-09-07 00:49:58 -0700634 } catch (RemoteException e) {
635 return null;
636 }
637 }
Michael Jurkae8d1bf72013-09-09 15:58:54 +0200638
639 /**
640 * Gets an Intent that will launch an activity that crops the given
641 * image and sets the device's wallpaper. If there is a default HOME activity
642 * that supports cropping wallpapers, it will be preferred as the default.
Ying Wang930d4e52013-09-14 11:57:17 -0700643 * Use this method instead of directly creating a {@link #ACTION_CROP_AND_SET_WALLPAPER}
Michael Jurkae8d1bf72013-09-09 15:58:54 +0200644 * intent.
Adam Lesinskibba72d12013-10-11 18:10:56 -0700645 *
646 * @param imageUri The image URI that will be set in the intent. The must be a content
647 * URI and its provider must resolve its type to "image/*"
648 *
649 * @throws IllegalArgumentException if the URI is not a content URI or its MIME type is
650 * not "image/*"
Michael Jurkae8d1bf72013-09-09 15:58:54 +0200651 */
652 public Intent getCropAndSetWallpaperIntent(Uri imageUri) {
Adam Lesinskibba72d12013-10-11 18:10:56 -0700653 if (!ContentResolver.SCHEME_CONTENT.equals(imageUri.getScheme())) {
654 throw new IllegalArgumentException("Image URI must be of the "
655 + ContentResolver.SCHEME_CONTENT + " scheme type");
656 }
657
Michael Jurkae8d1bf72013-09-09 15:58:54 +0200658 final PackageManager packageManager = mContext.getPackageManager();
659 Intent cropAndSetWallpaperIntent =
660 new Intent(ACTION_CROP_AND_SET_WALLPAPER, imageUri);
661 cropAndSetWallpaperIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
662
663 // Find out if the default HOME activity supports CROP_AND_SET_WALLPAPER
664 Intent homeIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME);
665 ResolveInfo resolvedHome = packageManager.resolveActivity(homeIntent,
666 PackageManager.MATCH_DEFAULT_ONLY);
667 if (resolvedHome != null) {
668 cropAndSetWallpaperIntent.setPackage(resolvedHome.activityInfo.packageName);
669
670 List<ResolveInfo> cropAppList = packageManager.queryIntentActivities(
671 cropAndSetWallpaperIntent, 0);
672 if (cropAppList.size() > 0) {
673 return cropAndSetWallpaperIntent;
674 }
675 }
676
677 // fallback crop activity
678 cropAndSetWallpaperIntent.setPackage("com.android.wallpapercropper");
Adam Lesinskibba72d12013-10-11 18:10:56 -0700679 List<ResolveInfo> cropAppList = packageManager.queryIntentActivities(
680 cropAndSetWallpaperIntent, 0);
681 if (cropAppList.size() > 0) {
682 return cropAndSetWallpaperIntent;
683 }
684 // If the URI is not of the right type, or for some reason the system wallpaper
685 // cropper doesn't exist, return null
686 throw new IllegalArgumentException("Cannot use passed URI to set wallpaper; " +
687 "check that the type returned by ContentProvider matches image/*");
Michael Jurkae8d1bf72013-09-09 15:58:54 +0200688 }
689
Dianne Hackborneb034652009-09-07 00:49:58 -0700690 /**
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700691 * Change the current system wallpaper to the bitmap in the given resource.
692 * The resource is opened as a raw data stream and copied into the
693 * wallpaper; it must be a valid PNG or JPEG image. On success, the intent
694 * {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast.
695 *
Nicolas Falliere9530e3a2012-06-18 17:21:06 -0700696 * <p>This method requires the caller to hold the permission
697 * {@link android.Manifest.permission#SET_WALLPAPER}.
698 *
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700699 * @param resid The bitmap to save.
700 *
Michael Jurkab668d0b2013-10-04 15:11:05 -0700701 * @throws IOException If an error occurs reverting to the built-in
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700702 * wallpaper.
703 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700704 public void setResource(int resid) throws IOException {
Mike Lockwoodc067c9c2011-10-31 12:50:12 -0400705 if (sGlobals.mService == null) {
706 Log.w(TAG, "WallpaperService not running");
707 return;
708 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700709 try {
710 Resources resources = mContext.getResources();
711 /* Set the wallpaper to the default values */
Dianne Hackborn840c3a22009-09-02 17:35:17 -0700712 ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700713 "res:" + resources.getResourceName(resid));
714 if (fd != null) {
715 FileOutputStream fos = null;
716 try {
717 fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
718 setWallpaper(resources.openRawResource(resid), fos);
719 } finally {
720 if (fos != null) {
721 fos.close();
722 }
723 }
724 }
725 } catch (RemoteException e) {
Romain Guy407ec782011-08-24 17:06:58 -0700726 // Ignore
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700727 }
728 }
729
730 /**
731 * Change the current system wallpaper to a bitmap. The given bitmap is
732 * converted to a PNG and stored as the wallpaper. On success, the intent
733 * {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast.
734 *
Nicolas Falliere9530e3a2012-06-18 17:21:06 -0700735 * <p>This method requires the caller to hold the permission
736 * {@link android.Manifest.permission#SET_WALLPAPER}.
737 *
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700738 * @param bitmap The bitmap to save.
739 *
Michael Jurkab668d0b2013-10-04 15:11:05 -0700740 * @throws IOException If an error occurs reverting to the built-in
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700741 * wallpaper.
742 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700743 public void setBitmap(Bitmap bitmap) throws IOException {
Mike Lockwoodc067c9c2011-10-31 12:50:12 -0400744 if (sGlobals.mService == null) {
745 Log.w(TAG, "WallpaperService not running");
746 return;
747 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700748 try {
Dianne Hackborn840c3a22009-09-02 17:35:17 -0700749 ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null);
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700750 if (fd == null) {
751 return;
752 }
753 FileOutputStream fos = null;
754 try {
755 fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
756 bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
757 } finally {
758 if (fos != null) {
759 fos.close();
760 }
761 }
762 } catch (RemoteException e) {
Romain Guy407ec782011-08-24 17:06:58 -0700763 // Ignore
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700764 }
765 }
766
767 /**
768 * Change the current system wallpaper to a specific byte stream. The
769 * give InputStream is copied into persistent storage and will now be
770 * used as the wallpaper. Currently it must be either a JPEG or PNG
771 * image. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
772 * is broadcast.
773 *
Nicolas Falliere9530e3a2012-06-18 17:21:06 -0700774 * <p>This method requires the caller to hold the permission
775 * {@link android.Manifest.permission#SET_WALLPAPER}.
776 *
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700777 * @param data A stream containing the raw data to install as a wallpaper.
778 *
Michael Jurkab668d0b2013-10-04 15:11:05 -0700779 * @throws IOException If an error occurs reverting to the built-in
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700780 * wallpaper.
781 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700782 public void setStream(InputStream data) throws IOException {
Mike Lockwoodc067c9c2011-10-31 12:50:12 -0400783 if (sGlobals.mService == null) {
784 Log.w(TAG, "WallpaperService not running");
785 return;
786 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700787 try {
Dianne Hackborn840c3a22009-09-02 17:35:17 -0700788 ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null);
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700789 if (fd == null) {
790 return;
791 }
792 FileOutputStream fos = null;
793 try {
794 fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
795 setWallpaper(data, fos);
796 } finally {
797 if (fos != null) {
798 fos.close();
799 }
800 }
801 } catch (RemoteException e) {
Romain Guy407ec782011-08-24 17:06:58 -0700802 // Ignore
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700803 }
804 }
805
806 private void setWallpaper(InputStream data, FileOutputStream fos)
807 throws IOException {
808 byte[] buffer = new byte[32768];
809 int amt;
810 while ((amt=data.read(buffer)) > 0) {
811 fos.write(buffer, 0, amt);
812 }
813 }
814
815 /**
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700816 * Return whether any users are currently set to use the wallpaper
817 * with the given resource ID. That is, their wallpaper has been
818 * set through {@link #setResource(int)} with the same resource id.
819 */
820 public boolean hasResourceWallpaper(int resid) {
821 if (sGlobals.mService == null) {
822 Log.w(TAG, "WallpaperService not running");
823 return false;
824 }
825 try {
826 Resources resources = mContext.getResources();
827 String name = "res:" + resources.getResourceName(resid);
828 return sGlobals.mService.hasNamedWallpaper(name);
829 } catch (RemoteException e) {
830 return false;
831 }
832 }
833
834 /**
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700835 * Returns the desired minimum width for the wallpaper. Callers of
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700836 * {@link #setBitmap(android.graphics.Bitmap)} or
837 * {@link #setStream(java.io.InputStream)} should check this value
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700838 * beforehand to make sure the supplied wallpaper respects the desired
839 * minimum width.
840 *
841 * If the returned value is <= 0, the caller should use the width of
842 * the default display instead.
843 *
844 * @return The desired minimum width for the wallpaper. This value should
845 * be honored by applications that set the wallpaper but it is not
846 * mandatory.
847 */
848 public int getDesiredMinimumWidth() {
Mike Lockwoodc067c9c2011-10-31 12:50:12 -0400849 if (sGlobals.mService == null) {
850 Log.w(TAG, "WallpaperService not running");
851 return 0;
852 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700853 try {
Dianne Hackborn840c3a22009-09-02 17:35:17 -0700854 return sGlobals.mService.getWidthHint();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700855 } catch (RemoteException e) {
856 // Shouldn't happen!
857 return 0;
858 }
859 }
860
861 /**
862 * Returns the desired minimum height for the wallpaper. Callers of
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700863 * {@link #setBitmap(android.graphics.Bitmap)} or
864 * {@link #setStream(java.io.InputStream)} should check this value
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700865 * beforehand to make sure the supplied wallpaper respects the desired
866 * minimum height.
867 *
868 * If the returned value is <= 0, the caller should use the height of
869 * the default display instead.
870 *
871 * @return The desired minimum height for the wallpaper. This value should
872 * be honored by applications that set the wallpaper but it is not
873 * mandatory.
874 */
875 public int getDesiredMinimumHeight() {
Mike Lockwoodc067c9c2011-10-31 12:50:12 -0400876 if (sGlobals.mService == null) {
877 Log.w(TAG, "WallpaperService not running");
878 return 0;
879 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700880 try {
Dianne Hackborn840c3a22009-09-02 17:35:17 -0700881 return sGlobals.mService.getHeightHint();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700882 } catch (RemoteException e) {
883 // Shouldn't happen!
884 return 0;
885 }
886 }
887
888 /**
889 * For use only by the current home application, to specify the size of
890 * wallpaper it would like to use. This allows such applications to have
891 * a virtual wallpaper that is larger than the physical screen, matching
892 * the size of their workspace.
Dianne Hackbornc5bf7582012-04-25 19:12:07 -0700893 *
894 * <p>Note developers, who don't seem to be reading this. This is
895 * for <em>home screens</em> to tell what size wallpaper they would like.
896 * Nobody else should be calling this! Certainly not other non-home-screen
897 * apps that change the wallpaper. Those apps are supposed to
898 * <b>retrieve</b> the suggested size so they can construct a wallpaper
899 * that matches it.
900 *
Nicolas Falliere9530e3a2012-06-18 17:21:06 -0700901 * <p>This method requires the caller to hold the permission
902 * {@link android.Manifest.permission#SET_WALLPAPER_HINTS}.
903 *
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700904 * @param minimumWidth Desired minimum width
905 * @param minimumHeight Desired minimum height
906 */
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700907 public void suggestDesiredDimensions(int minimumWidth, int minimumHeight) {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700908 try {
Mike Lockwoodc067c9c2011-10-31 12:50:12 -0400909 if (sGlobals.mService == null) {
910 Log.w(TAG, "WallpaperService not running");
911 } else {
912 sGlobals.mService.setDimensionHints(minimumWidth, minimumHeight);
913 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700914 } catch (RemoteException e) {
Romain Guy407ec782011-08-24 17:06:58 -0700915 // Ignore
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700916 }
917 }
Adam Cohen041a0ba2011-11-09 20:10:27 -0800918
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700919 /**
Dianne Hackbornc8a0a752009-08-10 23:05:49 -0700920 * Set the position of the current wallpaper within any larger space, when
921 * that wallpaper is visible behind the given window. The X and Y offsets
922 * are floating point numbers ranging from 0 to 1, representing where the
923 * wallpaper should be positioned within the screen space. These only
924 * make sense when the wallpaper is larger than the screen.
925 *
926 * @param windowToken The window who these offsets should be associated
Scott Main8b2e0002009-09-29 18:17:31 -0700927 * with, as returned by {@link android.view.View#getWindowToken()
Dianne Hackbornc8a0a752009-08-10 23:05:49 -0700928 * View.getWindowToken()}.
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800929 * @param xOffset The offset along the X dimension, from 0 to 1.
Dianne Hackbornc8a0a752009-08-10 23:05:49 -0700930 * @param yOffset The offset along the Y dimension, from 0 to 1.
931 */
932 public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
Adam Cohen791a6332012-01-12 14:38:38 -0800933 try {
934 //Log.v(TAG, "Sending new wallpaper offsets from app...");
Jeff Brownf9e989d2013-04-04 23:04:03 -0700935 WindowManagerGlobal.getWindowSession().setWallpaperPosition(
Adam Cohen791a6332012-01-12 14:38:38 -0800936 windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
937 //Log.v(TAG, "...app returning after sending offsets!");
938 } catch (RemoteException e) {
939 // Ignore.
940 }
Dianne Hackbornc8a0a752009-08-10 23:05:49 -0700941 }
Adam Cohen041a0ba2011-11-09 20:10:27 -0800942
Dianne Hackbornc8a0a752009-08-10 23:05:49 -0700943 /**
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800944 * For applications that use multiple virtual screens showing a wallpaper,
945 * specify the step size between virtual screens. For example, if the
Dianne Hackborn23ef7b42009-11-18 18:20:39 -0800946 * launcher has 3 virtual screens, it would specify an xStep of 0.5,
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800947 * since the X offset for those screens are 0.0, 0.5 and 1.0
948 * @param xStep The X offset delta from one screen to the next one
949 * @param yStep The Y offset delta from one screen to the next one
950 */
951 public void setWallpaperOffsetSteps(float xStep, float yStep) {
952 mWallpaperXStep = xStep;
953 mWallpaperYStep = yStep;
954 }
955
956 /**
Dianne Hackborn75804932009-10-20 20:15:20 -0700957 * Send an arbitrary command to the current active wallpaper.
958 *
959 * @param windowToken The window who these offsets should be associated
960 * with, as returned by {@link android.view.View#getWindowToken()
961 * View.getWindowToken()}.
962 * @param action Name of the command to perform. This must be a scoped
963 * name to avoid collisions, such as "com.mycompany.wallpaper.DOIT".
964 * @param x Arbitrary integer argument based on command.
965 * @param y Arbitrary integer argument based on command.
966 * @param z Arbitrary integer argument based on command.
967 * @param extras Optional additional information for the command, or null.
968 */
969 public void sendWallpaperCommand(IBinder windowToken, String action,
970 int x, int y, int z, Bundle extras) {
971 try {
972 //Log.v(TAG, "Sending new wallpaper offsets from app...");
Jeff Brownf9e989d2013-04-04 23:04:03 -0700973 WindowManagerGlobal.getWindowSession().sendWallpaperCommand(
Dianne Hackborn75804932009-10-20 20:15:20 -0700974 windowToken, action, x, y, z, extras, false);
975 //Log.v(TAG, "...app returning after sending offsets!");
976 } catch (RemoteException e) {
977 // Ignore.
978 }
979 }
980
981 /**
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700982 * Clear the offsets previously associated with this window through
983 * {@link #setWallpaperOffsets(IBinder, float, float)}. This reverts
984 * the window to its default state, where it does not cause the wallpaper
985 * to scroll from whatever its last offsets were.
986 *
987 * @param windowToken The window who these offsets should be associated
Scott Main8b2e0002009-09-29 18:17:31 -0700988 * with, as returned by {@link android.view.View#getWindowToken()
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700989 * View.getWindowToken()}.
990 */
991 public void clearWallpaperOffsets(IBinder windowToken) {
992 try {
Jeff Brownf9e989d2013-04-04 23:04:03 -0700993 WindowManagerGlobal.getWindowSession().setWallpaperPosition(
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800994 windowToken, -1, -1, -1, -1);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700995 } catch (RemoteException e) {
996 // Ignore.
997 }
998 }
999
1000 /**
Michael Jurkab668d0b2013-10-04 15:11:05 -07001001 * Remove any currently set wallpaper, reverting to the system's built-in
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001002 * wallpaper. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
1003 * is broadcast.
1004 *
Nicolas Falliere9530e3a2012-06-18 17:21:06 -07001005 * <p>This method requires the caller to hold the permission
1006 * {@link android.Manifest.permission#SET_WALLPAPER}.
1007 *
Michael Jurkab668d0b2013-10-04 15:11:05 -07001008 * @throws IOException If an error occurs reverting to the built-in
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001009 * wallpaper.
1010 */
1011 public void clear() throws IOException {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001012 setResource(com.android.internal.R.drawable.default_wallpaper);
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001013 }
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001014}