another small step towards fixing [2501808] sapphire: OOM in GPU Surface area

release the Surface in SurfaceView when it's not visible, after it comes back from relayout(),
it should not be holding buffers at this point, but it's cleaner to have it in the released state.

also log a warning in Surface.finalize() when there is work to do, as it means Surface.release() wasn't
called when it should have.

Change-Id: Id637d4ec2916d8fd800b0344d8dec6cecce02051
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 183fce3..255e317 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -28,6 +28,7 @@
  */
 public class Surface implements Parcelable {
     private static final String LOG_TAG = "Surface";
+    private static final boolean DEBUG_RELEASE = false;
     
     /* flags used in constructor (keep in sync with ISurfaceComposer.h) */
 
@@ -155,6 +156,9 @@
     // non compatibility mode.
     private Matrix mCompatibleMatrix;
 
+    @SuppressWarnings("unused")
+    private Exception mCreationStack;
+
     /**
      * Exception thrown when a surface couldn't be created or resized
      */
@@ -181,6 +185,9 @@
     public Surface(SurfaceSession s,
             int pid, int display, int w, int h, int format, int flags)
         throws OutOfResourcesException {
+        if (DEBUG_RELEASE) {
+            mCreationStack = new Exception();
+        }
         mCanvas = new CompatibleCanvas();
         init(s,pid,null,display,w,h,format,flags);
     }
@@ -192,6 +199,9 @@
     public Surface(SurfaceSession s,
             int pid, String name, int display, int w, int h, int format, int flags)
         throws OutOfResourcesException {
+        if (DEBUG_RELEASE) {
+            mCreationStack = new Exception();
+        }
         mCanvas = new CompatibleCanvas();
         init(s,pid,name,display,w,h,format,flags);
     }
@@ -202,6 +212,9 @@
      * {@hide}
      */
     public Surface() {
+        if (DEBUG_RELEASE) {
+            mCreationStack = new Exception();
+        }
         mCanvas = new CompatibleCanvas();
     }
 
@@ -407,6 +420,15 @@
     /* no user serviceable parts here ... */
     @Override
     protected void finalize() throws Throwable {
+        if (mSurface != 0 || mSurfaceControl != 0) {
+            if (DEBUG_RELEASE) {
+                Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" 
+                        + mSurface + ", " + mSurfaceControl + ")", mCreationStack);
+            } else {
+                Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" 
+                        + mSurface + ", " + mSurfaceControl + ")");
+            }
+        }
         release();
     }
     
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index c44854a..7f7d207 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -422,7 +422,7 @@
                 if (visibleChanged && (!visible || mNewSurfaceNeeded)) {
                     reportSurfaceDestroyed();
                 }
-                
+
                 mNewSurfaceNeeded = false;
                 
                 mSurfaceLock.lock();
@@ -470,6 +470,8 @@
                                 c.surfaceChanged(mSurfaceHolder, mFormat, mWidth, mHeight);
                             }
                         }
+                    } else {
+                        mSurface.release();
                     }
                 } finally {
                     mIsCreating = false;