Merge "Fix smallest width configuration calculation" into nyc-dev

This commit is contained in:
Jorim Jaggi
2016-05-12 01:50:04 +00:00
committed by Android (Google) Code Review
6 changed files with 143 additions and 24 deletions

View File

@@ -246,7 +246,8 @@ public class DividerSnapAlgorithm {
int dividerMax = isHorizontalDivision
? mDisplayHeight
: mDisplayWidth;
mTargets.add(new SnapTarget(-mDividerSize, SnapTarget.FLAG_DISMISS_START, 0.35f));
mTargets.add(new SnapTarget(-mDividerSize, -mDividerSize, SnapTarget.FLAG_DISMISS_START,
0.35f));
switch (mSnapMode) {
case SNAP_MODE_16_9:
addRatio16_9Targets(isHorizontalDivision, dividerMax);
@@ -259,7 +260,8 @@ public class DividerSnapAlgorithm {
break;
}
int navBarSize = isHorizontalDivision ? mInsets.bottom : mInsets.right;
mTargets.add(new SnapTarget(dividerMax - navBarSize, SnapTarget.FLAG_DISMISS_END, 0.35f));
mTargets.add(new SnapTarget(dividerMax - navBarSize, dividerMax,
SnapTarget.FLAG_DISMISS_END, 0.35f));
}
private void addNonDismissingTargets(boolean isHorizontalDivision, int topPosition,
@@ -269,13 +271,15 @@ public class DividerSnapAlgorithm {
maybeAddTarget(bottomPosition, dividerMax - mInsets.bottom
- (bottomPosition + mDividerSize));
}
private void addFixedDivisionTargets(boolean isHorizontalDivision, int dividerMax) {
int start = isHorizontalDivision ? mInsets.top : mInsets.left;
int end = isHorizontalDivision
? mDisplayHeight - mInsets.bottom
: mDisplayWidth - mInsets.right;
int topPosition = (int) (start + mFixedRatio * (end - start)) - mDividerSize / 2;
int bottomPosition = (int) (start + (1 - mFixedRatio) * (end - start)) - mDividerSize / 2;
int size = (int) (mFixedRatio * (end - start)) - mDividerSize / 2;
int topPosition = start + size;
int bottomPosition = end - size - mDividerSize;
addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax);
}
@@ -301,13 +305,14 @@ public class DividerSnapAlgorithm {
*/
private void maybeAddTarget(int position, int smallerSize) {
if (smallerSize >= mMinimalSizeResizableTask) {
mTargets.add(new SnapTarget(position, SnapTarget.FLAG_NONE));
mTargets.add(new SnapTarget(position, position, SnapTarget.FLAG_NONE));
}
}
private void addMiddleTarget(boolean isHorizontalDivision) {
mTargets.add(new SnapTarget(DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision,
mInsets, mDisplayWidth, mDisplayHeight, mDividerSize), SnapTarget.FLAG_NONE));
int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision,
mInsets, mDisplayWidth, mDisplayHeight, mDividerSize);
mTargets.add(new SnapTarget(position, position, SnapTarget.FLAG_NONE));
}
public SnapTarget getMiddleTarget() {
@@ -370,7 +375,15 @@ public class DividerSnapAlgorithm {
/** If the divider reaches this value, the right/bottom task should be dismissed */
public static final int FLAG_DISMISS_END = 2;
/** Position of this snap target. The right/bottom edge of the top/left task snaps here. */
public final int position;
/**
* Like {@link #position}, but used to calculate the task bounds which might be different
* from the stack bounds.
*/
public final int taskPosition;
public final int flag;
/**
@@ -379,12 +392,13 @@ public class DividerSnapAlgorithm {
*/
private final float distanceMultiplier;
public SnapTarget(int position, int flag) {
this(position, flag, 1f);
public SnapTarget(int position, int taskPosition, int flag) {
this(position, taskPosition, flag, 1f);
}
public SnapTarget(int position, int flag, float distanceMultiplier) {
public SnapTarget(int position, int taskPosition, int flag, float distanceMultiplier) {
this.position = position;
this.taskPosition = taskPosition;
this.flag = flag;
this.distanceMultiplier = distanceMultiplier;
}

View File

@@ -535,7 +535,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
anim.addUpdateListener(animation -> resizeStack((Integer) animation.getAnimatedValue(),
taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f
? TASK_POSITION_SAME
: snapTarget.position, snapTarget));
: snapTarget.taskPosition, snapTarget));
Runnable endAction = () -> {
commitSnapFlags(snapTarget);
mWindowManagerProxy.setResizing(false);

View File

@@ -1508,16 +1508,18 @@ final class TaskRecord {
? Configuration.ORIENTATION_PORTRAIT
: Configuration.ORIENTATION_LANDSCAPE;
// For calculating screen layout and smallest screen width, we need to use the non-decor
// inset screen area for the calculation for compatibility reasons, i.e. screen area without
// system bars that could never go away in Honeycomb.
// For calculating screen layout, we need to use the non-decor inset screen area for the
// calculation for compatibility reasons, i.e. screen area without system bars that could
// never go away in Honeycomb.
final int compatScreenWidthDp = (int)(mTmpNonDecorBounds.width() / density);
final int compatScreenHeightDp = (int)(mTmpNonDecorBounds.height() / density);
final int sl = Configuration.resetScreenLayout(serviceConfig.screenLayout);
final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
config.smallestScreenWidthDp = Math.min(compatScreenHeightDp, compatScreenWidthDp);
config.screenLayout = Configuration.reduceScreenLayout(sl, longSize,
config.smallestScreenWidthDp);
final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);;
config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
config.smallestScreenWidthDp = mService.mWindowManager.getSmallestWidthForTaskBounds(
insetBounds != null ? insetBounds : bounds);
return config;
}

View File

@@ -19,6 +19,10 @@ package com.android.server.wm;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
@@ -30,6 +34,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -41,6 +46,8 @@ import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DockedDividerUtils;
import com.android.server.wm.DimLayer.DimLayerUser;
import com.android.server.wm.WindowManagerService.H;
@@ -96,6 +103,7 @@ public class DockedStackDividerController implements DimLayerUser {
private WindowState mWindow;
private final Rect mTmpRect = new Rect();
private final Rect mTmpRect2 = new Rect();
private final Rect mTmpRect3 = new Rect();
private final Rect mLastRect = new Rect();
private boolean mLastVisibility = false;
private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners
@@ -121,6 +129,7 @@ public class DockedStackDividerController implements DimLayerUser {
private float mDividerAnimationTarget;
private float mLastAnimationProgress;
private float mLastDividerProgress;
private final DividerSnapAlgorithm[] mSnapAlgorithmForRotation = new DividerSnapAlgorithm[4];
DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
mService = service;
@@ -133,6 +142,77 @@ public class DockedStackDividerController implements DimLayerUser {
loadDimens();
}
int getSmallestWidthDpForBounds(Rect bounds) {
final DisplayInfo di = mDisplayContent.getDisplayInfo();
// If the bounds are fullscreen, return the value of the fullscreen configuration
if (bounds == null || (bounds.left == 0 && bounds.top == 0
&& bounds.right == di.logicalWidth && bounds.bottom == di.logicalHeight)) {
return mService.mCurConfiguration.smallestScreenWidthDp;
}
final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth;
final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight;
int minWidth = Integer.MAX_VALUE;
// Go through all screen orientations and find the orientation in which the task has the
// smallest width.
for (int rotation = 0; rotation < 4; rotation++) {
mTmpRect.set(bounds);
mDisplayContent.rotateBounds(di.rotation, rotation, mTmpRect);
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
mTmpRect2.set(0, 0,
rotated ? baseDisplayHeight : baseDisplayWidth,
rotated ? baseDisplayWidth : baseDisplayHeight);
final int orientation = mTmpRect2.width() <= mTmpRect2.height()
? ORIENTATION_PORTRAIT
: ORIENTATION_LANDSCAPE;
final int dockSide = TaskStack.getDockSideUnchecked(mTmpRect, mTmpRect2, orientation);
final int position = DockedDividerUtils.calculatePositionForBounds(mTmpRect, dockSide,
getContentWidth());
// Since we only care about feasible states, snap to the closest snap target, like it
// would happen when actually rotating the screen.
final int snappedPosition = mSnapAlgorithmForRotation[rotation]
.calculateNonDismissingSnapTarget(position).position;
DockedDividerUtils.calculateBoundsForPosition(snappedPosition, dockSide, mTmpRect,
mTmpRect2.width(), mTmpRect2.height(), getContentWidth());
mService.mPolicy.getStableInsetsLw(rotation, mTmpRect2.width(), mTmpRect2.height(),
mTmpRect3);
mService.subtractInsets(mTmpRect2, mTmpRect3, mTmpRect);
minWidth = Math.min(mTmpRect.width(), minWidth);
}
return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
}
private void initSnapAlgorithmForRotations() {
final Configuration baseConfig = mService.mCurConfiguration;
// Initialize the snap algorithms for all 4 screen orientations.
final Configuration config = new Configuration();
for (int rotation = 0; rotation < 4; rotation++) {
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
final int dw = rotated
? mDisplayContent.mBaseDisplayHeight
: mDisplayContent.mBaseDisplayWidth;
final int dh = rotated
? mDisplayContent.mBaseDisplayWidth
: mDisplayContent.mBaseDisplayHeight;
mService.mPolicy.getStableInsetsLw(rotation, dw, dh, mTmpRect);
config.setToDefaults();
config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
config.screenWidthDp = (int)
(mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, baseConfig.uiMode) /
mDisplayContent.getDisplayMetrics().density);
config.screenHeightDp = (int)
(mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, baseConfig.uiMode) /
mDisplayContent.getDisplayMetrics().density);
final Context rotationContext = mService.mContext.createConfigurationContext(config);
mSnapAlgorithmForRotation[rotation] = new DividerSnapAlgorithm(
rotationContext.getResources(), dw, dh, getContentWidth(),
config.orientation == ORIENTATION_PORTRAIT, mTmpRect);
}
}
private void loadDimens() {
final Context context = mService.mContext;
mDividerWindowWidth = context.getResources().getDimensionPixelSize(
@@ -141,6 +221,7 @@ public class DockedStackDividerController implements DimLayerUser {
com.android.internal.R.dimen.docked_stack_divider_insets);
mDividerWindowWidthInactive = WindowManagerService.dipToPixel(
DIVIDER_WIDTH_INACTIVE_DP, mDisplayContent.getDisplayMetrics());
initSnapAlgorithmForRotations();
}
void onConfigurationChanged() {

View File

@@ -1197,16 +1197,20 @@ public class TaskStack implements DimLayer.DimLayerUser,
}
mDisplayContent.getLogicalDisplayRect(mTmpRect);
final int orientation = mService.mCurConfiguration.orientation;
return getDockSideUnchecked(bounds, mTmpRect, orientation);
}
static int getDockSideUnchecked(Rect bounds, Rect displayRect, int orientation) {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// Portrait mode, docked either at the top or the bottom.
if (bounds.top - mTmpRect.top <= mTmpRect.bottom - bounds.bottom) {
if (bounds.top - displayRect.top <= displayRect.bottom - bounds.bottom) {
return DOCKED_TOP;
} else {
return DOCKED_BOTTOM;
}
} else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
// Landscape mode, docked either on the left or on the right.
if (bounds.left - mTmpRect.left <= mTmpRect.right - bounds.right) {
if (bounds.left - displayRect.left <= displayRect.right - bounds.right) {
return DOCKED_LEFT;
} else {
return DOCKED_RIGHT;

View File

@@ -501,7 +501,7 @@ public class WindowManagerService extends IWindowManager.Stub
final float[] mTmpFloats = new float[9];
final Rect mTmpRect = new Rect();
final Rect mTmpRect2 = new Rect();
final Region mTmpRegion = new Region();
final Rect mTmpRect3 = new Rect();
boolean mDisplayReady;
boolean mSafeMode;
@@ -10889,8 +10889,7 @@ public class WindowManagerService extends IWindowManager.Stub
getStableInsetsLocked(mTmpRect2);
final DisplayInfo di = getDefaultDisplayInfoLocked();
mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
mTmpRect.inset(mTmpRect2);
inOutBounds.intersect(mTmpRect);
subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
}
}
@@ -10906,8 +10905,27 @@ public class WindowManagerService extends IWindowManager.Stub
getNonDecorInsetsLocked(mTmpRect2);
final DisplayInfo di = getDefaultDisplayInfoLocked();
mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
mTmpRect.inset(mTmpRect2);
inOutBounds.intersect(mTmpRect);
subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
}
}
void subtractInsets(Rect display, Rect insets, Rect inOutBounds) {
mTmpRect3.set(display);
mTmpRect3.inset(insets);
inOutBounds.intersect(mTmpRect3);
}
/**
* Calculates the smallest width for a task given the {@param bounds}. It does that by iterating
* across all screen orientations, and returns the minimum of the task width taking into account
* that the bounds might change because the snap algorithm snaps to a different value.
*
* @return the smallest width to be used in the Configuration, in dips
*/
public int getSmallestWidthForTaskBounds(Rect bounds) {
synchronized (mWindowMap) {
return getDefaultDisplayContentLocked().getDockedDividerController()
.getSmallestWidthDpForBounds(bounds);
}
}