736 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			736 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2009 The Android Open Source Project
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  *      http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  */
 | |
| 
 | |
| package android.app;
 | |
| 
 | |
| import android.content.Context;
 | |
| import android.content.Intent;
 | |
| import android.content.res.Resources;
 | |
| import android.graphics.Bitmap;
 | |
| import android.graphics.BitmapFactory;
 | |
| import android.graphics.Canvas;
 | |
| import android.graphics.ColorFilter;
 | |
| import android.graphics.Paint;
 | |
| import android.graphics.PixelFormat;
 | |
| import android.graphics.Rect;
 | |
| import android.graphics.drawable.BitmapDrawable;
 | |
| import android.graphics.drawable.Drawable;
 | |
| import android.os.Bundle;
 | |
| import android.os.Handler;
 | |
| import android.os.IBinder;
 | |
| import android.os.Looper;
 | |
| import android.os.Message;
 | |
| import android.os.ParcelFileDescriptor;
 | |
| import android.os.RemoteException;
 | |
| import android.os.ServiceManager;
 | |
| import android.util.DisplayMetrics;
 | |
| import android.util.Log;
 | |
| import android.view.ViewRoot;
 | |
| 
 | |
| import java.io.FileOutputStream;
 | |
| import java.io.IOException;
 | |
| import java.io.InputStream;
 | |
| 
 | |
| /**
 | |
|  * Provides access to the system wallpaper. With WallpaperManager, you can
 | |
|  * get the current wallpaper, get the desired dimensions for the wallpaper, set
 | |
|  * the wallpaper, and more. Get an instance of WallpaperManager with
 | |
|  * {@link #getInstance(android.content.Context) getInstance()}. 
 | |
|  */
 | |
