Merge "Letterbox Reachability: Add a central stop for repositioning." into sc-v2-dev

This commit is contained in:
TreeHugger Robot
2021-10-01 13:40:26 +00:00
committed by Android (Google) Code Review
7 changed files with 159 additions and 82 deletions

View File

@@ -4915,16 +4915,15 @@
device orientation. --> device orientation. -->
<bool name="config_letterboxIsReachabilityEnabled">false</bool> <bool name="config_letterboxIsReachabilityEnabled">false</bool>
<!-- Default horizonal position of a center of the letterboxed app window when reachability is <!-- Default horizonal position of the letterboxed app window when reachability is
enabled and an app is fullscreen in landscape device orientation. enabled and an app is fullscreen in landscape device orientation. When reachability is
0 corresponds to the left side of the screen and 1 to the right side. If given value < 0.0 enabled, the position can change between left, center and right. This config defines the
or > 1, it is ignored and right positionis used (1.0). The position multiplier is changed default one:
to a symmetrical value computed as (1 - current multiplier) after each double tap in the - Option 0 - Left.
letterbox area. --> - Option 1 - Center.
<item name="config_letterboxDefaultPositionMultiplierForReachability" - Option 2 - Right.
format="float" type="dimen"> If given value is outside of this range, the option 1 (center) is assummed. -->
0.9 <integer name="config_letterboxDefaultPositionForReachability">1</integer>
</item>
<!-- If true, hide the display cutout with display area --> <!-- If true, hide the display cutout with display area -->
<bool name="config_hideDisplayCutoutWithDisplayArea">false</bool> <bool name="config_hideDisplayCutoutWithDisplayArea">false</bool>

View File

@@ -4262,7 +4262,7 @@
<java-symbol type="color" name="config_letterboxBackgroundColor" /> <java-symbol type="color" name="config_letterboxBackgroundColor" />
<java-symbol type="dimen" name="config_letterboxHorizontalPositionMultiplier" /> <java-symbol type="dimen" name="config_letterboxHorizontalPositionMultiplier" />
<java-symbol type="bool" name="config_letterboxIsReachabilityEnabled" /> <java-symbol type="bool" name="config_letterboxIsReachabilityEnabled" />
<java-symbol type="dimen" name="config_letterboxDefaultPositionMultiplierForReachability" /> <java-symbol type="integer" name="config_letterboxDefaultPositionForReachability" />
<java-symbol type="bool" name="config_hideDisplayCutoutWithDisplayArea" /> <java-symbol type="bool" name="config_hideDisplayCutoutWithDisplayArea" />

View File

