From 0586a1b77a788a119166a37fccd909bf9ed65f23 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Sun, 6 Sep 2009 21:08:27 -0700 Subject: [PATCH] Fix issue #2095422: Some fades from opaque to transparent don't work ViewRoot was using Surface.clear(), which has different behavior in different processes -- in the system process it would kill the surface, causing all windows in that process to immediately disappear instead of animating away. This change makes Surface.release() public and uses that instead. It also renames Surface.clear() to Surface.destroy(). Also fixed some issues in the window manager that were causing the wallpaper to not get immediately resized when the orientation changes and its target window is removed and re-added. Change-Id: I2a992e365cf5747511f0bf1193db32dc2525b218 --- .../service/wallpaper/WallpaperService.java | 3 +- core/java/android/view/Surface.java | 12 +- core/java/android/view/ViewRoot.java | 4 +- core/jni/android_view_Surface.cpp | 4 +- .../android/server/WindowManagerService.java | 145 ++++++++++++++---- 5 files changed, 130 insertions(+), 38 deletions(-) diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 2cdfc665f69f1..2e4f1d2fb7510 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -377,6 +377,7 @@ public abstract class WallpaperService extends Service { if (!mCreated) { mLayout.type = mIWallpaperEngine.mWindowType; mLayout.gravity = Gravity.LEFT|Gravity.TOP; + mLayout.setTitle(WallpaperService.this.getClass().getName()); mLayout.windowAnimations = com.android.internal.R.style.Animation_Wallpaper; mSession.add(mWindow, mLayout, View.VISIBLE, mContentInsets); @@ -558,7 +559,7 @@ public abstract class WallpaperService extends Service { mSession.remove(mWindow); } catch (RemoteException e) { } - mSurfaceHolder.mSurface.clear(); + mSurfaceHolder.mSurface.release(); mCreated = false; } } diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 5cecac31266e5..b85667bdb321a 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -181,7 +181,7 @@ public class Surface implements Parcelable { public Surface(SurfaceSession s, int pid, int display, int w, int h, int format, int flags) throws OutOfResourcesException { - mCanvas = new Canvas(); + mCanvas = new CompatibleCanvas(); init(s,pid,display,w,h,format,flags); } @@ -271,8 +271,12 @@ public class Surface implements Parcelable { */ public native boolean isValid(); - /** Call this free the surface up. {@hide} */ - public native void clear(); + /** Free all server-side state associated with this surface and + * release this object's reference. {@hide} */ + public native void destroy(); + + /** Release the local reference to the server-side surface. @hide */ + public native void release(); /** draw into a surface */ public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException, IllegalArgumentException @@ -400,6 +404,4 @@ public class Surface implements Parcelable { throws OutOfResourcesException; private native void init(Parcel source); - - private native void release(); } diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index fafe00f417094..b61465a74bf36 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -1575,7 +1575,7 @@ public final class ViewRoot extends Handler implements ViewParent, if (mUseGL) { destroyGL(); } - mSurface.clear(); + mSurface.release(); try { sWindowSession.remove(mWindow); @@ -2532,7 +2532,7 @@ public final class ViewRoot extends Handler implements ViewParent, } } - mSurface.clear(); + mSurface.release(); } if (mAdded) { mAdded = false; diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 02677f4daa400..40c8aa0b4821b 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -214,7 +214,7 @@ static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel) setSurface(env, clazz, rhs); } -static void Surface_clear(JNIEnv* env, jobject clazz, uintptr_t *ostack) +static void Surface_destroy(JNIEnv* env, jobject clazz, uintptr_t *ostack) { const sp& surface(getSurfaceControl(env, clazz)); if (SurfaceControl::isValid(surface)) { @@ -622,7 +622,7 @@ static JNINativeMethod gSurfaceMethods[] = { {"nativeClassInit", "()V", (void*)nativeClassInit }, {"init", "(Landroid/view/SurfaceSession;IIIIII)V", (void*)Surface_init }, {"init", "(Landroid/os/Parcel;)V", (void*)Surface_initParcel }, - {"clear", "()V", (void*)Surface_clear }, + {"destroy", "()V", (void*)Surface_destroy }, {"release", "()V", (void*)Surface_release }, {"copyFrom", "(Landroid/view/Surface;)V", (void*)Surface_copyFrom }, {"isValid", "()Z", (void*)Surface_isValid }, diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index b4f47681f665d..c8ff6cbae3f6a 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -1207,8 +1207,11 @@ public class WindowManagerService extends IWindowManager.Stub || mLowerWallpaperTarget != null; } - boolean adjustWallpaperWindowsLocked() { - boolean changed = false; + static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1; + static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2; + + int adjustWallpaperWindowsLocked() { + int changed = 0; final int dw = mDisplay.getWidth(); final int dh = mDisplay.getHeight(); @@ -1274,12 +1277,12 @@ public class WindowManagerService extends IWindowManager.Stub if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) { if (DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper not changing: waiting for app anim in current target"); - return false; + return 0; } if (foundW != null && foundW.mAppToken != null) { if (DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper not changing: waiting for app anim in found target"); - return false; + return 0; } } @@ -1410,7 +1413,13 @@ public class WindowManagerService extends IWindowManager.Stub while (curTokenIndex > 0) { curTokenIndex--; WindowToken token = mWallpaperTokens.get(curTokenIndex); - token.hidden = !visible; + if (token.hidden == visible) { + changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED; + token.hidden = !visible; + // Need to do a layout to ensure the wallpaper now has the + // correct size. + mLayoutNeeded = true; + } int curWallpaperIndex = token.windows.size(); while (curWallpaperIndex > 0) { @@ -1463,7 +1472,7 @@ public class WindowManagerService extends IWindowManager.Stub + " from " + oldIndex + " to " + foundI); localmWindows.add(foundI, wallpaper); - changed = true; + changed |= ADJUST_WALLPAPER_LAYERS_CHANGED; } } @@ -1574,7 +1583,12 @@ public class WindowManagerService extends IWindowManager.Stub while (curTokenIndex > 0) { curTokenIndex--; WindowToken token = mWallpaperTokens.get(curTokenIndex); - token.hidden = !visible; + if (token.hidden == visible) { + token.hidden = !visible; + // Need to do a layout to ensure the wallpaper now has the + // correct size. + mLayoutNeeded = true; + } int curWallpaperIndex = token.windows.size(); while (curWallpaperIndex > 0) { @@ -1999,10 +2013,15 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mWindowMap) { WindowState w = windowForClientLocked(session, client); if ((w != null) && (w.mSurface != null)) { + if (SHOW_TRANSACTIONS) Log.i(TAG, ">>> OPEN TRANSACTION"); Surface.openTransaction(); try { + if (SHOW_TRANSACTIONS) Log.i( + TAG, " SURFACE " + w.mSurface + + ": transparentRegionHint=" + region); w.mSurface.setTransparentRegionHint(region); } finally { + if (SHOW_TRANSACTIONS) Log.i(TAG, "<<< CLOSE TRANSACTION"); Surface.closeTransaction(); } } @@ -2149,13 +2168,17 @@ public class WindowManagerService extends IWindowManager.Stub Surface surface = win.createSurfaceLocked(); if (surface != null) { outSurface.copyFrom(surface); + if (SHOW_TRANSACTIONS) Log.i(TAG, + " OUT SURFACE " + outSurface + ": copied"); } else { - outSurface.clear(); + // For some reason there isn't a surface. Clear the + // caller's object so they see the same state. + outSurface.release(); } } catch (Exception e) { Log.w(TAG, "Exception thrown when creating surface for client " - + client + " (" + win.mAttrs.getTitle() + ")", - e); + + client + " (" + win.mAttrs.getTitle() + ")", + e); Binder.restoreCallingIdentity(origId); return 0; } @@ -2196,7 +2219,11 @@ public class WindowManagerService extends IWindowManager.Stub } } } - outSurface.clear(); + // We are being 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. + outSurface.release(); } if (focusMayChange) { @@ -2217,7 +2244,7 @@ public class WindowManagerService extends IWindowManager.Stub } } if (wallpaperMayMove) { - if (adjustWallpaperWindowsLocked()) { + if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { assignLayers = true; } } @@ -6281,6 +6308,8 @@ public class WindowManagerService extends IWindowManager.Stub if (localLOGV) Log.v( TAG, "First window added to " + this + ", creating SurfaceSession"); mSurfaceSession = new SurfaceSession(); + if (SHOW_TRANSACTIONS) Log.i( + TAG, " NEW SURFACE SESSION " + mSurfaceSession); mSessions.add(this); } mNumWindow++; @@ -6298,6 +6327,8 @@ public class WindowManagerService extends IWindowManager.Stub if (localLOGV) Log.v( TAG, "Last window removed from " + this + ", destroying " + mSurfaceSession); + if (SHOW_TRANSACTIONS) Log.i( + TAG, " KILL SURFACE SESSION " + mSurfaceSession); try { mSurfaceSession.kill(); } catch (Exception e) { @@ -6794,6 +6825,12 @@ public class WindowManagerService extends IWindowManager.Stub mSurface = new Surface( mSession.mSurfaceSession, mSession.mPid, 0, w, h, mAttrs.format, flags); + if (SHOW_TRANSACTIONS) Log.i(TAG, " CREATE SURFACE " + + mSurface + " IN SESSION " + + mSession.mSurfaceSession + + ": pid=" + mSession.mPid + " format=" + + mAttrs.format + " flags=0x" + + Integer.toHexString(flags)); } catch (Surface.OutOfResourcesException e) { Log.w(TAG, "OutOfResourcesException creating surface"); reclaimSomeSurfaceMemoryLocked(this, "create"); @@ -6823,6 +6860,8 @@ public class WindowManagerService extends IWindowManager.Stub mSurface.setLayer(mAnimLayer); mSurface.hide(); if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) { + if (SHOW_TRANSACTIONS) Log.i(TAG, " SURFACE " + + mSurface + ": DITHER"); mSurface.setFlags(Surface.SURFACE_DITHER, Surface.SURFACE_DITHER); } @@ -6868,7 +6907,7 @@ public class WindowManagerService extends IWindowManager.Stub Log.i(TAG, " SURFACE " + mSurface + ": DESTROY (" + mAttrs.getTitle() + ")", ex); } - mSurface.clear(); + mSurface.destroy(); } catch (RuntimeException e) { Log.w(TAG, "Exception thrown when destroying Window " + this + " surface " + mSurface + " session " + mSession @@ -8840,6 +8879,8 @@ public class WindowManagerService extends IWindowManager.Stub if (w.commitFinishDrawingLocked(currentTime)) { if ((w.mAttrs.flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { + if (DEBUG_WALLPAPER) Log.v(TAG, + "First draw done in potential wallpaper target " + w); wallpaperMayChange = true; } } @@ -9134,10 +9175,23 @@ public class WindowManagerService extends IWindowManager.Stub } if (wallpaperMayChange) { - if (adjustWallpaperWindowsLocked()) { + if (DEBUG_WALLPAPER) Log.v(TAG, + "Wallpaper may change! Adjusting"); + int adjResult = adjustWallpaperWindowsLocked(); + if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { + if (DEBUG_WALLPAPER) Log.v(TAG, + "Wallpaper layer changed: assigning layers + relayout"); + restart = true; + mLayoutNeeded = true; assignLayersLocked(); + } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) { + if (DEBUG_WALLPAPER) Log.v(TAG, + "Wallpaper visibility changed: relayout"); + restart = true; + mLayoutNeeded = true; } if (mLayoutNeeded) { + restart = true; performLayoutLockedInner(); } } @@ -9184,6 +9238,10 @@ public class WindowManagerService extends IWindowManager.Stub w.mLastRequestedHeight = height; w.mLastShownFrame.set(w.mShownFrame); try { + if (SHOW_TRANSACTIONS) Log.i( + TAG, " SURFACE " + w.mSurface + + ": POS " + w.mShownFrame.left + + ", " + w.mShownFrame.top); w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top); } catch (RuntimeException e) { Log.w(TAG, "Error positioning surface in " + w, e); @@ -9196,14 +9254,6 @@ public class WindowManagerService extends IWindowManager.Stub width = w.mShownFrame.width(); height = w.mShownFrame.height(); w.mLastShownFrame.set(w.mShownFrame); - if (resize) { - if (SHOW_TRANSACTIONS) Log.i( - TAG, " SURFACE " + w.mSurface + ": (" - + w.mShownFrame.left + "," - + w.mShownFrame.top + ") (" - + w.mShownFrame.width() + "x" - + w.mShownFrame.height() + ")"); - } } if (resize) { @@ -9211,6 +9261,12 @@ public class WindowManagerService extends IWindowManager.Stub if (height < 1) height = 1; if (w.mSurface != null) { try { + if (SHOW_TRANSACTIONS) Log.i( + TAG, " SURFACE " + w.mSurface + ": POS " + + w.mShownFrame.left + "," + + w.mShownFrame.top + " SIZE " + + w.mShownFrame.width() + "x" + + w.mShownFrame.height()); w.mSurface.setSize(width, height); w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top); @@ -9239,6 +9295,22 @@ public class WindowManagerService extends IWindowManager.Stub w.mLastFrame.set(w.mFrame); w.mLastContentInsets.set(w.mContentInsets); w.mLastVisibleInsets.set(w.mVisibleInsets); + // If the screen is currently frozen, then keep + // it frozen until this window draws at its new + // orientation. + if (mDisplayFrozen) { + if (DEBUG_ORIENTATION) Log.v(TAG, + "Resizing while display frozen: " + w); + w.mOrientationChanging = true; + if (mWindowsFreezingScreen) { + mWindowsFreezingScreen = true; + // XXX should probably keep timeout from + // when we first froze the display. + mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); + mH.sendMessageDelayed(mH.obtainMessage( + H.WINDOW_FREEZE_TIMEOUT), 2000); + } + } // If the orientation is changing, then we need to // hold off on unfreezing the display until this // window has been redrawn; to do that, we need @@ -9340,7 +9412,11 @@ public class WindowManagerService extends IWindowManager.Stub w.mLastVScale = w.mVScale; if (SHOW_TRANSACTIONS) Log.i( TAG, " SURFACE " + w.mSurface + ": alpha=" - + w.mShownAlpha + " layer=" + w.mAnimLayer); + + w.mShownAlpha + " layer=" + w.mAnimLayer + + " matrix=[" + (w.mDsDx*w.mHScale) + + "," + (w.mDtDx*w.mVScale) + + "][" + (w.mDsDy*w.mHScale) + + "," + (w.mDtDy*w.mVScale) + "]"); if (w.mSurface != null) { try { w.mSurface.setAlpha(w.mShownAlpha); @@ -9571,6 +9647,8 @@ public class WindowManagerService extends IWindowManager.Stub i--; WindowState win = mResizingWindows.get(i); try { + if (DEBUG_ORIENTATION) Log.v(TAG, "Reporting new frame to " + + win + ": " + win.mFrame); win.mClient.resized(win.mFrame.width(), win.mFrame.height(), win.mLastContentInsets, win.mLastVisibleInsets, win.mDrawPending); @@ -9642,7 +9720,7 @@ public class WindowManagerService extends IWindowManager.Stub mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS); } if (wallpaperDestroyed) { - needRelayout = adjustWallpaperWindowsLocked(); + needRelayout = adjustWallpaperWindowsLocked() != 0; } if (needRelayout) { requestAnimationLocked(0); @@ -9720,7 +9798,7 @@ public class WindowManagerService extends IWindowManager.Stub + " token=" + win.mToken + " pid=" + ws.mSession.mPid + " uid=" + ws.mSession.mUid); - ws.mSurface.clear(); + ws.mSurface.destroy(); ws.mSurface = null; mForceRemoves.add(ws); i--; @@ -9730,7 +9808,7 @@ public class WindowManagerService extends IWindowManager.Stub Log.w(TAG, "LEAKED SURFACE (app token hidden): " + ws + " surface=" + ws.mSurface + " token=" + win.mAppToken); - ws.mSurface.clear(); + ws.mSurface.destroy(); ws.mSurface = null; leakedSurface = true; } @@ -9766,7 +9844,7 @@ public class WindowManagerService extends IWindowManager.Stub // surface and ask the app to request another one. Log.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry."); if (surface != null) { - surface.clear(); + surface.destroy(); win.mSurface = null; } @@ -10025,6 +10103,16 @@ public class WindowManagerService extends IWindowManager.Stub w.dump(pw, " "); } } + if (mResizingWindows.size() > 0) { + pw.println(" "); + pw.println(" Windows waiting to resize:"); + for (int i=mResizingWindows.size()-1; i>=0; i--) { + WindowState w = mResizingWindows.get(i); + pw.print(" Resizing #"); pw.print(i); pw.print(' '); + pw.print(w); pw.println(":"); + w.dump(pw, " "); + } + } if (mSessions.size() > 0) { pw.println(" "); pw.println(" All active sessions:"); @@ -10227,7 +10315,8 @@ public class WindowManagerService extends IWindowManager.Stub mDimSurface.setLayer(w.mAnimLayer-1); final float target = w.mExiting ? 0 : w.mAttrs.dimAmount; - if (SHOW_TRANSACTIONS) Log.i(TAG, "layer=" + (w.mAnimLayer-1) + ", target=" + target); + if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface + + ": layer=" + (w.mAnimLayer-1) + " target=" + target); if (mDimTargetAlpha != target) { // If the desired dim level has changed, then // start an animation to it.