summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Bryce Lee <brycelee@google.com> 2017-01-24 11:05:01 -0800
committer Bryce Lee <brycelee@google.com> 2017-01-31 16:07:29 -0800
commitf0a6fdbf53882949db0a141693dd33302b42d51b (patch)
tree6d771994263d5a97a61dac3f9b613fda59bc64fd
parent9f5d2b08868a990bc4d1f6b0bbf52bf14b60c3af (diff)
Allow opening activity to specify orientation.
An activity's window is initially not visible. This means it is not accounted for until it becomes visible, which means requested orientations will not be honored until after onCreate. This changelist removes the visibility check previously used determining the orientation. This changelist also addresses an issue where an ActivityRecord member variable tracking the last configuration sent was not being initially updated. Fixes: 33844887 Fixes: 33814250 Fixes: 34165818 Fixes: 34177026 Fixes: 33809086 Fixes: 34111451 Test: Verified reported issues fixed in apps mentioned in bugs Test: Added additional unit tests to exercise override getOrientation. Change-Id: I26b7e808b6f3d857543e3a187b6c318e88afa063 Signed-off-by: Bryce Lee <brycelee@google.com>
-rw-r--r--services/core/java/com/android/server/am/ActivityRecord.java15
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java14
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java58
6 files changed, 90 insertions, 22 deletions
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index baf777220691..38b36a677a4d 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1899,11 +1899,22 @@ final class ActivityRecord implements AppWindowContainerListener {
task.taskId, requestedOrientation);
}
- // TODO: now used only in one place to address race-condition. Remove when that will be fixed.
- void setLastReportedConfiguration(@NonNull Configuration config) {
+ /**
+ * Set the last reported global configuration to the client. Should be called whenever a new
+ * global configuration is sent to the client for this activity.
+ */
+ void setLastReportedGlobalConfiguration(@NonNull Configuration config) {
mLastReportedConfiguration.setTo(config);
}
+ /**
+ * Set the last reported merged configuration to the client. Should be called whenever a new
+ * merged configuration is sent to the client for this activity.
+ */
+ void setLastReportedMergedOverrideConfiguration(@NonNull Configuration config) {
+ mLastReportedOverrideConfiguration.setTo(config);
+ }
+
/** Call when override config was sent to the Window Manager to update internal records. */
void onOverrideConfigurationSent() {
mLastReportedOverrideConfiguration.setTo(task.getMergedOverrideConfiguration());
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index b2b3e61ca534..ef06fc581ebb 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1333,10 +1333,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Because we could be starting an Activity in the system process this may not go across
// a Binder interface which would create a new Configuration. Consequently we have to
// always create a new Configuration here.
+
+ final Configuration globalConfiguration =
+ new Configuration(mService.getGlobalConfiguration());
+ r.setLastReportedGlobalConfiguration(globalConfiguration);
+ final Configuration mergedOverrideConfiguration =
+ new Configuration(task.getMergedOverrideConfiguration());
+ r.setLastReportedMergedOverrideConfiguration(mergedOverrideConfiguration);
+
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
- new Configuration(mService.getGlobalConfiguration()),
- new Configuration(task.getMergedOverrideConfiguration()), r.compat,
+ globalConfiguration,
+ mergedOverrideConfiguration, r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
@@ -1731,7 +1739,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// We'll update with whatever configuration it now says
// it used to launch.
if (config != null) {
- r.setLastReportedConfiguration(config);
+ r.setLastReportedGlobalConfiguration(config);
}
// We are now idle. If someone is waiting for a thumbnail from
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index bcc720d05424..d64376973616 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1151,10 +1151,11 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
*/
@Override
int getOrientation() {
- if (hidden || hiddenRequested) {
- return SCREEN_ORIENTATION_UNSET;
+ if (fillsParent() && (isVisible() || mService.mOpeningApps.contains(this))) {
+ return mOrientation;
}
- return mOrientation;
+
+ return SCREEN_ORIENTATION_UNSET;
}
/** Returns the app's preferred orientation regardless of its currently visibility state. */
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 5b96263b1817..5e25da31d4eb 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -510,14 +510,13 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon
* specification...
*/
int getOrientation() {
-
- if (!fillsParent() || !isVisible()) {
- // Ignore invisible containers or containers that don't completely fills their parents.
+ if (!fillsParent()) {
+ // Ignore containers that don't completely fills their parents.
return SCREEN_ORIENTATION_UNSET;
}
- // The container fills its parent so we can use it orientation if it has one specified,
- // otherwise we prefer to use the orientation of its topmost child that has one
+ // The container fills its parent and is visible so we can use it orientation if it has one
+ // specified; otherwise we prefer to use the orientation of its topmost child that has one
// specified and fall back on this container's unset or unspecified value as a candidate
// if none of the children have a better candidate for the orientation.
if (mOrientation != SCREEN_ORIENTATION_UNSET
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d62c62e7b328..88c6d2742650 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2441,6 +2441,15 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ /**
+ * Updates the device orientation from the present app tokens.
+ *
+ * Note: A place this is method called is before an {@link android.app.Activity} starts to
+ * ensure that it is created in the proper orientation. It is imperative that the present
+ * {@link AppWindowToken} specify that they can influence the orientation, accomplished with the
+ * override of {@link WindowContainer#canSpecifyOrientation()}. Visibility changes only will not
+ * guarantee this as other operations (such as freezing the screen) can defer these operations.
+ */
@Override
public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
IBinder freezeThisOneIfNeeded, int displayId) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
index 4f740ac46646..4f9cd9547a52 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
@@ -388,6 +388,32 @@ public class WindowContainerTests extends WindowTestsBase {
}
@Test
+ public void testGetOrientation_childSpecified() throws Exception {
+ testGetOrientation_childSpecifiedConfig(false, SCREEN_ORIENTATION_LANDSCAPE,
+ SCREEN_ORIENTATION_LANDSCAPE);
+ testGetOrientation_childSpecifiedConfig(false, SCREEN_ORIENTATION_UNSET,
+ SCREEN_ORIENTATION_UNSET);
+ }
+
+ private void testGetOrientation_childSpecifiedConfig(boolean childVisible, int childOrientation,
+ int expectedOrientation) {
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
+ final TestWindowContainer root = builder.setLayer(0).build();
+ root.setFillsParent(true);
+
+ builder.setIsVisible(childVisible);
+
+ if (childOrientation != SCREEN_ORIENTATION_UNSET) {
+ builder.setOrientation(childOrientation);
+ }
+
+ final TestWindowContainer child1 = root.addChildWindow(builder);
+ child1.setFillsParent(true);
+
+ assertTrue(root.getOrientation() == expectedOrientation);
+ }
+
+ @Test
public void testGetOrientation_Unset() throws Exception {
final TestWindowContainerBuilder builder = new TestWindowContainerBuilder();
final TestWindowContainer root = builder.setLayer(0).setIsVisible(true).build();
@@ -407,18 +433,17 @@ public class WindowContainerTests extends WindowTestsBase {
invisibleChild1VisibleAndSet.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
// Landscape well because the container is visible and that is what we set on it above.
assertEquals(SCREEN_ORIENTATION_LANDSCAPE, invisibleChild1VisibleAndSet.getOrientation());
- // Unset because the container isn't visible even though it has a child that thinks it is
- // visible.
- assertEquals(SCREEN_ORIENTATION_UNSET, invisible.getOrientation());
- // Unspecified because we are visible and we didn't specify an orientation and there isn't
- // a visible child.
- assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, root.getOrientation());
+ // Landscape because even though the container isn't visible it has a child that is
+ // specifying it can influence the orientation by being visible.
+ assertEquals(SCREEN_ORIENTATION_LANDSCAPE, invisible.getOrientation());
+ // Landscape because the grandchild is visible and therefore can participate.
+ assertEquals(SCREEN_ORIENTATION_LANDSCAPE, root.getOrientation());
builder.setIsVisible(true).setLayer(-3);
final TestWindowContainer visibleUnset = root.addChildWindow(builder);
visibleUnset.setOrientation(SCREEN_ORIENTATION_UNSET);
assertEquals(SCREEN_ORIENTATION_UNSET, visibleUnset.getOrientation());
- assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, root.getOrientation());
+ assertEquals(SCREEN_ORIENTATION_LANDSCAPE, root.getOrientation());
}
@@ -690,6 +715,7 @@ public class WindowContainerTests extends WindowTestsBase {
private boolean mIsAnimating;
private boolean mIsVisible;
private boolean mFillsParent;
+ private Integer mOrientation;
private boolean mOnParentSetCalled;
@@ -708,11 +734,13 @@ public class WindowContainerTests extends WindowTestsBase {
return 1;
};
- TestWindowContainer(int layer, boolean isAnimating, boolean isVisible) {
+ TestWindowContainer(int layer, boolean isAnimating, boolean isVisible,
+ Integer orientation) {
mLayer = layer;
mIsAnimating = isAnimating;
mIsVisible = isVisible;
mFillsParent = true;
+ mOrientation = orientation;
}
TestWindowContainer getParentWindow() {
@@ -758,6 +786,11 @@ public class WindowContainerTests extends WindowTestsBase {
}
@Override
+ int getOrientation() {
+ return mOrientation != null ? mOrientation : super.getOrientation();
+ }
+
+ @Override
boolean fillsParent() {
return mFillsParent;
}
@@ -771,6 +804,7 @@ public class WindowContainerTests extends WindowTestsBase {
private int mLayer;
private boolean mIsAnimating;
private boolean mIsVisible;
+ private Integer mOrientation;
public TestWindowContainerBuilder() {
reset();
@@ -791,15 +825,21 @@ public class WindowContainerTests extends WindowTestsBase {
return this;
}
+ TestWindowContainerBuilder setOrientation(int orientation) {
+ mOrientation = orientation;
+ return this;
+ }
+
TestWindowContainerBuilder reset() {
mLayer = 0;
mIsAnimating = false;
mIsVisible = false;
+ mOrientation = null;
return this;
}
TestWindowContainer build() {
- return new TestWindowContainer(mLayer, mIsAnimating, mIsVisible);
+ return new TestWindowContainer(mLayer, mIsAnimating, mIsVisible, mOrientation);
}
}
}