diff options
5 files changed, 61 insertions, 37 deletions
diff --git a/core/java/android/util/MergedConfiguration.java b/core/java/android/util/MergedConfiguration.java index 68d0309cfc9e..ae6605043b2e 100644 --- a/core/java/android/util/MergedConfiguration.java +++ b/core/java/android/util/MergedConfiguration.java @@ -161,6 +161,21 @@ public class MergedConfiguration implements Parcelable { return "{mGlobalConfig=" + mGlobalConfig + " mOverrideConfig=" + mOverrideConfig + "}"; } + @Override + public int hashCode() { + return mMergedConfig.hashCode(); + } + + @Override + public boolean equals(Object that) { + if (!(that instanceof MergedConfiguration)) { + return false; + } + + if (that == this) return true; + return mMergedConfig.equals(((MergedConfiguration) that).mMergedConfig); + } + public void dump(PrintWriter pw, String prefix) { pw.println(prefix + "mGlobalConfig=" + mGlobalConfig); pw.println(prefix + "mOverrideConfig=" + mOverrideConfig); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e27eab92319b..e38a55f76b7d 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1904,14 +1904,16 @@ public final class ViewRootImpl implements ViewParent, + " outsets=" + mPendingOutsets.toShortString() + " surface=" + mSurface); - final Configuration pendingMergedConfig = - mPendingMergedConfiguration.getMergedConfiguration(); - if (pendingMergedConfig.seq != 0) { + // If the pending {@link MergedConfiguration} handed back from + // {@link #relayoutWindow} does not match the one last reported, + // WindowManagerService has reported back a frame from a configuration not yet + // handled by the client. In this case, we need to accept the configuration so we + // do not lay out and draw with the wrong configuration. + if (!mPendingMergedConfiguration.equals(mLastReportedMergedConfiguration)) { if (DEBUG_CONFIGURATION) Log.v(mTag, "Visible with new config: " - + pendingMergedConfig); + + mPendingMergedConfiguration.getMergedConfiguration()); performConfigurationChange(mPendingMergedConfiguration, !mFirst, INVALID_DISPLAY /* same display */); - pendingMergedConfig.seq = 0; updatedConfiguration = true; } @@ -3596,6 +3598,13 @@ public final class ViewRootImpl implements ViewParent, mView.setLayoutDirection(currentLayoutDirection); } mView.dispatchConfigurationChanged(config); + + // We could have gotten this {@link Configuration} update after we called + // {@link #performTraversals} with an older {@link Configuration}. As a result, our + // window frame may be stale. We must ensure the next pass of {@link #performTraversals} + // catches this. + mForceNextWindowRelayout = true; + requestLayout(); } } @@ -3757,10 +3766,10 @@ public final class ViewRootImpl implements ViewParent, SomeArgs args = (SomeArgs) msg.obj; final int displayId = args.argi3; - final MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg4; + MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg4; final boolean displayChanged = mDisplay.getDisplayId() != displayId; - if (mergedConfiguration != null) { + if (!mLastReportedMergedConfiguration.equals(mergedConfiguration)) { // If configuration changed - notify about that and, maybe, about move to // display. performConfigurationChange(mergedConfiguration, false /* force */, @@ -6094,7 +6103,7 @@ public final class ViewRootImpl implements ViewParent, if (params != null) { if (DBG) Log.d(mTag, "WindowLayout in layoutWindow:" + params); } - mPendingMergedConfiguration.getMergedConfiguration().seq = 0; + //Log.d(mTag, ">>>>>> CALLING relayout"); if (params != null && mOrigWindowType != params.type) { // For compatibility with old apps, don't crash here. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index ceddc4e23fe5..613c830f31f2 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -30,7 +30,6 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.Process.ROOT_UID; import static android.os.Process.SHELL_UID; import static android.os.Process.SYSTEM_UID; -import static android.os.Process.THREAD_PRIORITY_DISPLAY; import static android.os.Process.myPid; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.os.UserHandle.USER_NULL; @@ -50,7 +49,6 @@ import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHA import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; @@ -233,7 +231,6 @@ import com.android.server.DisplayThread; import com.android.server.EventLogTags; import com.android.server.FgThread; import com.android.server.LocalServices; -import com.android.server.ThreadPriorityBooster; import com.android.server.UiThread; import com.android.server.Watchdog; import com.android.server.input.InputManagerService; @@ -2020,8 +2017,7 @@ public class WindowManagerService extends IWindowManager.Stub win.setDisplayLayoutNeeded(); mWindowPlacerLocked.performSurfacePlacement(true); } - result = win.relayoutVisibleWindow(mergedConfiguration, result, attrChanges, - oldVisibility); + result = win.relayoutVisibleWindow(result, attrChanges, oldVisibility); try { result = createSurfaceControl(outSurface, result, win, winAnimator); @@ -2159,6 +2155,15 @@ public class WindowManagerService extends IWindowManager.Stub if (!win.isGoneForLayoutLw()) { win.mResizedWhileGone = false; } + + // We must always send the latest {@link MergedConfiguration}, regardless of whether we + // have already reported it. The client might not have processed the previous value yet + // and needs process it before handling the corresponding window frame. the variable + // {@code mergedConfiguration} is an out parameter that will be passed back to the + // client over IPC and checked there. + win.getMergedConfiguration(mergedConfiguration); + win.setReportedConfiguration(mergedConfiguration); + outFrame.set(win.mCompatFrame); outOverscanInsets.set(win.mOverscanInsets); outContentInsets.set(win.mContentInsets); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index f74948f8e7f0..d1fbf900ef70 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2207,8 +2207,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - void prepareWindowToDisplayDuringRelayout(MergedConfiguration mergedConfiguration, - boolean wasVisible) { + void prepareWindowToDisplayDuringRelayout(boolean wasVisible) { // We need to turn on screen regardless of visibility. if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) { if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this); @@ -2230,16 +2229,16 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (isDrawnLw() && mService.okToDisplay()) { mWinAnimator.applyEnterAnimationLocked(); } + } - if (isConfigChanged()) { - final Configuration globalConfig = mService.mRoot.getConfiguration(); - final Configuration overrideConfig = getMergedOverrideConfiguration(); - mergedConfiguration.setConfiguration(globalConfig, overrideConfig); - if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this - + " visible with new global config: " + globalConfig - + " merged override config: " + overrideConfig); - mLastReportedConfiguration.setTo(getConfiguration()); - } + void getMergedConfiguration(MergedConfiguration outConfiguration) { + final Configuration globalConfig = mService.mRoot.getConfiguration(); + final Configuration overrideConfig = getMergedOverrideConfiguration(); + outConfiguration.setConfiguration(globalConfig, overrideConfig); + } + + void setReportedConfiguration(MergedConfiguration config) { + mLastReportedConfiguration.setTo(config.getMergedConfiguration()); } void adjustStartingWindowFlags() { @@ -3005,14 +3004,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP try { if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this + ": " + mCompatFrame); - final MergedConfiguration mergedConfiguration; - if (isConfigChanged()) { - mergedConfiguration = new MergedConfiguration(mService.mRoot.getConfiguration(), - getMergedOverrideConfiguration()); - mLastReportedConfiguration.setTo(mergedConfiguration.getMergedConfiguration()); - } else { - mergedConfiguration = null; - } + final MergedConfiguration mergedConfiguration = + new MergedConfiguration(mService.mRoot.getConfiguration(), + getMergedOverrideConfiguration()); + + setReportedConfiguration(mergedConfiguration); + if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == DRAW_PENDING) Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING"); @@ -4342,8 +4339,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return !mLastSurfaceInsets.equals(mAttrs.surfaceInsets); } - int relayoutVisibleWindow(MergedConfiguration mergedConfiguration, int result, int attrChanges, - int oldVisibility) { + int relayoutVisibleWindow(int result, int attrChanges, int oldVisibility) { final boolean wasVisible = isVisibleLw(); result |= (!wasVisible || !isDrawnLw()) ? RELAYOUT_RES_FIRST_TIME : 0; @@ -4366,7 +4362,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mWinAnimator.mEnteringAnimation = true; - prepareWindowToDisplayDuringRelayout(mergedConfiguration, wasVisible); + prepareWindowToDisplayDuringRelayout(wasVisible); if ((attrChanges & FORMAT_CHANGED) != 0) { // If the format can't be changed in place, preserve the old surface until the app draws diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java index c809c325726f..67db5f4d12dd 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java @@ -218,8 +218,7 @@ public class WindowStateTests extends WindowTestsBase { root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; root.mTurnOnScreen = false; - root.prepareWindowToDisplayDuringRelayout(new MergedConfiguration(), - wasVisible /*wasVisible*/); + root.prepareWindowToDisplayDuringRelayout(wasVisible /*wasVisible*/); assertTrue(root.mTurnOnScreen); } } |