Reducing number of configuration changes during PiP transition.
- Fixes issue with the incorrect calculation of configuration smallest width for floating and always-fullscreen stacks. Fullscreen stacks now have the smallest width matching the display, and floating stacks are set to the smallest size of their bounds. - This CL also ensures that we test the combined global/override configs for changes in case changes when moving between stacks results in a shift in the configuration between the parent to the override of the child (ie. when going from fullscreen -> pinned) - Also ensure that we are animating to the right fullscreen bounds for the PiP transition, accounting for the insets when calculating the config change the same way we would do for fullscreen tasks. Bug: 33779483 Test: android.server.cts.ActivityManagerConfigChangeTests passes Test: android.server.cts.ActivityManagerPinnedStackTests Test: #testSingleConfigurationChangeDuringTransition Change-Id: I2c2b695572cd17087d522cf6c8ebd105e57e08b8
This commit is contained in:
@@ -22,7 +22,6 @@ import static android.app.ActivityManager.StackId;
|
||||
import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
|
||||
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
|
||||
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
|
||||
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
|
||||
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
|
||||
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
|
||||
import static android.app.AppOpsManager.MODE_ALLOWED;
|
||||
@@ -47,7 +46,6 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
|
||||
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
|
||||
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
|
||||
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
|
||||
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
|
||||
import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
|
||||
import static android.os.Build.VERSION_CODES.HONEYCOMB;
|
||||
import static android.os.Build.VERSION_CODES.O;
|
||||
@@ -85,7 +83,6 @@ import android.content.res.CompatibilityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Debug;
|
||||
import android.os.IBinder;
|
||||
@@ -290,8 +287,8 @@ final class ActivityRecord implements AppWindowContainerListener {
|
||||
/**
|
||||
* Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)}
|
||||
*/
|
||||
private final Configuration mTmpGlobalConfig = new Configuration();
|
||||
private final Configuration mTmpTaskConfig = new Configuration();
|
||||
private final Configuration mTmpConfig1 = new Configuration();
|
||||
private final Configuration mTmpConfig2 = new Configuration();
|
||||
|
||||
private static String startingWindowStateToString(int state) {
|
||||
switch (state) {
|
||||
@@ -1975,13 +1972,13 @@ final class ActivityRecord implements AppWindowContainerListener {
|
||||
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
|
||||
"Ensuring correct configuration: " + this);
|
||||
|
||||
// Short circuit: if the two configurations are equal (the common case), then there is
|
||||
// nothing to do.
|
||||
final Configuration newGlobalConfig = service.getGlobalConfiguration();
|
||||
final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
|
||||
if (mLastReportedConfiguration.equals(newGlobalConfig)
|
||||
&& mLastReportedOverrideConfiguration.equals(newTaskMergedOverrideConfig)
|
||||
&& !forceNewConfig) {
|
||||
// Short circuit: if the two full configurations are equal (the common case), then there is
|
||||
// nothing to do. We test the full configuration instead of the global and merged override
|
||||
// configurations because there are cases (like moving a task to the pinned stack) where
|
||||
// the combine configurations are equal, but would otherwise differ in the override config
|
||||
mTmpConfig1.setTo(mLastReportedConfiguration);
|
||||
mTmpConfig1.updateFrom(mLastReportedOverrideConfiguration);
|
||||
if (task.getConfiguration().equals(mTmpConfig1) && !forceNewConfig) {
|
||||
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
|
||||
"Configuration unchanged in " + this);
|
||||
return true;
|
||||
@@ -1997,14 +1994,16 @@ final class ActivityRecord implements AppWindowContainerListener {
|
||||
|
||||
// Okay we now are going to make this activity have the new config.
|
||||
// But then we need to figure out how it needs to deal with that.
|
||||
mTmpGlobalConfig.setTo(mLastReportedConfiguration);
|
||||
mTmpTaskConfig.setTo(mLastReportedOverrideConfiguration);
|
||||
final Configuration newGlobalConfig = service.getGlobalConfiguration();
|
||||
final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
|
||||
mTmpConfig1.setTo(mLastReportedConfiguration);
|
||||
mTmpConfig2.setTo(mLastReportedOverrideConfiguration);
|
||||
mLastReportedConfiguration.setTo(newGlobalConfig);
|
||||
mLastReportedOverrideConfiguration.setTo(newTaskMergedOverrideConfig);
|
||||
|
||||
int taskChanges = getTaskConfigurationChanges(this, newTaskMergedOverrideConfig,
|
||||
mTmpTaskConfig);
|
||||
final int changes = mTmpGlobalConfig.diff(newGlobalConfig) | taskChanges;
|
||||
mTmpConfig2);
|
||||
final int changes = mTmpConfig1.diff(newGlobalConfig) | taskChanges;
|
||||
if (changes == 0 && !forceNewConfig) {
|
||||
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
|
||||
"Configuration no differences in " + this);
|
||||
|
||||
@@ -35,7 +35,6 @@ import android.content.pm.IPackageManager;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.GraphicBuffer;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Debug;
|
||||
@@ -52,6 +51,7 @@ import com.android.internal.app.IVoiceInteractor;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
|
||||
import com.android.server.wm.AppWindowContainerController;
|
||||
import com.android.server.wm.StackWindowController;
|
||||
import com.android.server.wm.TaskWindowContainerController;
|
||||
import com.android.server.wm.TaskWindowContainerListener;
|
||||
|
||||
@@ -278,7 +278,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
|
||||
private final Rect mTmpStableBounds = new Rect();
|
||||
private final Rect mTmpNonDecorBounds = new Rect();
|
||||
private final Rect mTmpRect = new Rect();
|
||||
private final Rect mTmpRect2 = new Rect();
|
||||
|
||||
// Last non-fullscreen bounds the task was launched in or resized to.
|
||||
// The information is persisted and used to determine the appropriate stack to launch the
|
||||
@@ -1838,66 +1837,38 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
|
||||
return !mTmpConfig.equals(newConfig);
|
||||
}
|
||||
|
||||
private void subtractNonDecorInsets(Rect inOutBounds, Rect inInsetBounds,
|
||||
boolean overrideWidth, boolean overrideHeight) {
|
||||
mTmpRect2.set(inInsetBounds);
|
||||
mService.mWindowManager.subtractNonDecorInsets(mTmpRect2);
|
||||
int leftInset = mTmpRect2.left - inInsetBounds.left;
|
||||
int topInset = mTmpRect2.top - inInsetBounds.top;
|
||||
int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
|
||||
int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
|
||||
inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
|
||||
}
|
||||
|
||||
private void subtractStableInsets(Rect inOutBounds, Rect inInsetBounds,
|
||||
boolean overrideWidth, boolean overrideHeight) {
|
||||
mTmpRect2.set(inInsetBounds);
|
||||
mService.mWindowManager.subtractStableInsets(mTmpRect2);
|
||||
int leftInset = mTmpRect2.left - inInsetBounds.left;
|
||||
int topInset = mTmpRect2.top - inInsetBounds.top;
|
||||
int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
|
||||
int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
|
||||
inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
|
||||
}
|
||||
|
||||
/** Clears passed config and fills it with new override values. */
|
||||
private void calculateOverrideConfig(Configuration config, Rect bounds, Rect insetBounds,
|
||||
boolean overrideWidth, boolean overrideHeight) {
|
||||
mTmpNonDecorBounds.set(bounds);
|
||||
mTmpStableBounds.set(bounds);
|
||||
|
||||
final Configuration parentConfig = getParent().getConfiguration();
|
||||
config.unset();
|
||||
final Configuration parentConfig = getParent().getConfiguration();
|
||||
final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
|
||||
final boolean isFloatingTask = mStack != null && StackId.tasksAreFloating(mStack.mStackId);
|
||||
if (isFloatingTask) {
|
||||
// Floating tasks should not be resized to the screen's bounds.
|
||||
config.screenWidthDp = (int) (mTmpStableBounds.width() / density);
|
||||
config.screenHeightDp = (int) (mTmpStableBounds.height() / density);
|
||||
} else {
|
||||
// For calculating screenWidthDp, screenWidthDp, we use the stable inset screen area,
|
||||
// i.e. the screen area without the system bars.
|
||||
// Additionally task dimensions should not be bigger than its parents dimensions.
|
||||
subtractNonDecorInsets(mTmpNonDecorBounds, insetBounds != null ? insetBounds : bounds,
|
||||
overrideWidth, overrideHeight);
|
||||
subtractStableInsets(mTmpStableBounds, insetBounds != null ? insetBounds : bounds,
|
||||
overrideWidth, overrideHeight);
|
||||
config.screenWidthDp = Math.min(
|
||||
(int) (mTmpStableBounds.width() / density), parentConfig.screenWidthDp);
|
||||
config.screenHeightDp = Math.min(
|
||||
(int) (mTmpStableBounds.height() / density), parentConfig.screenHeightDp);
|
||||
}
|
||||
|
||||
// TODO: Orientation?
|
||||
config.orientation = (config.screenWidthDp <= config.screenHeightDp)
|
||||
? Configuration.ORIENTATION_PORTRAIT
|
||||
: Configuration.ORIENTATION_LANDSCAPE;
|
||||
if (mStack != null) {
|
||||
final StackWindowController stackController = mStack.getWindowContainerController();
|
||||
stackController.adjustConfigurationForBounds(bounds, insetBounds,
|
||||
mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
|
||||
config, parentConfig);
|
||||
} else {
|
||||
// No stack, give some default values
|
||||
config.smallestScreenWidthDp =
|
||||
mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
|
||||
config.screenWidthDp = config.screenHeightDp = config.smallestScreenWidthDp;
|
||||
Slog.wtf(TAG, "Expected stack when caclulating override config");
|
||||
}
|
||||
|
||||
// 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 compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
|
||||
final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
|
||||
// We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
|
||||
// calculation with partial default.
|
||||
final int sl = Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_XLARGE;
|
||||
@@ -1905,8 +1876,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
|
||||
final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
|
||||
config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
|
||||
|
||||
config.smallestScreenWidthDp = mService.mWindowManager.getSmallestWidthForTaskBounds(
|
||||
insetBounds != null ? insetBounds : bounds);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -152,11 +152,6 @@ public class DockedStackDividerController implements DimLayerUser {
|
||||
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 mDisplayContent.getConfiguration().smallestScreenWidthDp;
|
||||
}
|
||||
final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth;
|
||||
final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight;
|
||||
int minWidth = Integer.MAX_VALUE;
|
||||
@@ -185,7 +180,7 @@ public class DockedStackDividerController implements DimLayerUser {
|
||||
mTmpRect2.width(), mTmpRect2.height(), getContentWidth());
|
||||
mService.mPolicy.getStableInsetsLw(rotation, mTmpRect2.width(), mTmpRect2.height(),
|
||||
mTmpRect3);
|
||||
mService.subtractInsets(mTmpRect2, mTmpRect3, mTmpRect);
|
||||
mService.intersectDisplayInsetBounds(mTmpRect2, mTmpRect3, mTmpRect);
|
||||
minWidth = Math.min(mTmpRect.width(), minWidth);
|
||||
}
|
||||
return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
|
||||
|
||||
import android.app.ActivityManager.StackId;
|
||||
import android.app.RemoteAction;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
@@ -24,6 +27,8 @@ import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.view.DisplayInfo;
|
||||
|
||||
import com.android.server.UiThread;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
@@ -48,6 +53,12 @@ public class StackWindowController
|
||||
|
||||
private final H mHandler;
|
||||
|
||||
// Temp bounds only used in adjustConfigurationForBounds()
|
||||
private final Rect mTmpRect = new Rect();
|
||||
private final Rect mTmpStableInsets = new Rect();
|
||||
private final Rect mTmpNonDecorInsets = new Rect();
|
||||
private final Rect mTmpDisplayBounds = new Rect();
|
||||
|
||||
public StackWindowController(int stackId, StackWindowListener listener,
|
||||
int displayId, boolean onTop, Rect outBounds) {
|
||||
this(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
|
||||
@@ -289,6 +300,107 @@ public class StackWindowController
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the screen size in dp's for the {@param config} for the given params.
|
||||
*/
|
||||
public void adjustConfigurationForBounds(Rect bounds, Rect insetBounds,
|
||||
Rect nonDecorBounds, Rect stableBounds, boolean overrideWidth,
|
||||
boolean overrideHeight, float density, Configuration config,
|
||||
Configuration parentConfig) {
|
||||
synchronized (mWindowMap) {
|
||||
final TaskStack stack = mContainer;
|
||||
final DisplayContent displayContent = stack.getDisplayContent();
|
||||
final DisplayInfo di = displayContent.getDisplayInfo();
|
||||
|
||||
// Get the insets and display bounds
|
||||
mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
|
||||
mTmpStableInsets);
|
||||
mService.mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
|
||||
mTmpNonDecorInsets);
|
||||
mTmpDisplayBounds.set(0, 0, di.logicalWidth, di.logicalHeight);
|
||||
|
||||
int width;
|
||||
int height;
|
||||
if (StackId.tasksAreFloating(mStackId)) {
|
||||
// Floating tasks should not be resized to the screen's bounds.
|
||||
|
||||
if (bounds.width() == mTmpDisplayBounds.width() &&
|
||||
bounds.height() == mTmpDisplayBounds.height()) {
|
||||
// If the bounds we are animating is the same as the fullscreen stack
|
||||
// dimensions, then apply the same inset calculations that we normally do for
|
||||
// the fullscreen stack, without intersecting it with the display bounds
|
||||
stableBounds.inset(mTmpStableInsets);
|
||||
nonDecorBounds.inset(mTmpNonDecorInsets);
|
||||
}
|
||||
width = (int) (stableBounds.width() / density);
|
||||
height = (int) (stableBounds.height() / density);
|
||||
} else {
|
||||
// For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
|
||||
// area, i.e. the screen area without the system bars.
|
||||
// Additionally task dimensions should not be bigger than its parents dimensions.
|
||||
// The non decor inset are areas that could never be removed in Honeycomb. See
|
||||
// {@link WindowManagerPolicy#getNonDecorInsetsLw}.
|
||||
intersectDisplayBoundsExcludeInsets(nonDecorBounds,
|
||||
insetBounds != null ? insetBounds : bounds, mTmpNonDecorInsets,
|
||||
mTmpDisplayBounds, overrideWidth, overrideHeight);
|
||||
intersectDisplayBoundsExcludeInsets(stableBounds,
|
||||
insetBounds != null ? insetBounds : bounds, mTmpStableInsets,
|
||||
mTmpDisplayBounds, overrideWidth, overrideHeight);
|
||||
width = Math.min((int) (stableBounds.width() / density),
|
||||
parentConfig.screenWidthDp);
|
||||
height = Math.min((int) (stableBounds.height() / density),
|
||||
parentConfig.screenHeightDp);
|
||||
}
|
||||
|
||||
config.screenWidthDp = width;
|
||||
config.screenHeightDp = height;
|
||||
config.smallestScreenWidthDp = getSmallestWidthForTaskBounds(
|
||||
insetBounds != null ? insetBounds : bounds, density);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
|
||||
* inset areas.
|
||||
*
|
||||
* @param inOutBounds The inOutBounds to subtract the stable inset areas from.
|
||||
*/
|
||||
private void intersectDisplayBoundsExcludeInsets(Rect inOutBounds, Rect inInsetBounds,
|
||||
Rect stableInsets, Rect displayBounds, boolean overrideWidth, boolean overrideHeight) {
|
||||
mTmpRect.set(inInsetBounds);
|
||||
mService.intersectDisplayInsetBounds(displayBounds, stableInsets, mTmpRect);
|
||||
int leftInset = mTmpRect.left - inInsetBounds.left;
|
||||
int topInset = mTmpRect.top - inInsetBounds.top;
|
||||
int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect.right;
|
||||
int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect.bottom;
|
||||
inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the smallest width for a task given the {@param bounds}.
|
||||
*
|
||||
* @return the smallest width to be used in the Configuration, in dips
|
||||
*/
|
||||
private int getSmallestWidthForTaskBounds(Rect bounds, float density) {
|
||||
final DisplayContent displayContent = mContainer.getDisplayContent();
|
||||
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
|
||||
|
||||
if (bounds == null || (bounds.width() == displayInfo.logicalWidth &&
|
||||
bounds.height() == displayInfo.logicalHeight)) {
|
||||
// If the bounds are fullscreen, return the value of the fullscreen configuration
|
||||
return displayContent.getConfiguration().smallestScreenWidthDp;
|
||||
} else if (StackId.tasksAreFloating(mStackId)) {
|
||||
// For floating tasks, calculate the smallest width from the bounds of the task
|
||||
return (int) (Math.min(bounds.width(), bounds.height()) / density);
|
||||
} else {
|
||||
// Iterating across all screen orientations, and return the minimum of the task
|
||||
// width taking into account that the bounds might change because the snap algorithm
|
||||
// snaps to a different value
|
||||
return displayContent.getDockedDividerController()
|
||||
.getSmallestWidthDpForBounds(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void requestResize(Rect bounds) {
|
||||
mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
|
||||
}
|
||||
|
||||
@@ -1476,7 +1476,10 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
|
||||
|
||||
@Override
|
||||
public void getFullScreenBounds(Rect bounds) {
|
||||
getDisplayContent().getContentRect(bounds);
|
||||
// This is currently only used for the pinned stack animation when leaving PiP
|
||||
// (see {@link BoundsAnimationController}), and in that case we need to animate this back
|
||||
// to the full bounds to match the fullscreen stack
|
||||
getDisplayContent().getLogicalDisplayRect(bounds);
|
||||
}
|
||||
|
||||
public boolean hasMovementAnimations() {
|
||||
|
||||
@@ -7543,63 +7543,12 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
private void getNonDecorInsetsLocked(Rect outInsets) {
|
||||
final DisplayInfo di = getDefaultDisplayInfoLocked();
|
||||
mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
|
||||
* inset areas.
|
||||
*
|
||||
* @param inOutBounds The inOutBounds to subtract the stable inset areas from.
|
||||
*/
|
||||
public void subtractStableInsets(Rect inOutBounds) {
|
||||
synchronized (mWindowMap) {
|
||||
getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect2);
|
||||
final DisplayInfo di = getDefaultDisplayInfoLocked();
|
||||
mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
|
||||
subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersects the specified {@code inOutBounds} with the display frame that excludes
|
||||
* areas that could never be removed in Honeycomb. See
|
||||
* {@link WindowManagerPolicy#getNonDecorInsetsLw}.
|
||||
*
|
||||
* @param inOutBounds The inOutBounds to subtract the inset areas from.
|
||||
*/
|
||||
public void subtractNonDecorInsets(Rect inOutBounds) {
|
||||
synchronized (mWindowMap) {
|
||||
getNonDecorInsetsLocked(mTmpRect2);
|
||||
final DisplayInfo di = getDefaultDisplayInfoLocked();
|
||||
mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
|
||||
subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
|
||||
}
|
||||
}
|
||||
|
||||
void subtractInsets(Rect display, Rect insets, Rect inOutBounds) {
|
||||
void intersectDisplayInsetBounds(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) {
|
||||
// TODO(multi-display): Use correct display content here
|
||||
return getDefaultDisplayContentLocked().getDockedDividerController()
|
||||
.getSmallestWidthDpForBounds(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
MousePositionTracker mMousePositionTracker = new MousePositionTracker();
|
||||
|
||||
private static class MousePositionTracker implements PointerEventListener {
|
||||
|
||||
Reference in New Issue
Block a user