OSDN Git Service

Avoid unnecessarily redrawing the wallpaper.
authorJeff Brown <jeffbrown@google.com>
Sun, 23 Jan 2011 21:14:23 +0000 (13:14 -0800)
committerJeff Brown <jeffbrown@google.com>
Sun, 23 Jan 2011 21:14:23 +0000 (13:14 -0800)
Added some logic to ImageWallpaper to avoid redrawing the wallpaper
when it is not necessary.  Even with the resize fixes, we were still
redrawing the wallpaper an extra 5 times due to visibility and
offset changes which had no real effect.

Change-Id: Ifa39b7bb8c0f7a6a41bc81e00cc2159440f529c5

core/java/com/android/internal/service/wallpaper/ImageWallpaper.java

index d2e53b3..d49902e 100644 (file)
@@ -41,6 +41,9 @@ import android.content.BroadcastReceiver;
  * Default built-in wallpaper that simply shows a static image.
  */
 public class ImageWallpaper extends WallpaperService {
+    private static final String TAG = "ImageWallpaper";
+    private static final boolean DEBUG = false;
+
     WallpaperManager mWallpaperManager;
     private HandlerThread mThread;
 
@@ -77,10 +80,19 @@ public class ImageWallpaper extends WallpaperService {
         float mXOffset;
         float mYOffset;
 
+        boolean mVisible = true;
+        boolean mRedrawNeeded;
+        boolean mOffsetsChanged;
+        int mLastXTranslation;
+        int mLastYTranslation;
+
         class WallpaperObserver extends BroadcastReceiver {
             public void onReceive(Context context, Intent intent) {
-                updateWallpaper();
-                drawFrame();
+                synchronized (mLock) {
+                    updateWallpaperLocked();
+                    drawFrameLocked(true, false);
+                }
+
                 // Assume we are the only one using the wallpaper in this
                 // process, and force a GC now to release the old wallpaper.
                 System.gc();
@@ -93,7 +105,10 @@ public class ImageWallpaper extends WallpaperService {
             IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
             mReceiver = new WallpaperObserver();
             registerReceiver(mReceiver, filter);
-            updateWallpaper();
+
+            synchronized (mLock) {
+                updateWallpaperLocked();
+            }
             surfaceHolder.setSizeFromLayout();
         }
 
@@ -105,9 +120,12 @@ public class ImageWallpaper extends WallpaperService {
 
         @Override
         public void onVisibilityChanged(boolean visible) {
-            drawFrame();
+            synchronized (mLock) {
+                mVisible = visible;
+                drawFrameLocked(false, false);
+            }
         }
-        
+
         @Override
         public void onTouchEvent(MotionEvent event) {
             super.onTouchEvent(event);
@@ -117,15 +135,27 @@ public class ImageWallpaper extends WallpaperService {
         public void onOffsetsChanged(float xOffset, float yOffset,
                 float xOffsetStep, float yOffsetStep,
                 int xPixels, int yPixels) {
-            mXOffset = xOffset;
-            mYOffset = yOffset;
-            drawFrame();
+            synchronized (mLock) {
+                if (mXOffset != xOffset || mYOffset != yOffset) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Offsets changed to (" + xOffset + "," + yOffset + ").");
+                    }
+                    mXOffset = xOffset;
+                    mYOffset = yOffset;
+                    drawFrameLocked(false, true);
+                } else {
+                    drawFrameLocked(false, false);
+                }
+            }
         }
 
         @Override
         public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
             super.onSurfaceChanged(holder, format, width, height);
-            drawFrame();
+            
+            synchronized (mLock) {
+                drawFrameLocked(true, false);
+            }
         }
 
         @Override
@@ -137,13 +167,30 @@ public class ImageWallpaper extends WallpaperService {
         public void onSurfaceDestroyed(SurfaceHolder holder) {
             super.onSurfaceDestroyed(holder);
         }
-        
-        void drawFrame() {
+
+        void drawFrameLocked(boolean redrawNeeded, boolean offsetsChanged) {
+            mRedrawNeeded |= redrawNeeded;
+            mOffsetsChanged |= offsetsChanged;
+
+            if (!mVisible) {
+                if (DEBUG) {
+                    Log.d(TAG, "Suppressed drawFrame since wallpaper is not visible.");
+                }
+                return;
+            }
+            if (!mRedrawNeeded && !mOffsetsChanged) {
+                if (DEBUG) {
+                    Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
+                            + "and offsets have not changed.");
+                }
+                return;
+            }
+
             SurfaceHolder sh = getSurfaceHolder();
             Canvas c = sh.lockCanvas();
             if (c != null) {
-                final Rect frame = sh.getSurfaceFrame();
-                synchronized (mLock) {
+                try {
+                    final Rect frame = sh.getSurfaceFrame();
                     final Drawable background = mBackground;
                     final int dw = frame.width();
                     final int dh = frame.height();
@@ -154,8 +201,22 @@ public class ImageWallpaper extends WallpaperService {
                     int xPixels = availw < 0 ? (int)(availw*mXOffset+.5f) : (availw/2);
                     int yPixels = availh < 0 ? (int)(availh*mYOffset+.5f) : (availh/2);
 
+                    mOffsetsChanged = false;
+                    if (!mRedrawNeeded) {
+                        if (xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
+                            if (DEBUG) {
+                                Log.d(TAG, "Suppressed drawFrame since the image has not "
+                                        + "actually moved an integral number of pixels.");
+                            }
+                            return;
+                        }
+                    }
+                    mRedrawNeeded = false;
+                    mLastXTranslation = xPixels;
+                    mLastYTranslation = yPixels;
+
                     c.translate(xPixels, yPixels);
-                    if (availw<0 || availh<0) {
+                    if (availw < 0 || availh < 0) {
                         c.save(Canvas.CLIP_SAVE_FLAG);
                         c.clipRect(0, 0, bw, bh, Op.DIFFERENCE);
                         c.drawColor(0xff000000);
@@ -164,35 +225,35 @@ public class ImageWallpaper extends WallpaperService {
                     if (background != null) {
                         background.draw(c);
                     }
+                } finally {
+                    sh.unlockCanvasAndPost(c);
                 }
-                sh.unlockCanvasAndPost(c);
             }
         }
 
-        void updateWallpaper() {
-            synchronized (mLock) {
-                Throwable exception = null;
+        void updateWallpaperLocked() {
+            Throwable exception = null;
+            try {
+                mBackground = mWallpaperManager.getFastDrawable();
+            } catch (RuntimeException e) {
+                exception = e;
+            } catch (OutOfMemoryError e) {
+                exception = e;
+            }
+            if (exception != null) {
+                mBackground = null;
+                // Note that if we do fail at this, and the default wallpaper can't
+                // be loaded, we will go into a cycle.  Don't do a build where the
+                // default wallpaper can't be loaded.
+                Log.w(TAG, "Unable to load wallpaper!", exception);
                 try {
-                    mBackground = mWallpaperManager.getFastDrawable();
-                } catch (RuntimeException e) {
-                    exception = e;
-                } catch (OutOfMemoryError e) {
-                    exception = e;
-                }
-                if (exception != null) {
-                    mBackground = null;
-                    // Note that if we do fail at this, and the default wallpaper can't
-                    // be loaded, we will go into a cycle.  Don't do a build where the
-                    // default wallpaper can't be loaded.
-                    Log.w("ImageWallpaper", "Unable to load wallpaper!", exception);
-                    try {
-                        mWallpaperManager.clear();
-                    } catch (IOException ex) {
-                        // now we're really screwed.
-                        Log.w("ImageWallpaper", "Unable reset to default wallpaper!", ex);
-                    }
+                    mWallpaperManager.clear();
+                } catch (IOException ex) {
+                    // now we're really screwed.
+                    Log.w(TAG, "Unable reset to default wallpaper!", ex);
                 }
             }
+            mRedrawNeeded = true;
         }
     }
 }