Merge "Avoid clearing size compat when app is shown from paused"

This commit is contained in:
Chris Li
2020-11-06 20:02:18 +00:00
committed by Android (Google) Code Review
4 changed files with 87 additions and 25 deletions

View File

@@ -6372,7 +6372,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
onDescendantOrientationChanged(freezeToken, this);
if (onDescendantOrientationChanged(freezeToken, this)) {
// The app is just becoming visible, and the parent Task has updated with the
// orientation request. Update the size compat mode.
updateSizeCompatMode();
}
}
/**
@@ -6538,6 +6542,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return;
}
if (task == null || (!handlesOrientationChangeFromDescendant()
&& task.getLastTaskBoundsComputeActivity() != this)) {
// Don't compute when Task hasn't computed its bounds for this app, because the Task can
// be letterboxed, and its bounds may not be accurate until then.
return;
}
Configuration overrideConfig = getRequestedOverrideConfiguration();
final Configuration fullConfig = getConfiguration();
@@ -6562,20 +6573,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mCompatDisplayInsets = new CompatDisplayInsets(mDisplayContent, this);
}
void clearSizeCompatMode(boolean recomputeTask) {
@VisibleForTesting
void clearSizeCompatMode() {
mSizeCompatScale = 1f;
mSizeCompatBounds = null;
mCompatDisplayInsets = null;
if (recomputeTask) {
// Recompute from Task because letterbox can also happen on Task level.
task.onRequestedOverrideConfigurationChanged(task.getRequestedOverrideConfiguration());
}
}
@VisibleForTesting
void clearSizeCompatMode() {
clearSizeCompatMode(true /* recomputeTask */);
// Recompute from Task because letterbox can also happen on Task level.
task.onRequestedOverrideConfigurationChanged(task.getRequestedOverrideConfiguration());
}
@Override

View File