@@ -36,6 +36,7 @@ import android.view.WindowManager;
import com.android.server.UiThread; import com.android.server.UiThread;
import java.util.function.IntConsumer;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
@@ -70,7 +71,7 @@ public class Letterbox {
private final LetterboxSurface mFullWindowSurface = new LetterboxSurface("fullWindow"); private final LetterboxSurface mFullWindowSurface = new LetterboxSurface("fullWindow");
private final LetterboxSurface[] mSurfaces = { mLeft, mTop, mRight, mBottom }; private final LetterboxSurface[] mSurfaces = { mLeft, mTop, mRight, mBottom };
// Reachability gestures. // Reachability gestures.
private final Runnable mDoubleTapCallback; private final IntConsumer mDoubleTapCallback;
/** /**
* Constructs a Letterbox. * Constructs a Letterbox.
@@ -84,7 +85,7 @@ public class Letterbox {
Supplier<Boolean> hasWallpaperBackgroundSupplier, Supplier<Boolean> hasWallpaperBackgroundSupplier,
Supplier<Integer> blurRadiusSupplier, Supplier<Integer> blurRadiusSupplier,
Supplier<Float> darkScrimAlphaSupplier, Supplier<Float> darkScrimAlphaSupplier,
Runnable doubleTapCallback) { IntConsumer doubleTapCallback) {
mSurfaceControlFactory = surfaceControlFactory; mSurfaceControlFactory = surfaceControlFactory;
mTransactionFactory = transactionFactory; mTransactionFactory = transactionFactory;
mAreCornersRounded = areCornersRounded; mAreCornersRounded = areCornersRounded;
@@ -262,7 +263,7 @@ public class Letterbox {
@Override @Override
public boolean onDoubleTapEvent(MotionEvent e) { public boolean onDoubleTapEvent(MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_UP) { if (e.getAction() == MotionEvent.ACTION_UP) {
mDoubleTapCallback.run(); mDoubleTapCallback.accept((int) e.getX());
return true; return true;
} }
return false; return false;

View File

@@ -54,6 +54,27 @@ final class LetterboxConfiguration {
/** Using wallpaper as a background which can be blurred or dimmed with dark scrim. */ /** Using wallpaper as a background which can be blurred or dimmed with dark scrim. */
static final int LETTERBOX_BACKGROUND_WALLPAPER = 3; static final int LETTERBOX_BACKGROUND_WALLPAPER = 3;
/**
* Enum for Letterbox reachability position types.
*
* <p>Order from left to right is important since it's used in {@link
* #movePositionForReachabilityToNextRightStop} and {@link
* #movePositionForReachabilityToNextLeftStop}.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({LETTERBOX_REACHABILITY_POSITION_LEFT, LETTERBOX_REACHABILITY_POSITION_CENTER,
LETTERBOX_REACHABILITY_POSITION_RIGHT})
@interface LetterboxReachabilityPosition {};
/** Letterboxed app window is aligned to the left side. */
static final int LETTERBOX_REACHABILITY_POSITION_LEFT = 0;
/** Letterboxed app window is positioned in the horizontal center. */
static final int LETTERBOX_REACHABILITY_POSITION_CENTER = 1;
/** Letterboxed app window is aligned to the right side. */
static final int LETTERBOX_REACHABILITY_POSITION_RIGHT = 2;
final Context mContext; final Context mContext;
// Aspect ratio of letterbox for fixed orientation, values <= // Aspect ratio of letterbox for fixed orientation, values <=
@@ -85,25 +106,25 @@ final class LetterboxConfiguration {
// side of the screen and 1.0 to the right side. // side of the screen and 1.0 to the right side.
private float mLetterboxHorizontalPositionMultiplier; private float mLetterboxHorizontalPositionMultiplier;
// Default horizontal position of a center of the letterboxed app window when reachability is // Default horizontal position the letterboxed app window when reachability is enabled and
// enabled and an app is fullscreen in landscape device orientatio. 0 corresponds to the left // an app is fullscreen in landscape device orientatio.
// side of the screen and 1.0 to the right side. // It is used as a starting point for mLetterboxPositionForReachability.
// It is used as a starting point for mLetterboxHorizontalMultiplierForReachability. @LetterboxReachabilityPosition
private float mDefaultPositionMultiplierForReachability; private int mDefaultPositionForReachability;
// Whether reachability repositioning is allowed for letterboxed fullscreen apps in landscape // Whether reachability repositioning is allowed for letterboxed fullscreen apps in landscape
// device orientation. // device orientation.
private boolean mIsReachabilityEnabled; private boolean mIsReachabilityEnabled;
// Horizontal position of a center of the letterboxed app window. 0 corresponds to // Horizontal position of a center of the letterboxed app window which is global to prevent
// the left side of the screen and 1 to the right side. Keep it global to prevent // "jumps" when switching between letterboxed apps. It's updated to reposition the app window
// "jumps" when switching between letterboxed apps. It's updated to reposition the app // in response to a double tap gesture (see LetterboxUiController#handleDoubleTap). Used in
// window in response to a double tap gesture (see LetterboxUiController#handleDoubleTap). // LetterboxUiController#getHorizontalPositionMultiplier which is called from
// Used in LetterboxUiController#getHorizontalPositionMultiplier which is called from
// ActivityRecord#updateResolvedBoundsHorizontalPosition. // ActivityRecord#updateResolvedBoundsHorizontalPosition.
// TODO(b/199426138): Global reachability setting causes a jump when resuming an app from // TODO(b/199426138): Global reachability setting causes a jump when resuming an app from
// Overview after changing position in another app. // Overview after changing position in another app.
private volatile float mLetterboxHorizontalMultiplierForReachability; @LetterboxReachabilityPosition
private volatile int mLetterboxPositionForReachability;
LetterboxConfiguration(Context systemUiContext) { LetterboxConfiguration(Context systemUiContext) {
mContext = systemUiContext; mContext = systemUiContext;
@@ -120,9 +141,8 @@ final class LetterboxConfiguration {
R.dimen.config_letterboxHorizontalPositionMultiplier); R.dimen.config_letterboxHorizontalPositionMultiplier);
mIsReachabilityEnabled = mContext.getResources().getBoolean( mIsReachabilityEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsReachabilityEnabled); R.bool.config_letterboxIsReachabilityEnabled);
mDefaultPositionMultiplierForReachability = mContext.getResources().getFloat( mDefaultPositionForReachability = readLetterboxReachabilityPositionFromConfig(mContext);
R.dimen.config_letterboxDefaultPositionMultiplierForReachability); mLetterboxPositionForReachability = mDefaultPositionForReachability;
mLetterboxHorizontalMultiplierForReachability = mDefaultPositionMultiplierForReachability;
} }
/** /**
@@ -395,58 +415,90 @@ final class LetterboxConfiguration {
} }
/* /*
* Gets default horizontal position of a center of the letterboxed app window when reachability * Gets default horizontal position of the letterboxed app window when reachability is enabled.
* is enabled specified in {@link * Specified in {@link R.integer.config_letterboxDefaultPositionForReachability} or via an ADB
* R.dimen.config_letterboxDefaultPositionMultiplierForReachability} or via an ADB command. * command.
* 0 corresponds to the left side of the screen and 1 to the right side. The returned value is
* >= 0.0 and <= 1.0.
*/ */
float getDefaultPositionMultiplierForReachability() { @LetterboxReachabilityPosition
return (mDefaultPositionMultiplierForReachability < 0.0f int getDefaultPositionForReachability() {
|| mDefaultPositionMultiplierForReachability > 1.0f) return mDefaultPositionForReachability;
// Default to a right position if invalid value is provided.
? 1.0f : mDefaultPositionMultiplierForReachability;
} }
/** /**
* Overrides default horizontal position of a center of the letterboxed app window when * Overrides default horizonal position of the letterboxed app window when reachability
* reachability is enabled. If given value < 0.0 or > 1.0, then it and a value of {@link * is enabled.
* R.dimen.config_letterboxDefaultPositionMultiplierForReachability} are ignored and the right
* position (1.0) is used.
*/ */
void setDefaultPositionMultiplierForReachability(float multiplier) { void setDefaultPositionForReachability(@LetterboxReachabilityPosition int position) {
mDefaultPositionMultiplierForReachability = multiplier; mDefaultPositionForReachability = position;
} }
/** /**
* Resets default horizontal position of a center of the letterboxed app window when * Resets default horizontal position of the letterboxed app window when reachability is
* reachability is enabled to {@link * enabled to {@link R.integer.config_letterboxDefaultPositionForReachability}.
* R.dimen.config_letterboxDefaultPositionMultiplierForReachability}.
*/ */
void resetDefaultPositionMultiplierForReachability() { void resetDefaultPositionForReachability() {
mDefaultPositionMultiplierForReachability = mContext.getResources().getFloat( mDefaultPositionForReachability = readLetterboxReachabilityPositionFromConfig(mContext);
R.dimen.config_letterboxDefaultPositionMultiplierForReachability); }
@LetterboxReachabilityPosition
private static int readLetterboxReachabilityPositionFromConfig(Context context) {
int position = context.getResources().getInteger(
R.integer.config_letterboxDefaultPositionForReachability);
return position == LETTERBOX_REACHABILITY_POSITION_LEFT
|| position == LETTERBOX_REACHABILITY_POSITION_CENTER
|| position == LETTERBOX_REACHABILITY_POSITION_RIGHT
? position : LETTERBOX_REACHABILITY_POSITION_CENTER;
} }
/* /*
* Gets horizontal position of a center of the letterboxed app window when reachability * Gets horizontal position of a center of the letterboxed app window when reachability
* is enabled specified. 0 corresponds to the left side of the screen and 1 to the right side. * is enabled specified. 0 corresponds to the left side of the screen and 1 to the right side.
* *
* <p>The position multiplier is changed to a symmetrical value computed as (1 - current * <p>The position multiplier is changed after each double tap in the letterbox area.
* multiplier) after each double tap in the letterbox area.
*/ */
float getHorizontalMultiplierForReachability() { float getHorizontalMultiplierForReachability() {
return mLetterboxHorizontalMultiplierForReachability; switch (mLetterboxPositionForReachability) {
case LETTERBOX_REACHABILITY_POSITION_LEFT:
return 0.0f;
case LETTERBOX_REACHABILITY_POSITION_CENTER:
return 0.5f;
case LETTERBOX_REACHABILITY_POSITION_RIGHT:
return 1.0f;
default:
throw new AssertionError(
"Unexpected letterbox position type: " + mLetterboxPositionForReachability);
}
}
/** Returns a string representing the given {@link LetterboxReachabilityPosition}. */
static String letterboxReachabilityPositionToString(
@LetterboxReachabilityPosition int position) {
switch (position) {
case LETTERBOX_REACHABILITY_POSITION_LEFT:
return "LETTERBOX_REACHABILITY_POSITION_LEFT";
case LETTERBOX_REACHABILITY_POSITION_CENTER:
return "LETTERBOX_REACHABILITY_POSITION_CENTER";
case LETTERBOX_REACHABILITY_POSITION_RIGHT:
return "LETTERBOX_REACHABILITY_POSITION_RIGHT";
default:
throw new AssertionError(
"Unexpected letterbox position type: " + position);
}
} }
/** /**
* Changes horizontal position of a center of the letterboxed app window to the opposite * Changes letterbox position for reachability to the next available one on the right side.
* (1 - current multiplier) when reachability is enabled specified. 0 corresponds to the left
* side of the screen and 1 to the right side.
*/ */
void flipHorizontalMultiplierForReachability() { void movePositionForReachabilityToNextRightStop() {
mLetterboxHorizontalMultiplierForReachability = mLetterboxPositionForReachability = Math.min(
1.0f - mLetterboxHorizontalMultiplierForReachability; mLetterboxPositionForReachability + 1, LETTERBOX_REACHABILITY_POSITION_RIGHT);
}
/**
* Changes letterbox position for reachability to the next available one on the left side.
*/
void movePositionForReachabilityToNextLeftStop() {
mLetterboxPositionForReachability = Math.max(mLetterboxPositionForReachability - 1, 0);
} }
} }

