Loading services/core/java/com/android/server/wm/ActivityRecord.java +1 −1 Original line number Diff line number Diff line Loading @@ -1612,7 +1612,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A newParent.setResumedActivity(this, "onParentChanged"); mImeInsetsFrozenUntilStartInput = false; } mLetterboxUiController.onActivityParentChanged(newParent); mLetterboxUiController.updateInheritedLetterbox(); } if (rootTask != null && rootTask.topRunningActivity() == this) { Loading services/core/java/com/android/server/wm/LetterboxUiController.java +48 −33 Original line number Diff line number Diff line Loading @@ -112,6 +112,8 @@ import com.android.internal.statusbar.LetterboxDetails; import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.function.BooleanSupplier; import java.util.function.Consumer; Loading @@ -126,8 +128,7 @@ import java.util.function.Predicate; final class LetterboxUiController { private static final Predicate<ActivityRecord> FIRST_OPAQUE_NOT_FINISHING_ACTIVITY_PREDICATE = activityRecord -> activityRecord.fillsParent() && !activityRecord.isFinishing() && activityRecord.nowVisible; activityRecord -> activityRecord.fillsParent() && !activityRecord.isFinishing(); private static final String TAG = TAG_WITH_CLASS_NAME ? "LetterboxUiController" : TAG_ATM; Loading Loading @@ -185,6 +186,10 @@ final class LetterboxUiController { // Corresponds to OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS private final boolean mIsOverrideEnableCompatFakeFocusEnabled; // The list of observers for the destroy event of candidate opaque activities // when dealing with translucent activities. private final List<LetterboxUiController> mDestroyListeners = new ArrayList<>(); @Nullable private final Boolean mBooleanPropertyAllowOrientationOverride; @Nullable Loading @@ -198,6 +203,10 @@ final class LetterboxUiController { @Nullable private WindowContainerListener mLetterboxConfigListener; @Nullable @VisibleForTesting ActivityRecord mFirstOpaqueActivityBeneath; private boolean mShowWallpaperForLetterboxBackground; // In case of transparent activities we might need to access the aspectRatio of the Loading Loading @@ -361,6 +370,10 @@ final class LetterboxUiController { mLetterbox.destroy(); mLetterbox = null; } for (int i = mDestroyListeners.size() - 1; i >= 0; i--) { mDestroyListeners.get(i).updateInheritedLetterbox(); } mDestroyListeners.clear(); if (mLetterboxConfigListener != null) { mLetterboxConfigListener.onRemoved(); mLetterboxConfigListener = null; Loading Loading @@ -1577,7 +1590,11 @@ final class LetterboxUiController { * first opaque activity beneath. * @param parent The parent container. */ void onActivityParentChanged(WindowContainer<?> parent) { void updateInheritedLetterbox() { final WindowContainer<?> parent = mActivityRecord.getParent(); if (parent == null) { return; } if (!mLetterboxConfiguration.isTranslucentLetterboxingEnabled()) { return; } Loading @@ -1587,27 +1604,28 @@ final class LetterboxUiController { } // In case mActivityRecord.hasCompatDisplayInsetsWithoutOverride() we don't apply the // opaque activity constraints because we're expecting the activity is already letterboxed. if (mActivityRecord.getTask() == null || mActivityRecord.fillsParent() || mActivityRecord.hasCompatDisplayInsetsWithoutInheritance()) { return; } final ActivityRecord firstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity( mFirstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity( FIRST_OPAQUE_NOT_FINISHING_ACTIVITY_PREDICATE /* callback */, mActivityRecord /* boundary */, false /* includeBoundary */, true /* traverseTopToBottom */); if (firstOpaqueActivityBeneath == null || firstOpaqueActivityBeneath.isEmbedded()) { if (mFirstOpaqueActivityBeneath == null || mFirstOpaqueActivityBeneath.isEmbedded()) { // We skip letterboxing if the translucent activity doesn't have any opaque // activities beneath or the activity below is embedded which never has letterbox. mActivityRecord.recomputeConfiguration(); return; } inheritConfiguration(firstOpaqueActivityBeneath); if (mActivityRecord.getTask() == null || mActivityRecord.fillsParent() || mActivityRecord.hasCompatDisplayInsetsWithoutInheritance()) { return; } mFirstOpaqueActivityBeneath.mLetterboxUiController.mDestroyListeners.add(this); inheritConfiguration(mFirstOpaqueActivityBeneath); mLetterboxConfigListener = WindowContainer.overrideConfigurationPropagation( mActivityRecord, firstOpaqueActivityBeneath, (opaqueConfig, transparentConfig) -> { final Configuration mutatedConfiguration = fromOriginalTranslucentConfig(transparentConfig); mActivityRecord, mFirstOpaqueActivityBeneath, (opaqueConfig, transparentOverrideConfig) -> { resetTranslucentOverrideConfig(transparentOverrideConfig); final Rect parentBounds = parent.getWindowConfiguration().getBounds(); final Rect bounds = mutatedConfiguration.windowConfiguration.getBounds(); final Rect bounds = transparentOverrideConfig.windowConfiguration.getBounds(); final Rect letterboxBounds = opaqueConfig.windowConfiguration.getBounds(); // We cannot use letterboxBounds directly here because the position relies on // letterboxing. Using letterboxBounds directly, would produce a double offset. Loading @@ -1616,9 +1634,9 @@ final class LetterboxUiController { parentBounds.top + letterboxBounds.height()); // We need to initialize appBounds to avoid NPE. The actual value will // be set ahead when resolving the Configuration for the activity. mutatedConfiguration.windowConfiguration.setAppBounds(new Rect()); inheritConfiguration(firstOpaqueActivityBeneath); return mutatedConfiguration; transparentOverrideConfig.windowConfiguration.setAppBounds(new Rect()); inheritConfiguration(mFirstOpaqueActivityBeneath); return transparentOverrideConfig; }); } Loading Loading @@ -1691,26 +1709,19 @@ final class LetterboxUiController { 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 */)); return Optional.ofNullable(mFirstOpaqueActivityBeneath); } // When overriding translucent activities configuration we need to keep some of the // original properties private Configuration fromOriginalTranslucentConfig(Configuration translucentConfig) { final Configuration configuration = new Configuration(translucentConfig); /** Resets the screen size related fields so they can be resolved by requested bounds later. */ private static void resetTranslucentOverrideConfig(Configuration config) { // The values for the following properties will be defined during the configuration // resolution in {@link ActivityRecord#resolveOverrideConfiguration} using the // properties inherited from the first not finishing opaque activity beneath. configuration.orientation = ORIENTATION_UNDEFINED; configuration.screenWidthDp = configuration.compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED; configuration.screenHeightDp = configuration.compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED; configuration.smallestScreenWidthDp = configuration.compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; return configuration; config.orientation = ORIENTATION_UNDEFINED; config.screenWidthDp = config.compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED; config.screenHeightDp = config.compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED; config.smallestScreenWidthDp = config.compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; } private void inheritConfiguration(ActivityRecord firstOpaque) { Loading @@ -1729,6 +1740,10 @@ final class LetterboxUiController { } private void clearInheritedConfig() { if (mFirstOpaqueActivityBeneath != null) { mFirstOpaqueActivityBeneath.mLetterboxUiController.mDestroyListeners.remove(this); } mFirstOpaqueActivityBeneath = null; mLetterboxConfigListener = null; mInheritedMinAspectRatio = UNDEFINED_ASPECT_RATIO; mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO; Loading services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +98 −44 Original line number Diff line number Diff line Loading @@ -174,44 +174,6 @@ public class SizeCompatTests extends WindowTestsBase { setUpApp(builder.build()); } @Test public void testActivityInHistoryAndNotVisibleIsNotUsedAsOpaqueForTranslucentActivities() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2000, 1000); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = false; // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); assertFalse(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); } @Test public void testActivityInHistoryAndVisibleIsUsedAsOpaqueForTranslucentActivities() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2000, 1000); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = true; // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); assertTrue(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); } @Test public void testCleanLetterboxConfigListenerWhenTranslucentIsDestroyed() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); Loading @@ -236,7 +198,6 @@ public class SizeCompatTests extends WindowTestsBase { public void testHorizontalReachabilityEnabledForTranslucentActivities() { setUpDisplaySizeWithApp(2500, 1000); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = true; final LetterboxConfiguration config = mWm.mLetterboxConfiguration; config.setTranslucentLetterboxingOverrideEnabled(true); config.setLetterboxHorizontalPositionMultiplier(0.5f); Loading Loading @@ -312,7 +273,6 @@ public class SizeCompatTests extends WindowTestsBase { public void testVerticalReachabilityEnabledForTranslucentActivities() { setUpDisplaySizeWithApp(1000, 2500); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = true; final LetterboxConfiguration config = mWm.mLetterboxConfiguration; config.setTranslucentLetterboxingOverrideEnabled(true); config.setLetterboxVerticalPositionMultiplier(0.5f); Loading Loading @@ -384,6 +344,104 @@ public class SizeCompatTests extends WindowTestsBase { checkIsCentered.run(); } @Test public void testApplyStrategyAgainWhenOpaqueIsDestroyed() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2000, 1000); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); // Launch another opaque activity final ActivityRecord opaqueActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); mTask.addChild(opaqueActivity); // Transparent activity strategy not applied assertFalse(opaqueActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); // Launch translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // Transparent strategy applied assertTrue(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); spyOn(translucentActivity.mLetterboxUiController); clearInvocations(translucentActivity.mLetterboxUiController); // We destroy the first opaque activity opaqueActivity.setState(DESTROYED, "testing"); opaqueActivity.removeImmediately(); // Check that updateInheritedLetterbox() is invoked again verify(translucentActivity.mLetterboxUiController).updateInheritedLetterbox(); } @Test public void testResetOpaqueReferenceWhenOpaqueIsDestroyed() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2000, 1000); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); // Launch translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // Transparent strategy applied assertTrue(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); assertNotNull(translucentActivity.mLetterboxUiController.mFirstOpaqueActivityBeneath); spyOn(translucentActivity.mLetterboxUiController); clearInvocations(translucentActivity.mLetterboxUiController); // We destroy the first opaque activity mActivity.setState(DESTROYED, "testing"); mActivity.removeImmediately(); // Check that updateInheritedLetterbox() is invoked again verify(translucentActivity.mLetterboxUiController).updateInheritedLetterbox(); assertNull(translucentActivity.mLetterboxUiController.mFirstOpaqueActivityBeneath); } @Test public void testNotApplyStrategyAgainWhenOpaqueIsNotDestroyed() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2000, 1000); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); // Launch another opaque activity final ActivityRecord opaqueActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); mTask.addChild(opaqueActivity); // Transparent activity strategy not applied assertFalse(opaqueActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); // Launch translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // Transparent strategy applied assertTrue(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); spyOn(translucentActivity.mLetterboxUiController); clearInvocations(translucentActivity.mLetterboxUiController); // Check that updateInheritedLetterbox() is invoked again verify(translucentActivity.mLetterboxUiController, never()).updateInheritedLetterbox(); } @Test public void testApplyStrategyToTranslucentActivities() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); Loading @@ -391,7 +449,6 @@ public class SizeCompatTests extends WindowTestsBase { prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); mActivity.info.setMinAspectRatio(1.2f); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = true; // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) Loading Loading @@ -448,7 +505,6 @@ public class SizeCompatTests extends WindowTestsBase { prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); mActivity.info.setMinAspectRatio(1.2f); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = true; // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) Loading Loading @@ -542,7 +598,6 @@ public class SizeCompatTests extends WindowTestsBase { true /* ignoreOrientationRequest */); mActivity.mWmService.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier( 1.0f /*letterboxVerticalPositionMultiplier*/); mActivity.nowVisible = true; prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); // We launch a transparent activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) Loading Loading @@ -575,7 +630,6 @@ public class SizeCompatTests extends WindowTestsBase { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2800, 1400); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = true; prepareUnresizable(mActivity, -1f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); // Rotate to put activity in size compat mode. rotateDisplay(mActivity.mDisplayContent, ROTATION_90); Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +1 −1 Original line number Diff line number Diff line Loading @@ -1612,7 +1612,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A newParent.setResumedActivity(this, "onParentChanged"); mImeInsetsFrozenUntilStartInput = false; } mLetterboxUiController.onActivityParentChanged(newParent); mLetterboxUiController.updateInheritedLetterbox(); } if (rootTask != null && rootTask.topRunningActivity() == this) { Loading
services/core/java/com/android/server/wm/LetterboxUiController.java +48 −33 Original line number Diff line number Diff line Loading @@ -112,6 +112,8 @@ import com.android.internal.statusbar.LetterboxDetails; import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.function.BooleanSupplier; import java.util.function.Consumer; Loading @@ -126,8 +128,7 @@ import java.util.function.Predicate; final class LetterboxUiController { private static final Predicate<ActivityRecord> FIRST_OPAQUE_NOT_FINISHING_ACTIVITY_PREDICATE = activityRecord -> activityRecord.fillsParent() && !activityRecord.isFinishing() && activityRecord.nowVisible; activityRecord -> activityRecord.fillsParent() && !activityRecord.isFinishing(); private static final String TAG = TAG_WITH_CLASS_NAME ? "LetterboxUiController" : TAG_ATM; Loading Loading @@ -185,6 +186,10 @@ final class LetterboxUiController { // Corresponds to OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS private final boolean mIsOverrideEnableCompatFakeFocusEnabled; // The list of observers for the destroy event of candidate opaque activities // when dealing with translucent activities. private final List<LetterboxUiController> mDestroyListeners = new ArrayList<>(); @Nullable private final Boolean mBooleanPropertyAllowOrientationOverride; @Nullable Loading @@ -198,6 +203,10 @@ final class LetterboxUiController { @Nullable private WindowContainerListener mLetterboxConfigListener; @Nullable @VisibleForTesting ActivityRecord mFirstOpaqueActivityBeneath; private boolean mShowWallpaperForLetterboxBackground; // In case of transparent activities we might need to access the aspectRatio of the Loading Loading @@ -361,6 +370,10 @@ final class LetterboxUiController { mLetterbox.destroy(); mLetterbox = null; } for (int i = mDestroyListeners.size() - 1; i >= 0; i--) { mDestroyListeners.get(i).updateInheritedLetterbox(); } mDestroyListeners.clear(); if (mLetterboxConfigListener != null) { mLetterboxConfigListener.onRemoved(); mLetterboxConfigListener = null; Loading Loading @@ -1577,7 +1590,11 @@ final class LetterboxUiController { * first opaque activity beneath. * @param parent The parent container. */ void onActivityParentChanged(WindowContainer<?> parent) { void updateInheritedLetterbox() { final WindowContainer<?> parent = mActivityRecord.getParent(); if (parent == null) { return; } if (!mLetterboxConfiguration.isTranslucentLetterboxingEnabled()) { return; } Loading @@ -1587,27 +1604,28 @@ final class LetterboxUiController { } // In case mActivityRecord.hasCompatDisplayInsetsWithoutOverride() we don't apply the // opaque activity constraints because we're expecting the activity is already letterboxed. if (mActivityRecord.getTask() == null || mActivityRecord.fillsParent() || mActivityRecord.hasCompatDisplayInsetsWithoutInheritance()) { return; } final ActivityRecord firstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity( mFirstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity( FIRST_OPAQUE_NOT_FINISHING_ACTIVITY_PREDICATE /* callback */, mActivityRecord /* boundary */, false /* includeBoundary */, true /* traverseTopToBottom */); if (firstOpaqueActivityBeneath == null || firstOpaqueActivityBeneath.isEmbedded()) { if (mFirstOpaqueActivityBeneath == null || mFirstOpaqueActivityBeneath.isEmbedded()) { // We skip letterboxing if the translucent activity doesn't have any opaque // activities beneath or the activity below is embedded which never has letterbox. mActivityRecord.recomputeConfiguration(); return; } inheritConfiguration(firstOpaqueActivityBeneath); if (mActivityRecord.getTask() == null || mActivityRecord.fillsParent() || mActivityRecord.hasCompatDisplayInsetsWithoutInheritance()) { return; } mFirstOpaqueActivityBeneath.mLetterboxUiController.mDestroyListeners.add(this); inheritConfiguration(mFirstOpaqueActivityBeneath); mLetterboxConfigListener = WindowContainer.overrideConfigurationPropagation( mActivityRecord, firstOpaqueActivityBeneath, (opaqueConfig, transparentConfig) -> { final Configuration mutatedConfiguration = fromOriginalTranslucentConfig(transparentConfig); mActivityRecord, mFirstOpaqueActivityBeneath, (opaqueConfig, transparentOverrideConfig) -> { resetTranslucentOverrideConfig(transparentOverrideConfig); final Rect parentBounds = parent.getWindowConfiguration().getBounds(); final Rect bounds = mutatedConfiguration.windowConfiguration.getBounds(); final Rect bounds = transparentOverrideConfig.windowConfiguration.getBounds(); final Rect letterboxBounds = opaqueConfig.windowConfiguration.getBounds(); // We cannot use letterboxBounds directly here because the position relies on // letterboxing. Using letterboxBounds directly, would produce a double offset. Loading @@ -1616,9 +1634,9 @@ final class LetterboxUiController { parentBounds.top + letterboxBounds.height()); // We need to initialize appBounds to avoid NPE. The actual value will // be set ahead when resolving the Configuration for the activity. mutatedConfiguration.windowConfiguration.setAppBounds(new Rect()); inheritConfiguration(firstOpaqueActivityBeneath); return mutatedConfiguration; transparentOverrideConfig.windowConfiguration.setAppBounds(new Rect()); inheritConfiguration(mFirstOpaqueActivityBeneath); return transparentOverrideConfig; }); } Loading Loading @@ -1691,26 +1709,19 @@ final class LetterboxUiController { 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 */)); return Optional.ofNullable(mFirstOpaqueActivityBeneath); } // When overriding translucent activities configuration we need to keep some of the // original properties private Configuration fromOriginalTranslucentConfig(Configuration translucentConfig) { final Configuration configuration = new Configuration(translucentConfig); /** Resets the screen size related fields so they can be resolved by requested bounds later. */ private static void resetTranslucentOverrideConfig(Configuration config) { // The values for the following properties will be defined during the configuration // resolution in {@link ActivityRecord#resolveOverrideConfiguration} using the // properties inherited from the first not finishing opaque activity beneath. configuration.orientation = ORIENTATION_UNDEFINED; configuration.screenWidthDp = configuration.compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED; configuration.screenHeightDp = configuration.compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED; configuration.smallestScreenWidthDp = configuration.compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; return configuration; config.orientation = ORIENTATION_UNDEFINED; config.screenWidthDp = config.compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED; config.screenHeightDp = config.compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED; config.smallestScreenWidthDp = config.compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; } private void inheritConfiguration(ActivityRecord firstOpaque) { Loading @@ -1729,6 +1740,10 @@ final class LetterboxUiController { } private void clearInheritedConfig() { if (mFirstOpaqueActivityBeneath != null) { mFirstOpaqueActivityBeneath.mLetterboxUiController.mDestroyListeners.remove(this); } mFirstOpaqueActivityBeneath = null; mLetterboxConfigListener = null; mInheritedMinAspectRatio = UNDEFINED_ASPECT_RATIO; mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO; Loading
services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +98 −44 Original line number Diff line number Diff line Loading @@ -174,44 +174,6 @@ public class SizeCompatTests extends WindowTestsBase { setUpApp(builder.build()); } @Test public void testActivityInHistoryAndNotVisibleIsNotUsedAsOpaqueForTranslucentActivities() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2000, 1000); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = false; // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); assertFalse(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); } @Test public void testActivityInHistoryAndVisibleIsUsedAsOpaqueForTranslucentActivities() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2000, 1000); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = true; // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); assertTrue(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); } @Test public void testCleanLetterboxConfigListenerWhenTranslucentIsDestroyed() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); Loading @@ -236,7 +198,6 @@ public class SizeCompatTests extends WindowTestsBase { public void testHorizontalReachabilityEnabledForTranslucentActivities() { setUpDisplaySizeWithApp(2500, 1000); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = true; final LetterboxConfiguration config = mWm.mLetterboxConfiguration; config.setTranslucentLetterboxingOverrideEnabled(true); config.setLetterboxHorizontalPositionMultiplier(0.5f); Loading Loading @@ -312,7 +273,6 @@ public class SizeCompatTests extends WindowTestsBase { public void testVerticalReachabilityEnabledForTranslucentActivities() { setUpDisplaySizeWithApp(1000, 2500); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = true; final LetterboxConfiguration config = mWm.mLetterboxConfiguration; config.setTranslucentLetterboxingOverrideEnabled(true); config.setLetterboxVerticalPositionMultiplier(0.5f); Loading Loading @@ -384,6 +344,104 @@ public class SizeCompatTests extends WindowTestsBase { checkIsCentered.run(); } @Test public void testApplyStrategyAgainWhenOpaqueIsDestroyed() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2000, 1000); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); // Launch another opaque activity final ActivityRecord opaqueActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); mTask.addChild(opaqueActivity); // Transparent activity strategy not applied assertFalse(opaqueActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); // Launch translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // Transparent strategy applied assertTrue(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); spyOn(translucentActivity.mLetterboxUiController); clearInvocations(translucentActivity.mLetterboxUiController); // We destroy the first opaque activity opaqueActivity.setState(DESTROYED, "testing"); opaqueActivity.removeImmediately(); // Check that updateInheritedLetterbox() is invoked again verify(translucentActivity.mLetterboxUiController).updateInheritedLetterbox(); } @Test public void testResetOpaqueReferenceWhenOpaqueIsDestroyed() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2000, 1000); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); // Launch translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // Transparent strategy applied assertTrue(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); assertNotNull(translucentActivity.mLetterboxUiController.mFirstOpaqueActivityBeneath); spyOn(translucentActivity.mLetterboxUiController); clearInvocations(translucentActivity.mLetterboxUiController); // We destroy the first opaque activity mActivity.setState(DESTROYED, "testing"); mActivity.removeImmediately(); // Check that updateInheritedLetterbox() is invoked again verify(translucentActivity.mLetterboxUiController).updateInheritedLetterbox(); assertNull(translucentActivity.mLetterboxUiController.mFirstOpaqueActivityBeneath); } @Test public void testNotApplyStrategyAgainWhenOpaqueIsNotDestroyed() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2000, 1000); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); // Launch another opaque activity final ActivityRecord opaqueActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); mTask.addChild(opaqueActivity); // Transparent activity strategy not applied assertFalse(opaqueActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); // Launch translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // Transparent strategy applied assertTrue(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); spyOn(translucentActivity.mLetterboxUiController); clearInvocations(translucentActivity.mLetterboxUiController); // Check that updateInheritedLetterbox() is invoked again verify(translucentActivity.mLetterboxUiController, never()).updateInheritedLetterbox(); } @Test public void testApplyStrategyToTranslucentActivities() { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); Loading @@ -391,7 +449,6 @@ public class SizeCompatTests extends WindowTestsBase { prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); mActivity.info.setMinAspectRatio(1.2f); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = true; // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) Loading Loading @@ -448,7 +505,6 @@ public class SizeCompatTests extends WindowTestsBase { prepareUnresizable(mActivity, 1.5f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); mActivity.info.setMinAspectRatio(1.2f); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = true; // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) .setLaunchedFromUid(mActivity.getUid()) Loading Loading @@ -542,7 +598,6 @@ public class SizeCompatTests extends WindowTestsBase { true /* ignoreOrientationRequest */); mActivity.mWmService.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier( 1.0f /*letterboxVerticalPositionMultiplier*/); mActivity.nowVisible = true; prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); // We launch a transparent activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) Loading Loading @@ -575,7 +630,6 @@ public class SizeCompatTests extends WindowTestsBase { mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true); setUpDisplaySizeWithApp(2800, 1400); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); mActivity.nowVisible = true; prepareUnresizable(mActivity, -1f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); // Rotate to put activity in size compat mode. rotateDisplay(mActivity.mDisplayContent, ROTATION_90); Loading