diff options
| author | Dianne Hackborn <hackbod@google.com> | 2011-11-19 14:36:15 -0800 |
|---|---|---|
| committer | Dianne Hackborn <hackbod@google.com> | 2011-11-28 14:45:50 -0800 |
| commit | 6d05fd3c795088ac60f86382df5a66d631e8a0cb (patch) | |
| tree | c6363c2b687619f594e95b4b67b83c3d015dab58 /core/java/android/view/SurfaceView.java | |
| parent | e35581ad5ad635f9dcfe4ab6a432c48b46b782cd (diff) | |
Fix issue #5588689: Black camera preview after coming back from gmail
Make surface management between SurfaceView and the window manager
much more controlled, to ensure that SurfaceView always gets to report
the current surface is destroyed before the window manager actually
destroys it.
Also a small tweak to allow windows that have a wallpaper background
to still have a preview window. This makes launching home after it
has been killed feel much more responsive.
Change-Id: I0d22cf178a499601a770cb1dbadef7487e392d85
Diffstat (limited to 'core/java/android/view/SurfaceView.java')
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 152 |
1 files changed, 64 insertions, 88 deletions
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 9a57ea0679c4..0e684907ae0a 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -16,7 +16,6 @@ package android.view; -import android.util.DisplayMetrics; import com.android.internal.view.BaseIWindow; import android.content.Context; @@ -82,7 +81,6 @@ import java.util.concurrent.locks.ReentrantLock; public class SurfaceView extends View { static private final String TAG = "SurfaceView"; static private final boolean DEBUG = false; - static private final boolean localLOGV = DEBUG ? true : false; final ArrayList<SurfaceHolder.Callback> mCallbacks = new ArrayList<SurfaceHolder.Callback>(); @@ -90,7 +88,8 @@ public class SurfaceView extends View { final int[] mLocation = new int[2]; final ReentrantLock mSurfaceLock = new ReentrantLock(); - final Surface mSurface = new Surface(); + Surface mSurface = new Surface(); // Current surface in use + Surface mNewSurface = new Surface(); // New surface we are switching to boolean mDrawingStopped = true; final WindowManager.LayoutParams mLayout @@ -145,8 +144,7 @@ public class SurfaceView extends View { int mRequestedFormat = PixelFormat.RGB_565; boolean mHaveFrame = false; - boolean mDestroyReportNeeded = false; - boolean mNewSurfaceNeeded = false; + boolean mSurfaceCreated = false; long mLastLockTime = 0; boolean mVisible = false; @@ -236,46 +234,6 @@ public class SurfaceView extends View { updateWindow(false, false); } - /** - * This method is not intended for general use. It was created - * temporarily to improve performance of 3D layers in Launcher - * and should be removed and fixed properly. - * - * Do not call this method. Ever. - * - * @hide - */ - protected void showSurface() { - if (mSession != null) { - updateWindow(true, false); - } - } - - /** - * This method is not intended for general use. It was created - * temporarily to improve performance of 3D layers in Launcher - * and should be removed and fixed properly. - * - * Do not call this method. Ever. - * - * @hide - */ - protected void hideSurface() { - if (mSession != null && mWindow != null) { - mSurfaceLock.lock(); - try { - DisplayMetrics metrics = getResources().getDisplayMetrics(); - mLayout.x = metrics.widthPixels * 3; - mSession.relayout(mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, VISIBLE, false, - mWinFrame, mContentInsets, mVisibleInsets, mConfiguration, mSurface); - } catch (RemoteException e) { - // Ignore - } finally { - mSurfaceLock.unlock(); - } - } - } - @Override protected void onDetachedFromWindow() { if (mGlobalListenersAdded) { @@ -444,14 +402,13 @@ public class SurfaceView extends View { final boolean creating = mWindow == null; final boolean formatChanged = mFormat != mRequestedFormat; final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight; - final boolean visibleChanged = mVisible != mRequestedVisible - || mNewSurfaceNeeded; + final boolean visibleChanged = mVisible != mRequestedVisible; if (force || creating || formatChanged || sizeChanged || visibleChanged || mLeft != mLocation[0] || mTop != mLocation[1] || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) { - if (localLOGV) Log.i(TAG, "Changes: creating=" + creating + if (DEBUG) Log.i(TAG, "Changes: creating=" + creating + " format=" + formatChanged + " size=" + sizeChanged + " visible=" + visibleChanged + " left=" + (mLeft != mLocation[0]) @@ -496,15 +453,11 @@ public class SurfaceView extends View { mVisible ? VISIBLE : GONE, mContentInsets); } - if (visibleChanged && (!visible || mNewSurfaceNeeded)) { - reportSurfaceDestroyed(); - } - - mNewSurfaceNeeded = false; - boolean realSizeChanged; boolean reportDrawNeeded; - + + int relayoutResult; + mSurfaceLock.lock(); try { mUpdateWindowNeeded = false; @@ -512,17 +465,21 @@ public class SurfaceView extends View { mReportDrawNeeded = false; mDrawingStopped = !visible; - final int relayoutResult = mSession.relayout( + if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface); + + relayoutResult = mSession.relayout( mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, - visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets, - mVisibleInsets, mConfiguration, mSurface); - if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) { + visible ? VISIBLE : GONE, + WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY, + mWinFrame, mContentInsets, + mVisibleInsets, mConfiguration, mNewSurface); + if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) { mReportDrawNeeded = true; } - - if (localLOGV) Log.i(TAG, "New surface: " + mSurface + + if (DEBUG) Log.i(TAG, "New surface: " + mNewSurface + ", vis=" + visible + ", frame=" + mWinFrame); - + mSurfaceFrame.left = 0; mSurfaceFrame.top = 0; if (mTranslator == null) { @@ -547,28 +504,54 @@ public class SurfaceView extends View { try { redrawNeeded |= creating | reportDrawNeeded; - if (visible) { - mDestroyReportNeeded = true; + SurfaceHolder.Callback callbacks[] = null; - SurfaceHolder.Callback callbacks[]; - synchronized (mCallbacks) { - callbacks = new SurfaceHolder.Callback[mCallbacks.size()]; - mCallbacks.toArray(callbacks); + final boolean surfaceChanged = + (relayoutResult&WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED) != 0; + if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) { + mSurfaceCreated = false; + if (mSurface.isValid()) { + if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceDestroyed"); + callbacks = getSurfaceCallbacks(); + for (SurfaceHolder.Callback c : callbacks) { + c.surfaceDestroyed(mSurfaceHolder); + } } + } + + Surface tmpSurface = mSurface; + mSurface = mNewSurface; + mNewSurface = tmpSurface; + mNewSurface.release(); - if (visibleChanged) { + if (visible) { + if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) { + mSurfaceCreated = true; mIsCreating = true; + if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceCreated"); + if (callbacks == null) { + callbacks = getSurfaceCallbacks(); + } for (SurfaceHolder.Callback c : callbacks) { c.surfaceCreated(mSurfaceHolder); } } if (creating || formatChanged || sizeChanged || visibleChanged || realSizeChanged) { + if (DEBUG) Log.i(TAG, "surfaceChanged -- format=" + mFormat + + " w=" + myWidth + " h=" + myHeight); + if (callbacks == null) { + callbacks = getSurfaceCallbacks(); + } for (SurfaceHolder.Callback c : callbacks) { c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight); } } if (redrawNeeded) { + if (DEBUG) Log.i(TAG, "surfaceRedrawNeeded"); + if (callbacks == null) { + callbacks = getSurfaceCallbacks(); + } for (SurfaceHolder.Callback c : callbacks) { if (c instanceof SurfaceHolder.Callback2) { ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded( @@ -576,41 +559,34 @@ public class SurfaceView extends View { } } } - } else { - mSurface.release(); } } finally { mIsCreating = false; if (redrawNeeded) { + if (DEBUG) Log.i(TAG, "finishedDrawing"); mSession.finishDrawing(mWindow); } + mSession.performDeferredDestroy(mWindow); } } catch (RemoteException ex) { } - if (localLOGV) Log.v( + if (DEBUG) Log.v( TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y + " w=" + mLayout.width + " h=" + mLayout.height + ", frame=" + mSurfaceFrame); } } - private void reportSurfaceDestroyed() { - if (mDestroyReportNeeded) { - mDestroyReportNeeded = false; - SurfaceHolder.Callback callbacks[]; - synchronized (mCallbacks) { - callbacks = new SurfaceHolder.Callback[mCallbacks.size()]; - mCallbacks.toArray(callbacks); - } - for (SurfaceHolder.Callback c : callbacks) { - c.surfaceDestroyed(mSurfaceHolder); - } + private SurfaceHolder.Callback[] getSurfaceCallbacks() { + SurfaceHolder.Callback callbacks[]; + synchronized (mCallbacks) { + callbacks = new SurfaceHolder.Callback[mCallbacks.size()]; + mCallbacks.toArray(callbacks); } - super.onDetachedFromWindow(); + return callbacks; } void handleGetNewSurface() { - mNewSurfaceNeeded = true; updateWindow(false, false); } @@ -636,7 +612,7 @@ public class SurfaceView extends View { Rect visibleInsets, boolean reportDraw, Configuration newConfig) { SurfaceView surfaceView = mSurfaceView.get(); if (surfaceView != null) { - if (localLOGV) Log.v( + if (DEBUG) Log.v( "SurfaceView", surfaceView + " got resized: w=" + w + " h=" + h + ", cur w=" + mCurWidth + " h=" + mCurHeight); surfaceView.mSurfaceLock.lock(); @@ -754,7 +730,7 @@ public class SurfaceView extends View { private final Canvas internalLockCanvas(Rect dirty) { mSurfaceLock.lock(); - if (localLOGV) Log.i(TAG, "Locking canvas... stopped=" + if (DEBUG) Log.i(TAG, "Locking canvas... stopped=" + mDrawingStopped + ", win=" + mWindow); Canvas c = null; @@ -774,7 +750,7 @@ public class SurfaceView extends View { } } - if (localLOGV) Log.i(TAG, "Returned canvas: " + c); + if (DEBUG) Log.i(TAG, "Returned canvas: " + c); if (c != null) { mLastLockTime = SystemClock.uptimeMillis(); return c; |
