diff options
| author | 2017-09-26 00:28:52 +0000 | |
|---|---|---|
| committer | 2017-09-26 00:28:52 +0000 | |
| commit | 6833a07a078af8eeb868aee269bbb1860c01f244 (patch) | |
| tree | c4853f0b89317e180b8be5d0f0f2c316cf677a5b | |
| parent | 17c797cece154a98ae935d3d7b529f85b21a1026 (diff) | |
| parent | 9626a900da810ba57b5bfc2ef284c294058f8dba (diff) | |
Merge "Restrict when a window receives new Configurations." into oc-mr1-dev am: d71227355e
am: 9626a900da
Change-Id: If2664499c9f4233fbbdea7b488fed761d6faf1c1
4 files changed, 41 insertions, 12 deletions
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 361d91a07e59..4dc2ab5334a1 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -2136,7 +2136,14 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai try { // Protect against recursion. mStackSupervisor.inResumeTopActivity = true; - result = resumeTopActivityInnerLocked(prev, options); + // The contained logic must be synchronized, since we are both changing the visibility + // and updating the {@link Configuration}. {@link ActivityRecord#setVisibility} will + // ultimately cause the client code to schedule a layout. Since layouts retrieve the + // current {@link Configuration}, we must ensure that the below code updates it before + // the layout can occur. + synchronized (mWindowManager.getWindowManagerLock()) { + result = resumeTopActivityInnerLocked(prev, options); + } } finally { mStackSupervisor.inResumeTopActivity = false; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 6a5f6fafb275..10adc5a65388 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2193,8 +2193,18 @@ public class WindowManagerService extends IWindowManager.Stub // 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); + // Note: in the cases where the window is tied to an activity, we should not send a + // configuration update when the window has requested to be hidden. Doing so can lead + // to the client erroneously accepting a configuration that would have otherwise caused + // an activity restart. We instead hand back the last reported + // {@link MergedConfiguration}. + if (win.mAppToken == null || !win.mAppToken.isClientHidden()) { + win.getMergedConfiguration(mergedConfiguration); + } else { + win.getLastReportedMergedConfiguration(mergedConfiguration); + } + + win.setLastReportedMergedConfiguration(mergedConfiguration); outFrame.set(win.mCompatFrame); outOverscanInsets.set(win.mOverscanInsets); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index eba7c3aa35ca..49a7944a97bd 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -257,7 +257,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * We'll send configuration to client only if it is different from the last applied one and * client won't perform unnecessary updates. */ - private final Configuration mLastReportedConfiguration = new Configuration(); + private final MergedConfiguration mLastReportedConfiguration = new MergedConfiguration(); /** * Actual position of the surface shown on-screen (may be modified by animation). These are @@ -1244,7 +1244,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // this is not necessarily what the client has processed yet. Find a // better indicator consistent with the client. return (mOrientationChanging || (isVisible() - && getConfiguration().orientation != mLastReportedConfiguration.orientation)) + && getConfiguration().orientation != getLastReportedConfiguration().orientation)) && !mSeamlesslyRotated && !mOrientationChangeTimedOut; } @@ -1758,7 +1758,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP /** Returns true if last applied config was not yet requested by client. */ boolean isConfigChanged() { - return !mLastReportedConfiguration.equals(getConfiguration()); + return !getLastReportedConfiguration().equals(getConfiguration()); } void onWindowReplacementTimeout() { @@ -2312,8 +2312,16 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP outConfiguration.setConfiguration(globalConfig, overrideConfig); } - void setReportedConfiguration(MergedConfiguration config) { - mLastReportedConfiguration.setTo(config.getMergedConfiguration()); + void setLastReportedMergedConfiguration(MergedConfiguration config) { + mLastReportedConfiguration.setTo(config); + } + + void getLastReportedMergedConfiguration(MergedConfiguration config) { + config.setTo(mLastReportedConfiguration); + } + + private Configuration getLastReportedConfiguration() { + return mLastReportedConfiguration.getMergedConfiguration(); } void adjustStartingWindowFlags() { @@ -2853,7 +2861,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP new MergedConfiguration(mService.mRoot.getConfiguration(), getMergedOverrideConfiguration()); - setReportedConfiguration(mergedConfiguration); + setLastReportedMergedConfiguration(mergedConfiguration); if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == DRAW_PENDING) Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING"); @@ -3254,7 +3262,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } pw.print(prefix); pw.print("mFullConfiguration="); pw.println(getConfiguration()); pw.print(prefix); pw.print("mLastReportedConfiguration="); - pw.println(mLastReportedConfiguration); + pw.println(getLastReportedConfiguration()); } pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface); pw.print(" mShownPosition="); mShownPosition.printShortString(pw); @@ -3314,7 +3322,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP pw.print(prefix); pw.print("mOrientationChanging="); pw.print(mOrientationChanging); pw.print(" configOrientationChanging="); - pw.print(mLastReportedConfiguration.orientation + pw.print(getLastReportedConfiguration().orientation != getConfiguration().orientation); pw.print(" mAppFreezing="); pw.print(mAppFreezing); pw.print(" mTurnOnScreen="); pw.print(mTurnOnScreen); diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java index 0315c8d6f9ba..1aafac66bae4 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java @@ -32,6 +32,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.res.Configuration.EMPTY; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * A collection of static functions that can be referenced by other test packages to provide access @@ -51,7 +52,10 @@ public class WindowTestUtils { * Retrieves an instance of a mock {@link WindowManagerService}. */ public static WindowManagerService getMockWindowManagerService() { - return mock(WindowManagerService.class); + final WindowManagerService service = mock(WindowManagerService.class); + final WindowHashMap windowMap = new WindowHashMap(); + when(service.getWindowManagerLock()).thenReturn(windowMap); + return service; } /** |