Merge "Layout status/nav bar and decor window as normal window" into sc-v2-dev
This commit is contained in:
@@ -284,6 +284,21 @@ public final class ViewRootImpl implements ViewParent,
|
||||
*/
|
||||
private static final int SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS = 2500;
|
||||
|
||||
/**
|
||||
* If set to {@code true}, the new logic to layout system bars as normal window and to use
|
||||
* layout result to get insets will be applied. Otherwise, the old hard-coded window logic will
|
||||
* be applied.
|
||||
*/
|
||||
private static final String USE_FLEXIBLE_INSETS = "persist.debug.flexible_insets";
|
||||
|
||||
/**
|
||||
* A flag to indicate to use the new generalized insets window logic, or the old hard-coded
|
||||
* insets window layout logic.
|
||||
* {@hide}
|
||||
*/
|
||||
public static final boolean INSETS_LAYOUT_GENERALIZATION =
|
||||
SystemProperties.getBoolean(USE_FLEXIBLE_INSETS, false);
|
||||
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||
static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@ import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
@@ -3467,6 +3468,22 @@ public interface WindowManager extends ViewManager {
|
||||
*/
|
||||
public @InsetsState.InternalInsetsType int[] providesInsetsTypes;
|
||||
|
||||
/**
|
||||
* If specified, the insets provided by this window will be our window frame minus the
|
||||
* insets specified by providedInternalInsets.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public Insets providedInternalInsets = Insets.NONE;
|
||||
|
||||
/**
|
||||
* {@link LayoutParams} to be applied to the window when layout with a assigned rotation.
|
||||
* This will make layout during rotation change smoothly.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public LayoutParams[] paramsForRotation;
|
||||
|
||||
/**
|
||||
* Specifies types of insets that this window should avoid overlapping during layout.
|
||||
*
|
||||
@@ -3566,6 +3583,18 @@ public interface WindowManager extends ViewManager {
|
||||
return mFitInsetsIgnoringVisibility;
|
||||
}
|
||||
|
||||
private void checkNonRecursiveParams() {
|
||||
if (paramsForRotation == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = paramsForRotation.length - 1; i >= 0; i--) {
|
||||
if (paramsForRotation[i].paramsForRotation != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Params cannot contain params recursively.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LayoutParams() {
|
||||
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
type = TYPE_APPLICATION;
|
||||
@@ -3818,6 +3847,14 @@ public interface WindowManager extends ViewManager {
|
||||
} else {
|
||||
out.writeInt(0);
|
||||
}
|
||||
providedInternalInsets.writeToParcel(out, 0 /* parcelableFlags */);
|
||||
if (paramsForRotation != null) {
|
||||
checkNonRecursiveParams();
|
||||
out.writeInt(paramsForRotation.length);
|
||||
out.writeTypedArray(paramsForRotation, 0 /* parcelableFlags */);
|
||||
} else {
|
||||
out.writeInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<LayoutParams> CREATOR
|
||||
@@ -3887,6 +3924,12 @@ public interface WindowManager extends ViewManager {
|
||||
providesInsetsTypes = new int[insetsTypesLength];
|
||||
in.readIntArray(providesInsetsTypes);
|
||||
}
|
||||
providedInternalInsets = Insets.CREATOR.createFromParcel(in);
|
||||
int paramsForRotationLength = in.readInt();
|
||||
if (paramsForRotationLength > 0) {
|
||||
paramsForRotation = new LayoutParams[paramsForRotationLength];
|
||||
in.readTypedArray(paramsForRotation, LayoutParams.CREATOR);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"PointlessBitwiseExpression"})
|
||||
@@ -4169,6 +4212,17 @@ public interface WindowManager extends ViewManager {
|
||||
changes |= LAYOUT_CHANGED;
|
||||
}
|
||||
|
||||
if (!providedInternalInsets.equals(o.providedInternalInsets)) {
|
||||
providedInternalInsets = o.providedInternalInsets;
|
||||
changes |= LAYOUT_CHANGED;
|
||||
}
|
||||
|
||||
if (!Arrays.equals(paramsForRotation, o.paramsForRotation)) {
|
||||
paramsForRotation = o.paramsForRotation;
|
||||
checkNonRecursiveParams();
|
||||
changes |= LAYOUT_CHANGED;
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
@@ -4356,6 +4410,18 @@ public interface WindowManager extends ViewManager {
|
||||
sb.append(InsetsState.typeToString(providesInsetsTypes[i]));
|
||||
}
|
||||
}
|
||||
if (!providedInternalInsets.equals(Insets.NONE)) {
|
||||
sb.append(" providedInternalInsets=");
|
||||
sb.append(providedInternalInsets);
|
||||
}
|
||||
if (paramsForRotation != null && paramsForRotation.length != 0) {
|
||||
sb.append(System.lineSeparator());
|
||||
sb.append(prefix).append(" paramsForRotation=");
|
||||
for (int i = 0; i < paramsForRotation.length; ++i) {
|
||||
if (i > 0) sb.append(' ');
|
||||
sb.append(paramsForRotation[i].toString());
|
||||
}
|
||||
}
|
||||
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
|
||||
@@ -23,10 +23,12 @@ import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
|
||||
import static android.app.StatusBarManager.WindowType;
|
||||
import static android.app.StatusBarManager.WindowVisibleState;
|
||||
import static android.app.StatusBarManager.windowStateToString;
|
||||
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||
import static android.view.InsetsState.containsType;
|
||||
import static android.view.ViewRootImpl.INSETS_LAYOUT_GENERALIZATION;
|
||||
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
|
||||
import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS;
|
||||
import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS;
|
||||
@@ -67,6 +69,7 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.ContentObserver;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
@@ -199,6 +202,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
|
||||
|
||||
private Bundle mSavedState;
|
||||
private NavigationBarView mNavigationBarView;
|
||||
private NavigationBarFrame mFrame;
|
||||
|
||||
private @WindowVisibleState int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
|
||||
|
||||
@@ -489,34 +493,17 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
|
||||
}
|
||||
|
||||
public View createView(Bundle savedState) {
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT,
|
||||
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
|
||||
WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
|
||||
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|
||||
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
|
||||
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
|
||||
| WindowManager.LayoutParams.FLAG_SLIPPERY,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
lp.token = new Binder();
|
||||
lp.accessibilityTitle = mContext.getString(R.string.nav_bar);
|
||||
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
|
||||
lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
lp.windowAnimations = 0;
|
||||
lp.setTitle("NavigationBar" + mContext.getDisplayId());
|
||||
lp.setFitInsetsTypes(0 /* types */);
|
||||
lp.setTrustedOverlay();
|
||||
|
||||
NavigationBarFrame frame = (NavigationBarFrame) LayoutInflater.from(mContext).inflate(
|
||||
mFrame = (NavigationBarFrame) LayoutInflater.from(mContext).inflate(
|
||||
R.layout.navigation_bar_window, null);
|
||||
View barView = LayoutInflater.from(frame.getContext()).inflate(
|
||||
R.layout.navigation_bar, frame);
|
||||
View barView = LayoutInflater.from(mFrame.getContext()).inflate(
|
||||
R.layout.navigation_bar, mFrame);
|
||||
barView.addOnAttachStateChangeListener(this);
|
||||
mNavigationBarView = barView.findViewById(R.id.navigation_bar_view);
|
||||
|
||||
if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + barView);
|
||||
mContext.getSystemService(WindowManager.class).addView(frame, lp);
|
||||
mContext.getSystemService(WindowManager.class).addView(mFrame,
|
||||
getBarLayoutParams(mContext.getResources().getConfiguration().windowConfiguration
|
||||
.getRotation()));
|
||||
mDisplayId = mContext.getDisplayId();
|
||||
mIsOnDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
|
||||
|
||||
@@ -670,6 +657,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
|
||||
mHandler.removeCallbacks(mAutoDim);
|
||||
mHandler.removeCallbacks(mOnVariableDurationHomeLongClick);
|
||||
mHandler.removeCallbacks(mEnableLayoutTransitions);
|
||||
mFrame = null;
|
||||
mNavigationBarView = null;
|
||||
mOrientationHandle = null;
|
||||
}
|
||||
@@ -688,6 +676,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
|
||||
* Called when a non-reloading configuration change happens and we need to update.
|
||||
*/
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
final int rotation = newConfig.windowConfiguration.getRotation();
|
||||
final Locale locale = mContext.getResources().getConfiguration().locale;
|
||||
final int ld = TextUtils.getLayoutDirectionFromLocale(locale);
|
||||
if (!locale.equals(mLocale) || ld != mLayoutDirection) {
|
||||
@@ -701,9 +690,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
|
||||
refreshLayout(ld);
|
||||
}
|
||||
|
||||
repositionNavigationBar();
|
||||
repositionNavigationBar(rotation);
|
||||
if (canShowSecondaryHandle()) {
|
||||
int rotation = newConfig.windowConfiguration.getRotation();
|
||||
if (rotation != mCurrentRotation) {
|
||||
mCurrentRotation = rotation;
|
||||
orientSecondaryHomeHandle();
|
||||
@@ -1068,13 +1056,12 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
|
||||
|| (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0;
|
||||
}
|
||||
|
||||
private void repositionNavigationBar() {
|
||||
if (!mNavigationBarView.isAttachedToWindow()) return;
|
||||
private void repositionNavigationBar(int rotation) {
|
||||
if (mNavigationBarView == null || !mNavigationBarView.isAttachedToWindow()) return;
|
||||
|
||||
prepareNavigationBarView();
|
||||
|
||||
mWindowManager.updateViewLayout((View) mNavigationBarView.getParent(),
|
||||
((View) mNavigationBarView.getParent()).getLayoutParams());
|
||||
mWindowManager.updateViewLayout(mFrame, getBarLayoutParams(rotation));
|
||||
}
|
||||
|
||||
private void updateScreenPinningGestures() {
|
||||
@@ -1509,13 +1496,94 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
|
||||
private final NavigationBarA11yHelper.NavA11yEventListener mAccessibilityListener =
|
||||
this::updateAccessibilityServicesState;
|
||||
|
||||
private WindowManager.LayoutParams getBarLayoutParams(int rotation) {
|
||||
WindowManager.LayoutParams lp = getBarLayoutParamsForRotation(rotation);
|
||||
lp.paramsForRotation = new WindowManager.LayoutParams[4];
|
||||
for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
|
||||
lp.paramsForRotation[rot] = getBarLayoutParamsForRotation(rot);
|
||||
}
|
||||
return lp;
|
||||
}
|
||||
|
||||
private WindowManager.LayoutParams getBarLayoutParamsForRotation(int rotation) {
|
||||
int width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
int height = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
int insetsHeight = -1;
|
||||
int gravity = Gravity.BOTTOM;
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
boolean navBarCanMove = true;
|
||||
if (mWindowManager != null && mWindowManager.getCurrentWindowMetrics() != null) {
|
||||
Rect displaySize = mWindowManager.getCurrentWindowMetrics().getBounds();
|
||||
navBarCanMove = displaySize.width() != displaySize.height()
|
||||
&& mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_navBarCanMove);
|
||||
}
|
||||
if (!navBarCanMove) {
|
||||
height = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.navigation_bar_frame_height);
|
||||
insetsHeight = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.navigation_bar_height);
|
||||
} else {
|
||||
switch (rotation) {
|
||||
case ROTATION_UNDEFINED:
|
||||
case Surface.ROTATION_0:
|
||||
case Surface.ROTATION_180:
|
||||
height = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.navigation_bar_frame_height);
|
||||
insetsHeight = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.navigation_bar_height);
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
gravity = Gravity.RIGHT;
|
||||
width = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.navigation_bar_width);
|
||||
break;
|
||||
case Surface.ROTATION_270:
|
||||
gravity = Gravity.LEFT;
|
||||
width = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.navigation_bar_width);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||
width,
|
||||
height,
|
||||
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
|
||||
WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
|
||||
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|
||||
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
|
||||
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
|
||||
| WindowManager.LayoutParams.FLAG_SLIPPERY,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
lp.gravity = gravity;
|
||||
if (insetsHeight != -1) {
|
||||
lp.providedInternalInsets = Insets.of(0, height - insetsHeight, 0, 0);
|
||||
} else {
|
||||
lp.providedInternalInsets = Insets.NONE;
|
||||
}
|
||||
}
|
||||
lp.token = new Binder();
|
||||
lp.accessibilityTitle = mContext.getString(R.string.nav_bar);
|
||||
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
|
||||
lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
lp.windowAnimations = 0;
|
||||
lp.setTitle("NavigationBar" + mContext.getDisplayId());
|
||||
lp.setFitInsetsTypes(0 /* types */);
|
||||
lp.setTrustedOverlay();
|
||||
return lp;
|
||||
}
|
||||
|
||||
private boolean canShowSecondaryHandle() {
|
||||
return mNavBarMode == NAV_BAR_MODE_GESTURAL && mOrientationHandle != null;
|
||||
}
|
||||
|
||||
private final Consumer<Integer> mRotationWatcher = rotation -> {
|
||||
if (mNavigationBarView.needsReorient(rotation)) {
|
||||
repositionNavigationBar();
|
||||
if (mNavigationBarView != null
|
||||
&& mNavigationBarView.needsReorient(rotation)) {
|
||||
repositionNavigationBar(rotation);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
|
||||
import static android.view.ViewRootImpl.INSETS_LAYOUT_GENERALIZATION;
|
||||
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
|
||||
@@ -34,6 +36,7 @@ import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.Surface;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
|
||||
@@ -118,21 +121,7 @@ public class StatusBarWindowController {
|
||||
// Now that the status bar window encompasses the sliding panel and its
|
||||
// translucent backdrop, the entire thing is made TRANSLUCENT and is
|
||||
// hardware-accelerated.
|
||||
mLp = new WindowManager.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
mBarHeight,
|
||||
WindowManager.LayoutParams.TYPE_STATUS_BAR,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
|
||||
| WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
mLp.privateFlags |= PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
|
||||
mLp.token = new Binder();
|
||||
mLp.gravity = Gravity.TOP;
|
||||
mLp.setFitInsetsTypes(0 /* types */);
|
||||
mLp.setTitle("StatusBar");
|
||||
mLp.packageName = mContext.getPackageName();
|
||||
mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
mLp = getBarLayoutParams(mContext.getDisplay().getRotation());
|
||||
|
||||
mWindowManager.addView(mStatusBarView, mLp);
|
||||
mLpChanged.copyFrom(mLp);
|
||||
@@ -141,6 +130,63 @@ public class StatusBarWindowController {
|
||||
calculateStatusBarLocationsForAllRotations();
|
||||
}
|
||||
|
||||
private WindowManager.LayoutParams getBarLayoutParams(int rotation) {
|
||||
WindowManager.LayoutParams lp = getBarLayoutParamsForRotation(rotation);
|
||||
lp.paramsForRotation = new WindowManager.LayoutParams[4];
|
||||
for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
|
||||
lp.paramsForRotation[rot] = getBarLayoutParamsForRotation(rot);
|
||||
}
|
||||
return lp;
|
||||
}
|
||||
|
||||
private WindowManager.LayoutParams getBarLayoutParamsForRotation(int rotation) {
|
||||
int height = mBarHeight;
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
Rect displayBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
|
||||
int defaultAndUpsideDownHeight;
|
||||
int theOtherHeight;
|
||||
if (displayBounds.width() > displayBounds.height()) {
|
||||
defaultAndUpsideDownHeight = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.status_bar_height_landscape);
|
||||
theOtherHeight = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.status_bar_height_portrait);
|
||||
} else {
|
||||
defaultAndUpsideDownHeight = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.status_bar_height_portrait);
|
||||
theOtherHeight = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.status_bar_height_landscape);
|
||||
}
|
||||
switch (rotation) {
|
||||
case ROTATION_UNDEFINED:
|
||||
case Surface.ROTATION_0:
|
||||
case Surface.ROTATION_180:
|
||||
height = defaultAndUpsideDownHeight;
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
case Surface.ROTATION_270:
|
||||
height = theOtherHeight;
|
||||
break;
|
||||
}
|
||||
}
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.MATCH_PARENT,
|
||||
height,
|
||||
WindowManager.LayoutParams.TYPE_STATUS_BAR,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
|
||||
| WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
lp.privateFlags |= PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
|
||||
lp.token = new Binder();
|
||||
lp.gravity = Gravity.TOP;
|
||||
lp.setFitInsetsTypes(0 /* types */);
|
||||
lp.setTitle("StatusBar");
|
||||
lp.packageName = mContext.getPackageName();
|
||||
lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
return lp;
|
||||
|
||||
}
|
||||
|
||||
private void calculateStatusBarLocationsForAllRotations() {
|
||||
Rect[] bounds = new Rect[4];
|
||||
bounds[0] = mContentInsetsProvider
|
||||
|
||||
@@ -39,6 +39,7 @@ import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
|
||||
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
||||
import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
|
||||
import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
|
||||
import static android.view.ViewRootImpl.INSETS_LAYOUT_GENERALIZATION;
|
||||
import static android.view.ViewRootImpl.computeWindowBounds;
|
||||
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
|
||||
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
|
||||
@@ -333,6 +334,7 @@ public class DisplayPolicy {
|
||||
private static final Rect sTmpRect = new Rect();
|
||||
private static final Rect sTmpNavFrame = new Rect();
|
||||
private static final Rect sTmpStatusFrame = new Rect();
|
||||
private static final Rect sTmpDecorFrame = new Rect();
|
||||
private static final Rect sTmpScreenDecorFrame = new Rect();
|
||||
private static final Rect sTmpLastParentFrame = new Rect();
|
||||
private static final Rect sTmpDisplayFrameBounds = new Rect();
|
||||
@@ -430,8 +432,10 @@ public class DisplayPolicy {
|
||||
|
||||
final int displayId = displayContent.getDisplayId();
|
||||
|
||||
mBarContentFrames.put(TYPE_STATUS_BAR, new Rect());
|
||||
mBarContentFrames.put(TYPE_NAVIGATION_BAR, new Rect());
|
||||
if (!INSETS_LAYOUT_GENERALIZATION) {
|
||||
mBarContentFrames.put(TYPE_STATUS_BAR, new Rect());
|
||||
mBarContentFrames.put(TYPE_NAVIGATION_BAR, new Rect());
|
||||
}
|
||||
|
||||
final Resources r = mContext.getResources();
|
||||
mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer);
|
||||
@@ -1081,7 +1085,9 @@ public class DisplayPolicy {
|
||||
mStatusBar = win;
|
||||
final TriConsumer<DisplayFrames, WindowState, Rect> frameProvider =
|
||||
(displayFrames, windowState, rect) -> {
|
||||
rect.bottom = rect.top + getStatusBarHeight(displayFrames);
|
||||
if (!INSETS_LAYOUT_GENERALIZATION) {
|
||||
rect.bottom = rect.top + getStatusBarHeight(displayFrames);
|
||||
}
|
||||
};
|
||||
mDisplayContent.setInsetProvider(ITYPE_STATUS_BAR, win, frameProvider);
|
||||
mDisplayContent.setInsetProvider(ITYPE_TOP_MANDATORY_GESTURES, win, frameProvider);
|
||||
@@ -1091,18 +1097,22 @@ public class DisplayPolicy {
|
||||
mNavigationBar = win;
|
||||
mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win,
|
||||
(displayFrames, windowState, inOutFrame) -> {
|
||||
|
||||
// In Gesture Nav, navigation bar frame is larger than frame to
|
||||
// calculate inset.
|
||||
if (navigationBarPosition(displayFrames.mDisplayWidth,
|
||||
displayFrames.mDisplayHeight,
|
||||
displayFrames.mRotation) == NAV_BAR_BOTTOM
|
||||
&& !mNavButtonForcedVisible) {
|
||||
sTmpRect.set(inOutFrame);
|
||||
sTmpRect.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
|
||||
inOutFrame.top = sTmpRect.bottom
|
||||
- getNavigationBarHeight(displayFrames.mRotation,
|
||||
mDisplayContent.getConfiguration().uiMode);
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
inOutFrame.inset(windowState.getLayoutingAttrs(
|
||||
displayFrames.mRotation).providedInternalInsets);
|
||||
} else {
|
||||
// In Gesture Nav, navigation bar frame is larger than frame to
|
||||
// calculate inset.
|
||||
if (navigationBarPosition(displayFrames.mDisplayWidth,
|
||||
displayFrames.mDisplayHeight,
|
||||
displayFrames.mRotation) == NAV_BAR_BOTTOM
|
||||
&& !mNavButtonForcedVisible) {
|
||||
sTmpRect.set(inOutFrame);
|
||||
sTmpRect.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
|
||||
inOutFrame.top = sTmpRect.bottom
|
||||
- getNavigationBarHeight(displayFrames.mRotation,
|
||||
mDisplayContent.getConfiguration().uiMode);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1163,7 +1173,14 @@ public class DisplayPolicy {
|
||||
mExtraNavBarAltPosition = getAltBarPosition(attrs);
|
||||
break;
|
||||
}
|
||||
mDisplayContent.setInsetProvider(insetsType, win, null);
|
||||
if (!INSETS_LAYOUT_GENERALIZATION) {
|
||||
mDisplayContent.setInsetProvider(insetsType, win, null);
|
||||
} else {
|
||||
mDisplayContent.setInsetProvider(insetsType, win, (displayFrames,
|
||||
windowState, inOutFrame) -> inOutFrame.inset(
|
||||
windowState.getLayoutingAttrs(displayFrames.mRotation)
|
||||
.providedInternalInsets));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1254,8 +1271,17 @@ public class DisplayPolicy {
|
||||
}
|
||||
|
||||
private int getStatusBarHeight(DisplayFrames displayFrames) {
|
||||
return Math.max(mStatusBarHeightForRotation[displayFrames.mRotation],
|
||||
displayFrames.mDisplayCutoutSafe.top);
|
||||
int statusBarHeight;
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
if (mStatusBar != null) {
|
||||
statusBarHeight = mStatusBar.getLayoutingAttrs(displayFrames.mRotation).height;
|
||||
} else {
|
||||
statusBarHeight = 0;
|
||||
}
|
||||
} else {
|
||||
statusBarHeight = mStatusBarHeightForRotation[displayFrames.mRotation];
|
||||
}
|
||||
return Math.max(statusBarHeight, displayFrames.mDisplayCutoutSafe.top);
|
||||
}
|
||||
|
||||
WindowState getStatusBar() {
|
||||
@@ -1425,13 +1451,30 @@ public class DisplayPolicy {
|
||||
WindowFrames simulatedWindowFrames, SparseArray<Rect> contentFrames,
|
||||
Consumer<Rect> layout) {
|
||||
win.setSimulatedWindowFrames(simulatedWindowFrames);
|
||||
final int requestedHeight = win.mRequestedHeight;
|
||||
final int requestedWidth = win.mRequestedWidth;
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
// Without a full layout process, in order to layout the system bars correctly, we need
|
||||
// to set the requested size and the initial display frames to the window.
|
||||
WindowManager.LayoutParams params = win.getLayoutingAttrs(displayFrames.mRotation);
|
||||
win.setRequestedSize(params.width, params.height);
|
||||
sTmpDecorFrame.set(0, 0, displayFrames.mDisplayWidth, displayFrames.mDisplayHeight);
|
||||
simulatedWindowFrames.setFrames(sTmpDecorFrame /* parentFrame */,
|
||||
sTmpDecorFrame /* displayFrame */);
|
||||
simulatedWindowFrames.mIsSimulatingDecorWindow = true;
|
||||
}
|
||||
final Rect contentFrame = new Rect();
|
||||
try {
|
||||
layout.accept(contentFrame);
|
||||
} finally {
|
||||
win.setSimulatedWindowFrames(null);
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
win.setRequestedSize(requestedWidth, requestedHeight);
|
||||
}
|
||||
}
|
||||
if (!INSETS_LAYOUT_GENERALIZATION) {
|
||||
contentFrames.put(win.mAttrs.type, contentFrame);
|
||||
}
|
||||
contentFrames.put(win.mAttrs.type, contentFrame);
|
||||
mDisplayContent.getInsetsStateController().computeSimulatedState(
|
||||
win, displayFrames, simulatedWindowFrames);
|
||||
}
|
||||
@@ -1442,15 +1485,31 @@ public class DisplayPolicy {
|
||||
* some temporal states, but doesn't change the window frames used to show on screen.
|
||||
*/
|
||||
void simulateLayoutDisplay(DisplayFrames displayFrames, SparseArray<Rect> barContentFrames) {
|
||||
final WindowFrames simulatedWindowFrames = new WindowFrames();
|
||||
if (mNavigationBar != null) {
|
||||
simulateLayoutDecorWindow(mNavigationBar, displayFrames, simulatedWindowFrames,
|
||||
barContentFrames, contentFrame -> layoutNavigationBar(displayFrames,
|
||||
contentFrame));
|
||||
final WindowFrames simulatedWindowFrames = new WindowFrames();
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
simulateLayoutDecorWindow(mNavigationBar, displayFrames, simulatedWindowFrames,
|
||||
barContentFrames,
|
||||
contentFrame -> simulateLayoutForContentFrame(displayFrames,
|
||||
mNavigationBar, contentFrame));
|
||||
} else {
|
||||
simulateLayoutDecorWindow(mNavigationBar, displayFrames, simulatedWindowFrames,
|
||||
barContentFrames, contentFrame -> layoutNavigationBar(displayFrames,
|
||||
contentFrame));
|
||||
}
|
||||
}
|
||||
if (mStatusBar != null) {
|
||||
simulateLayoutDecorWindow(mStatusBar, displayFrames, simulatedWindowFrames,
|
||||
barContentFrames, contentFrame -> layoutStatusBar(displayFrames, contentFrame));
|
||||
final WindowFrames simulatedWindowFrames = new WindowFrames();
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
simulateLayoutDecorWindow(mStatusBar, displayFrames, simulatedWindowFrames,
|
||||
barContentFrames,
|
||||
contentFrame -> simulateLayoutForContentFrame(displayFrames,
|
||||
mStatusBar, contentFrame));
|
||||
} else {
|
||||
simulateLayoutDecorWindow(mStatusBar, displayFrames, simulatedWindowFrames,
|
||||
barContentFrames,
|
||||
contentFrame -> layoutStatusBar(displayFrames, contentFrame));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1469,7 +1528,7 @@ public class DisplayPolicy {
|
||||
windowFrames.setFrames(sTmpStatusFrame /* parentFrame */,
|
||||
sTmpStatusFrame /* displayFrame */);
|
||||
// Let the status bar determine its size.
|
||||
mStatusBar.computeFrameAndUpdateSourceFrame();
|
||||
mStatusBar.computeFrameAndUpdateSourceFrame(displayFrames);
|
||||
|
||||
// For layout, the status bar is always at the top with our fixed height.
|
||||
int statusBarBottom = displayFrames.mUnrestricted.top
|
||||
@@ -1520,18 +1579,18 @@ public class DisplayPolicy {
|
||||
} else if (navBarPosition == NAV_BAR_RIGHT) {
|
||||
// Landscape screen; nav bar goes to the right.
|
||||
navigationFrame.left = Math.min(cutoutSafeUnrestricted.right, navigationFrame.right)
|
||||
- getNavigationBarWidth(rotation, uiMode);
|
||||
- getNavigationBarWidth(rotation, uiMode, navBarPosition);
|
||||
} else if (navBarPosition == NAV_BAR_LEFT) {
|
||||
// Seascape screen; nav bar goes to the left.
|
||||
navigationFrame.right = Math.max(cutoutSafeUnrestricted.left, navigationFrame.left)
|
||||
+ getNavigationBarWidth(rotation, uiMode);
|
||||
+ getNavigationBarWidth(rotation, uiMode, navBarPosition);
|
||||
}
|
||||
|
||||
// Compute the final frame.
|
||||
final WindowFrames windowFrames = mNavigationBar.getLayoutingWindowFrames();
|
||||
windowFrames.setFrames(navigationFrame /* parentFrame */,
|
||||
navigationFrame /* displayFrame */);
|
||||
mNavigationBar.computeFrameAndUpdateSourceFrame();
|
||||
mNavigationBar.computeFrameAndUpdateSourceFrame(displayFrames);
|
||||
sTmpRect.set(windowFrames.mFrame);
|
||||
sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
|
||||
contentFrame.set(sTmpRect);
|
||||
@@ -1540,6 +1599,16 @@ public class DisplayPolicy {
|
||||
return navBarPosition;
|
||||
}
|
||||
|
||||
private void simulateLayoutForContentFrame(DisplayFrames displayFrames, WindowState win,
|
||||
Rect simulatedContentFrame) {
|
||||
layoutWindowLw(win, null /* attached */, displayFrames);
|
||||
final Rect contentFrame = sTmpRect;
|
||||
contentFrame.set(win.getLayoutingWindowFrames().mFrame);
|
||||
// Excluding the display cutout before set to the simulated content frame.
|
||||
contentFrame.intersect(displayFrames.mDisplayCutoutSafe);
|
||||
simulatedContentFrame.set(contentFrame);
|
||||
}
|
||||
|
||||
private boolean canReceiveInput(WindowState win) {
|
||||
boolean notFocusable =
|
||||
(win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0;
|
||||
@@ -1561,16 +1630,16 @@ public class DisplayPolicy {
|
||||
* @param displayFrames The display frames.
|
||||
*/
|
||||
public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
|
||||
if (win == mNavigationBar) {
|
||||
if (win == mNavigationBar && !INSETS_LAYOUT_GENERALIZATION) {
|
||||
mNavigationBarPosition = layoutNavigationBar(displayFrames,
|
||||
mBarContentFrames.get(TYPE_NAVIGATION_BAR));
|
||||
return;
|
||||
}
|
||||
if ((win == mStatusBar && !canReceiveInput(win))) {
|
||||
if ((win == mStatusBar && !canReceiveInput(win)) && !INSETS_LAYOUT_GENERALIZATION) {
|
||||
layoutStatusBar(displayFrames, mBarContentFrames.get(TYPE_STATUS_BAR));
|
||||
return;
|
||||
}
|
||||
final WindowManager.LayoutParams attrs = win.getAttrs();
|
||||
final WindowManager.LayoutParams attrs = win.getLayoutingAttrs(displayFrames.mRotation);
|
||||
|
||||
final int type = attrs.type;
|
||||
final int fl = attrs.flags;
|
||||
@@ -1578,7 +1647,7 @@ public class DisplayPolicy {
|
||||
final int sim = attrs.softInputMode;
|
||||
|
||||
displayFrames = win.getDisplayFrames(displayFrames);
|
||||
final WindowFrames windowFrames = win.getWindowFrames();
|
||||
final WindowFrames windowFrames = win.getLayoutingWindowFrames();
|
||||
|
||||
sTmpLastParentFrame.set(windowFrames.mParentFrame);
|
||||
final Rect pf = windowFrames.mParentFrame;
|
||||
@@ -1589,7 +1658,13 @@ public class DisplayPolicy {
|
||||
final boolean layoutInsetDecor = (fl & FLAG_LAYOUT_INSET_DECOR) == FLAG_LAYOUT_INSET_DECOR;
|
||||
|
||||
final InsetsState state = win.getInsetsState();
|
||||
computeWindowBounds(attrs, state, win.mToken.getBounds(), df);
|
||||
if (windowFrames.mIsSimulatingDecorWindow && INSETS_LAYOUT_GENERALIZATION) {
|
||||
// Override the bounds in window token has many side effects. Directly use the display
|
||||
// frame set for the simulated layout for this case.
|
||||
computeWindowBounds(attrs, state, df, df);
|
||||
} else {
|
||||
computeWindowBounds(attrs, state, win.mToken.getBounds(), df);
|
||||
}
|
||||
if (attached == null) {
|
||||
pf.set(df);
|
||||
if ((pfl & PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME) != 0) {
|
||||
@@ -1689,7 +1764,17 @@ public class DisplayPolicy {
|
||||
windowFrames.setContentChanged(true);
|
||||
}
|
||||
|
||||
win.computeFrameAndUpdateSourceFrame();
|
||||
win.computeFrameAndUpdateSourceFrame(displayFrames);
|
||||
if (INSETS_LAYOUT_GENERALIZATION && attrs.type == TYPE_STATUS_BAR) {
|
||||
if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top) {
|
||||
// Make sure that the zone we're avoiding for the cutout is at least as tall as the
|
||||
// status bar; otherwise fullscreen apps will end up cutting halfway into the status
|
||||
// bar.
|
||||
displayFrames.mDisplayCutoutSafe.top = Math.max(
|
||||
displayFrames.mDisplayCutoutSafe.top,
|
||||
windowFrames.mFrame.bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WindowState getTopFullscreenOpaqueWindow() {
|
||||
@@ -2118,11 +2203,37 @@ public class DisplayPolicy {
|
||||
return mUiContext;
|
||||
}
|
||||
|
||||
private int getNavigationBarWidth(int rotation, int uiMode) {
|
||||
if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
|
||||
return mNavigationBarWidthForRotationInCarMode[rotation];
|
||||
private int getNavigationBarWidth(int rotation, int uiMode, int position) {
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
if (mNavigationBar == null) {
|
||||
return 0;
|
||||
}
|
||||
LayoutParams lp = mNavigationBar.mAttrs;
|
||||
if (lp.paramsForRotation != null
|
||||
&& lp.paramsForRotation.length == 4
|
||||
&& lp.paramsForRotation[rotation] != null) {
|
||||
lp = lp.paramsForRotation[rotation];
|
||||
}
|
||||
if (position == NAV_BAR_LEFT) {
|
||||
if (lp.width > lp.providedInternalInsets.right) {
|
||||
return lp.width - lp.providedInternalInsets.right;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if (position == NAV_BAR_RIGHT) {
|
||||
if (lp.width > lp.providedInternalInsets.left) {
|
||||
return lp.width - lp.providedInternalInsets.left;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return lp.width;
|
||||
} else {
|
||||
return mNavigationBarWidthForRotationDefault[rotation];
|
||||
if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
|
||||
return mNavigationBarWidthForRotationInCarMode[rotation];
|
||||
} else {
|
||||
return mNavigationBarWidthForRotationDefault[rotation];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2149,7 +2260,7 @@ public class DisplayPolicy {
|
||||
if (hasNavigationBar()) {
|
||||
final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation);
|
||||
if (navBarPosition == NAV_BAR_LEFT || navBarPosition == NAV_BAR_RIGHT) {
|
||||
width -= getNavigationBarWidth(rotation, uiMode);
|
||||
width -= getNavigationBarWidth(rotation, uiMode, navBarPosition);
|
||||
}
|
||||
}
|
||||
if (displayCutout != null) {
|
||||
@@ -2159,10 +2270,21 @@ public class DisplayPolicy {
|
||||
}
|
||||
|
||||
private int getNavigationBarHeight(int rotation, int uiMode) {
|
||||
if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
|
||||
return mNavigationBarHeightForRotationInCarMode[rotation];
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
if (mNavigationBar == null) {
|
||||
return 0;
|
||||
}
|
||||
LayoutParams lp = mNavigationBar.getLayoutingAttrs(rotation);
|
||||
if (lp.height < lp.providedInternalInsets.top) {
|
||||
return 0;
|
||||
}
|
||||
return lp.height - lp.providedInternalInsets.top;
|
||||
} else {
|
||||
return mNavigationBarHeightForRotationDefault[rotation];
|
||||
if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
|
||||
return mNavigationBarHeightForRotationInCarMode[rotation];
|
||||
} else {
|
||||
return mNavigationBarHeightForRotationDefault[rotation];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2179,10 +2301,17 @@ public class DisplayPolicy {
|
||||
* @return navigation bar frame height
|
||||
*/
|
||||
private int getNavigationBarFrameHeight(int rotation, int uiMode) {
|
||||
if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
|
||||
return mNavigationBarHeightForRotationInCarMode[rotation];
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
if (mNavigationBar == null) {
|
||||
return 0;
|
||||
}
|
||||
return mNavigationBar.mAttrs.height;
|
||||
} else {
|
||||
return mNavigationBarFrameHeightForRotationDefault[rotation];
|
||||
if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
|
||||
return mNavigationBarHeightForRotationInCarMode[rotation];
|
||||
} else {
|
||||
return mNavigationBarFrameHeightForRotationDefault[rotation];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2303,9 +2432,9 @@ public class DisplayPolicy {
|
||||
if (position == NAV_BAR_BOTTOM) {
|
||||
outInsets.bottom = getNavigationBarHeight(displayRotation, uiMode);
|
||||
} else if (position == NAV_BAR_RIGHT) {
|
||||
outInsets.right = getNavigationBarWidth(displayRotation, uiMode);
|
||||
outInsets.right = getNavigationBarWidth(displayRotation, uiMode, position);
|
||||
} else if (position == NAV_BAR_LEFT) {
|
||||
outInsets.left = getNavigationBarWidth(displayRotation, uiMode);
|
||||
outInsets.left = getNavigationBarWidth(displayRotation, uiMode, position);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2331,6 +2460,17 @@ public class DisplayPolicy {
|
||||
|
||||
@NavigationBarPosition
|
||||
int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) {
|
||||
if (INSETS_LAYOUT_GENERALIZATION && mNavigationBar != null) {
|
||||
final int gravity = mNavigationBar.getLayoutingAttrs(displayRotation).gravity;
|
||||
switch (gravity) {
|
||||
case Gravity.LEFT:
|
||||
return NAV_BAR_LEFT;
|
||||
case Gravity.RIGHT:
|
||||
return NAV_BAR_RIGHT;
|
||||
default:
|
||||
return NAV_BAR_BOTTOM;
|
||||
}
|
||||
}
|
||||
if (navigationBarCanMove() && displayWidth > displayHeight) {
|
||||
if (displayRotation == Surface.ROTATION_270) {
|
||||
return NAV_BAR_LEFT;
|
||||
@@ -2694,7 +2834,24 @@ public class DisplayPolicy {
|
||||
|
||||
private Rect getBarContentFrameForWindow(WindowState win, int windowType) {
|
||||
final Rect rotatedBarFrame = win.mToken.getFixedRotationBarContentFrame(windowType);
|
||||
return rotatedBarFrame != null ? rotatedBarFrame : mBarContentFrames.get(windowType);
|
||||
if (rotatedBarFrame != null) {
|
||||
return rotatedBarFrame;
|
||||
}
|
||||
if (!INSETS_LAYOUT_GENERALIZATION) {
|
||||
return mBarContentFrames.get(windowType);
|
||||
}
|
||||
// We only need a window specific information for the fixed rotation, use raw insets state
|
||||
// for all other cases.
|
||||
InsetsState insetsState = mDisplayContent.getInsetsStateController().getRawInsetsState();
|
||||
final Rect tmpRect = new Rect();
|
||||
if (windowType == TYPE_NAVIGATION_BAR) {
|
||||
tmpRect.set(insetsState.getSource(InsetsState.ITYPE_NAVIGATION_BAR).getFrame());
|
||||
}
|
||||
if (windowType == TYPE_STATUS_BAR) {
|
||||
tmpRect.set(insetsState.getSource(InsetsState.ITYPE_STATUS_BAR).getFrame());
|
||||
}
|
||||
tmpRect.intersect(mDisplayContent.mDisplayFrames.mDisplayCutoutSafe);
|
||||
return tmpRect;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -88,6 +88,11 @@ public class WindowFrames {
|
||||
// screen size compatibility mode.
|
||||
final Rect mCompatFrame = new Rect();
|
||||
|
||||
/**
|
||||
* {@code true} if the window frame is a simulated frame and attached to a decor window.
|
||||
*/
|
||||
boolean mIsSimulatingDecorWindow = false;
|
||||
|
||||
/**
|
||||
* Whether the parent frame would have been different if there was no display cutout.
|
||||
*/
|
||||
|
||||
@@ -2515,7 +2515,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||
}
|
||||
if (winAnimator.mSurfaceController != null) {
|
||||
win.calculateSurfaceBounds(win.getAttrs(), mTmpRect);
|
||||
win.calculateSurfaceBounds(win.getLayoutingAttrs(
|
||||
win.getWindowConfiguration().getRotation()), mTmpRect);
|
||||
outSurfaceSize.set(mTmpRect.width(), mTmpRect.height());
|
||||
}
|
||||
getInsetsSourceControls(win, outActiveControls);
|
||||
|
||||
@@ -34,6 +34,7 @@ import static android.view.InsetsState.ITYPE_IME;
|
||||
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||
import static android.view.SurfaceControl.Transaction;
|
||||
import static android.view.SurfaceControl.getGlobalTransaction;
|
||||
import static android.view.ViewRootImpl.INSETS_LAYOUT_GENERALIZATION;
|
||||
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
|
||||
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
|
||||
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
|
||||
@@ -1259,8 +1260,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
frame.inset(left, top, right, bottom);
|
||||
}
|
||||
|
||||
void computeFrameAndUpdateSourceFrame() {
|
||||
computeFrame();
|
||||
void computeFrameAndUpdateSourceFrame(DisplayFrames displayFrames) {
|
||||
computeFrame(displayFrames);
|
||||
// Update the source frame to provide insets to other windows during layout. If the
|
||||
// simulated frames exist, then this is not computing a stable result so just skip.
|
||||
if (mControllableInsetProvider != null && mSimulatedWindowFrames == null) {
|
||||
@@ -1271,7 +1272,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
/**
|
||||
* Perform standard frame computation. The result can be obtained with getFrame() if so desired.
|
||||
*/
|
||||
void computeFrame() {
|
||||
void computeFrame(DisplayFrames displayFrames) {
|
||||
if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) {
|
||||
// This window is being replaced and either already got information that it's being
|
||||
// removed or we are still waiting for some information. Because of this we don't
|
||||
@@ -1384,7 +1385,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
final int fw = windowFrames.mFrame.width();
|
||||
final int fh = windowFrames.mFrame.height();
|
||||
|
||||
applyGravityAndUpdateFrame(windowFrames, layoutContainingFrame, layoutDisplayFrame);
|
||||
applyGravityAndUpdateFrame(windowFrames, layoutContainingFrame, layoutDisplayFrame,
|
||||
displayFrames);
|
||||
|
||||
if (mAttrs.type == TYPE_DOCK_DIVIDER) {
|
||||
if (!windowFrames.mFrame.equals(windowFrames.mLastFrame)) {
|
||||
@@ -1477,6 +1479,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
return mAttrs;
|
||||
}
|
||||
|
||||
WindowManager.LayoutParams getLayoutingAttrs(int rotation) {
|
||||
if (!INSETS_LAYOUT_GENERALIZATION) {
|
||||
return mAttrs;
|
||||
}
|
||||
final WindowManager.LayoutParams[] paramsForRotation = mAttrs.paramsForRotation;
|
||||
if (paramsForRotation == null || paramsForRotation.length != 4
|
||||
|| paramsForRotation[rotation] == null) {
|
||||
return mAttrs;
|
||||
}
|
||||
return paramsForRotation[rotation];
|
||||
}
|
||||
|
||||
/** Retrieves the flags used to disable system UI functions. */
|
||||
int getDisableFlags() {
|
||||
return mDisableFlags;
|
||||
@@ -4412,12 +4426,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
|
||||
private void applyGravityAndUpdateFrame(WindowFrames windowFrames, Rect containingFrame,
|
||||
Rect displayFrame) {
|
||||
Rect displayFrame, DisplayFrames displayFrames) {
|
||||
final int pw = containingFrame.width();
|
||||
final int ph = containingFrame.height();
|
||||
final Task task = getTask();
|
||||
final boolean inNonFullscreenContainer = !inAppWindowThatMatchesParentBounds();
|
||||
final boolean noLimits = (mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0;
|
||||
final WindowManager.LayoutParams attrs = getLayoutingAttrs(displayFrames.mRotation);
|
||||
final boolean noLimits = (attrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0;
|
||||
|
||||
// We need to fit it to the display if either
|
||||
// a) The window is in a fullscreen container, or we don't have a task (we assume fullscreen
|
||||
@@ -4427,49 +4442,54 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
// screen, but SurfaceViews want to be always at a specific location so we don't fit it to
|
||||
// the display.
|
||||
final boolean fitToDisplay = (task == null || !inNonFullscreenContainer)
|
||||
|| ((mAttrs.type != TYPE_BASE_APPLICATION) && !noLimits);
|
||||
|| ((attrs.type != TYPE_BASE_APPLICATION) && !noLimits);
|
||||
float x, y;
|
||||
int w,h;
|
||||
|
||||
final boolean hasCompatScale = hasCompatScale();
|
||||
if ((mAttrs.flags & FLAG_SCALED) != 0) {
|
||||
if (mAttrs.width < 0) {
|
||||
if ((attrs.flags & FLAG_SCALED) != 0 || mAttrs != attrs) {
|
||||
// For the window with different layout attrs for different rotations, we need to avoid
|
||||
// using requested size. Otherwise, when finishing a simulated rotation, the information
|
||||
// coming from WindowManagerServices to the ViewRootImpl may not contain the correct
|
||||
// value for the new rotation, and there will be a quick flash of wrong layout when the
|
||||
// simulated activity faded out.
|
||||
if (attrs.width < 0) {
|
||||
w = pw;
|
||||
} else if (hasCompatScale) {
|
||||
w = (int)(mAttrs.width * mGlobalScale + .5f);
|
||||
w = (int) (attrs.width * mGlobalScale + .5f);
|
||||
} else {
|
||||
w = mAttrs.width;
|
||||
w = attrs.width;
|
||||
}
|
||||
if (mAttrs.height < 0) {
|
||||
if (attrs.height < 0) {
|
||||
h = ph;
|
||||
} else if (hasCompatScale) {
|
||||
h = (int)(mAttrs.height * mGlobalScale + .5f);
|
||||
h = (int) (attrs.height * mGlobalScale + .5f);
|
||||
} else {
|
||||
h = mAttrs.height;
|
||||
h = attrs.height;
|
||||
}
|
||||
} else {
|
||||
if (mAttrs.width == MATCH_PARENT) {
|
||||
if (attrs.width == MATCH_PARENT) {
|
||||
w = pw;
|
||||
} else if (hasCompatScale) {
|
||||
w = (int)(mRequestedWidth * mGlobalScale + .5f);
|
||||
w = (int) (mRequestedWidth * mGlobalScale + .5f);
|
||||
} else {
|
||||
w = mRequestedWidth;
|
||||
}
|
||||
if (mAttrs.height == MATCH_PARENT) {
|
||||
if (attrs.height == MATCH_PARENT) {
|
||||
h = ph;
|
||||
} else if (hasCompatScale) {
|
||||
h = (int)(mRequestedHeight * mGlobalScale + .5f);
|
||||
h = (int) (mRequestedHeight * mGlobalScale + .5f);
|
||||
} else {
|
||||
h = mRequestedHeight;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasCompatScale) {
|
||||
x = mAttrs.x * mGlobalScale;
|
||||
y = mAttrs.y * mGlobalScale;
|
||||
x = attrs.x * mGlobalScale;
|
||||
y = attrs.y * mGlobalScale;
|
||||
} else {
|
||||
x = mAttrs.x;
|
||||
y = mAttrs.y;
|
||||
x = attrs.x;
|
||||
y = attrs.y;
|
||||
}
|
||||
|
||||
if (inNonFullscreenContainer && !layoutInParentFrame()) {
|
||||
@@ -4496,13 +4516,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
|
||||
// Set mFrame
|
||||
Gravity.apply(mAttrs.gravity, w, h, containingFrame,
|
||||
(int) (x + mAttrs.horizontalMargin * pw),
|
||||
(int) (y + mAttrs.verticalMargin * ph), windowFrames.mFrame);
|
||||
|
||||
Gravity.apply(attrs.gravity, w, h, containingFrame,
|
||||
(int) (x + attrs.horizontalMargin * pw),
|
||||
(int) (y + attrs.verticalMargin * ph), windowFrames.mFrame);
|
||||
// Now make sure the window fits in the overall display frame.
|
||||
if (fitToDisplay) {
|
||||
Gravity.applyDisplay(mAttrs.gravity, displayFrame, windowFrames.mFrame);
|
||||
Gravity.applyDisplay(attrs.gravity, displayFrame, windowFrames.mFrame);
|
||||
}
|
||||
|
||||
// We need to make sure we update the CompatFrame as it is used for
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.view.ViewRootImpl.INSETS_LAYOUT_GENERALIZATION;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
|
||||
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
|
||||
@@ -451,9 +453,24 @@ class WindowToken extends WindowContainer<WindowState> {
|
||||
}
|
||||
|
||||
Rect getFixedRotationBarContentFrame(int windowType) {
|
||||
return isFixedRotationTransforming()
|
||||
? mFixedRotationTransformState.mBarContentFrames.get(windowType)
|
||||
: null;
|
||||
if (!isFixedRotationTransforming()) {
|
||||
return null;
|
||||
}
|
||||
if (!INSETS_LAYOUT_GENERALIZATION) {
|
||||
return mFixedRotationTransformState.mBarContentFrames.get(windowType);
|
||||
}
|
||||
final DisplayFrames displayFrames = mFixedRotationTransformState.mDisplayFrames;
|
||||
final Rect tmpRect = new Rect();
|
||||
if (windowType == TYPE_NAVIGATION_BAR) {
|
||||
tmpRect.set(displayFrames.mInsetsState.getSource(InsetsState.ITYPE_NAVIGATION_BAR)
|
||||
.getFrame());
|
||||
}
|
||||
if (windowType == TYPE_STATUS_BAR) {
|
||||
tmpRect.set(displayFrames.mInsetsState.getSource(InsetsState.ITYPE_STATUS_BAR)
|
||||
.getFrame());
|
||||
}
|
||||
tmpRect.intersect(displayFrames.mDisplayCutoutSafe);
|
||||
return tmpRect;
|
||||
}
|
||||
|
||||
InsetsState getFixedRotationTransformInsetsState() {
|
||||
|
||||
@@ -24,7 +24,7 @@ import static android.view.InsetsState.ITYPE_TOP_GESTURES;
|
||||
import static android.view.Surface.ROTATION_0;
|
||||
import static android.view.Surface.ROTATION_270;
|
||||
import static android.view.Surface.ROTATION_90;
|
||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
import static android.view.ViewRootImpl.INSETS_LAYOUT_GENERALIZATION;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
|
||||
@@ -50,13 +50,13 @@ import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.util.Pair;
|
||||
@@ -69,7 +69,6 @@ import android.view.PrivacyIndicatorBounds;
|
||||
import android.view.RoundedCorners;
|
||||
import android.view.WindowInsets.Side;
|
||||
import android.view.WindowInsets.Type;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -109,12 +108,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
|
||||
mWindow = spy(createWindow(null, TYPE_APPLICATION, "window"));
|
||||
// We only test window frames set by DisplayPolicy, so here prevents computeFrameLw from
|
||||
// changing those frames.
|
||||
doNothing().when(mWindow).computeFrame();
|
||||
|
||||
final WindowManager.LayoutParams attrs = mWindow.mAttrs;
|
||||
attrs.width = MATCH_PARENT;
|
||||
attrs.height = MATCH_PARENT;
|
||||
attrs.format = PixelFormat.TRANSLUCENT;
|
||||
doNothing().when(mWindow).computeFrame(any());
|
||||
|
||||
spyOn(mStatusBarWindow);
|
||||
spyOn(mNavBarWindow);
|
||||
@@ -219,7 +213,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addingWindow_ignoresInsetsTypes_InWindowTypeWithPredefinedInsets() {
|
||||
public void addingWindow_InWindowTypeWithPredefinedInsets() {
|
||||
mDisplayPolicy.removeWindowLw(mStatusBarWindow); // Removes the existing one.
|
||||
WindowState win = createWindow(null, TYPE_STATUS_BAR, "StatusBar");
|
||||
win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR};
|
||||
@@ -230,7 +224,13 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
|
||||
|
||||
InsetsSourceProvider provider =
|
||||
mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR);
|
||||
assertNotEquals(new Rect(0, 0, 500, 100), provider.getSource().getFrame());
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
// In the new flexible insets setup, the insets frame should always respect the window
|
||||
// layout result.
|
||||
assertEquals(new Rect(0, 0, 500, 100), provider.getSource().getFrame());
|
||||
} else {
|
||||
assertNotEquals(new Rect(0, 0, 500, 100), provider.getSource().getFrame());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -733,10 +733,12 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
|
||||
|
||||
@Test
|
||||
public void testFixedRotationInsetsSourceFrame() {
|
||||
mDisplayContent.mBaseDisplayHeight = DISPLAY_HEIGHT;
|
||||
mDisplayContent.mBaseDisplayWidth = DISPLAY_WIDTH;
|
||||
doReturn((mDisplayContent.getRotation() + 1) % 4).when(mDisplayContent)
|
||||
.rotationForActivityInDifferentOrientation(eq(mWindow.mActivityRecord));
|
||||
mWindow.mAboveInsetsState.addSource(mDisplayContent.getInsetsStateController()
|
||||
.getRawInsetsState().peekSource(ITYPE_STATUS_BAR));
|
||||
mWindow.mAboveInsetsState.set(
|
||||
mDisplayContent.getInsetsStateController().getRawInsetsState());
|
||||
final Rect frame = mDisplayPolicy.getInsetsPolicy().getInsetsForWindow(mWindow)
|
||||
.getSource(ITYPE_STATUS_BAR).getFrame();
|
||||
mDisplayContent.rotateInDifferentOrientationIfNeeded(mWindow.mActivityRecord);
|
||||
|
||||
@@ -313,7 +313,9 @@ public class DisplayPolicyTests extends WindowTestsBase {
|
||||
displayInfo.logicalHeight = 2000;
|
||||
displayInfo.rotation = ROTATION_0;
|
||||
|
||||
displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs);
|
||||
WindowManager.LayoutParams attrs = mNavBarWindow.mAttrs;
|
||||
displayPolicy.addWindowLw(mNavBarWindow, attrs);
|
||||
mNavBarWindow.setRequestedSize(attrs.width, attrs.height);
|
||||
mNavBarWindow.getControllableInsetProvider().setServerVisible(true);
|
||||
final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
|
||||
mImeWindow.mAboveInsetsState.set(state);
|
||||
|
||||
@@ -58,8 +58,6 @@ public class DisplayPolicyTestsBase extends WindowTestsBase {
|
||||
static final int DISPLAY_HEIGHT = 1000;
|
||||
static final int DISPLAY_DENSITY = 320;
|
||||
|
||||
static final int STATUS_BAR_HEIGHT = 10;
|
||||
static final int NAV_BAR_HEIGHT = 15;
|
||||
static final int DISPLAY_CUTOUT_HEIGHT = 8;
|
||||
static final int IME_HEIGHT = 415;
|
||||
|
||||
|
||||
@@ -57,12 +57,14 @@ import org.mockito.Mockito;
|
||||
public class WindowFrameTests extends WindowTestsBase {
|
||||
|
||||
private DisplayContent mTestDisplayContent;
|
||||
private DisplayFrames mTestDisplayFrames;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
DisplayInfo testDisplayInfo = new DisplayInfo(mDisplayInfo);
|
||||
testDisplayInfo.displayCutout = null;
|
||||
mTestDisplayContent = createNewDisplay(testDisplayInfo);
|
||||
mTestDisplayFrames = mTestDisplayContent.mDisplayFrames;
|
||||
}
|
||||
|
||||
// Do not use this function directly in the tests below. Instead, use more explicit function
|
||||
@@ -99,7 +101,7 @@ public class WindowFrameTests extends WindowTestsBase {
|
||||
// Here the window has FILL_PARENT, FILL_PARENT
|
||||
// so we expect it to fill the entire available frame.
|
||||
w.getWindowFrames().setFrames(pf, pf);
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertFrame(w, 0, 0, 1000, 1000);
|
||||
assertRelFrame(w, 0, 0, 1000, 1000);
|
||||
|
||||
@@ -108,14 +110,14 @@ public class WindowFrameTests extends WindowTestsBase {
|
||||
// and we use mRequestedWidth/mRequestedHeight
|
||||
w.mAttrs.width = 300;
|
||||
w.mAttrs.height = 300;
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
// Explicit width and height without requested width/height
|
||||
// gets us nothing.
|
||||
assertFrame(w, 0, 0, 0, 0);
|
||||
|
||||
w.mRequestedWidth = 300;
|
||||
w.mRequestedHeight = 300;
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
// With requestedWidth/Height we can freely choose our size within the
|
||||
// parent bounds.
|
||||
assertFrame(w, 0, 0, 300, 300);
|
||||
@@ -128,14 +130,14 @@ public class WindowFrameTests extends WindowTestsBase {
|
||||
w.mRequestedWidth = -1;
|
||||
w.mAttrs.width = 100;
|
||||
w.mAttrs.height = 100;
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertFrame(w, 0, 0, 100, 100);
|
||||
w.mAttrs.flags = 0;
|
||||
|
||||
// But sizes too large will be clipped to the containing frame
|
||||
w.mRequestedWidth = 1200;
|
||||
w.mRequestedHeight = 1200;
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertFrame(w, 0, 0, 1000, 1000);
|
||||
|
||||
// Before they are clipped though windows will be shifted
|
||||
@@ -143,7 +145,7 @@ public class WindowFrameTests extends WindowTestsBase {
|
||||
w.mAttrs.y = 300;
|
||||
w.mRequestedWidth = 1000;
|
||||
w.mRequestedHeight = 1000;
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertFrame(w, 0, 0, 1000, 1000);
|
||||
|
||||
// If there is room to move around in the parent frame the window will be shifted according
|
||||
@@ -153,18 +155,18 @@ public class WindowFrameTests extends WindowTestsBase {
|
||||
w.mRequestedWidth = 300;
|
||||
w.mRequestedHeight = 300;
|
||||
w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP;
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertFrame(w, 700, 0, 1000, 300);
|
||||
assertRelFrame(w, 700, 0, 1000, 300);
|
||||
w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM;
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertFrame(w, 700, 700, 1000, 1000);
|
||||
assertRelFrame(w, 700, 700, 1000, 1000);
|
||||
// Window specified x and y are interpreted as offsets in the opposite
|
||||
// direction of gravity
|
||||
w.mAttrs.x = 100;
|
||||
w.mAttrs.y = 100;
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertFrame(w, 600, 600, 900, 900);
|
||||
assertRelFrame(w, 600, 600, 900, 900);
|
||||
}
|
||||
@@ -191,7 +193,7 @@ public class WindowFrameTests extends WindowTestsBase {
|
||||
final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
|
||||
final WindowFrames windowFrames = w.getWindowFrames();
|
||||
windowFrames.setFrames(pf, pf);
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
// For non fullscreen tasks the containing frame is based off the
|
||||
// task bounds not the parent frame.
|
||||
assertEquals(resolvedTaskBounds, w.getFrame());
|
||||
@@ -204,7 +206,7 @@ public class WindowFrameTests extends WindowTestsBase {
|
||||
final int cfBottom = logicalHeight / 2;
|
||||
final Rect cf = new Rect(0, 0, cfRight, cfBottom);
|
||||
windowFrames.setFrames(pf, pf);
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertEquals(resolvedTaskBounds, w.getFrame());
|
||||
assertEquals(0, w.getRelativeFrame().left);
|
||||
assertEquals(0, w.getRelativeFrame().top);
|
||||
@@ -233,7 +235,7 @@ public class WindowFrameTests extends WindowTestsBase {
|
||||
final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
|
||||
final WindowFrames windowFrames = w.getWindowFrames();
|
||||
windowFrames.setFrames(pf, pf);
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
// For non fullscreen tasks the containing frame is based off the
|
||||
// task bounds not the parent frame.
|
||||
assertFrame(w, taskLeft, taskTop, taskRight, taskBottom);
|
||||
@@ -249,7 +251,7 @@ public class WindowFrameTests extends WindowTestsBase {
|
||||
task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
|
||||
task.setBounds(null);
|
||||
windowFrames.setFrames(pf, pf);
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertFrame(w, cf);
|
||||
}
|
||||
|
||||
@@ -285,7 +287,7 @@ public class WindowFrameTests extends WindowTestsBase {
|
||||
final Rect winRect = new Rect(200, 200, 300, 500);
|
||||
task.setBounds(winRect);
|
||||
w.getWindowFrames().setFrames(pf, pf);
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertFrame(w, winRect.left, imeFrame.top - winRect.height(), winRect.right, imeFrame.top);
|
||||
|
||||
// Now check that it won't get moved beyond the top
|
||||
@@ -293,7 +295,7 @@ public class WindowFrameTests extends WindowTestsBase {
|
||||
task.setBounds(winRect);
|
||||
w.setBounds(winRect);
|
||||
w.getWindowFrames().setFrames(pf, pf);
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertFrame(w, winRect.left, 0, winRect.right, winRect.height());
|
||||
|
||||
// Now we have status bar. Check that it won't go into the status bar area.
|
||||
@@ -301,14 +303,14 @@ public class WindowFrameTests extends WindowTestsBase {
|
||||
statusBarFrame.bottom = 60;
|
||||
state.getSource(ITYPE_STATUS_BAR).setFrame(statusBarFrame);
|
||||
w.getWindowFrames().setFrames(pf, pf);
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertFrame(w, winRect.left, statusBarFrame.bottom, winRect.right,
|
||||
statusBarFrame.bottom + winRect.height());
|
||||
|
||||
// Check that it's moved back without ime insets
|
||||
state.removeSource(ITYPE_IME);
|
||||
w.getWindowFrames().setFrames(pf, pf);
|
||||
w.computeFrame();
|
||||
w.computeFrame(mTestDisplayFrames);
|
||||
assertEquals(winRect, w.getFrame());
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
||||
@@ -29,11 +30,13 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
import static android.os.Process.SYSTEM_UID;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static android.view.ViewRootImpl.INSETS_LAYOUT_GENERALIZATION;
|
||||
import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
|
||||
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
|
||||
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
|
||||
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
|
||||
@@ -83,10 +86,12 @@ import android.service.voice.IVoiceInteractionSession;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.Gravity;
|
||||
import android.view.IDisplayWindowInsetsController;
|
||||
import android.view.IWindow;
|
||||
import android.view.InsetsSourceControl;
|
||||
import android.view.InsetsState;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
import android.view.View;
|
||||
@@ -132,6 +137,9 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
DisplayInfo mDisplayInfo = new DisplayInfo();
|
||||
DisplayContent mDefaultDisplay;
|
||||
|
||||
static final int STATUS_BAR_HEIGHT = 10;
|
||||
static final int NAV_BAR_HEIGHT = 15;
|
||||
|
||||
/**
|
||||
* It is {@link #mDefaultDisplay} by default. If the test class or method is annotated with
|
||||
* {@link UseTestDisplay}, it will be an additional display.
|
||||
@@ -268,6 +276,14 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
}
|
||||
if (addAll || ArrayUtils.contains(requestedWindows, W_STATUS_BAR)) {
|
||||
mStatusBarWindow = createCommonWindow(null, TYPE_STATUS_BAR, "mStatusBarWindow");
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
mStatusBarWindow.mAttrs.height = STATUS_BAR_HEIGHT;
|
||||
mStatusBarWindow.mAttrs.gravity = Gravity.TOP;
|
||||
mStatusBarWindow.mAttrs.layoutInDisplayCutoutMode =
|
||||
LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
mStatusBarWindow.setRequestedSize(WindowManager.LayoutParams.MATCH_PARENT,
|
||||
STATUS_BAR_HEIGHT);
|
||||
}
|
||||
}
|
||||
if (addAll || ArrayUtils.contains(requestedWindows, W_NOTIFICATION_SHADE)) {
|
||||
mNotificationShadeWindow = createCommonWindow(null, TYPE_NOTIFICATION_SHADE,
|
||||
@@ -275,6 +291,15 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
}
|
||||
if (addAll || ArrayUtils.contains(requestedWindows, W_NAVIGATION_BAR)) {
|
||||
mNavBarWindow = createCommonWindow(null, TYPE_NAVIGATION_BAR, "mNavBarWindow");
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
mNavBarWindow.mAttrs.height = NAV_BAR_HEIGHT;
|
||||
mNavBarWindow.mAttrs.gravity = Gravity.BOTTOM;
|
||||
mNavBarWindow.mAttrs.paramsForRotation = new WindowManager.LayoutParams[4];
|
||||
for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
|
||||
mNavBarWindow.mAttrs.paramsForRotation[rot] =
|
||||
getNavBarLayoutParamsForRotation(rot);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addAll || ArrayUtils.contains(requestedWindows, W_DOCK_DIVIDER)) {
|
||||
mDockedDividerWindow = createCommonWindow(null, TYPE_DOCK_DIVIDER,
|
||||
@@ -302,6 +327,37 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
waitUntilHandlersIdle();
|
||||
}
|
||||
|
||||
private WindowManager.LayoutParams getNavBarLayoutParamsForRotation(int rotation) {
|
||||
int width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
int height = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
int gravity = Gravity.BOTTOM;
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
switch (rotation) {
|
||||
case ROTATION_UNDEFINED:
|
||||
case Surface.ROTATION_0:
|
||||
case Surface.ROTATION_180:
|
||||
height = NAV_BAR_HEIGHT;
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
gravity = Gravity.RIGHT;
|
||||
width = NAV_BAR_HEIGHT;
|
||||
break;
|
||||
case Surface.ROTATION_270:
|
||||
gravity = Gravity.LEFT;
|
||||
width = NAV_BAR_HEIGHT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR);
|
||||
lp.width = width;
|
||||
lp.height = height;
|
||||
if (INSETS_LAYOUT_GENERALIZATION) {
|
||||
lp.gravity = gravity;
|
||||
}
|
||||
return lp;
|
||||
}
|
||||
|
||||
void beforeCreateTestDisplay() {
|
||||
// Called before display is created.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user