OSDN Git Service

Fix Bitmap leaks in ImageWallpaper
authorAdrian Roos <roosa@google.com>
Wed, 12 Nov 2014 17:02:42 +0000 (18:02 +0100)
committerAdrian Roos <roosa@google.com>
Thu, 13 Nov 2014 15:46:17 +0000 (15:46 +0000)
Bug: 18350603
Change-Id: I42ec057cd287955dcf3c382c237806fd9d6666a7

packages/SystemUI/src/com/android/systemui/ImageWallpaper.java

index 4857adc..0516768 100644 (file)
@@ -174,7 +174,7 @@ public class ImageWallpaper extends WallpaperService {
 
         public void trimMemory(int level) {
             if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW &&
-                    mBackground != null && mIsHwAccelerated) {
+                    mBackground != null) {
                 if (DEBUG) {
                     Log.d(TAG, "trimMemory");
                 }
@@ -212,6 +212,7 @@ public class ImageWallpaper extends WallpaperService {
                 unregisterReceiver(mReceiver);
             }
             mBackground = null;
+            mWallpaperManager.forgetLoadedWallpaper();
         }
 
         void updateSurfaceSize(SurfaceHolder surfaceHolder) {
@@ -337,111 +338,116 @@ public class ImageWallpaper extends WallpaperService {
         }
 
         void drawFrame() {
-            int newRotation = ((WindowManager) getSystemService(WINDOW_SERVICE)).
-                    getDefaultDisplay().getRotation();
-
-            // Sometimes a wallpaper is not large enough to cover the screen in one dimension.
-            // Call updateSurfaceSize -- it will only actually do the update if the dimensions
-            // should change
-            if (newRotation != mLastRotation) {
-                // Update surface size (if necessary)
-                updateSurfaceSize(getSurfaceHolder());
-            }
-            SurfaceHolder sh = getSurfaceHolder();
-            final Rect frame = sh.getSurfaceFrame();
-            final int dw = frame.width();
-            final int dh = frame.height();
-            boolean surfaceDimensionsChanged = dw != mLastSurfaceWidth || dh != mLastSurfaceHeight;
-
-            boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation;
-            if (!redrawNeeded && !mOffsetsChanged) {
-                if (DEBUG) {
-                    Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
-                            + "and offsets have not changed.");
+            try {
+                int newRotation = ((WindowManager) getSystemService(WINDOW_SERVICE)).
+                        getDefaultDisplay().getRotation();
+
+                // Sometimes a wallpaper is not large enough to cover the screen in one dimension.
+                // Call updateSurfaceSize -- it will only actually do the update if the dimensions
+                // should change
+                if (newRotation != mLastRotation) {
+                    // Update surface size (if necessary)
+                    updateSurfaceSize(getSurfaceHolder());
                 }
-                return;
-            }
-            mLastRotation = newRotation;
+                SurfaceHolder sh = getSurfaceHolder();
+                final Rect frame = sh.getSurfaceFrame();
+                final int dw = frame.width();
+                final int dh = frame.height();
+                boolean surfaceDimensionsChanged = dw != mLastSurfaceWidth
+                        || dh != mLastSurfaceHeight;
 
-            // Load bitmap if it is not yet loaded or if it was loaded at a different size
-            if (mBackground == null || surfaceDimensionsChanged) {
-                if (DEBUG) {
-                    Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " +
-                            mBackground + ", " +
-                            ((mBackground == null) ? 0 : mBackground.getWidth()) + ", " +
-                            ((mBackground == null) ? 0 : mBackground.getHeight()) + ", " +
-                            dw + ", " + dh);
-                }
-                mWallpaperManager.forgetLoadedWallpaper();
-                updateWallpaperLocked();
-                if (mBackground == null) {
+                boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation;
+                if (!redrawNeeded && !mOffsetsChanged) {
                     if (DEBUG) {
-                        Log.d(TAG, "Unable to load bitmap");
+                        Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
+                                + "and offsets have not changed.");
                     }
                     return;
                 }
-                if (DEBUG) {
-                    if (dw != mBackground.getWidth() || dh != mBackground.getHeight()) {
-                        Log.d(TAG, "Surface != bitmap dimensions: surface w/h, bitmap w/h: " +
-                                dw + ", " + dh + ", " + mBackground.getWidth() + ", " +
-                                mBackground.getHeight());
+                mLastRotation = newRotation;
+
+                // Load bitmap if it is not yet loaded or if it was loaded at a different size
+                if (mBackground == null || surfaceDimensionsChanged) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " +
+                                mBackground + ", " +
+                                ((mBackground == null) ? 0 : mBackground.getWidth()) + ", " +
+                                ((mBackground == null) ? 0 : mBackground.getHeight()) + ", " +
+                                dw + ", " + dh);
+                    }
+                    mWallpaperManager.forgetLoadedWallpaper();
+                    updateWallpaperLocked();
+                    if (mBackground == null) {
+                        if (DEBUG) {
+                            Log.d(TAG, "Unable to load bitmap");
+                        }
+                        return;
+                    }
+                    if (DEBUG) {
+                        if (dw != mBackground.getWidth() || dh != mBackground.getHeight()) {
+                            Log.d(TAG, "Surface != bitmap dimensions: surface w/h, bitmap w/h: " +
+                                    dw + ", " + dh + ", " + mBackground.getWidth() + ", " +
+                                    mBackground.getHeight());
+                        }
                     }
                 }
-            }
 
-            // Center the scaled image
-            mScale = Math.max(1f, Math.max(dw / (float) mBackground.getWidth(),
-                    dh / (float) mBackground.getHeight()));
-            final int availw = dw - (int) (mBackground.getWidth() * mScale);
-            final int availh = dh - (int) (mBackground.getHeight() * mScale);
-            int xPixels = availw / 2;
-            int yPixels = availh / 2;
-
-            // Adjust the image for xOffset/yOffset values. If window manager is handling offsets,
-            // mXOffset and mYOffset are set to 0.5f by default and therefore xPixels and yPixels
-            // will remain unchanged
-            final int availwUnscaled = dw - mBackground.getWidth();
-            final int availhUnscaled = dh - mBackground.getHeight();
-            if (availwUnscaled < 0) xPixels += (int)(availwUnscaled * (mXOffset - .5f) + .5f);
-            if (availhUnscaled < 0) yPixels += (int)(availhUnscaled * (mYOffset - .5f) + .5f);
-
-            mOffsetsChanged = false;
-            mRedrawNeeded = false;
-            if (surfaceDimensionsChanged) {
-                mLastSurfaceWidth = dw;
-                mLastSurfaceHeight = dh;
-            }
-            if (!redrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
-                if (DEBUG) {
-                    Log.d(TAG, "Suppressed drawFrame since the image has not "
-                            + "actually moved an integral number of pixels.");
+                // Center the scaled image
+                mScale = Math.max(1f, Math.max(dw / (float) mBackground.getWidth(),
+                        dh / (float) mBackground.getHeight()));
+                final int availw = dw - (int) (mBackground.getWidth() * mScale);
+                final int availh = dh - (int) (mBackground.getHeight() * mScale);
+                int xPixels = availw / 2;
+                int yPixels = availh / 2;
+
+                // Adjust the image for xOffset/yOffset values. If window manager is handling offsets,
+                // mXOffset and mYOffset are set to 0.5f by default and therefore xPixels and yPixels
+                // will remain unchanged
+                final int availwUnscaled = dw - mBackground.getWidth();
+                final int availhUnscaled = dh - mBackground.getHeight();
+                if (availwUnscaled < 0)
+                    xPixels += (int) (availwUnscaled * (mXOffset - .5f) + .5f);
+                if (availhUnscaled < 0)
+                    yPixels += (int) (availhUnscaled * (mYOffset - .5f) + .5f);
+
+                mOffsetsChanged = false;
+                mRedrawNeeded = false;
+                if (surfaceDimensionsChanged) {
+                    mLastSurfaceWidth = dw;
+                    mLastSurfaceHeight = dh;
                 }
-                return;
-            }
-            mLastXTranslation = xPixels;
-            mLastYTranslation = yPixels;
+                if (!redrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Suppressed drawFrame since the image has not "
+                                + "actually moved an integral number of pixels.");
+                    }
+                    return;
+                }
+                mLastXTranslation = xPixels;
+                mLastYTranslation = yPixels;
 
-            if (DEBUG) {
-                Log.d(TAG, "Redrawing wallpaper");
-            }
+                if (DEBUG) {
+                    Log.d(TAG, "Redrawing wallpaper");
+                }
 
-            if (mIsHwAccelerated) {
-                if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
+                if (mIsHwAccelerated) {
+                    if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
+                        drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
+                    }
+                } else {
                     drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
                 }
-            } else {
-                drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
-                if (FIXED_SIZED_SURFACE) {
+            } finally {
+                if (FIXED_SIZED_SURFACE && !mIsHwAccelerated) {
                     // If the surface is fixed-size, we should only need to
                     // draw it once and then we'll let the window manager
                     // position it appropriately.  As such, we no longer needed
                     // the loaded bitmap.  Yay!
-                    // hw-accelerated path retains bitmap for faster rotation
+                    // hw-accelerated renderer retains bitmap for faster rotation
                     mBackground = null;
                     mWallpaperManager.forgetLoadedWallpaper();
                 }
             }
-
         }
 
         private void updateWallpaperLocked() {