Notify client to clear intermediate rotated adjustments am: 8fea9c8e89

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13660605

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I6842db2e211bce2997293b66b2888aa49f1d7f75
This commit is contained in:
Riddle Hsu
2021-02-22 17:16:49 +00:00
committed by Automerger Merge Worker
3 changed files with 43 additions and 7 deletions

View File

@@ -1513,6 +1513,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
final int rotation = rotationForActivityInDifferentOrientation(r);
if (rotation == ROTATION_UNDEFINED) {
// The display rotation won't be changed by current top activity. The client side
// adjustments of previous rotated activity should be cleared earlier. Otherwise if
// the current top is in the same process, it may get the rotated state. The transform
// will be cleared later with transition callback to ensure smooth animation.
if (hasTopFixedRotationLaunchingApp()) {
mFixedRotationLaunchingApp.notifyFixedRotationTransform(false /* enabled */);
}
return false;
}
if (!r.getParent().matchParentBounds()) {

View File

@@ -622,11 +622,6 @@ class WindowToken extends WindowContainer<WindowState> {
state.mIsTransforming = false;
if (applyDisplayRotation != null) {
applyDisplayRotation.run();
} else {
// The display will not rotate to the rotation of this container, let's cancel them.
for (int i = state.mAssociatedTokens.size() - 1; i >= 0; i--) {
state.mAssociatedTokens.get(i).cancelFixedRotationTransform();
}
}
// The state is cleared at the end, because it is used to indicate that other windows can
// use seamless rotation when applying rotation to display.
@@ -634,11 +629,15 @@ class WindowToken extends WindowContainer<WindowState> {
final WindowToken token = state.mAssociatedTokens.get(i);
token.mFixedRotationTransformState = null;
token.notifyFixedRotationTransform(false /* enabled */);
if (applyDisplayRotation == null) {
// Notify cancellation because the display does not change rotation.
token.cancelFixedRotationTransform();
}
}
}
/** Notifies application side to enable or disable the rotation adjustment of display info. */
private void notifyFixedRotationTransform(boolean enabled) {
void notifyFixedRotationTransform(boolean enabled) {
FixedRotationAdjustments adjustments = null;
// A token may contain windows of the same processes or different processes. The list is
// used to avoid sending the same adjustments to a process multiple times.
@@ -682,7 +681,6 @@ class WindowToken extends WindowContainer<WindowState> {
// The window may be detached or detaching.
return;
}
notifyFixedRotationTransform(false /* enabled */);
final int originalRotation = getWindowConfiguration().getRotation();
onConfigurationChanged(parent.getConfiguration());
onCancelFixedRotationTransform(originalRotation);

View File

@@ -88,6 +88,7 @@ import static org.mockito.Mockito.doCallRealMethod;
import android.annotation.SuppressLint;
import android.app.ActivityTaskManager;
import android.app.WindowConfiguration;
import android.app.servertransaction.FixedRotationAdjustmentsItem;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Region;
@@ -1345,6 +1346,36 @@ public class DisplayContentTests extends WindowTestsBase {
assertFalse(recentsActivity.hasFixedRotationTransform());
}
@Test
public void testClearIntermediateFixedRotationAdjustments() throws RemoteException {
final ActivityRecord activity = new ActivityTestsBase.StackBuilder(mWm.mRoot)
.setDisplay(mDisplayContent).build().getTopMostActivity();
mDisplayContent.setFixedRotationLaunchingApp(activity,
(mDisplayContent.getRotation() + 1) % 4);
// Create a window so FixedRotationAdjustmentsItem can be sent.
createWindow(null, TYPE_APPLICATION_STARTING, activity, "AppWin");
final ActivityRecord activity2 = new ActivityTestsBase.StackBuilder(mWm.mRoot)
.setDisplay(mDisplayContent).build().getTopMostActivity();
activity2.setVisible(false);
clearInvocations(mWm.mAtmService.getLifecycleManager());
// The first activity has applied fixed rotation but the second activity becomes the top
// before the transition is done and it has the same rotation as display, so the dispatched
// rotation adjustment of first activity must be cleared.
mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(activity2,
false /* checkOpening */);
final ArgumentCaptor<FixedRotationAdjustmentsItem> adjustmentsCaptor =
ArgumentCaptor.forClass(FixedRotationAdjustmentsItem.class);
verify(mWm.mAtmService.getLifecycleManager(), atLeastOnce()).scheduleTransaction(
eq(activity.app.getThread()), adjustmentsCaptor.capture());
// The transformation is kept for animation in real case.
assertTrue(activity.hasFixedRotationTransform());
final FixedRotationAdjustmentsItem clearAdjustments = FixedRotationAdjustmentsItem.obtain(
activity.token, null /* fixedRotationAdjustments */);
// The captor may match other items. The first one must be the item to clear adjustments.
assertEquals(clearAdjustments, adjustmentsCaptor.getAllValues().get(0));
}
@Test
public void testRemoteRotation() {
DisplayContent dc = createNewDisplay();