Merge "Improve first opaque activity candidate detection" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
3d8f16685e
@@ -1640,7 +1640,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
if (isState(RESUMED)) {
|
||||
newParent.setResumedActivity(this, "onParentChanged");
|
||||
}
|
||||
mLetterboxUiController.onActivityParentChanged(newParent);
|
||||
mLetterboxUiController.updateInheritedLetterbox();
|
||||
}
|
||||
|
||||
if (rootTask != null && rootTask.topRunningActivity() == this) {
|
||||
|
||||
@@ -113,6 +113,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;
|
||||
@@ -127,8 +129,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;
|
||||
|
||||
@@ -180,6 +181,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
|
||||
@@ -193,6 +198,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
|
||||
@@ -353,6 +362,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;
|
||||
@@ -1571,7 +1584,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;
|
||||
}
|
||||
@@ -1581,22 +1598,24 @@ final class LetterboxUiController {
|
||||
}
|
||||
// In case mActivityRecord.hasCompatDisplayInsetsWithoutOverride() we don't apply the
|
||||
// opaque activity constraints because we're expecting the activity is already letterboxed.
|
||||
mFirstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity(
|
||||
FIRST_OPAQUE_NOT_FINISHING_ACTIVITY_PREDICATE /* callback */,
|
||||
mActivityRecord /* boundary */, false /* includeBoundary */,
|
||||
true /* traverseTopToBottom */);
|
||||
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;
|
||||
}
|
||||
if (mActivityRecord.getTask() == null || mActivityRecord.fillsParent()
|
||||
|| mActivityRecord.hasCompatDisplayInsetsWithoutInheritance()) {
|
||||
return;
|
||||
}
|
||||
final ActivityRecord firstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity(
|
||||
FIRST_OPAQUE_NOT_FINISHING_ACTIVITY_PREDICATE /* callback */,
|
||||
mActivityRecord /* boundary */, false /* includeBoundary */,
|
||||
true /* traverseTopToBottom */);
|
||||
if (firstOpaqueActivityBeneath == null || firstOpaqueActivityBeneath.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.
|
||||
return;
|
||||
}
|
||||
inheritConfiguration(firstOpaqueActivityBeneath);
|
||||
mFirstOpaqueActivityBeneath.mLetterboxUiController.mDestroyListeners.add(this);
|
||||
inheritConfiguration(mFirstOpaqueActivityBeneath);
|
||||
mLetterboxConfigListener = WindowContainer.overrideConfigurationPropagation(
|
||||
mActivityRecord, firstOpaqueActivityBeneath,
|
||||
mActivityRecord, mFirstOpaqueActivityBeneath,
|
||||
(opaqueConfig, transparentOverrideConfig) -> {
|
||||
resetTranslucentOverrideConfig(transparentOverrideConfig);
|
||||
final Rect parentBounds = parent.getWindowConfiguration().getBounds();
|
||||
@@ -1610,7 +1629,7 @@ final class LetterboxUiController {
|
||||
// We need to initialize appBounds to avoid NPE. The actual value will
|
||||
// be set ahead when resolving the Configuration for the activity.
|
||||
transparentOverrideConfig.windowConfiguration.setAppBounds(new Rect());
|
||||
inheritConfiguration(firstOpaqueActivityBeneath);
|
||||
inheritConfiguration(mFirstOpaqueActivityBeneath);
|
||||
return transparentOverrideConfig;
|
||||
});
|
||||
}
|
||||
@@ -1684,10 +1703,7 @@ 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);
|
||||
}
|
||||
|
||||
/** Resets the screen size related fields so they can be resolved by requested bounds later. */
|
||||
@@ -1718,6 +1734,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;
|
||||
|
||||
@@ -178,44 +178,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);
|
||||
@@ -240,7 +202,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);
|
||||
@@ -316,7 +277,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);
|
||||
@@ -388,6 +348,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);
|
||||
@@ -395,7 +453,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())
|
||||
@@ -456,7 +513,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())
|
||||
@@ -550,7 +606,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)
|
||||
@@ -583,7 +638,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);
|
||||
|
||||
Reference in New Issue
Block a user