[2/n] Letterbox Education: Add information about fixed orientation letterbox to TaskInfo

Bug: 207010227
Test: atest WmTests:ActivityRecordTests
Test: atest WmTests:SizeCompatTests
Test: atest WMShellUnitTests:ShellTaskOrganizerTests
Change-Id: I04e82eb494c84bd78c269dd244bdd4a3e4d5fcc8
This commit is contained in:
tomnatan
2022-01-20 12:09:34 +00:00
parent d95703d19f
commit 72b8801b69
8 changed files with 153 additions and 5 deletions

View File

@@ -213,6 +213,12 @@ public class TaskInfo {
*/
public boolean topActivityInSizeCompat;
/**
* Whether the direct top activity is eligible for letterbox education.
* @hide
*/
public boolean topActivityEligibleForLetterboxEducation;
/**
* Whether this task is resizable. Unlike {@link #resizeMode} (which is what the top activity
* supports), this is what the system actually uses for resizability based on other policy and
@@ -398,7 +404,8 @@ public class TaskInfo {
/** @hide */
public boolean hasCompatUI() {
return hasCameraCompatControl() || topActivityInSizeCompat;
return hasCameraCompatControl() || topActivityInSizeCompat
|| topActivityEligibleForLetterboxEducation;
}
/**
@@ -460,6 +467,8 @@ public class TaskInfo {
return displayId == that.displayId
&& taskId == that.taskId
&& topActivityInSizeCompat == that.topActivityInSizeCompat
&& topActivityEligibleForLetterboxEducation
== that.topActivityEligibleForLetterboxEducation
&& cameraCompatControlState == that.cameraCompatControlState
// Bounds are important if top activity has compat controls.
&& (!hasCompatUI() || configuration.windowConfiguration.getBounds()
@@ -507,6 +516,7 @@ public class TaskInfo {
isVisible = source.readBoolean();
isSleeping = source.readBoolean();
topActivityInSizeCompat = source.readBoolean();
topActivityEligibleForLetterboxEducation = source.readBoolean();
mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR);
displayAreaFeatureId = source.readInt();
cameraCompatControlState = source.readInt();
@@ -551,6 +561,7 @@ public class TaskInfo {
dest.writeBoolean(isVisible);
dest.writeBoolean(isSleeping);
dest.writeBoolean(topActivityInSizeCompat);
dest.writeBoolean(topActivityEligibleForLetterboxEducation);
dest.writeTypedObject(mTopActivityLocusId, flags);
dest.writeInt(displayAreaFeatureId);
dest.writeInt(cameraCompatControlState);
@@ -585,6 +596,8 @@ public class TaskInfo {
+ " isVisible=" + isVisible
+ " isSleeping=" + isSleeping
+ " topActivityInSizeCompat=" + topActivityInSizeCompat
+ " topActivityEligibleForLetterboxEducation= "
+ topActivityEligibleForLetterboxEducation
+ " locusId=" + mTopActivityLocusId
+ " displayAreaFeatureId=" + displayAreaFeatureId
+ " cameraCompatControlState="

View File

@@ -5134,6 +5134,9 @@
If given value is outside of this range, the option 1 (center) is assummed. -->
<integer name="config_letterboxDefaultPositionForReachability">1</integer>
<!-- Whether displaying letterbox education is enabled for letterboxed fullscreen apps. -->
<bool name="config_letterboxIsEducationEnabled">false</bool>
<!-- Whether a camera compat controller is enabled to allow the user to apply or revert
treatment for stretched issues in camera viewfinder. -->
<bool name="config_isCameraCompatControlForStretchedIssuesEnabled">false</bool>

View File

@@ -4323,6 +4323,7 @@
<java-symbol type="dimen" name="config_letterboxHorizontalPositionMultiplier" />
<java-symbol type="bool" name="config_letterboxIsReachabilityEnabled" />
<java-symbol type="integer" name="config_letterboxDefaultPositionForReachability" />
<java-symbol type="bool" name="config_letterboxIsEducationEnabled" />
<java-symbol type="bool" name="config_isCameraCompatControlForStretchedIssuesEnabled" />
<java-symbol type="bool" name="config_hideDisplayCutoutWithDisplayArea" />

View File

@@ -362,6 +362,45 @@ public class ShellTaskOrganizerTests {
verify(mCompatUI).onCompatInfoChanged(taskInfo1, null /* taskListener */);
}
@Test
public void testOnEligibleForLetterboxEducationActivityChanged() {
final RunningTaskInfo taskInfo1 = createTaskInfo(12, WINDOWING_MODE_FULLSCREEN);
taskInfo1.displayId = DEFAULT_DISPLAY;
taskInfo1.topActivityEligibleForLetterboxEducation = false;
final TrackingTaskListener taskListener = new TrackingTaskListener();
mOrganizer.addListenerForType(taskListener, TASK_LISTENER_TYPE_FULLSCREEN);
mOrganizer.onTaskAppeared(taskInfo1, null);
// Task listener sent to compat UI is null if top activity isn't eligible for letterbox
// education.
verify(mCompatUI).onCompatInfoChanged(taskInfo1, null /* taskListener */);
// Task listener is non-null if top activity is eligible for letterbox education and task
// is visible.
clearInvocations(mCompatUI);
final RunningTaskInfo taskInfo2 =
createTaskInfo(taskInfo1.taskId, WINDOWING_MODE_FULLSCREEN);
taskInfo2.displayId = taskInfo1.displayId;
taskInfo2.topActivityEligibleForLetterboxEducation = true;
taskInfo2.isVisible = true;
mOrganizer.onTaskInfoChanged(taskInfo2);
verify(mCompatUI).onCompatInfoChanged(taskInfo2, taskListener);
// Task listener is null if task is invisible.
clearInvocations(mCompatUI);
final RunningTaskInfo taskInfo3 =
createTaskInfo(taskInfo1.taskId, WINDOWING_MODE_FULLSCREEN);
taskInfo3.displayId = taskInfo1.displayId;
taskInfo3.topActivityEligibleForLetterboxEducation = true;
taskInfo3.isVisible = false;
mOrganizer.onTaskInfoChanged(taskInfo3);
verify(mCompatUI).onCompatInfoChanged(taskInfo3, null /* taskListener */);
clearInvocations(mCompatUI);
mOrganizer.onTaskVanished(taskInfo1);
verify(mCompatUI).onCompatInfoChanged(taskInfo1, null /* taskListener */);
}
@Test
public void testOnCameraCompatActivityChanged() {
final RunningTaskInfo taskInfo1 = createTaskInfo(1, WINDOWING_MODE_FULLSCREEN);
@@ -375,7 +414,7 @@ public class ShellTaskOrganizerTests {
// compat control.
verify(mCompatUI).onCompatInfoChanged(taskInfo1, null /* taskListener */);
// Task linster is non-null when request a camera compat control for a visible task.
// Task listener is non-null when request a camera compat control for a visible task.
clearInvocations(mCompatUI);
final RunningTaskInfo taskInfo2 =
createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());

View File

@@ -715,6 +715,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Nullable
private Rect mLetterboxBoundsForFixedOrientationAndAspectRatio;
// Whether the activity is eligible to be letterboxed for fixed orientation with respect to its
// requested orientation, even when it's letterbox for another reason (e.g., size compat mode)
// and therefore #isLetterboxedForFixedOrientationAndAspectRatio returns false.
private boolean mIsEligibleForFixedOrientationLetterbox;
// State of the Camera app compat control which is used to correct stretched viewfinder
// in apps that don't handle all possible configurations and changes between them correctly.
@CameraCompatControlState
@@ -7616,6 +7621,24 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return mLetterboxBoundsForFixedOrientationAndAspectRatio != null;
}
/**
* Whether this activity is eligible for letterbox eduction.
*
* <p>Conditions that need to be met:
*
* <ul>
* <li>{@link LetterboxConfiguration#getIsEducationEnabled} is true.
* <li>The activity is eligible for fixed orientation letterbox.
* <li>The activity is in fullscreen.
* </ul>
*/
// TODO(b/215316431): Add tests
boolean isEligibleForLetterboxEducation() {
return mWmService.mLetterboxConfiguration.getIsEducationEnabled()
&& mIsEligibleForFixedOrientationLetterbox
&& getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
}
/**
* In some cases, applying insets to bounds changes the orientation. For example, if a
* close-to-square display rotates to portrait to respect a portrait orientation activity, after
@@ -7678,6 +7701,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
private void resolveFixedOrientationConfiguration(@NonNull Configuration newParentConfig,
int windowingMode) {
mLetterboxBoundsForFixedOrientationAndAspectRatio = null;
mIsEligibleForFixedOrientationLetterbox = false;
final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
final Rect stableBounds = new Rect();
// If orientation is respected when insets are applied, then stableBounds will be empty.
@@ -7717,8 +7741,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// make it fit the available bounds by scaling down its bounds.
final int forcedOrientation = getRequestedConfigurationOrientation();
if (forcedOrientation == ORIENTATION_UNDEFINED
|| (forcedOrientation == parentOrientation && orientationRespectedWithInsets)) {
mIsEligibleForFixedOrientationLetterbox = forcedOrientation != ORIENTATION_UNDEFINED
&& forcedOrientation != parentOrientation;
if (!mIsEligibleForFixedOrientationLetterbox && (forcedOrientation == ORIENTATION_UNDEFINED
|| orientationRespectedWithInsets)) {
return;
}

View File

@@ -126,6 +126,9 @@ final class LetterboxConfiguration {
@LetterboxReachabilityPosition
private volatile int mLetterboxPositionForReachability;
// Whether education is allowed for letterboxed fullscreen apps.
private boolean mIsEducationEnabled;
LetterboxConfiguration(Context systemUiContext) {
mContext = systemUiContext;
mFixedOrientationLetterboxAspectRatio = mContext.getResources().getFloat(
@@ -143,6 +146,8 @@ final class LetterboxConfiguration {
R.bool.config_letterboxIsReachabilityEnabled);
mDefaultPositionForReachability = readLetterboxReachabilityPositionFromConfig(mContext);
mLetterboxPositionForReachability = mDefaultPositionForReachability;
mIsEducationEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsEducationEnabled);
}
/**
@@ -501,4 +506,27 @@ final class LetterboxConfiguration {
mLetterboxPositionForReachability = Math.max(mLetterboxPositionForReachability - 1, 0);
}
/**
* Whether education is allowed for letterboxed fullscreen apps.
*/
boolean getIsEducationEnabled() {
return mIsEducationEnabled;
}
/**
* Overrides whether education is allowed for letterboxed fullscreen apps.
*/
void setIsEducationEnabled(boolean enabled) {
mIsEducationEnabled = enabled;
}
/**
* Resets whether education is allowed for letterboxed fullscreen apps to
* {@link R.bool.config_letterboxIsEducationEnabled}.
*/
void resetIsEducationEnabled() {
mIsEducationEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsEducationEnabled);
}
}