| public class WallpaperManager {
 | |
|     private static String TAG = "WallpaperManager";
 | |
|     private static boolean DEBUG = false;
 | |
|     private float mWallpaperXStep = -1;
 | |
|     private float mWallpaperYStep = -1;
 | |
| 
 | |
|     /**
 | |
|      * Launch an activity for the user to pick the current global live
 | |
|      * wallpaper.
 | |
|      */
 | |
|     public static final String ACTION_LIVE_WALLPAPER_CHOOSER
 | |
|             = "android.service.wallpaper.LIVE_WALLPAPER_CHOOSER";
 | |
|     
 | |
|     /**
 | |
|      * Command for {@link #sendWallpaperCommand}: reported by the wallpaper
 | |
|      * host when the user taps on an empty area (not performing an action
 | |
|      * in the host).  The x and y arguments are the location of the tap in
 | |
|      * screen coordinates.
 | |
|      */
 | |
|     public static final String COMMAND_TAP = "android.wallpaper.tap";
 | |
|     
 | |
|     /**
 | |
|      * Command for {@link #sendWallpaperCommand}: reported by the wallpaper
 | |
|      * host when the user drops an object into an area of the host.  The x
 | |
|      * and y arguments are the location of the drop.
 | |
|      */
 | |
|     public static final String COMMAND_DROP = "android.home.drop";
 | |
|     
 | |
|     private final Context mContext;
 | |
|     
 | |
|     /**
 | |
|      * Special drawable that draws a wallpaper as fast as possible.  Assumes
 | |
|      * no scaling or placement off (0,0) of the wallpaper (this should be done
 | |
|      * at the time the bitmap is loaded).
 | |
|      */
 | |
|     static class FastBitmapDrawable extends Drawable {
 | |
|         private final Bitmap mBitmap;
 | |
|         private final int mWidth;
 | |
|         private final int mHeight;
 | |
|         private int mDrawLeft;
 | |
|         private int mDrawTop;
 | |
| 
 | |
|         private FastBitmapDrawable(Bitmap bitmap) {
 | |
|             mBitmap = bitmap;
 | |
|             mWidth = bitmap.getWidth();
 | |
|             mHeight = bitmap.getHeight();
 | |
|             setBounds(0, 0, mWidth, mHeight);
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public void draw(Canvas canvas) {
 | |
|             canvas.drawBitmap(mBitmap, mDrawLeft, mDrawTop, null);
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public int getOpacity() {
 | |
|             return PixelFormat.OPAQUE;
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public void setBounds(int left, int top, int right, int bottom) {
 | |
|             mDrawLeft = left + (right-left - mWidth) / 2;
 | |
|             mDrawTop = top + (bottom-top - mHeight) / 2;
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public void setBounds(Rect bounds) {
 | |
|             // TODO Auto-generated method stub
 | |
|             super.setBounds(bounds);
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public void setAlpha(int alpha) {
 | |
|             throw new UnsupportedOperationException(
 | |
|                     "Not supported with this drawable");
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public void setColorFilter(ColorFilter cf) {
 | |
|             throw new UnsupportedOperationException(
 | |
|                     "Not supported with this drawable");
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public void setDither(boolean dither) {
 | |
|             throw new UnsupportedOperationException(
 | |
|                     "Not supported with this drawable");
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public void setFilterBitmap(boolean filter) {
 | |
|             throw new UnsupportedOperationException(
 | |
|                     "Not supported with this drawable");
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public int getIntrinsicWidth() {
 | |
|             return mWidth;
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public int getIntrinsicHeight() {
 | |
|             return mHeight;
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public int getMinimumWidth() {
 | |
|             return mWidth;
 | |
|         }
 | |
| 
 | |
|         @Override
 | |
|         public int getMinimumHeight() {
 | |
|             return mHeight;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     static class Globals extends IWallpaperManagerCallback.Stub {
 | |
|         private IWallpaperManager mService;
 | |
|         private Bitmap mWallpaper;
 | |
|         private Bitmap mDefaultWallpaper;
 | |
|         
 | |
|         private static final int MSG_CLEAR_WALLPAPER = 1;
 | |
|         
 | |
|         private final Handler mHandler;
 | |
|         
 | |
|         Globals(Looper looper) {
 | |
|             IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
 | |
|             mService = IWallpaperManager.Stub.asInterface(b);
 | |
|             mHandler = new Handler(looper) {
 | |
|                 @Override
 | |
|                 public void handleMessage(Message msg) {
 | |
|                     switch (msg.what) {
 | |
|                         case MSG_CLEAR_WALLPAPER:
 | |
|                             synchronized (this) {
 | |
|                                 mWallpaper = null;
 | |
|                                 mDefaultWallpaper = null;
 | |
|                             }
 | |
|                             break;
 | |
|                     }
 | |
|                 }
 | |
|             };
 | |
|         }
 | |
|         
 | |
|         public void onWallpaperChanged() {
 | |
|             /* The wallpaper has changed but we shouldn't eagerly load the
 | |
|              * wallpaper as that would be inefficient. Reset the cached wallpaper
 | |
|              * to null so if the user requests the wallpaper again then we'll
 | |
|              * fetch it.
 | |
|              */
 | |
|             mHandler.sendEmptyMessage(MSG_CLEAR_WALLPAPER);
 | |
|         }
 | |
|         
 | |
|         public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault) {
 | |
|             synchronized (this) {
 | |
|                 if (mWallpaper != null) {
 | |
|                     return mWallpaper;
 | |
|                 }
 | |
|                 if (mDefaultWallpaper != null) {
 | |
|                     return mDefaultWallpaper;
 | |
|                 }
 | |
|                 mWallpaper = null;
 | |
|                 try {
 | |
|                     mWallpaper = getCurrentWallpaperLocked(context);
 | |
|                 } catch (OutOfMemoryError e) {
 | |
|                     Log.w(TAG, "No memory load current wallpaper", e);
 | |
|                 }
 | |
|                 if (mWallpaper == null && returnDefault) {
 | |
|                     mDefaultWallpaper = getDefaultWallpaperLocked(context);
 | |
|                     return mDefaultWallpaper;
 | |
|                 }
 | |
|                 return mWallpaper;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         private Bitmap getCurrentWallpaperLocked(Context context) {
 | |
|             try {
 | |
|                 Bundle params = new Bundle();
 | |
|                 ParcelFileDescriptor fd = mService.getWallpaper(this, params);
 | |
|                 if (fd != null) {
 | |
|                     int width = params.getInt("width", 0);
 | |
|                     int height = params.getInt("height", 0);
 | |
|                     
 | |
|                     if (width <= 0 || height <= 0) {
 | |
|                         // Degenerate case: no size requested, just load
 | |
|                         // bitmap as-is.
 | |
|                         Bitmap bm = BitmapFactory.decodeFileDescriptor(
 | |
|                                 fd.getFileDescriptor(), null, null);
 | |
|                         try {
 | |
|                             fd.close();
 | |
|                         } catch (IOException e) {
 | |
|                         }
 | |
|                         if (bm != null) {
 | |
|                             bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
 | |
|                         }
 | |
|                         return bm;
 | |
|                     }
 | |
|                     
 | |
|                     // Load the bitmap with full color depth, to preserve
 | |
|                     // quality for later processing.
 | |
|                     BitmapFactory.Options options = new BitmapFactory.Options();
 | |
|                     options.inDither = false;
 | |
|                     options.inPreferredConfig = Bitmap.Config.ARGB_8888;
 | |
|                     Bitmap bm = BitmapFactory.decodeFileDescriptor(
 | |
|                             fd.getFileDescriptor(), null, options);
 | |
|                     try {
 | |
|                         fd.close();
 | |
|                     } catch (IOException e) {
 | |
|                     }
 | |
|                     
 | |
|                     return generateBitmap(context, bm, width, height);
 | |
|                 }
 | |
|             } catch (RemoteException e) {
 | |
|             }
 | |
|             return null;
 | |
|         }
 | |
|         
 | |
|         private Bitmap getDefaultWallpaperLocked(Context context) {
 | |
|             try {
 | |
|                 InputStream is = context.getResources().openRawResource(
 | |
|                         com.android.internal.R.drawable.default_wallpaper);
 | |
|                 if (is != null) {
 | |
|                     int width = mService.getWidthHint();
 | |
|                     int height = mService.getHeightHint();
 | |
|                     
 | |
|                     if (width <= 0 || height <= 0) {
 | |
|                         // Degenerate case: no size requested, just load
 | |
|                         // bitmap as-is.
 | |
|                         Bitmap bm = BitmapFactory.decodeStream(is, null, null);
 | |
|                         try {
 | |
|                             is.close();
 | |
|                         } catch (IOException e) {
 | |
|                         }
 | |
|                         if (bm != null) {
 | |
|                             bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
 | |
|                         }
 | |
|                         return bm;
 | |
|                     }
 | |
|                     
 | |
|                     // Load the bitmap with full color depth, to preserve
 | |
|                     // quality for later processing.
 | |
|                     BitmapFactory.Options options = new BitmapFactory.Options();
 | |
|                     options.inDither = false;
 | |
|                     options.inPreferredConfig = Bitmap.Config.ARGB_8888;
 | |
|                     Bitmap bm = BitmapFactory.decodeStream(is, null, options);
 | |
|                     try {
 | |
|                         is.close();
 | |
|                     } catch (IOException e) {
 | |
|                     }
 | |
|                     
 | |
|                     try {
 | |
|                         return generateBitmap(context, bm, width, height);
 | |
|                     } catch (OutOfMemoryError e) {
 | |
|                         Log.w(TAG, "Can't generate default bitmap", e);
 | |
|                         return bm;
 | |
|                     }
 | |
|                 }
 | |
|             } catch (RemoteException e) {
 | |
|             }
 | |
|             return null;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     private static Object mSync = new Object();
 | |
|     private static Globals sGlobals;
 | |
| 
 | |
|     static void initGlobals(Looper looper) {
 | |
|         synchronized (mSync) {
 | |
|             if (sGlobals == null) {
 | |
|                 sGlobals = new Globals(looper);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /*package*/ WallpaperManager(Context context, Handler handler) {
 | |
|         mContext = context;
 | |
|         initGlobals(context.getMainLooper());
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Retrieve a WallpaperManager associated with the given Context.
 | |
|      */
 | |
|     public static WallpaperManager getInstance(Context context) {
 | |
|         return (WallpaperManager)context.getSystemService(
 | |
|                 Context.WALLPAPER_SERVICE);
 | |
|     }
 | |
|     
 | |
|     /** @hide */
 | |
|     public IWallpaperManager getIWallpaperManager() {
 | |
|         return sGlobals.mService;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Retrieve the current system wallpaper; if
 | |
|      * no wallpaper is set, the system default wallpaper is returned.
 | |
|      * This is returned as an
 | |
|      * abstract Drawable that you can install in a View to display whatever
 | |
|      * wallpaper the user has currently set. 
 | |
|      *
 | |
|      * @return Returns a Drawable object that will draw the wallpaper.
 | |
|      */
 | |
|     public Drawable getDrawable() {
 | |
|         Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
 | |
|         if (bm != null) {
 | |
|             Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
 | |
|             dr.setDither(false);
 | |
|             return dr;
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Retrieve the current system wallpaper; if there is no wallpaper set,
 | |
|      * a null pointer is returned. This is returned as an
 | |
|      * abstract Drawable that you can install in a View to display whatever
 | |
|      * wallpaper the user has currently set.  
 | |
|      *
 | |
|      * @return Returns a Drawable object that will draw the wallpaper or a
 | |
|      * null pointer if these is none.
 | |
|      */
 | |
|     public Drawable peekDrawable() {
 | |
|         Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
 | |
|         if (bm != null) {
 | |
|             Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
 | |
|             dr.setDither(false);
 | |
|             return dr;
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Like {@link #getDrawable()}, but the returned Drawable has a number
 | |
|      * of limitations to reduce its overhead as much as possible. It will
 | |
|      * never scale the wallpaper (only centering it if the requested bounds
 | |
|      * do match the bitmap bounds, which should not be typical), doesn't
 | |
|      * allow setting an alpha, color filter, or other attributes, etc.  The
 | |
|      * bounds of the returned drawable will be initialized to the same bounds
 | |
|      * as the wallpaper, so normally you will not need to touch it.  The
 | |
|      * drawable also assumes that it will be used in a context running in
 | |
|      * the same density as the screen (not in density compatibility mode).
 | |
|      *
 | |
|      * @return Returns a Drawable object that will draw the wallpaper.
 | |
|      */
 | |
|     public Drawable getFastDrawable() {
 | |
|         Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
 | |
|         if (bm != null) {
 | |
|             Drawable dr = new FastBitmapDrawable(bm);
 | |
|             return dr;
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Like {@link #getFastDrawable()}, but if there is no wallpaper set,
 | |
|      * a null pointer is returned.
 | |
|      *
 | |
|      * @return Returns an optimized Drawable object that will draw the
 | |
|      * wallpaper or a null pointer if these is none.
 | |
|      */
 | |
|     public Drawable peekFastDrawable() {
 | |
|         Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
 | |
|         if (bm != null) {
 | |
|             Drawable dr = new FastBitmapDrawable(bm);
 | |
|             return dr;
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * If the current wallpaper is a live wallpaper component, return the
 | |
|      * information about that wallpaper.  Otherwise, if it is a static image,
 | |
|      * simply return null.
 | |
|      */
 | |
|     public WallpaperInfo getWallpaperInfo() {
 | |
|         try {
 | |
|             return sGlobals.mService.getWallpaperInfo();
 | |
|         } catch (RemoteException e) {
 | |
|             return null;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Change the current system wallpaper to the bitmap in the given resource.
 | |
|      * The resource is opened as a raw data stream and copied into the
 | |
|      * wallpaper; it must be a valid PNG or JPEG image.  On success, the intent
 | |
|      * {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast.
 | |
|      *
 | |
|      * @param resid The bitmap to save.
 | |
|      *
 | |
|      * @throws IOException If an error occurs reverting to the default
 | |
|      * wallpaper.
 | |
|      */
 | |
|     public void setResource(int resid) throws IOException {
 | |
|         try {
 | |
|             Resources resources = mContext.getResources();
 | |
|             /* Set the wallpaper to the default values */
 | |
|             ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(
 | |
|                     "res:" + resources.getResourceName(resid));
 | |
|             if (fd != null) {
 | |
|                 FileOutputStream fos = null;
 | |
|                 try {
 | |
|                     fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
 | |
|                     setWallpaper(resources.openRawResource(resid), fos);
 | |
|                 } finally {
 | |
|                     if (fos != null) {
 | |
|                         fos.close();
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         } catch (RemoteException e) {
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Change the current system wallpaper to a bitmap.  The given bitmap is
 | |
|      * converted to a PNG and stored as the wallpaper.  On success, the intent
 | |
|      * {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast.
 | |
|      *
 | |
|      * @param bitmap The bitmap to save.
 | |
|      *
 | |
|      * @throws IOException If an error occurs reverting to the default
 | |
|      * wallpaper.
 | |
|      */
 | |
|     public void setBitmap(Bitmap bitmap) throws IOException {
 | |
|         try {
 | |
|             ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null);
 | |
|             if (fd == null) {
 | |
|                 return;
 | |
|             }
 | |
|             FileOutputStream fos = null;
 | |
|             try {
 | |
|                 fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
 | |
|                 bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
 | |
|             } finally {
 | |
|                 if (fos != null) {
 | |
|                     fos.close();
 | |
|                 }
 | |
|             }
 | |
|         } catch (RemoteException e) {
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Change the current system wallpaper to a specific byte stream.  The
 | |
|      * give InputStream is copied into persistent storage and will now be
 | |
|      * used as the wallpaper.  Currently it must be either a JPEG or PNG
 | |
|      * image.  On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
 | |
|      * is broadcast.
 | |
|      *
 | |
|      * @param data A stream containing the raw data to install as a wallpaper.
 | |
|      *
 | |
|      * @throws IOException If an error occurs reverting to the default
 | |
|      * wallpaper.
 | |
|      */
 | |
|     public void setStream(InputStream data) throws IOException {
 | |
|         try {
 | |
|             ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null);
 | |
|             if (fd == null) {
 | |
|                 return;
 | |
|             }
 | |
|             FileOutputStream fos = null;
 | |
|             try {
 | |
|                 fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
 | |
|                 setWallpaper(data, fos);
 | |
|             } finally {
 | |
|                 if (fos != null) {
 | |
|                     fos.close();
 | |
|                 }
 | |
|             }
 | |
|         } catch (RemoteException e) {
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void setWallpaper(InputStream data, FileOutputStream fos)
 | |
|             throws IOException {
 | |
|         byte[] buffer = new byte[32768];
 | |
|         int amt;
 | |
|         while ((amt=data.read(buffer)) > 0) {
 | |
|             fos.write(buffer, 0, amt);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the desired minimum width for the wallpaper. Callers of
 | |
|      * {@link #setBitmap(android.graphics.Bitmap)} or
 | |
|      * {@link #setStream(java.io.InputStream)} should check this value
 | |
|      * beforehand to make sure the supplied wallpaper respects the desired
 | |
|      * minimum width.
 | |
|      *
 | |
|      * If the returned value is <= 0, the caller should use the width of
 | |
|      * the default display instead.
 | |
|      *
 | |
|      * @return The desired minimum width for the wallpaper. This value should
 | |
|      * be honored by applications that set the wallpaper but it is not
 | |
|      * mandatory.
 | |
|      */
 | |
|     public int getDesiredMinimumWidth() {
 | |
|         try {
 | |
|             return sGlobals.mService.getWidthHint();
 | |
|         } catch (RemoteException e) {
 | |
|             // Shouldn't happen!
 | |
|             return 0;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the desired minimum height for the wallpaper. Callers of
 | |
|      * {@link #setBitmap(android.graphics.Bitmap)} or
 | |
|      * {@link #setStream(java.io.InputStream)} should check this value
 | |
|      * beforehand to make sure the supplied wallpaper respects the desired
 | |
|      * minimum height.
 | |
|      *
 | |
|      * If the returned value is <= 0, the caller should use the height of
 | |
|      * the default display instead.
 | |
|      *
 | |
|      * @return The desired minimum height for the wallpaper. This value should
 | |
|      * be honored by applications that set the wallpaper but it is not
 | |
|      * mandatory.
 | |
|      */
 | |
|     public int getDesiredMinimumHeight() {
 | |
|         try {
 | |
|             return sGlobals.mService.getHeightHint();
 | |
|         } catch (RemoteException e) {
 | |
|             // Shouldn't happen!
 | |
|             return 0;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * For use only by the current home application, to specify the size of
 | |
|      * wallpaper it would like to use.  This allows such applications to have
 | |
|      * a virtual wallpaper that is larger than the physical screen, matching
 | |
|      * the size of their workspace.
 | |
|      * @param minimumWidth Desired minimum width
 | |
|      * @param minimumHeight Desired minimum height
 | |
|      */
 | |
|     public void suggestDesiredDimensions(int minimumWidth, int minimumHeight) {
 | |
|         try {
 | |
|             sGlobals.mService.setDimensionHints(minimumWidth, minimumHeight);
 | |
|         } catch (RemoteException e) {
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Set the position of the current wallpaper within any larger space, when
 | |
|      * that wallpaper is visible behind the given window.  The X and Y offsets
 | |
|      * are floating point numbers ranging from 0 to 1, representing where the
 | |
|      * wallpaper should be positioned within the screen space.  These only
 | |
|      * make sense when the wallpaper is larger than the screen.
 | |
|      * 
 | |
|      * @param windowToken The window who these offsets should be associated
 | |
|      * with, as returned by {@link android.view.View#getWindowToken()
 | |
|      * View.getWindowToken()}.
 | |
|      * @param xOffset The offset along the X dimension, from 0 to 1.
 | |
|      * @param yOffset The offset along the Y dimension, from 0 to 1.
 | |
|      */
 | |
|     public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
 | |
|         try {
 | |
|             //Log.v(TAG, "Sending new wallpaper offsets from app...");
 | |
|             ViewRoot.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
 | |
|                     windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
 | |
|             //Log.v(TAG, "...app returning after sending offsets!");
 | |
|         } catch (RemoteException e) {
 | |
|             // Ignore.
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * For applications that use multiple virtual screens showing a wallpaper,
 | |
|      * specify the step size between virtual screens. For example, if the
 | |
|      * launcher has 3 virtual screens, it would specify an xStep of 0.5,
 | |
|      * since the X offset for those screens are 0.0, 0.5 and 1.0
 | |
|      * @param xStep The X offset delta from one screen to the next one 
 | |
|      * @param yStep The Y offset delta from one screen to the next one
 | |
|      */
 | |
|     public void setWallpaperOffsetSteps(float xStep, float yStep) {
 | |
|         mWallpaperXStep = xStep;
 | |
|         mWallpaperYStep = yStep;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Send an arbitrary command to the current active wallpaper.
 | |
|      * 
 | |
|      * @param windowToken The window who these offsets should be associated
 | |
|      * with, as returned by {@link android.view.View#getWindowToken()
 | |
|      * View.getWindowToken()}.
 | |
|      * @param action Name of the command to perform.  This must be a scoped
 | |
|      * name to avoid collisions, such as "com.mycompany.wallpaper.DOIT".
 | |
|      * @param x Arbitrary integer argument based on command.
 | |
|      * @param y Arbitrary integer argument based on command.
 | |
|      * @param z Arbitrary integer argument based on command.
 | |
|      * @param extras Optional additional information for the command, or null.
 | |
|      */
 | |
|     public void sendWallpaperCommand(IBinder windowToken, String action,
 | |
|             int x, int y, int z, Bundle extras) {
 | |
|         try {
 | |
|             //Log.v(TAG, "Sending new wallpaper offsets from app...");
 | |
|             ViewRoot.getWindowSession(mContext.getMainLooper()).sendWallpaperCommand(
 | |
|                     windowToken, action, x, y, z, extras, false);
 | |
|             //Log.v(TAG, "...app returning after sending offsets!");
 | |
|         } catch (RemoteException e) {
 | |
|             // Ignore.
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Clear the offsets previously associated with this window through
 | |
|      * {@link #setWallpaperOffsets(IBinder, float, float)}.  This reverts
 | |
|      * the window to its default state, where it does not cause the wallpaper
 | |
|      * to scroll from whatever its last offsets were.
 | |
|      * 
 | |
|      * @param windowToken The window who these offsets should be associated
 | |
|      * with, as returned by {@link android.view.View#getWindowToken()
 | |
|      * View.getWindowToken()}.
 | |
|      */
 | |
|     public void clearWallpaperOffsets(IBinder windowToken) {
 | |
|         try {
 | |
|             ViewRoot.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
 | |
|                     windowToken, -1, -1, -1, -1);
 | |
|         } catch (RemoteException e) {
 | |
|             // Ignore.
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Remove any currently set wallpaper, reverting to the system's default
 | |
|      * wallpaper. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
 | |
|      * is broadcast.
 | |
|      *
 | |
|      * @throws IOException If an error occurs reverting to the default
 | |
|      * wallpaper.
 | |
|      */
 | |
|     public void clear() throws IOException {
 | |
|         setResource(com.android.internal.R.drawable.default_wallpaper);
 | |
|     }
 | |
|     
 | |
|     static Bitmap generateBitmap(Context context, Bitmap bm, int width, int height) {
 | |
|         if (bm == null) {
 | |
|             return bm;
 | |
|         }
 | |
|         bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
 | |
|         
 | |
|         // This is the final bitmap we want to return.
 | |
|         // XXX We should get the pixel depth from the system (to match the
 | |
|         // physical display depth), when there is a way.
 | |
|         Bitmap newbm = Bitmap.createBitmap(width, height,
 | |
|                 Bitmap.Config.RGB_565);
 | |
|         newbm.setDensity(DisplayMetrics.DENSITY_DEVICE);
 | |
|         Canvas c = new Canvas(newbm);
 | |
|         c.setDensity(DisplayMetrics.DENSITY_DEVICE);
 | |
|         Rect targetRect = new Rect();
 | |
|         targetRect.left = targetRect.top = 0;
 | |
|         targetRect.right = bm.getWidth();
 | |
|         targetRect.bottom = bm.getHeight();
 | |
| 
 | |
|         int deltaw = 0;
 | |
|         int deltah = 0;
 | |
| 
 | |
|         if(targetRect.right > 0 && targetRect.bottom > 0) {
 | |
|             // We need to scale up so it covers the entire
 | |
|             // area.
 | |
|             float xScale = width / (float)targetRect.right;
 | |
|             float yScale = height / (float)targetRect.bottom;
 | |
|             if(xScale > yScale) {
 | |
|                 targetRect.right = (int)((float)targetRect.right * xScale);
 | |
|                 targetRect.bottom = (int)((float)targetRect.bottom * xScale);
 | |
|             } else {
 | |
|                 targetRect.right = (int)((float)targetRect.right * yScale);
 | |
|                 targetRect.bottom = (int)((float)targetRect.bottom * yScale);
 | |
|             }
 | |
|             deltaw = width - targetRect.right;
 | |
|             deltah = height - targetRect.bottom;
 | |
|         }
 | |
| 
 | |
|         targetRect.offset(deltaw/2, deltah/2);
 | |
|         Paint paint = new Paint();
 | |
|         paint.setFilterBitmap(true);
 | |
|         paint.setDither(true);
 | |
|         c.drawBitmap(bm, null, targetRect, paint);
 | |
|         
 | |
|         bm.recycle();
 | |
|         return newbm;
 | |
|     }
 | |
| }
 | 
