diff options
10 files changed, 231 insertions, 127 deletions
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index a9a628a..18167b6 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -608,7 +608,7 @@ public abstract class WallpaperService extends Service { final int relayoutResult = mSession.relayout( mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, - View.VISIBLE, false, mWinFrame, mContentInsets, + View.VISIBLE, 0, mWinFrame, mContentInsets, mVisibleInsets, mConfiguration, mSurfaceHolder.mSurface); if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface @@ -654,7 +654,7 @@ public abstract class WallpaperService extends Service { } redrawNeeded |= creating - || (relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0; + || (relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0; if (forceReport || creating || surfaceCreating || formatChanged || sizeChanged) { diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 282d7be..53d6e1f 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -54,9 +54,8 @@ interface IWindowSession { * @param requestedWidth The width the window wants to be. * @param requestedHeight The height the window wants to be. * @param viewVisibility Window root view's visibility. - * @param insetsPending Set to true if the client will be later giving - * internal insets; as a result, the window will not impact other window - * layouts until the insets are given. + * @param flags Request flags: {@link WindowManagerImpl#RELAYOUT_INSETS_PENDING}, + * {@link WindowManagerImpl#RELAYOUT_DEFER_SURFACE_DESTROY}. * @param outFrame Rect in which is placed the new position/size on * screen. * @param outContentInsets Rect in which is placed the offsets from @@ -80,11 +79,17 @@ interface IWindowSession { */ int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, - boolean insetsPending, out Rect outFrame, out Rect outContentInsets, + int flags, out Rect outFrame, out Rect outContentInsets, out Rect outVisibleInsets, out Configuration outConfig, out Surface outSurface); /** + * If a call to relayout() asked to have the surface destroy deferred, + * it must call this once it is okay to destroy that surface. + */ + void performDeferredDestroy(IWindow window); + + /** * Called by a client to report that it ran out of graphics memory. */ boolean outOfMemory(IWindow window); diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 9a57ea0..0e68490 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; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index d52db97..5060f83 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1427,7 +1427,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, if (!mStopped) { boolean focusChangedDueToTouchMode = ensureTouchModeLocally( - (relayoutResult&WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE) != 0); + (relayoutResult&WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE) != 0); if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight() || contentInsetsChanged) { childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width); @@ -1638,7 +1638,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, mLastDrawDurationNanos = System.nanoTime() - drawStartTime; } - if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0 + if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0 || mReportNextDraw) { if (LOCAL_LOGV) { Log.v(TAG, "FINISHED DRAWING: " + mWindowAttributes.getTitle()); @@ -1671,7 +1671,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, } // We were supposed to report when we are done drawing. Since we canceled the // draw, remember it here. - if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) { + if ((relayoutResult&WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) { mReportNextDraw = true; } if (fullRedrawNeeded) { @@ -3586,8 +3586,8 @@ public final class ViewRootImpl extends Handler implements ViewParent, mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredHeight() * appScale + 0.5f), - viewVisibility, insetsPending, mWinFrame, - mPendingContentInsets, mPendingVisibleInsets, + viewVisibility, insetsPending ? WindowManagerImpl.RELAYOUT_INSETS_PENDING : 0, + mWinFrame, mPendingContentInsets, mPendingVisibleInsets, mPendingConfiguration, mSurface); //Log.d(TAG, "<<<<<< BACK FROM relayout"); if (restore) { @@ -3717,7 +3717,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, // animation info. try { if ((relayoutWindow(mWindowAttributes, viewVisibility, false) - & WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) { + & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) { sWindowSession.finishDrawing(mWindow); } } catch (RemoteException e) { diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index dfd1d55..d711337 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -63,15 +63,34 @@ public class WindowManagerImpl implements WindowManager { * The user is navigating with keys (not the touch screen), so * navigational focus should be shown. */ - public static final int RELAYOUT_IN_TOUCH_MODE = 0x1; + public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1; /** * This is the first time the window is being drawn, * so the client must call drawingFinished() when done */ - public static final int RELAYOUT_FIRST_TIME = 0x2; - + public static final int RELAYOUT_RES_FIRST_TIME = 0x2; + /** + * The window manager has changed the surface from the last call. + */ + public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4; + + /** + * Flag for relayout: the client will be later giving + * internal insets; as a result, the window will not impact other window + * layouts until the insets are given. + */ + public static final int RELAYOUT_INSETS_PENDING = 0x1; + + /** + * Flag for relayout: the client may be currently using the current surface, + * so if it is to be destroyed as a part of the relayout the destroy must + * be deferred until later. The client will call performDeferredDestroy() + * when it is okay. + */ + public static final int RELAYOUT_DEFER_SURFACE_DESTROY = 0x2; + public static final int ADD_FLAG_APP_VISIBLE = 0x2; - public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_IN_TOUCH_MODE; + public static final int ADD_FLAG_IN_TOUCH_MODE = RELAYOUT_RES_IN_TOUCH_MODE; public static final int ADD_OKAY = 0; public static final int ADD_BAD_APP_TOKEN = -1; diff --git a/core/res/res/anim/app_starting_exit.xml b/core/res/res/anim/app_starting_exit.xml index ee8d80b..60e4109 100644 --- a/core/res/res/anim/app_starting_exit.xml +++ b/core/res/res/anim/app_starting_exit.xml @@ -18,7 +18,8 @@ */ --> -<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/decelerate_quad"> +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:detachWallpaper="true" android:interpolator="@interpolator/decelerate_quad"> <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="160" /> </set> diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java index ee62a56..77575f2 100644 --- a/services/java/com/android/server/wm/Session.java +++ b/services/java/com/android/server/wm/Session.java @@ -151,18 +151,22 @@ final class Session extends IWindowSession.Stub public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, - boolean insetsPending, Rect outFrame, Rect outContentInsets, + int flags, Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { if (false) Slog.d(WindowManagerService.TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid()); int res = mService.relayoutWindow(this, window, seq, attrs, - requestedWidth, requestedHeight, viewFlags, insetsPending, + requestedWidth, requestedHeight, viewFlags, flags, outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface); if (false) Slog.d(WindowManagerService.TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid()); return res; } + public void performDeferredDestroy(IWindow window) { + mService.performDeferredDestroyWindow(this, window); + } + public boolean outOfMemory(IWindow window) { return mService.outOfMemoryWindow(this, window); } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index ebb13d5..769e6cf 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -2499,12 +2499,13 @@ public class WindowManagerService extends IWindowManager.Stub public int relayoutWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int requestedWidth, - int requestedHeight, int viewVisibility, boolean insetsPending, + int requestedHeight, int viewVisibility, int flags, Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { boolean displayed = false; boolean inTouchMode; boolean configChanged; + boolean surfaceChanged = false; // if they don't have this permission, mask out the status bar bits int systemUiVisibility = 0; @@ -2534,6 +2535,9 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.adjustWindowParamsLw(attrs); } + win.mSurfaceDestroyDeferred = + (flags&WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY) != 0; + int attrChanges = 0; int flagChanges = 0; if (attrs != null) { @@ -2630,8 +2634,12 @@ public class WindowManagerService extends IWindowManager.Stub // To change the format, we need to re-build the surface. win.destroySurfaceLocked(); displayed = true; + surfaceChanged = true; } try { + if (win.mSurface == null) { + surfaceChanged = true; + } Surface surface = win.createSurfaceLocked(); if (surface != null) { outSurface.copyFrom(surface); @@ -2683,6 +2691,7 @@ public class WindowManagerService extends IWindowManager.Stub // If we are not currently running the exit animation, we // need to see about starting one. if (!win.mExiting || win.mSurfacePendingDestroy) { + surfaceChanged = true; // Try starting an animation; if there isn't one, we // can destroy the surface right away. int transit = WindowManagerPolicy.TRANSIT_EXIT; @@ -2715,10 +2724,10 @@ public class WindowManagerService extends IWindowManager.Stub if (win.mSurface == null || (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING) == 0 || win.mSurfacePendingDestroy) { - // We are being called from a local process, which + // We could be called from a local process, which // means outSurface holds its current surface. Ensure the - // surface object is cleared, but we don't want it actually - // destroyed at this point. + // surface object is cleared, but we don't necessarily want + // it actually destroyed at this point. win.mSurfacePendingDestroy = false; outSurface.release(); if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win); @@ -2760,7 +2769,7 @@ public class WindowManagerService extends IWindowManager.Stub } mLayoutNeeded = true; - win.mGivenInsetsPending = insetsPending; + win.mGivenInsetsPending = (flags&WindowManagerImpl.RELAYOUT_INSETS_PENDING) != 0; if (assignLayers) { assignLayersLocked(); } @@ -2797,8 +2806,25 @@ public class WindowManagerService extends IWindowManager.Stub Binder.restoreCallingIdentity(origId); - return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0) - | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0); + return (inTouchMode ? WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE : 0) + | (displayed ? WindowManagerImpl.RELAYOUT_RES_FIRST_TIME : 0) + | (surfaceChanged ? WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED : 0); + } + + public void performDeferredDestroyWindow(Session session, IWindow client) { + long origId = Binder.clearCallingIdentity(); + + try { + synchronized(mWindowMap) { + WindowState win = windowForClientLocked(session, client, false); + if (win == null) { + return; + } + win.destroyDeferredSurfaceLocked(); + } + } finally { + Binder.restoreCallingIdentity(origId); + } } public boolean outOfMemoryWindow(Session session, IWindow client) { @@ -3738,7 +3764,7 @@ public class WindowManagerService extends IWindowManager.Stub return; } - // If this is a translucent or wallpaper window, then don't + // If this is a translucent window, then don't // show a starting window -- the current effect (a full-screen // opaque starting window that fades away to the real contents // when it is ready) does not work for this. @@ -3755,7 +3781,16 @@ public class WindowManagerService extends IWindowManager.Stub } if (ent.array.getBoolean( com.android.internal.R.styleable.Window_windowShowWallpaper, false)) { - return; + if (mWallpaperTarget == null) { + // If this theme is requesting a wallpaper, and the wallpaper + // is not curently visible, then this effectively serves as + // an opaque window and our starting window transition animation + // can still work. We just need to make sure the starting window + // is also showing the wallpaper. + windowFlags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; + } else { + return; + } } } @@ -7659,7 +7694,8 @@ public class WindowManagerService extends IWindowManager.Stub // a detached wallpaper animation. if (nowAnimating) { if (w.mAnimation != null) { - if (w.mAnimation.getDetachWallpaper()) { + if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 + && w.mAnimation.getDetachWallpaper()) { windowDetachedWallpaper = w; } if (w.mAnimation.getBackgroundColor() != 0) { @@ -7679,7 +7715,8 @@ public class WindowManagerService extends IWindowManager.Stub // displayed behind it. if (w.mAppToken != null && w.mAppToken.animation != null && w.mAppToken.animating) { - if (w.mAppToken.animation.getDetachWallpaper()) { + if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 + && w.mAppToken.animation.getDetachWallpaper()) { windowDetachedWallpaper = w; } if (w.mAppToken.animation.getBackgroundColor() != 0) { diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index 23ec2d9..aa7bf2d 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -85,6 +85,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { boolean mPolicyVisibilityAfterAnim = true; boolean mAppFreezing; Surface mSurface; + Surface mPendingDestroySurface; boolean mReportDestroySurface; boolean mSurfacePendingDestroy; boolean mAttachedHidden; // is our parent window hidden? @@ -121,7 +122,13 @@ final class WindowState implements WindowManagerPolicy.WindowState { * we must tell them application to resize (and thus redraw itself). */ boolean mSurfaceResized; - + + /** + * Set if the client has asked that the destroy of its surface be delayed + * until it explicitly says it is okay. + */ + boolean mSurfaceDestroyDeferred; + /** * Insets that determine the actually visible area. These are in the application's * coordinate space (without compatibility scale applied). @@ -764,15 +771,32 @@ final class WindowState implements WindowManagerPolicy.WindowState { Slog.w(WindowManagerService.TAG, "Window " + this + " destroying surface " + mSurface + ", session " + mSession, e); } - if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { - RuntimeException e = null; - if (!WindowManagerService.HIDE_STACK_CRAWLS) { - e = new RuntimeException(); - e.fillInStackTrace(); + if (mSurfaceDestroyDeferred) { + if (mSurface != null && mPendingDestroySurface != mSurface) { + if (mPendingDestroySurface != null) { + if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { + RuntimeException e = null; + if (!WindowManagerService.HIDE_STACK_CRAWLS) { + e = new RuntimeException(); + e.fillInStackTrace(); + } + WindowManagerService.logSurface(this, "DESTROY PENDING", e); + } + mPendingDestroySurface.destroy(); + } + mPendingDestroySurface = mSurface; } - WindowManagerService.logSurface(this, "DESTROY", e); + } else { + if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { + RuntimeException e = null; + if (!WindowManagerService.HIDE_STACK_CRAWLS) { + e = new RuntimeException(); + e.fillInStackTrace(); + } + WindowManagerService.logSurface(this, "DESTROY", e); + } + mSurface.destroy(); } - mSurface.destroy(); } catch (RuntimeException e) { Slog.w(WindowManagerService.TAG, "Exception thrown when destroying Window " + this + " surface " + mSurface + " session " + mSession @@ -784,6 +808,28 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } + void destroyDeferredSurfaceLocked() { + try { + if (mPendingDestroySurface != null) { + if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) { + RuntimeException e = null; + if (!WindowManagerService.HIDE_STACK_CRAWLS) { + e = new RuntimeException(); + e.fillInStackTrace(); + } + mService.logSurface(this, "DESTROY PENDING", e); + } + mPendingDestroySurface.destroy(); + } + } catch (RuntimeException e) { + Slog.w(WindowManagerService.TAG, "Exception thrown when destroying Window " + + this + " surface " + mPendingDestroySurface + + " session " + mSession + ": " + e.toString()); + } + mSurfaceDestroyDeferred = false; + mPendingDestroySurface = null; + } + boolean finishDrawingLocked() { if (mDrawPending) { if (SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) Slog.v( @@ -977,6 +1023,9 @@ final class WindowState implements WindowManagerPolicy.WindowState { mAnimation.cancel(); mAnimation = null; } + if (mService.mWindowDetachedWallpaper == this) { + mService.mWindowDetachedWallpaper = null; + } mAnimLayer = mLayer; if (mIsImWindow) { mAnimLayer += mService.mInputMethodAnimLayerAdjustment; @@ -1415,6 +1464,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Removing " + this + " from " + mAttachedWindow); mAttachedWindow.mChildWindows.remove(this); } + destroyDeferredSurfaceLocked(); destroySurfaceLocked(); mSession.windowRemovedLocked(); try { @@ -1612,6 +1662,10 @@ final class WindowState implements WindowManagerPolicy.WindowState { pw.print(") "); pw.print(mSurfaceW); pw.print(" x "); pw.println(mSurfaceH); } + if (mPendingDestroySurface != null) { + pw.print(prefix); pw.print("mPendingDestroySurface="); + pw.println(mPendingDestroySurface); + } if (dumpAll) { pw.print(prefix); pw.print("mToken="); pw.println(mToken); pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken); @@ -1640,6 +1694,10 @@ final class WindowState implements WindowManagerPolicy.WindowState { if (!mRelayoutCalled) { pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled); } + if (mSurfaceResized || mSurfaceDestroyDeferred) { + pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized); + pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred); + } if (mXOffset != 0 || mYOffset != 0) { pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset); pw.print(" y="); pw.println(mYOffset); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java index 1d97e15..a640a91 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java @@ -79,12 +79,16 @@ public final class BridgeWindowSession implements IWindowSession { } public int relayout(IWindow arg0, int seq, LayoutParams arg1, int arg2, int arg3, int arg4, - boolean arg4_5, Rect arg5, Rect arg6, Rect arg7, Configuration arg7b, Surface arg8) + int arg4_5, Rect arg5, Rect arg6, Rect arg7, Configuration arg7b, Surface arg8) throws RemoteException { // pass for now. return 0; } + public void performDeferredDestroy(IWindow window) { + // pass for now. + } + public boolean outOfMemory(IWindow window) throws RemoteException { return false; } |
