Merge "Restrict when a window receives new Configurations." into oc-mr1-dev am: d71227355e
am: 9626a900da
Change-Id: If2664499c9f4233fbbdea7b488fed761d6faf1c1
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 361d91a..4dc2ab5 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 @@
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 6a5f6fa..10adc5a 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 @@
// 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 eba7c3a..49a7944 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 @@
* 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 @@
// 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 @@
/** 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 @@
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 @@
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 @@
}
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 @@
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 0315c8d..1aafac6 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.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 @@
* 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;
}
/**