@@ -571,6 +571,10 @@ class Task extends WindowContainer<WindowContainer> {
/** Current activity that is resumed, or null if there is none. */
ActivityRecord mResumedActivity = null;
/** Last activity that is used to compute the Task bounds. */
@Nullable
private ActivityRecord mLastTaskBoundsComputeActivity;
private boolean mForceShowForAllUsers;
/** When set, will force the task to report as invisible. */
@@ -1496,6 +1500,11 @@ class Task extends WindowContainer<WindowContainer> {
}
void cleanUpActivityReferences(ActivityRecord r) {
// mLastTaskBoundsComputeActivity is set at leaf Task
if (mLastTaskBoundsComputeActivity == r) {
mLastTaskBoundsComputeActivity = null;
}
final WindowContainer parent = getParent();
if (parent != null && parent.asTask() != null) {
parent.asTask().cleanUpActivityReferences(r);
@@ -2833,6 +2842,8 @@ class Task extends WindowContainer<WindowContainer> {
private void resolveLeafOnlyOverrideConfigs(Configuration newParentConfig,
Rect previousBounds) {
mLastTaskBoundsComputeActivity = getTopNonFinishingActivity(false /* includeOverlays */);
int windowingMode =
getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
if (windowingMode == WINDOWING_MODE_UNDEFINED) {
@@ -2963,6 +2974,11 @@ class Task extends WindowContainer<WindowContainer> {
return bounds;
}
@Nullable
ActivityRecord getLastTaskBoundsComputeActivity() {
return mLastTaskBoundsComputeActivity;
}
/** Updates the task's bounds and override configuration to match what is expected for the
* input stack. */
void updateOverrideConfigurationForStack(Task inStack) {
@@ -3307,18 +3323,6 @@ class Task extends WindowContainer<WindowContainer> {
// No one in higher hierarchy handles this request, let's adjust our bounds to fulfill
// it if possible.
if (getParent() != null) {
final ActivityRecord activity = requestingContainer.asActivityRecord();
if (activity != null) {
// Clear the size compat cache to recompute the bounds for requested orientation;
// otherwise when Task#computeFullscreenBounds(), it will not try to do Task level
// letterboxing because app may prefer to keep its original size (size compat).
//
// Normally, ActivityRecord#clearSizeCompatMode() recomputes from its parent Task,
// which is the leaf Task. However, because this orientation request is new to all
// Tasks, pass false to clearSizeCompatMode, and trigger onConfigurationChanged from
// here (root Task) to make sure all Tasks are up-to-date.
activity.clearSizeCompatMode(false /* recomputeTask */);
}
onConfigurationChanged(getParent().getConfiguration());
return true;
}

View File

@@ -41,6 +41,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doCallRealMethod;
import android.app.ActivityManager;
@@ -702,7 +703,6 @@ public class SizeCompatTests extends WindowTestsBase {
// size compat cache.
verify(mTask).onDescendantOrientationChanged(any(), same(newActivity));
verify(mTask).computeFullscreenBounds(any(), any(), any(), anyInt());
verify(newActivity).clearSizeCompatMode(false /* recomputeTask */);
final Rect displayBounds = display.getBounds();
final Rect taskBounds = mTask.getBounds();
@@ -744,7 +744,6 @@ public class SizeCompatTests extends WindowTestsBase {
// size compat cache.
verify(mTask).onDescendantOrientationChanged(any(), same(newActivity));
verify(mTask).computeFullscreenBounds(any(), any(), any(), anyInt());
verify(newActivity).clearSizeCompatMode(false /* recomputeTask */);
final Rect displayBounds = display.getBounds();
final Rect taskBounds = mTask.getBounds();
@@ -761,6 +760,40 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(taskBounds, newActivityBounds);
}
@Test
public void testDisplayIgnoreOrientationRequest_pausedAppNotLostSizeCompat() {
// Set up a display in landscape and ignoring orientation request.
setUpDisplaySizeWithApp(2800, 1400);
final DisplayContent display = mActivity.mDisplayContent;
display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
// Portrait fixed app.
prepareUnresizable(0, SCREEN_ORIENTATION_PORTRAIT);
clearInvocations(mActivity);
assertTrue(mTask.isTaskLetterboxed());
assertFalse(mActivity.inSizeCompatMode());
assertEquals(mTask.getLastTaskBoundsComputeActivity(), mActivity);
// Rotate display to portrait.
rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
// App should be in size compat.
assertFalse(mTask.isTaskLetterboxed());
assertScaled();
assertEquals(mTask.getLastTaskBoundsComputeActivity(), mActivity);
final Rect activityBounds = new Rect(mActivity.getBounds());
mStack.resumeTopActivityUncheckedLocked(null /* prev */, null /* options */);
// App still in size compat, and the bounds don't change.
verify(mActivity, never()).clearSizeCompatMode();
assertFalse(mTask.isTaskLetterboxed());
assertScaled();
assertEquals(mTask.getLastTaskBoundsComputeActivity(), mActivity);
assertEquals(activityBounds, mActivity.getBounds());
}
private static WindowState addWindowToActivity(ActivityRecord activity) {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;

View File

@@ -257,4 +257,24 @@ public class TaskTests extends WindowTestsBase {
task.resolveOverrideConfiguration(parentConfig);
assertThat(resolvedOverride.getWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED);
}
@Test
public void testCleanUpActivityReferences_clearLastTaskBoundsComputeActivity() {
final Task rootTask = createTaskStackOnDisplay(mDisplayContent);
final Task leafTask = createTaskInStack(rootTask, 0 /* userId */);
final ActivityRecord activity2 = createActivityRecord(mDisplayContent, leafTask);
final ActivityRecord activity1 = createActivityRecord(mDisplayContent, leafTask);
activity1.finishing = false;
leafTask.resolveOverrideConfiguration(rootTask.getConfiguration());
assertEquals(activity1, leafTask.getLastTaskBoundsComputeActivity());
leafTask.cleanUpActivityReferences(activity2);
assertNotNull(leafTask.getLastTaskBoundsComputeActivity());
leafTask.cleanUpActivityReferences(activity1);
assertNull(leafTask.getLastTaskBoundsComputeActivity());
}
}