diff options
Diffstat (limited to 'services')
5 files changed, 166 insertions, 31 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 780c0d2..aea31a8 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -89,6 +89,12 @@ static const int kRecordThreadSleepUs = 5000; static const nsecs_t kSetParametersTimeout = seconds(2); +// minimum sleep time for the mixer thread loop when tracks are active but in underrun +static const uint32_t kMinThreadSleepTimeUs = 5000; +// maximum divider applied to the active sleep time in the mixer thread loop +static const uint32_t kMaxThreadSleepTimeShift = 2; + + // ---------------------------------------------------------------------------- static bool recordingAllowed() { @@ -1846,6 +1852,7 @@ bool AudioFlinger::MixerThread::threadLoop() uint32_t activeSleepTime = activeSleepTimeUs(); uint32_t idleSleepTime = idleSleepTimeUs(); uint32_t sleepTime = idleSleepTime; + uint32_t sleepTimeShift = 0; Vector< sp<EffectChain> > effectChains; #ifdef DEBUG_CPU_USAGE ThreadCpuUsage cpu; @@ -1937,6 +1944,7 @@ bool AudioFlinger::MixerThread::threadLoop() standbyTime = systemTime() + kStandbyTimeInNsecs; sleepTime = idleSleepTime; + sleepTimeShift = 0; continue; } } @@ -1953,6 +1961,10 @@ bool AudioFlinger::MixerThread::threadLoop() // mix buffers... mAudioMixer->process(); sleepTime = 0; + // increase sleep time progressively when application underrun condition clears + if (sleepTimeShift > 0) { + sleepTimeShift--; + } standbyTime = systemTime() + kStandbyTimeInNsecs; //TODO: delay standby when effects have a tail } else { @@ -1960,7 +1972,17 @@ bool AudioFlinger::MixerThread::threadLoop() // buffer size, then write 0s to the output if (sleepTime == 0) { if (mixerStatus == MIXER_TRACKS_ENABLED) { - sleepTime = activeSleepTime; + sleepTime = activeSleepTime >> sleepTimeShift; + if (sleepTime < kMinThreadSleepTimeUs) { + sleepTime = kMinThreadSleepTimeUs; + } + // reduce sleep time in case of consecutive application underruns to avoid + // starving the audio HAL. As activeSleepTimeUs() is larger than a buffer + // duration we would end up writing less data than needed by the audio HAL if + // the condition persists. + if (sleepTimeShift < kMaxThreadSleepTimeShift) { + sleepTimeShift++; + } } else { sleepTime = idleSleepTime; } diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 6b23b33..2a0d2a0 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -1689,6 +1689,11 @@ public class PowerManagerService extends IPowerManager.Stub // before showing it to the user. We want the light off // until it is ready to be shown to the user, not it using // whatever the last value it had. + if (DEBUG_SCREEN_ON) { + Slog.i(TAG, "Forcing brightness 0: mPowerState=0x" + + Integer.toHexString(mPowerState) + + " mSkippedScreenOn=" + mSkippedScreenOn); + } mScreenBrightness.forceValueLocked(Power.BRIGHTNESS_OFF); } } @@ -2038,12 +2043,14 @@ public class PowerManagerService extends IPowerManager.Stub } finally { Binder.restoreCallingIdentity(identity); } - mScreenBrightness.setTargetLocked(brightness, steps, - INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); - if (DEBUG_SCREEN_ON) { - RuntimeException e = new RuntimeException("here"); - e.fillInStackTrace(); - Slog.i(TAG, "Setting screen brightness: " + brightness, e); + if (!mSkippedScreenOn) { + mScreenBrightness.setTargetLocked(brightness, steps, + INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); + if (DEBUG_SCREEN_ON) { + RuntimeException e = new RuntimeException("here"); + e.fillInStackTrace(); + Slog.i(TAG, "Setting screen brightness: " + brightness, e); + } } } @@ -2086,6 +2093,11 @@ public class PowerManagerService extends IPowerManager.Stub ? LightsService.BRIGHTNESS_MODE_SENSOR : LightsService.BRIGHTNESS_MODE_USER); if ((mask & SCREEN_BRIGHT_BIT) != 0) { + if (DEBUG_SCREEN_ON) { + RuntimeException e = new RuntimeException("here"); + e.fillInStackTrace(); + Slog.i(TAG, "Set LCD brightness: " + value, e); + } mLcdLight.setBrightness(value, brightnessMode); } if ((mask & BUTTON_BRIGHT_BIT) != 0) { @@ -2137,7 +2149,7 @@ public class PowerManagerService extends IPowerManager.Stub delta = (targetValue - (nominalCurrentValue >= 0 ? nominalCurrentValue : curValue)) / stepsToTarget; - if (mSpew) { + if (mSpew || DEBUG_SCREEN_ON) { String noticeMe = nominalCurrentValue == curValue ? "" : " ******************"; Slog.i(TAG, "setTargetLocked mask=" + mask + " curValue=" + curValue + " target=" + target + " targetValue=" + targetValue + " delta=" + delta @@ -2527,8 +2539,10 @@ public class PowerManagerService extends IPowerManager.Stub } if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) { - mScreenBrightness.setTargetLocked(lcdValue, AUTOBRIGHTNESS_ANIM_STEPS, - INITIAL_SCREEN_BRIGHTNESS, (int)mScreenBrightness.curValue); + if (!mSkippedScreenOn) { + mScreenBrightness.setTargetLocked(lcdValue, AUTOBRIGHTNESS_ANIM_STEPS, + INITIAL_SCREEN_BRIGHTNESS, (int)mScreenBrightness.curValue); + } } if (mButtonBrightnessOverride < 0) { mButtonLight.setBrightness(buttonValue); 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); |