Fix translucent activities when unfolding

In the unfold process only the top activity bounds were calculated.
Now we update the bounds of the first opaque activity beneath.

Bug: 261721427
Test: Run `atest SizeCompatTests`

Change-Id: I5895a417aecdc66d1b17184cbe700ef1da5e1148
This commit is contained in:
Massimo Carli
2023-01-31 17:08:59 +00:00
parent 25e0c530d2
commit c6e2e10733
3 changed files with 75 additions and 5 deletions

View File

@@ -8293,7 +8293,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
void recomputeConfiguration() {
onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
// We check if the current activity is transparent. In that case we need to
// recomputeConfiguration of the first opaque activity beneath, to allow a
// proper computation of the new bounds.
if (!mLetterboxUiController.applyOnOpaqueActivityBelow(
ActivityRecord::recomputeConfiguration)) {
onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
}
}
boolean isInTransition() {

View File

@@ -81,6 +81,7 @@ import static com.android.server.wm.LetterboxConfiguration.letterboxBackgroundTy
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager.TaskDescription;
import android.content.pm.ActivityInfo.ScreenOrientation;
@@ -104,7 +105,9 @@ import com.android.internal.statusbar.LetterboxDetails;
import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType;
import java.io.PrintWriter;
import java.util.Optional;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Predicate;
/** Controls behaviour of the letterbox UI for {@link mActivityRecord}. */
@@ -1471,6 +1474,32 @@ final class LetterboxUiController {
return mInheritedCompatDisplayInsets;
}
/**
* In case of translucent activities, it consumes the {@link ActivityRecord} of the first opaque
* activity beneath using the given consumer and returns {@code true}.
*/
boolean applyOnOpaqueActivityBelow(@NonNull Consumer<ActivityRecord> consumer) {
return findOpaqueNotFinishingActivityBelow()
.map(activityRecord -> {
consumer.accept(activityRecord);
return true;
}).orElse(false);
}
/**
* @return The first not finishing opaque activity beneath the current translucent activity
* if it exists and the strategy is enabled.
*/
private Optional<ActivityRecord> findOpaqueNotFinishingActivityBelow() {
if (!hasInheritedLetterboxBehavior() || mActivityRecord.getTask() == null) {
return Optional.empty();
}
return Optional.ofNullable(mActivityRecord.getTask().getActivity(
FIRST_OPAQUE_NOT_FINISHING_ACTIVITY_PREDICATE /* callback */,
mActivityRecord /* boundary */, false /* includeBoundary */,
true /* traverseTopToBottom */));
}
private void inheritConfiguration(ActivityRecord firstOpaque) {
// To avoid wrong behaviour, we're not forcing a specific aspet ratio to activities
// which are not already providing one (e.g. permission dialogs) and presumably also

View File

@@ -270,6 +270,35 @@ public class SizeCompatTests extends WindowTestsBase {
verify(mActivity).isFinishing();
}
@Test
public void testTranslucentActivitiesWhenUnfolding() {
mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
setUpDisplaySizeWithApp(2800, 1400);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mActivity.mWmService.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(
1.0f /*letterboxVerticalPositionMultiplier*/);
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
// We launch a transparent activity
final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
.setLaunchedFromUid(mActivity.getUid())
.setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
.build();
doReturn(false).when(translucentActivity).fillsParent();
mTask.addChild(translucentActivity);
mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
spyOn(mActivity);
// Halffold
setFoldablePosture(translucentActivity, true /* isHalfFolded */, false /* isTabletop */);
verify(mActivity).recomputeConfiguration();
clearInvocations(mActivity);
// Unfold
setFoldablePosture(translucentActivity, false /* isHalfFolded */, false /* isTabletop */);
verify(mActivity).recomputeConfiguration();
}
@Test
public void testRestartProcessIfVisible() {
setUpDisplaySizeWithApp(1000, 2500);
@@ -3339,14 +3368,20 @@ public class SizeCompatTests extends WindowTestsBase {
}
private void setFoldablePosture(boolean isHalfFolded, boolean isTabletop) {
final DisplayRotation r = mActivity.mDisplayContent.getDisplayRotation();
private void setFoldablePosture(ActivityRecord activity, boolean isHalfFolded,
boolean isTabletop) {
final DisplayRotation r = activity.mDisplayContent.getDisplayRotation();
doReturn(isHalfFolded).when(r).isDisplaySeparatingHinge();
doReturn(false).when(r).isDeviceInPosture(any(DeviceState.class), anyBoolean());
if (isHalfFolded) {
doReturn(true).when(r).isDeviceInPosture(DeviceState.HALF_FOLDED, isTabletop);
doReturn(true).when(r)
.isDeviceInPosture(DeviceState.HALF_FOLDED, isTabletop);
}
mActivity.recomputeConfiguration();
activity.recomputeConfiguration();
}
private void setFoldablePosture(boolean isHalfFolded, boolean isTabletop) {
setFoldablePosture(mActivity, isHalfFolded, isTabletop);
}
@Test