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