From d5523dc7b7318f2774109dd30716ff7b74560e61 Mon Sep 17 00:00:00 2001 From: Craig Mautner Date: Tue, 2 Oct 2012 13:49:22 -0700 Subject: [PATCH] Call Surface.destroy when Display is removed. Prevents leaked Surfaces. Bug: 7272421. Change-Id: I6c87eb11bb0bedcf8de451b04477c70c248f905d --- .../server/display/OverlayDisplayAdapter.java | 35 +++++++---- .../server/display/OverlayDisplayWindow.java | 7 +-- .../com/android/server/wm/DimAnimator.java | 59 ++++++++++++------- .../com/android/server/wm/DimSurface.java | 57 +++++++++++------- .../com/android/server/wm/WindowAnimator.java | 37 +++++++++--- 5 files changed, 129 insertions(+), 66 deletions(-) diff --git a/services/java/com/android/server/display/OverlayDisplayAdapter.java b/services/java/com/android/server/display/OverlayDisplayAdapter.java index 0767fc05d7000..4eea77f5d61d7 100644 --- a/services/java/com/android/server/display/OverlayDisplayAdapter.java +++ b/services/java/com/android/server/display/OverlayDisplayAdapter.java @@ -19,14 +19,11 @@ package com.android.server.display; import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; -import android.content.BroadcastReceiver; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.database.ContentObserver; +import android.graphics.SurfaceTexture; import android.os.Handler; import android.os.IBinder; -import android.os.UserHandle; import android.provider.Settings; import android.util.DisplayMetrics; import android.util.Slog; @@ -192,28 +189,42 @@ final class OverlayDisplayAdapter extends DisplayAdapter { private final int mDensityDpi; private Surface mSurface; + private SurfaceTexture mSurfaceTexture; private DisplayDeviceInfo mInfo; public OverlayDisplayDevice(IBinder displayToken, String name, int width, int height, float refreshRate, int densityDpi, - Surface surface) { + SurfaceTexture surfaceTexture) { super(OverlayDisplayAdapter.this, displayToken); mName = name; mWidth = width; mHeight = height; mRefreshRate = refreshRate; mDensityDpi = densityDpi; - mSurface = surface; + mSurfaceTexture = surfaceTexture; } - public void clearSurfaceLocked() { - mSurface = null; + public void clearSurfaceTextureLocked() { + if (mSurfaceTexture != null) { + mSurfaceTexture = null; + } sendTraversalRequestLocked(); } @Override public void performTraversalInTransactionLocked() { - setSurfaceInTransactionLocked(mSurface); + if (mSurfaceTexture != null) { + if (mSurface == null) { + mSurface = new Surface(mSurfaceTexture); + } + setSurfaceInTransactionLocked(mSurface); + } else { + setSurfaceInTransactionLocked(null); + if (mSurface != null) { + mSurface.destroy(); + mSurface = null; + } + } } @Override @@ -268,11 +279,11 @@ final class OverlayDisplayAdapter extends DisplayAdapter { // Called on the UI thread. @Override - public void onWindowCreated(Surface surface, float refreshRate) { + public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate) { synchronized (getSyncRoot()) { IBinder displayToken = Surface.createDisplay(mName); mDevice = new OverlayDisplayDevice(displayToken, mName, - mWidth, mHeight, refreshRate, mDensityDpi, surface); + mWidth, mHeight, refreshRate, mDensityDpi, surfaceTexture); sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED); } @@ -283,7 +294,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter { public void onWindowDestroyed() { synchronized (getSyncRoot()) { if (mDevice != null) { - mDevice.clearSurfaceLocked(); + mDevice.clearSurfaceTextureLocked(); sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_REMOVED); } } diff --git a/services/java/com/android/server/display/OverlayDisplayWindow.java b/services/java/com/android/server/display/OverlayDisplayWindow.java index d08f65fe5e2ee..a0edced4b8534 100644 --- a/services/java/com/android/server/display/OverlayDisplayWindow.java +++ b/services/java/com/android/server/display/OverlayDisplayWindow.java @@ -29,7 +29,6 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.ScaleGestureDetector; -import android.view.Surface; import android.view.TextureView; import android.view.View; import android.view.WindowManager; @@ -146,6 +145,7 @@ final class OverlayDisplayWindow implements DumpUtils.Dump { } } + @Override public void dump(PrintWriter pw) { pw.println("mWindowVisible=" + mWindowVisible); pw.println("mWindowX=" + mWindowX); @@ -291,8 +291,7 @@ final class OverlayDisplayWindow implements DumpUtils.Dump { @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { - mListener.onWindowCreated(new Surface(surfaceTexture), - mDefaultDisplayInfo.refreshRate); + mListener.onWindowCreated(surfaceTexture, mDefaultDisplayInfo.refreshRate); } @Override @@ -361,7 +360,7 @@ final class OverlayDisplayWindow implements DumpUtils.Dump { * Watches for significant changes in the overlay display window lifecycle. */ public interface Listener { - public void onWindowCreated(Surface surface, float refreshRate); + public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate); public void onWindowDestroyed(); } } \ No newline at end of file diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java index 9bca83483ef15..5874202dfaeb0 100644 --- a/services/java/com/android/server/wm/DimAnimator.java +++ b/services/java/com/android/server/wm/DimAnimator.java @@ -30,37 +30,37 @@ import java.io.PrintWriter; * all state used for dim animation. */ class DimAnimator { + static final String TAG = "DimAnimator"; + Surface mDimSurface; boolean mDimShown = false; float mDimCurrentAlpha; float mDimTargetAlpha; float mDimDeltaPerMs; long mLastDimAnimTime; - + int mLastDimWidth, mLastDimHeight; DimAnimator (SurfaceSession session, final int layerStack) { - if (mDimSurface == null) { - try { - if (WindowManagerService.DEBUG_SURFACE_TRACE) { - mDimSurface = new WindowStateAnimator.SurfaceTrace(session, - "DimAnimator", - 16, 16, PixelFormat.OPAQUE, - Surface.FX_SURFACE_DIM | Surface.HIDDEN); - } else { - mDimSurface = new Surface(session, "DimAnimator", - 16, 16, PixelFormat.OPAQUE, - Surface.FX_SURFACE_DIM | Surface.HIDDEN); - } - if (WindowManagerService.SHOW_TRANSACTIONS || - WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, - " DIM " + mDimSurface + ": CREATE"); - mDimSurface.setLayerStack(layerStack); - mDimSurface.setAlpha(0.0f); - mDimSurface.show(); - } catch (Exception e) { - Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e); + try { + if (WindowManagerService.DEBUG_SURFACE_TRACE) { + mDimSurface = new WindowStateAnimator.SurfaceTrace(session, + "DimAnimator", + 16, 16, PixelFormat.OPAQUE, + Surface.FX_SURFACE_DIM | Surface.HIDDEN); + } else { + mDimSurface = new Surface(session, "DimAnimator", + 16, 16, PixelFormat.OPAQUE, + Surface.FX_SURFACE_DIM | Surface.HIDDEN); } + if (WindowManagerService.SHOW_TRANSACTIONS || + WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, + " DIM " + mDimSurface + ": CREATE"); + mDimSurface.setLayerStack(layerStack); + mDimSurface.setAlpha(0.0f); + mDimSurface.show(); + } catch (Exception e) { + Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e); } } @@ -69,6 +69,11 @@ class DimAnimator { * {@link #updateSurface} after all windows are examined. */ void updateParameters(final Resources res, final Parameters params, final long currentTime) { + if (mDimSurface == null) { + Slog.e(TAG, "updateParameters: no Surface"); + return; + } + // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose a // corner. final int dw = (int) (params.mDimWidth * 1.5); @@ -133,6 +138,11 @@ class DimAnimator { * false when the animation is finished and the dim surface is hidden. */ boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) { + if (mDimSurface == null) { + Slog.e(TAG, "updateSurface: no Surface"); + return false; + } + if (!dimming) { if (mDimTargetAlpha != 0) { mLastDimAnimTime = currentTime; @@ -187,6 +197,13 @@ class DimAnimator { return animating; } + public void kill() { + if (mDimSurface != null) { + mDimSurface.destroy(); + mDimSurface = null; + } + } + public void printTo(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("mDimSurface="); pw.print(mDimSurface); diff --git a/services/java/com/android/server/wm/DimSurface.java b/services/java/com/android/server/wm/DimSurface.java index ddbd70db11239..4225868b2f108 100644 --- a/services/java/com/android/server/wm/DimSurface.java +++ b/services/java/com/android/server/wm/DimSurface.java @@ -24,6 +24,8 @@ import android.view.SurfaceSession; import java.io.PrintWriter; class DimSurface { + static final String TAG = "DimSurface"; + Surface mDimSurface; boolean mDimShown = false; int mDimColor = 0; @@ -31,27 +33,25 @@ class DimSurface { int mLastDimWidth, mLastDimHeight; DimSurface(SurfaceSession session, final int layerStack) { - if (mDimSurface == null) { - try { - if (WindowManagerService.DEBUG_SURFACE_TRACE) { - mDimSurface = new WindowStateAnimator.SurfaceTrace(session, - "DimSurface", - 16, 16, PixelFormat.OPAQUE, - Surface.FX_SURFACE_DIM | Surface.HIDDEN); - } else { - mDimSurface = new Surface(session, "DimSurface", - 16, 16, PixelFormat.OPAQUE, - Surface.FX_SURFACE_DIM | Surface.HIDDEN); - } - if (WindowManagerService.SHOW_TRANSACTIONS || - WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, - " DIM " + mDimSurface + ": CREATE"); - mDimSurface.setLayerStack(layerStack); - mDimSurface.setAlpha(0.0f); - mDimSurface.show(); - } catch (Exception e) { - Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e); + try { + if (WindowManagerService.DEBUG_SURFACE_TRACE) { + mDimSurface = new WindowStateAnimator.SurfaceTrace(session, + "DimSurface", + 16, 16, PixelFormat.OPAQUE, + Surface.FX_SURFACE_DIM | Surface.HIDDEN); + } else { + mDimSurface = new Surface(session, "DimSurface", + 16, 16, PixelFormat.OPAQUE, + Surface.FX_SURFACE_DIM | Surface.HIDDEN); } + if (WindowManagerService.SHOW_TRANSACTIONS || + WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, + " DIM " + mDimSurface + ": CREATE"); + mDimSurface.setLayerStack(layerStack); + mDimSurface.setAlpha(0.0f); + mDimSurface.show(); + } catch (Exception e) { + Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e); } } @@ -59,6 +59,11 @@ class DimSurface { * Show the dim surface. */ void show(int dw, int dh, int layer, int color) { + if (mDimSurface == null) { + Slog.e(TAG, "show: no Surface"); + return; + } + if (!mDimShown) { if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" + dw + "x" + dh + " layer=" + layer + ")"); @@ -88,6 +93,11 @@ class DimSurface { } void hide() { + if (mDimSurface == null) { + Slog.e(TAG, "hide: no Surface"); + return; + } + if (mDimShown) { mDimShown = false; try { @@ -99,6 +109,13 @@ class DimSurface { } } + void kill() { + if (mDimSurface != null) { + mDimSurface.destroy(); + mDimSurface = null; + } + } + public void printTo(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("mDimSurface="); pw.println(mDimSurface); pw.print(prefix); pw.print("mDimShown="); pw.print(mDimShown); diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java index 377e89ce1a347..b67fb5197b463 100644 --- a/services/java/com/android/server/wm/WindowAnimator.java +++ b/services/java/com/android/server/wm/WindowAnimator.java @@ -147,6 +147,22 @@ public class WindowAnimator { } void removeDisplayLocked(final int displayId) { + final DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.get(displayId); + if (displayAnimator != null) { + if (displayAnimator.mWindowAnimationBackgroundSurface != null) { + displayAnimator.mWindowAnimationBackgroundSurface.kill(); + displayAnimator.mWindowAnimationBackgroundSurface = null; + } + if (displayAnimator.mScreenRotationAnimation != null) { + displayAnimator.mScreenRotationAnimation.kill(); + displayAnimator.mScreenRotationAnimation = null; + } + if (displayAnimator.mDimAnimator != null) { + displayAnimator.mDimAnimator.kill(); + displayAnimator.mDimAnimator = null; + } + } + mDisplayContentsAnimators.delete(displayId); } @@ -527,11 +543,15 @@ public class WindowAnimator { } } - windowAnimationBackgroundSurface.show(mDw, mDh, - animLayer - WindowManagerService.LAYER_OFFSET_DIM, - windowAnimationBackgroundColor); + if (windowAnimationBackgroundSurface != null) { + windowAnimationBackgroundSurface.show(mDw, mDh, + animLayer - WindowManagerService.LAYER_OFFSET_DIM, + windowAnimationBackgroundColor); + } } else { - windowAnimationBackgroundSurface.hide(); + if (windowAnimationBackgroundSurface != null) { + windowAnimationBackgroundSurface.hide(); + } } } @@ -643,9 +663,8 @@ public class WindowAnimator { final DimAnimator.Parameters dimParams = displayAnimator.mDimParams; final DimAnimator dimAnimator = displayAnimator.mDimAnimator; - if (dimParams != null) { - dimAnimator.updateParameters( - mContext.getResources(), dimParams, mCurrentTime); + if (dimAnimator != null && dimParams != null) { + dimAnimator.updateParameters(mContext.getResources(), dimParams, mCurrentTime); } if (dimAnimator != null && dimAnimator.mDimShown) { mAnimating |= dimAnimator.updateSurface(isDimmingLocked(displayId), @@ -801,9 +820,9 @@ public class WindowAnimator { private class DisplayContentsAnimator { WinAnimatorList mWinAnimators = new WinAnimatorList(); - final DimAnimator mDimAnimator; + DimAnimator mDimAnimator = null; DimAnimator.Parameters mDimParams = null; - final DimSurface mWindowAnimationBackgroundSurface; + DimSurface mWindowAnimationBackgroundSurface = null; ScreenRotationAnimation mScreenRotationAnimation = null; public DisplayContentsAnimator(int displayId) {