View File

@@ -3434,6 +3434,9 @@ class Task extends TaskFragment {
// Whether the direct top activity is in size compat mode on foreground.
info.topActivityInSizeCompat = isTopActivityResumed
&& mReuseActivitiesReport.top.inSizeCompatMode();
// Whether the direct top activity is eligible for letterbox education.
info.topActivityEligibleForLetterboxEducation = isTopActivityResumed
&& mReuseActivitiesReport.top.isEligibleForLetterboxEducation();
// Whether the direct top activity requested showing camera compat control.
info.cameraCompatControlState = isTopActivityResumed
? mReuseActivitiesReport.top.getCameraCompatControlState()

View File

@@ -822,6 +822,29 @@ public class WindowManagerShellCommand extends ShellCommand {
return 0;
}
private int runSetLetterboxIsEducationEnabled(PrintWriter pw) throws RemoteException {
String arg = getNextArg();
final boolean enabled;
switch (arg) {
case "true":
case "1":
enabled = true;
break;
case "false":
case "0":
enabled = false;
break;
default:
getErrPrintWriter().println("Error: expected true, 1, false, 0, but got " + arg);
return -1;
}
synchronized (mInternal.mGlobalLock) {
mLetterboxConfiguration.setIsEducationEnabled(enabled);
}
return 0;
}
private int runSetLetterboxStyle(PrintWriter pw) throws RemoteException {
if (peekNextArg() == null) {
getErrPrintWriter().println("Error: No arguments provided.");
@@ -859,6 +882,9 @@ public class WindowManagerShellCommand extends ShellCommand {
case "--defaultPositionForReachability":
runSetLetterboxDefaultPositionForReachability(pw);
break;
case "--isEducationEnabled":
runSetLetterboxIsEducationEnabled(pw);
break;
default:
getErrPrintWriter().println(
"Error: Unrecognized letterbox style option: " + arg);
@@ -903,6 +929,9 @@ public class WindowManagerShellCommand extends ShellCommand {
case "defaultPositionForReachability":
mLetterboxConfiguration.getDefaultPositionForReachability();
break;
case "isEducationEnabled":
mLetterboxConfiguration.getIsEducationEnabled();
break;
default:
getErrPrintWriter().println(
"Error: Unrecognized letterbox style option: " + arg);
@@ -998,6 +1027,7 @@ public class WindowManagerShellCommand extends ShellCommand {
mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
mLetterboxConfiguration.resetIsReachabilityEnabled();
mLetterboxConfiguration.resetDefaultPositionForReachability();
mLetterboxConfiguration.resetIsEducationEnabled();
}
}
@@ -1014,6 +1044,8 @@ public class WindowManagerShellCommand extends ShellCommand {
pw.println("Default position for reachability: "
+ LetterboxConfiguration.letterboxReachabilityPositionToString(
mLetterboxConfiguration.getDefaultPositionForReachability()));
pw.println("Is education enabled: "
+ mLetterboxConfiguration.getIsEducationEnabled());
pw.println("Background type: "
+ LetterboxConfiguration.letterboxBackgroundTypeToString(
@@ -1154,10 +1186,12 @@ public class WindowManagerShellCommand extends ShellCommand {
pw.println(" --defaultPositionForReachability [left|center|right]");
pw.println(" Default horizontal position of app window when reachability is.");
pw.println(" enabled.");
pw.println(" --isEducationEnabled [true|1|false|0]");
pw.println(" Whether education is allowed for letterboxed fullscreen apps.");
pw.println(" reset-letterbox-style [aspectRatio|cornerRadius|backgroundType");
pw.println(" |backgroundColor|wallpaperBlurRadius|wallpaperDarkScrimAlpha");
pw.println(" |horizontalPositionMultiplier|isReachabilityEnabled");
pw.println(" |defaultPositionMultiplierForReachability]");
pw.println(" isEducationEnabled||defaultPositionMultiplierForReachability]");
pw.println(" Resets overrides to default values for specified properties separated");
pw.println(" by space, e.g. 'reset-letterbox-style aspectRatio cornerRadius'.");
pw.println(" If no arguments provided, all values will be reset.");