Home | History | Annotate | Download | only in wallpaper
      1 /*
      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 
     17 package com.android.internal.service.wallpaper;
     18 
     19 import com.android.internal.view.WindowManagerPolicyThread;
     20 
     21 import android.app.WallpaperManager;
     22 import android.graphics.Canvas;
     23 import android.graphics.Rect;
     24 import android.graphics.Region.Op;
     25 import android.graphics.drawable.Drawable;
     26 import android.os.HandlerThread;
     27 import android.os.Looper;
     28 import android.os.Process;
     29 import android.service.wallpaper.WallpaperService;
     30 import android.util.Log;
     31 import android.view.MotionEvent;
     32 import android.view.SurfaceHolder;
     33 import android.content.Context;
     34 import android.content.IntentFilter;
     35 import android.content.Intent;
     36 import android.content.BroadcastReceiver;
     37 
     38 /**
     39  * Default built-in wallpaper that simply shows a static image.
     40  */
     41 public class ImageWallpaper extends WallpaperService {
     42     WallpaperManager mWallpaperManager;
     43     private HandlerThread mThread;
     44 
     45     @Override
     46     public void onCreate() {
     47         super.onCreate();
     48         mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
     49         Looper looper = WindowManagerPolicyThread.getLooper();
     50         if (looper != null) {
     51             setCallbackLooper(looper);
     52         } else {
     53             mThread = new HandlerThread("Wallpaper", Process.THREAD_PRIORITY_FOREGROUND);
     54             mThread.start();
     55             setCallbackLooper(mThread.getLooper());
     56         }
     57     }
     58 
     59     public Engine onCreateEngine() {
     60         return new DrawableEngine();
     61     }
     62 
     63     @Override
     64     public void onDestroy() {
     65         super.onDestroy();
     66         if (mThread != null) {
     67             mThread.quit();
     68         }
     69     }
     70 
     71     class DrawableEngine extends Engine {
     72         private final Object mLock = new Object();
     73         private WallpaperObserver mReceiver;
     74         Drawable mBackground;
     75         float mXOffset;
     76         float mYOffset;
     77 
     78         class WallpaperObserver extends BroadcastReceiver {
     79             public void onReceive(Context context, Intent intent) {
     80                 updateWallpaper();
     81                 drawFrame();
     82                 // Assume we are the only one using the wallpaper in this
     83                 // process, and force a GC now to release the old wallpaper.
     84                 System.gc();
     85             }
     86         }
     87 
     88         @Override
     89         public void onCreate(SurfaceHolder surfaceHolder) {
     90             super.onCreate(surfaceHolder);
     91             IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
     92             mReceiver = new WallpaperObserver();
     93             registerReceiver(mReceiver, filter);
     94             updateWallpaper();
     95             surfaceHolder.setSizeFromLayout();
     96         }
     97 
     98         @Override
     99         public void onDestroy() {
    100             super.onDestroy();
    101             unregisterReceiver(mReceiver);
    102         }
    103 
    104         @Override
    105         public void onVisibilityChanged(boolean visible) {
    106             drawFrame();
    107         }
    108 
    109         @Override
    110         public void onTouchEvent(MotionEvent event) {
    111             super.onTouchEvent(event);
    112         }
    113 
    114         @Override
    115         public void onOffsetsChanged(float xOffset, float yOffset,
    116                 float xOffsetStep, float yOffsetStep,
    117                 int xPixels, int yPixels) {
    118             mXOffset = xOffset;
    119             mYOffset = yOffset;
    120             drawFrame();
    121         }
    122 
    123         @Override
    124         public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    125             super.onSurfaceChanged(holder, format, width, height);
    126             drawFrame();
    127         }
    128 
    129         @Override
    130         public void onSurfaceCreated(SurfaceHolder holder) {
    131             super.onSurfaceCreated(holder);
    132         }
    133 
    134         @Override
    135         public void onSurfaceDestroyed(SurfaceHolder holder) {
    136             super.onSurfaceDestroyed(holder);
    137         }
    138 
    139         void drawFrame() {
    140             SurfaceHolder sh = getSurfaceHolder();
    141             Canvas c = sh.lockCanvas();
    142             if (c != null) {
    143                 final Rect frame = sh.getSurfaceFrame();
    144                 synchronized (mLock) {
    145                     final Drawable background = mBackground;
    146                     final int dw = frame.width();
    147                     final int dh = frame.height();
    148                     final int bw = background != null ? background.getIntrinsicWidth() : 0;
    149                     final int bh = background != null ? background.getIntrinsicHeight() : 0;
    150                     final int availw = dw-bw;
    151                     final int availh = dh-bh;
    152                     int xPixels = availw < 0 ? (int)(availw*mXOffset+.5f) : (availw/2);
    153                     int yPixels = availh < 0 ? (int)(availh*mYOffset+.5f) : (availh/2);
    154 
    155                     c.translate(xPixels, yPixels);
    156                     if (availw<0 || availh<0) {
    157                         c.save(Canvas.CLIP_SAVE_FLAG);
    158                         c.clipRect(0, 0, bw, bh, Op.DIFFERENCE);
    159                         c.drawColor(0xff000000);
    160                         c.restore();
    161                     }
    162                     if (background != null) {
    163                         background.draw(c);
    164                     }
    165                 }
    166                 sh.unlockCanvasAndPost(c);
    167             }
    168         }
    169 
    170         void updateWallpaper() {
    171             synchronized (mLock) {
    172                 try {
    173                     mBackground = mWallpaperManager.getFastDrawable();
    174                 } catch (RuntimeException e) {
    175                     Log.w("ImageWallpaper", "Unable to load wallpaper!", e);
    176                 }
    177             }
    178         }
    179     }
    180 }
    181