Allow foreground AppWindowToken to influence orientation.

It is possible for an activity to request an orientation after
finish has been called, causing the system orientation to be
re-evaluated. Since the activity is closing, it will no longer be
eligible to influence orientation. If another stack/task is brought
to the foreground, it will as well won't be able to participate
since it is not considered an opening app and won't be visible. As a
result, we set the orientation to unspecified, leading to the
foreground activity to be resumed in the wrong orientation.

This changelist addresses the issue by allowing an AppWindowToken to
participate in orientation calculations if it is not closing and is
on top of the wm hierarchy, regardless of its visibility.

Change-Id: I0f316d6d824398d084c7648cf2dc2c2d07b4410d
Fixes: 63982461
Fixes: 63513655
Test: bit FrameworksServicesTests:com.android.server.wm.AppWindowTokenTests#testGetOrientation
Test: go/wm-smoke
This commit is contained in:
Bryce Lee
2017-07-28 20:48:43 -07:00
parent 3cace2a148
commit 00d586d8f0
5 changed files with 30 additions and 1 deletions

View File

@@ -1311,7 +1311,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
// an Activity in another task being started in the wrong orientation during the transition.
if (!(sendingToBottom || mService.mClosingApps.contains(this))
&& (isVisible() || mService.mOpeningApps.contains(this))) {
&& (isVisible() || mService.mOpeningApps.contains(this) || isOnTop())) {
return mOrientation;
}

View File

@@ -3308,6 +3308,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
setLayoutNeeded();
}
@Override
boolean isOnTop() {
// Considered always on top
return true;
}
@Override
void positionChildAt(int position, TaskStack child, boolean includingParents) {
if (StackId.isAlwaysOnTop(child.mStackId) && position != POSITION_TOP) {

View File

@@ -472,6 +472,13 @@ class WindowContainer<E extends WindowContainer> implements Comparable<WindowCon
return false;
}
/**
a * Returns whether this child is on top of the window hierarchy.
*/
boolean isOnTop() {
return getParent().getTopChild() == this && getParent().isOnTop();
}
/** Returns the top child container. */
E getTopChild() {
return mChildren.peekLast();

View File

@@ -185,6 +185,11 @@ public class AppWindowTokenTests extends WindowTestsBase {
assertEquals(SCREEN_ORIENTATION_UNSET, token.getOrientation());
// Can specify orientation if the current orientation candidate is orientation behind.
assertEquals(SCREEN_ORIENTATION_LANDSCAPE, token.getOrientation(SCREEN_ORIENTATION_BEHIND));
token.sendingToBottom = false;
token.setIsOnTop(true);
// Allow for token to provide orientation hidden if on top and not being sent to bottom.
assertEquals(SCREEN_ORIENTATION_LANDSCAPE, token.getOrientation());
}
@Test

View File

@@ -89,6 +89,7 @@ public class WindowTestUtils {
/** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
public static class TestAppWindowToken extends AppWindowToken {
boolean mOnTop = false;
TestAppWindowToken(DisplayContent dc) {
super(dc.mService, new IApplicationToken.Stub() {}, false, dc, true /* fillsParent */,
@@ -125,6 +126,15 @@ public class WindowTestUtils {
int positionInParent() {
return getParent().mChildren.indexOf(this);
}
void setIsOnTop(boolean onTop) {
mOnTop = onTop;
}
@Override
boolean isOnTop() {
return mOnTop;
}
}
/* Used so we can gain access to some protected members of the {@link WindowToken} class */