View File

@@ -210,12 +210,23 @@ final class LetterboxUiController {
return mActivityRecord.mWmService.mContext.getResources(); return mActivityRecord.mWmService.mContext.getResources();
} }
private void handleDoubleTap() { private void handleDoubleTap(int x) {
if (!isReachabilityEnabled() || mActivityRecord.isInTransition()) { if (!isReachabilityEnabled() || mActivityRecord.isInTransition()) {
return; return;
} }
mLetterboxConfiguration.flipHorizontalMultiplierForReachability(); if (mLetterbox.getInnerFrame().left <= x && mLetterbox.getInnerFrame().right >= x) {
// Only react to clicks at the sides of the letterboxed app window.
return;
}
if (mLetterbox.getInnerFrame().left > x) {
// Moving to the next stop on the left side of the app window: right > center > left.
mLetterboxConfiguration.movePositionForReachabilityToNextLeftStop();
} else if (mLetterbox.getInnerFrame().right < x) {
// Moving to the next stop on the right side of the app window: left > center > right.
mLetterboxConfiguration.movePositionForReachabilityToNextRightStop();
}
// TODO(197549949): Add animation for transition. // TODO(197549949): Add animation for transition.
mActivityRecord.recomputeConfiguration(); mActivityRecord.recomputeConfiguration();

View File

@@ -23,6 +23,9 @@ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING; import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR; import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR;
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_WALLPAPER; import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_WALLPAPER;
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_REACHABILITY_POSITION_CENTER;
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_REACHABILITY_POSITION_LEFT;
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_REACHABILITY_POSITION_RIGHT;
import android.content.res.Resources.NotFoundException; import android.content.res.Resources.NotFoundException;
import android.graphics.Color; import android.graphics.Color;
@@ -44,6 +47,7 @@ import com.android.internal.protolog.ProtoLogImpl;
import com.android.server.LocalServices; import com.android.server.LocalServices;
import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType; import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType;
import com.android.server.wm.LetterboxConfiguration.LetterboxReachabilityPosition;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
@@ -787,22 +791,33 @@ public class WindowManagerShellCommand extends ShellCommand {
return 0; return 0;
} }
private int runSetLetterboxDefaultPositionMultiplierForReachability(PrintWriter pw) private int runSetLetterboxDefaultPositionForReachability(PrintWriter pw)
throws RemoteException { throws RemoteException {
final float multiplier; @LetterboxReachabilityPosition final int position;
try { try {
String arg = getNextArgRequired(); String arg = getNextArgRequired();
multiplier = Float.parseFloat(arg); switch (arg) {
} catch (NumberFormatException e) { case "left":
getErrPrintWriter().println("Error: bad multiplier format " + e); position = LETTERBOX_REACHABILITY_POSITION_LEFT;
return -1; break;
case "center":
position = LETTERBOX_REACHABILITY_POSITION_CENTER;
break;
case "right":
position = LETTERBOX_REACHABILITY_POSITION_RIGHT;
break;
default:
getErrPrintWriter().println(
"Error: 'left', 'center' or 'right' are expected as an argument");
return -1;
}
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
getErrPrintWriter().println( getErrPrintWriter().println(
"Error: multiplier should be provided as an argument " + e); "Error: 'left', 'center' or 'right' are expected as an argument" + e);
return -1; return -1;
} }
synchronized (mInternal.mGlobalLock) { synchronized (mInternal.mGlobalLock) {
mLetterboxConfiguration.setDefaultPositionMultiplierForReachability(multiplier); mLetterboxConfiguration.setDefaultPositionForReachability(position);
} }
return 0; return 0;
} }
@@ -841,8 +856,8 @@ public class WindowManagerShellCommand extends ShellCommand {
case "--isReachabilityEnabled": case "--isReachabilityEnabled":
runSetLetterboxIsReachabilityEnabled(pw); runSetLetterboxIsReachabilityEnabled(pw);
break; break;
case "--defaultPositionMultiplierReachability": case "--defaultPositionForReachability":
runSetLetterboxDefaultPositionMultiplierForReachability(pw); runSetLetterboxDefaultPositionForReachability(pw);
break; break;
default: default:
getErrPrintWriter().println( getErrPrintWriter().println(
@@ -885,8 +900,8 @@ public class WindowManagerShellCommand extends ShellCommand {
case "isReachabilityEnabled": case "isReachabilityEnabled":
mLetterboxConfiguration.getIsReachabilityEnabled(); mLetterboxConfiguration.getIsReachabilityEnabled();
break; break;
case "defaultPositionMultiplierForReachability": case "defaultPositionForReachability":
mLetterboxConfiguration.getDefaultPositionMultiplierForReachability(); mLetterboxConfiguration.getDefaultPositionForReachability();
break; break;
default: default:
getErrPrintWriter().println( getErrPrintWriter().println(
@@ -982,7 +997,7 @@ public class WindowManagerShellCommand extends ShellCommand {
mLetterboxConfiguration.resetLetterboxBackgroundWallpaperDarkScrimAlpha(); mLetterboxConfiguration.resetLetterboxBackgroundWallpaperDarkScrimAlpha();
mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier(); mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
mLetterboxConfiguration.resetIsReachabilityEnabled(); mLetterboxConfiguration.resetIsReachabilityEnabled();
mLetterboxConfiguration.resetDefaultPositionMultiplierForReachability(); mLetterboxConfiguration.resetDefaultPositionForReachability();
} }
} }
@@ -996,8 +1011,9 @@ public class WindowManagerShellCommand extends ShellCommand {
+ mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio()); + mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio());
pw.println("Is reachability enabled: " pw.println("Is reachability enabled: "
+ mLetterboxConfiguration.getIsReachabilityEnabled()); + mLetterboxConfiguration.getIsReachabilityEnabled());
pw.println("Default position multiplier for reachability: " pw.println("Default position for reachability: "
+ mLetterboxConfiguration.getDefaultPositionMultiplierForReachability()); + LetterboxConfiguration.letterboxReachabilityPositionToString(
mLetterboxConfiguration.getDefaultPositionForReachability()));
pw.println("Background type: " pw.println("Background type: "
+ LetterboxConfiguration.letterboxBackgroundTypeToString( + LetterboxConfiguration.letterboxBackgroundTypeToString(
@@ -1135,11 +1151,9 @@ public class WindowManagerShellCommand extends ShellCommand {
pw.println(" --isReachabilityEnabled [true|1|false|0]"); pw.println(" --isReachabilityEnabled [true|1|false|0]");
pw.println(" Whether reachability repositioning is allowed for letterboxed"); pw.println(" Whether reachability repositioning is allowed for letterboxed");
pw.println(" fullscreen apps in landscape device orientation."); pw.println(" fullscreen apps in landscape device orientation.");
pw.println(" --defaultPositionMultiplierReachability multiplier"); pw.println(" --defaultPositionForReachability [left|center|right]");
pw.println(" Default horizontal position of app window center when reachability is"); pw.println(" Default horizontal position of app window when reachability is.");
pw.println(" enabled. If multiplier < 0.0 or > 1, both it and "); pw.println(" enabled.");
pw.println(" R.dimen.config_letterboxDefaultPositionMultiplierForReachability");
pw.println(" are ignored and right position (1.0) is used.");
pw.println(" reset-letterbox-style [aspectRatio|cornerRadius|backgroundType"); pw.println(" reset-letterbox-style [aspectRatio|cornerRadius|backgroundType");
pw.println(" |backgroundColor|wallpaperBlurRadius|wallpaperDarkScrimAlpha"); pw.println(" |backgroundColor|wallpaperBlurRadius|wallpaperDarkScrimAlpha");
pw.println(" |horizontalPositionMultiplier|isReachabilityEnabled"); pw.println(" |horizontalPositionMultiplier|isReachabilityEnabled");

View File

@@ -63,7 +63,7 @@ public class LetterboxTest {
mLetterbox = new Letterbox(mSurfaces, StubTransaction::new, mLetterbox = new Letterbox(mSurfaces, StubTransaction::new,
() -> mAreCornersRounded, () -> Color.valueOf(mColor), () -> mAreCornersRounded, () -> Color.valueOf(mColor),
() -> mHasWallpaperBackground, () -> mBlurRadius, () -> mDarkScrimAlpha, () -> mHasWallpaperBackground, () -> mBlurRadius, () -> mDarkScrimAlpha,
/* doubleTapCallback= */ () -> {}); /* doubleTapCallback= */ x -> {});
mTransaction = spy(StubTransaction.class); mTransaction = spy(StubTransaction.class);
} }