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 174c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornpackage com.android.internal.service.wallpaper; 184c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn 19ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackbornimport com.android.internal.view.WindowManagerPolicyThread; 20ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackborn 214c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.app.WallpaperManager; 224c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.graphics.Canvas; 23759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackbornimport android.graphics.Rect; 24e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopianimport android.graphics.Region.Op; 254c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.graphics.drawable.Drawable; 2619382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackbornimport android.os.HandlerThread; 27ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackbornimport android.os.Looper; 2819382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackbornimport android.os.Process; 294c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.service.wallpaper.WallpaperService; 30c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackbornimport android.util.Log; 318df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackbornimport android.view.MotionEvent; 324c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.view.SurfaceHolder; 33ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guyimport android.content.Context; 34ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guyimport android.content.IntentFilter; 35ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guyimport android.content.Intent; 36ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guyimport android.content.BroadcastReceiver; 374c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn 384c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn/** 394c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn * Default built-in wallpaper that simply shows a static image. 404c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn */ 414c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornpublic class ImageWallpaper extends WallpaperService { 42ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy WallpaperManager mWallpaperManager; 4319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn private HandlerThread mThread; 44ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy 45ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy @Override 46ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy public void onCreate() { 47ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy super.onCreate(); 48ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE); 49ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackborn Looper looper = WindowManagerPolicyThread.getLooper(); 50ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackborn if (looper != null) { 51ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackborn setCallbackLooper(looper); 52ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackborn } else { 53ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackborn mThread = new HandlerThread("Wallpaper", Process.THREAD_PRIORITY_FOREGROUND); 54ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackborn mThread.start(); 55ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackborn setCallbackLooper(mThread.getLooper()); 56ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackborn } 57ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy } 58ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy 59ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy public Engine onCreateEngine() { 60284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn return new DrawableEngine(); 61ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy } 62ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy 6319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn @Override 6419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn public void onDestroy() { 6519382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn super.onDestroy(); 66ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackborn if (mThread != null) { 67ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackborn mThread.quit(); 68ac3587d7ced544091264a35249dbd3f9531a3cabDianne Hackborn } 6919382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn } 7019382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn 71ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy class DrawableEngine extends Engine { 72ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy private final Object mLock = new Object(); 73284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn private WallpaperObserver mReceiver; 744c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn Drawable mBackground; 757341d7a104b47996445d069a695e155a07184606Dianne Hackborn float mXOffset; 767341d7a104b47996445d069a695e155a07184606Dianne Hackborn float mYOffset; 77759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn 78284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn class WallpaperObserver extends BroadcastReceiver { 79284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn public void onReceive(Context context, Intent intent) { 80284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn updateWallpaper(); 81284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn drawFrame(); 8219382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn // Assume we are the only one using the wallpaper in this 8319382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn // process, and force a GC now to release the old wallpaper. 8419382ac1a4e4e7c23a1346d299368763f149de9cDianne Hackborn System.gc(); 85284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn } 86284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn } 87284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn 884c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn @Override 89759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn public void onCreate(SurfaceHolder surfaceHolder) { 90759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn super.onCreate(surfaceHolder); 91284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); 92284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn mReceiver = new WallpaperObserver(); 93284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn registerReceiver(mReceiver, filter); 940cd48879dca53a9f4d449126d406527bc4b94bafDianne Hackborn updateWallpaper(); 9572c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn surfaceHolder.setSizeFromLayout(); 964c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn } 974c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn 984c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn @Override 99284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn public void onDestroy() { 100284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn super.onDestroy(); 101284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn unregisterReceiver(mReceiver); 102284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn } 103284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn 104284ac93aa30642fda87d5c40263a1263677c21cdDianne Hackborn @Override 105759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn public void onVisibilityChanged(boolean visible) { 106ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy drawFrame(); 107759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn } 108759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn 109759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn @Override 1108df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn public void onTouchEvent(MotionEvent event) { 1118df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn super.onTouchEvent(event); 1128df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn } 1138df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn 1148df8b2b405c60cacf7a66c4e2ca078dd3d7ec7bdDianne Hackborn @Override 11572c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn public void onOffsetsChanged(float xOffset, float yOffset, 116bf6956b1d95442e9d9c483894d578fe6b7044cbbMarco Nelissen float xOffsetStep, float yOffsetStep, 11772c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn int xPixels, int yPixels) { 1187341d7a104b47996445d069a695e155a07184606Dianne Hackborn mXOffset = xOffset; 11907ef599b9f35572a3a75b884febe500a6c390e7eRomain Guy mYOffset = yOffset; 12072c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn drawFrame(); 12172c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn } 12272c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn 12372c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn @Override 1244c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { 1254c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn super.onSurfaceChanged(holder, format, width, height); 126ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy drawFrame(); 1274c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn } 1284c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn 1294c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn @Override 1304c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn public void onSurfaceCreated(SurfaceHolder holder) { 1314c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn super.onSurfaceCreated(holder); 1324c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn } 1334c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn 1344c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn @Override 1354c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn public void onSurfaceDestroyed(SurfaceHolder holder) { 1364c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn super.onSurfaceDestroyed(holder); 1374c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn } 1384c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn 139ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy void drawFrame() { 140759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn SurfaceHolder sh = getSurfaceHolder(); 14172c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn Canvas c = sh.lockCanvas(); 14272c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn if (c != null) { 1437341d7a104b47996445d069a695e155a07184606Dianne Hackborn final Rect frame = sh.getSurfaceFrame(); 14472c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn synchronized (mLock) { 14572c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn final Drawable background = mBackground; 1467341d7a104b47996445d069a695e155a07184606Dianne Hackborn final int dw = frame.width(); 1477341d7a104b47996445d069a695e155a07184606Dianne Hackborn final int dh = frame.height(); 148c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn final int bw = background != null ? background.getIntrinsicWidth() : 0; 149c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn final int bh = background != null ? background.getIntrinsicHeight() : 0; 150e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopian final int availw = dw-bw; 151e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopian final int availh = dh-bh; 152e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopian int xPixels = availw < 0 ? (int)(availw*mXOffset+.5f) : (availw/2); 153e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopian int yPixels = availh < 0 ? (int)(availh*mYOffset+.5f) : (availh/2); 154e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopian 1557341d7a104b47996445d069a695e155a07184606Dianne Hackborn c.translate(xPixels, yPixels); 156e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopian if (availw<0 || availh<0) { 157e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopian c.save(Canvas.CLIP_SAVE_FLAG); 158e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopian c.clipRect(0, 0, bw, bh, Op.DIFFERENCE); 159e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopian c.drawColor(0xff000000); 160e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopian c.restore(); 161e2d034c9014919a45ddd717d4e564e73771b2fefMathias Agopian } 162c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn if (background != null) { 163c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn background.draw(c); 164c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn } 165759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn } 16672c82ab9923025a91bbabb32e56bfea27bfd083bDianne Hackborn sh.unlockCanvasAndPost(c); 167759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn } 168759a39e8d2a8b27ef07e102394629dce68aa186bDianne Hackborn } 169ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy 170ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy void updateWallpaper() { 171ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy synchronized (mLock) { 172c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn try { 173c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn mBackground = mWallpaperManager.getFastDrawable(); 174c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn } catch (RuntimeException e) { 175c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn Log.w("ImageWallpaper", "Unable to load wallpaper!", e); 176c9dbbe28f7879bd377114587ed1f40235a2d37caDianne Hackborn } 177ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy } 178ef654bdd5bd957574abd4194d7b0585f3fc3fd34Romain Guy } 1794c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn } 1804c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn} 181