Migrate Navigation Bar to InsetsFrameProvider

This patch is moving the navigation bar related insets logic from
DisplayPolicy to com.android.systemui.navigationbar package. To fully
match the feature, callbacks between NavigationBar and
EdgeBackGestureHandler is added to handle the nav bar button force
visible case.

Bug: 239145252
Test: DisplayPolicyInsetsTests
Test: InsetsPolicyTest DisplayPolicyTests
Test: InsetsControllerTest
Change-Id: I628a9e24df14268f2c7e92ab8ecd8d5d0d611847
This commit is contained in:
Yunfan Chen
2022-09-28 18:53:38 +09:00
parent 7609165584
commit 070ae52e71
7 changed files with 202 additions and 167 deletions

View File

@@ -273,6 +273,9 @@ public class InsetsFrameProvider implements Parcelable {
/**
* Class to describe the insets size to be provided to window with specific window type. If not
* used, same insets size will be sent as instructed in the insetsSize and source.
*
* If the insetsSize of given type is set to {@code null}, the insets source frame will be used
* directly for that window type.
*/
public static class InsetsSizeOverride implements Parcelable {
public final int windowType;
@@ -280,7 +283,7 @@ public class InsetsFrameProvider implements Parcelable {
protected InsetsSizeOverride(Parcel in) {
windowType = in.readInt();
insetsSize = in.readParcelable(null, android.graphics.Insets.class);
insetsSize = in.readParcelable(null, Insets.class);
}
public InsetsSizeOverride(int type, Insets size) {

View File

@@ -25,11 +25,16 @@ import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES;
import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
@@ -77,6 +82,7 @@ import android.telecom.TelecomManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.InsetsFrameProvider;
@@ -238,6 +244,12 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private boolean mTransientShown;
private boolean mTransientShownFromGestureOnSystemBar;
/**
* This is to indicate whether the navigation bar button is forced visible. This is true
* when the setup wizard is on display. When that happens, the window frame should be provided
* as insets size directly.
*/
private boolean mIsButtonForceVisible;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
private LightBarController mLightBarController;
private final LightBarController mMainLightBarController;
@@ -597,6 +609,10 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mView.setTouchHandler(mTouchHandler);
setNavBarMode(mNavBarMode);
mEdgeBackGestureHandler.setStateChangeCallback(mView::updateStates);
mEdgeBackGestureHandler.setButtonForceVisibleChangeCallback((forceVisible) -> {
mIsButtonForceVisible = forceVisible;
repositionNavigationBar(mCurrentRotation);
});
mNavigationBarTransitions.addListener(this::onBarTransition);
mView.updateRotationButton();
@@ -782,7 +798,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mLayoutDirection = ld;
refreshLayout(ld);
}
repositionNavigationBar(rotation);
if (canShowSecondaryHandle()) {
if (rotation != mCurrentRotation) {
@@ -1571,23 +1586,15 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
width,
height,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
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.gravity = gravity;
if (insetsHeight != -1) {
lp.providedInsets = new InsetsFrameProvider[] {
new InsetsFrameProvider(ITYPE_NAVIGATION_BAR, Insets.of(0, 0, 0, insetsHeight))
};
} else {
lp.providedInsets = new InsetsFrameProvider[] {
new InsetsFrameProvider(ITYPE_NAVIGATION_BAR)
};
}
lp.providedInsets = getInsetsFrameProvider(insetsHeight, userContext);
lp.token = new Binder();
lp.accessibilityTitle = userContext.getString(R.string.nav_bar);
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC
@@ -1600,6 +1607,68 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
return lp;
}
private InsetsFrameProvider[] getInsetsFrameProvider(int insetsHeight, Context userContext) {
final InsetsFrameProvider navBarProvider;
if (insetsHeight != -1 && !mIsButtonForceVisible) {
navBarProvider = new InsetsFrameProvider(
ITYPE_NAVIGATION_BAR, Insets.of(0, 0, 0, insetsHeight));
// Use window frame for IME.
navBarProvider.insetsSizeOverrides = new InsetsFrameProvider.InsetsSizeOverride[] {
new InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, null)
};
} else {
navBarProvider = new InsetsFrameProvider(ITYPE_NAVIGATION_BAR);
navBarProvider.insetsSizeOverrides = new InsetsFrameProvider.InsetsSizeOverride[]{
new InsetsFrameProvider.InsetsSizeOverride(TYPE_INPUT_METHOD, null)
};
}
final boolean navBarTapThrough = userContext.getResources().getBoolean(
com.android.internal.R.bool.config_navBarTapThrough);
final InsetsFrameProvider bottomTappableProvider;
if (navBarTapThrough) {
bottomTappableProvider = new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT,
Insets.of(0, 0, 0, 0));
} else {
bottomTappableProvider = new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT);
}
if (!mEdgeBackGestureHandler.isHandlingGestures()) {
// 2/3 button navigation is on. Do not provide any gesture insets here. But need to keep
// the provider to support runtime update.
return new InsetsFrameProvider[] {
navBarProvider,
new InsetsFrameProvider(
ITYPE_BOTTOM_MANDATORY_GESTURES, Insets.NONE),
new InsetsFrameProvider(ITYPE_LEFT_GESTURES, InsetsFrameProvider.SOURCE_DISPLAY,
Insets.NONE, null),
new InsetsFrameProvider(ITYPE_RIGHT_GESTURES,
InsetsFrameProvider.SOURCE_DISPLAY,
Insets.NONE, null),
bottomTappableProvider
};
} else {
// Gesture navigation
final int gestureHeight = userContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.navigation_bar_gesture_height);
final DisplayCutout cutout = userContext.getDisplay().getCutout();
final int safeInsetsLeft = cutout != null ? cutout.getSafeInsetLeft() : 0;
final int safeInsetsRight = cutout != null ? cutout.getSafeInsetRight() : 0;
return new InsetsFrameProvider[] {
navBarProvider,
new InsetsFrameProvider(
ITYPE_BOTTOM_MANDATORY_GESTURES, Insets.of(0, 0, 0, gestureHeight)),
new InsetsFrameProvider(ITYPE_LEFT_GESTURES, InsetsFrameProvider.SOURCE_DISPLAY,
Insets.of(safeInsetsLeft
+ mEdgeBackGestureHandler.getEdgeWidthLeft(), 0, 0, 0), null),
new InsetsFrameProvider(ITYPE_RIGHT_GESTURES,
InsetsFrameProvider.SOURCE_DISPLAY,
Insets.of(0, 0, safeInsetsRight
+ mEdgeBackGestureHandler.getEdgeWidthRight(), 0), null),
bottomTappableProvider
};
}
}
private boolean canShowSecondaryHandle() {
return mNavBarMode == NAV_BAR_MODE_GESTURAL && mOrientationHandle != null;
}

View File

@@ -175,6 +175,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
private final OverviewProxyService mOverviewProxyService;
private final SysUiState mSysUiState;
private Runnable mStateChangeCallback;
private Consumer<Boolean> mButtonForceVisibleCallback;
private final PluginManager mPluginManager;
private final ProtoTracer mProtoTracer;
@@ -240,6 +241,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
private boolean mIsBackGestureAllowed;
private boolean mGestureBlockingActivityRunning;
private boolean mIsNewBackAffordanceEnabled;
private boolean mIsButtonForceVisible;
private InputMonitor mInputMonitor;
private InputChannelCompat.InputEventReceiver mInputEventReceiver;
@@ -402,12 +404,29 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
mStateChangeCallback = callback;
}
public void setButtonForceVisibleChangeCallback(Consumer<Boolean> callback) {
mButtonForceVisibleCallback = callback;
}
public int getEdgeWidthLeft() {
return mEdgeWidthLeft;
}
public int getEdgeWidthRight() {
return mEdgeWidthRight;
}
public void updateCurrentUserResources() {
Resources res = mNavigationModeController.getCurrentUserContext().getResources();
mEdgeWidthLeft = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
mEdgeWidthRight = mGestureNavigationSettingsObserver.getRightSensitivity(res);
mIsBackGestureAllowed =
!mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
final boolean previousForceVisible = mIsButtonForceVisible;
mIsButtonForceVisible =
mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
if (previousForceVisible != mIsButtonForceVisible && mButtonForceVisibleCallback != null) {
mButtonForceVisibleCallback.accept(mIsButtonForceVisible);
}
mIsBackGestureAllowed = !mIsButtonForceVisible;
final DisplayMetrics dm = res.getDisplayMetrics();
final float defaultGestureHeight = res.getDimension(

View File

@@ -19,14 +19,11 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.view.Display.TYPE_INTERNAL;
import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES;
import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
import static android.view.InsetsFrameProvider.SOURCE_FRAME;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
@@ -47,7 +44,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLO
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_UNRESTRICTED_GESTURE_EXCLUSION;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
@@ -208,15 +204,12 @@ public class DisplayPolicy {
private final Object mServiceAcquireLock = new Object();
private StatusBarManagerInternal mStatusBarManagerInternal;
@Px
private int mBottomGestureAdditionalInset;
@Px
private int mLeftGestureInset;
@Px
private int mRightGestureInset;
private boolean mCanSystemBarsBeShownByUser;
private boolean mNavButtonForcedVisible;
StatusBarManagerInternal getStatusBarManagerInternal() {
synchronized (mServiceAcquireLock) {
@@ -240,7 +233,6 @@ public class DisplayPolicy {
private volatile boolean mHasNavigationBar;
// Can the navigation bar ever move to the side?
private volatile boolean mNavigationBarCanMove;
private volatile boolean mNavigationBarLetsThroughTaps;
private volatile boolean mNavigationBarAlwaysShowOnSideGesture;
// Written by vr manager thread, only read in this class.
@@ -360,8 +352,6 @@ public class DisplayPolicy {
private PointerLocationView mPointerLocationView;
private int mDisplayCutoutTouchableRegionSize;
private RefreshRatePolicy mRefreshRatePolicy;
/**
@@ -1150,71 +1140,9 @@ public class DisplayPolicy {
break;
case TYPE_NAVIGATION_BAR:
mNavigationBar = win;
final TriConsumer<DisplayFrames, WindowContainer, Rect> navFrameProvider =
(displayFrames, windowContainer, inOutFrame) -> {
if (!mNavButtonForcedVisible) {
final LayoutParams lp =
win.mAttrs.forRotation(displayFrames.mRotation);
if (lp.providedInsets != null) {
for (InsetsFrameProvider provider : lp.providedInsets) {
if (provider.type != ITYPE_NAVIGATION_BAR) {
continue;
}
InsetsFrameProvider.calculateInsetsFrame(
displayFrames.mUnrestricted,
win.getBounds(), displayFrames.mDisplayCutoutSafe,
inOutFrame, provider.source,
provider.insetsSize, lp.privateFlags,
provider.minimalInsetsSizeInDisplayCutoutSafe);
}
}
inOutFrame.inset(win.mGivenContentInsets);
}
};
final SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> imeOverride =
new SparseArray<>();
// For IME, we don't modify the frame.
imeOverride.put(TYPE_INPUT_METHOD, null);
mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win,
navFrameProvider, imeOverride);
mDisplayContent.setInsetProvider(ITYPE_BOTTOM_MANDATORY_GESTURES, win,
(displayFrames, windowContainer, inOutFrame) -> {
inOutFrame.top -= mBottomGestureAdditionalInset;
});
mDisplayContent.setInsetProvider(ITYPE_LEFT_GESTURES, win,
(displayFrames, windowContainer, inOutFrame) -> {
final int leftSafeInset =
Math.max(displayFrames.mDisplayCutoutSafe.left, 0);
inOutFrame.left = 0;
inOutFrame.top = 0;
inOutFrame.bottom = displayFrames.mHeight;
inOutFrame.right = leftSafeInset + mLeftGestureInset;
});
mDisplayContent.setInsetProvider(ITYPE_RIGHT_GESTURES, win,
(displayFrames, windowContainer, inOutFrame) -> {
final int rightSafeInset =
Math.min(displayFrames.mDisplayCutoutSafe.right,
displayFrames.mUnrestricted.right);
inOutFrame.left = rightSafeInset - mRightGestureInset;
inOutFrame.top = 0;
inOutFrame.bottom = displayFrames.mHeight;
inOutFrame.right = displayFrames.mWidth;
});
mDisplayContent.setInsetProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT, win,
(displayFrames, windowContainer, inOutFrame) -> {
if ((win.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
|| mNavigationBarLetsThroughTaps) {
inOutFrame.setEmpty();
}
});
mInsetsSourceWindowsExceptIme.add(win);
if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
break;
}
// TODO(b/239145252): Temporarily skip the navigation bar as it is still with the hard-coded
// logic.
if (attrs.providedInsets != null && attrs.type != TYPE_NAVIGATION_BAR) {
if (attrs.providedInsets != null) {
for (int i = attrs.providedInsets.length - 1; i >= 0; i--) {
final InsetsFrameProvider provider = attrs.providedInsets[i];
switch (provider.type) {
@@ -1242,24 +1170,8 @@ public class DisplayPolicy {
// The index of the provider and corresponding insets types cannot change at
// runtime as ensured in WMS. Make use of the index in the provider directly
// to access the latest provided size at runtime.
final int index = i;
final TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider =
provider.insetsSize != null
? (displayFrames, windowContainer, inOutFrame) -> {
inOutFrame.inset(win.mGivenContentInsets);
final LayoutParams lp =
win.mAttrs.forRotation(displayFrames.mRotation);
final InsetsFrameProvider ifp =
win.mAttrs.forRotation(displayFrames.mRotation)
.providedInsets[index];
InsetsFrameProvider.calculateInsetsFrame(
displayFrames.mUnrestricted,
windowContainer.getBounds(),
displayFrames.mDisplayCutoutSafe,
inOutFrame, ifp.source,
ifp.insetsSize, lp.privateFlags,
ifp.minimalInsetsSizeInDisplayCutoutSafe);
} : null;
getFrameProvider(win, provider, i);
final InsetsFrameProvider.InsetsSizeOverride[] overrides =
provider.insetsSizeOverrides;
final SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>>
@@ -1267,27 +1179,10 @@ public class DisplayPolicy {
if (overrides != null) {
overrideProviders = new SparseArray<>();
for (int j = overrides.length - 1; j >= 0; j--) {
final int overrideIndex = j;
final TriConsumer<DisplayFrames, WindowContainer, Rect>
overrideFrameProvider =
(displayFrames, windowContainer, inOutFrame) -> {
final LayoutParams lp =
win.mAttrs.forRotation(
displayFrames.mRotation);
final InsetsFrameProvider ifp =
win.mAttrs.providedInsets[index];
InsetsFrameProvider.calculateInsetsFrame(
displayFrames.mUnrestricted,
windowContainer.getBounds(),
displayFrames.mDisplayCutoutSafe,
inOutFrame, ifp.source,
ifp.insetsSizeOverrides[
overrideIndex].insetsSize,
lp.privateFlags,
null);
};
overrideProviders.put(overrides[j].windowType,
overrideFrameProvider);
getOverrideFrameProvider(win, i, j);
overrideProviders.put(overrides[j].windowType, overrideFrameProvider);
}
} else {
overrideProviders = null;
@@ -1299,6 +1194,36 @@ public class DisplayPolicy {
}
}
@Nullable
private TriConsumer<DisplayFrames, WindowContainer, Rect> getFrameProvider(WindowState win,
InsetsFrameProvider provider, int index) {
if (provider.insetsSize == null && provider.source == SOURCE_FRAME) {
return null;
}
return (displayFrames, windowContainer, inOutFrame) -> {
inOutFrame.inset(win.mGivenContentInsets);
final LayoutParams lp = win.mAttrs.forRotation(displayFrames.mRotation);
final InsetsFrameProvider ifp = lp.providedInsets[index];
InsetsFrameProvider.calculateInsetsFrame(displayFrames.mUnrestricted,
windowContainer.getBounds(), displayFrames.mDisplayCutoutSafe, inOutFrame,
ifp.source, ifp.insetsSize, lp.privateFlags,
ifp.minimalInsetsSizeInDisplayCutoutSafe);
};
}
@NonNull
private TriConsumer<DisplayFrames, WindowContainer, Rect> getOverrideFrameProvider(
WindowState win, int index, int overrideIndex) {
return (displayFrames, windowContainer, inOutFrame) -> {
final LayoutParams lp = win.mAttrs.forRotation(displayFrames.mRotation);
final InsetsFrameProvider ifp = lp.providedInsets[index];
InsetsFrameProvider.calculateInsetsFrame(displayFrames.mUnrestricted,
windowContainer.getBounds(), displayFrames.mDisplayCutoutSafe, inOutFrame,
ifp.source, ifp.insetsSizeOverrides[overrideIndex].insetsSize, lp.privateFlags,
null);
};
}
@WindowManagerPolicy.AltBarPosition
private int getAltBarPosition(WindowManager.LayoutParams params) {
switch (params.gravity) {
@@ -1386,16 +1311,6 @@ public class DisplayPolicy {
mInsetsSourceWindowsExceptIme.remove(win);
}
private int getStatusBarHeight(DisplayFrames displayFrames) {
int statusBarHeight;
if (mStatusBar != null) {
statusBarHeight = mStatusBar.mAttrs.forRotation(displayFrames.mRotation).height;
} else {
statusBarHeight = 0;
}
return Math.max(statusBarHeight, displayFrames.mDisplayCutoutSafe.top);
}
WindowState getStatusBar() {
return mStatusBar != null ? mStatusBar : mStatusBarAlt;
}
@@ -1892,27 +1807,12 @@ public class DisplayPolicy {
final Resources res = getCurrentUserResources();
final int portraitRotation = displayRotation.getPortraitRotation();
if (hasStatusBar()) {
mDisplayCutoutTouchableRegionSize = res.getDimensionPixelSize(
R.dimen.display_cutout_touchable_region_size);
} else {
mDisplayCutoutTouchableRegionSize = 0;
}
mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode);
mLeftGestureInset = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
mRightGestureInset = mGestureNavigationSettingsObserver.getRightSensitivity(res);
mNavButtonForcedVisible =
mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
mNavigationBarLetsThroughTaps = res.getBoolean(R.bool.config_navBarTapThrough);
mNavigationBarAlwaysShowOnSideGesture =
res.getBoolean(R.bool.config_navBarAlwaysShowOnSideEdgeGesture);
// This should calculate how much above the frame we accept gestures.
mBottomGestureAdditionalInset =
res.getDimensionPixelSize(R.dimen.navigation_bar_gesture_height)
- getNavigationBarFrameHeight(portraitRotation);
updateConfigurationAndScreenSizeDependentBehaviors();
final boolean shouldAttach =

View File

@@ -266,6 +266,7 @@ import android.view.InputApplicationHandle;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputWindowHandle;
import android.view.InsetsFrameProvider;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.InsetsVisibilities;
@@ -2276,6 +2277,27 @@ public class WindowManagerService extends IWindowManager.Stub
"Insets types can not be changed after the window is "
+ "added.");
}
final InsetsFrameProvider.InsetsSizeOverride[] overrides =
win.mAttrs.providedInsets[i].insetsSizeOverrides;
final InsetsFrameProvider.InsetsSizeOverride[] newOverrides =
attrs.providedInsets[i].insetsSizeOverrides;
if (!(overrides == null && newOverrides == null)) {
if (overrides == null || newOverrides == null
|| (overrides.length != newOverrides.length)) {
throw new IllegalArgumentException(
"Insets override types can not be changed after the "
+ "window is added.");
} else {
final int overrideTypes = overrides.length;
for (int j = 0; j < overrideTypes; j++) {
if (overrides[j].windowType != newOverrides[j].windowType) {
throw new IllegalArgumentException(
"Insets override types can not be changed after"
+ " the window is added.");
}
}
}
}
}
}
}

View File

@@ -19,6 +19,8 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES;
import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
@@ -74,7 +76,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testControlsForDispatch_regular() {
addStatusBar();
addWindow(TYPE_NAVIGATION_BAR, "navBar");
addNavigationBar();
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
@@ -86,7 +88,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testControlsForDispatch_multiWindowTaskVisible() {
addStatusBar();
addWindow(TYPE_NAVIGATION_BAR, "navBar");
addNavigationBar();
final WindowState win = createWindow(null, WINDOWING_MODE_MULTI_WINDOW,
ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app");
@@ -99,7 +101,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testControlsForDispatch_freeformTaskVisible() {
addStatusBar();
addWindow(TYPE_NAVIGATION_BAR, "navBar");
addNavigationBar();
final WindowState win = createWindow(null, WINDOWING_MODE_FREEFORM,
ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app");
@@ -112,7 +114,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testControlsForDispatch_forceStatusBarVisible() {
addStatusBar().mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
addWindow(TYPE_NAVIGATION_BAR, "navBar");
addNavigationBar();
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
@@ -126,7 +128,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade").mAttrs.privateFlags |=
PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
addStatusBar();
addWindow(TYPE_NAVIGATION_BAR, "navBar");
addNavigationBar();
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
@@ -139,7 +141,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
public void testControlsForDispatch_statusBarForceShowNavigation_butFocusedAnyways() {
WindowState notifShade = addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade");
notifShade.mAttrs.privateFlags |= PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
addWindow(TYPE_NAVIGATION_BAR, "navBar");
addNavigationBar();
mDisplayContent.getInsetsPolicy().updateBarControlTarget(notifShade);
InsetsSourceControl[] controls
@@ -155,7 +157,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController());
mDisplayContent.getInsetsPolicy().setRemoteInsetsControllerControlsSystemBars(true);
addStatusBar();
addWindow(TYPE_NAVIGATION_BAR, "navBar");
addNavigationBar();
final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();
@@ -166,7 +168,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testControlsForDispatch_topAppHidesStatusBar() {
addStatusBar();
addWindow(TYPE_NAVIGATION_BAR, "navBar");
addNavigationBar();
// Add a fullscreen (MATCH_PARENT x MATCH_PARENT) app window which hides status bar.
final WindowState fullscreenApp = addWindow(TYPE_APPLICATION, "fullscreenApp");
@@ -261,7 +263,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
final WindowState statusBar = addStatusBar();
statusBar.setHasSurface(true);
statusBar.getControllableInsetProvider().setServerVisible(true);
final WindowState navBar = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar");
final WindowState navBar = addNavigationBar();
navBar.setHasSurface(true);
navBar.getControllableInsetProvider().setServerVisible(true);
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
@@ -301,8 +303,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testShowTransientBars_statusBarCanBeTransient_appGetsStatusBarFakeControl() {
addStatusBar().getControllableInsetProvider().getSource().setVisible(false);
addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().setServerVisible(true);
addNavigationBar().getControllableInsetProvider().setServerVisible(true);
final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy());
doNothing().when(policy).startAnimation(anyBoolean(), any());
@@ -331,8 +332,8 @@ public class InsetsPolicyTest extends WindowTestsBase {
public void testAbortTransientBars_bothCanBeAborted_appGetsBothRealControls() {
final InsetsSource statusBarSource =
addStatusBar().getControllableInsetProvider().getSource();
final InsetsSource navBarSource = addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource();
final InsetsSource navBarSource =
addNavigationBar().getControllableInsetProvider().getSource();
statusBarSource.setVisible(false);
navBarSource.setVisible(false);
mAppWindow.mAboveInsetsState.addSource(navBarSource);
@@ -383,8 +384,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testShowTransientBars_abortsWhenControlTargetChanges() {
addStatusBar().getControllableInsetProvider().getSource().setVisible(false);
addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource().setVisible(false);
addNavigationBar().getControllableInsetProvider().getSource().setVisible(false);
final WindowState app = addWindow(TYPE_APPLICATION, "app");
final WindowState app2 = addWindow(TYPE_APPLICATION, "app");
@@ -400,9 +400,15 @@ public class InsetsPolicyTest extends WindowTestsBase {
assertFalse(policy.isTransient(ITYPE_NAVIGATION_BAR));
}
private WindowState addNonFocusableWindow(int type, String name) {
WindowState win = addWindow(type, name);
private WindowState addNavigationBar() {
final WindowState win = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");
win.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
win.mAttrs.providedInsets = new InsetsFrameProvider[] {
new InsetsFrameProvider(ITYPE_NAVIGATION_BAR),
new InsetsFrameProvider(ITYPE_BOTTOM_MANDATORY_GESTURES),
new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT)
};
mDisplayContent.getDisplayPolicy().addWindowLw(win, win.mAttrs);
return win;
}
@@ -429,6 +435,10 @@ public class InsetsPolicyTest extends WindowTestsBase {
}
private InsetsSourceControl[] addWindowAndGetControlsForDispatch(WindowState win) {
mDisplayContent.getDisplayPolicy().addWindowLw(win, win.mAttrs);
// Force update the focus in DisplayPolicy here. Otherwise, without server side focus
// update, the policy relying on windowing type will never get updated.
mDisplayContent.getDisplayPolicy().focusChangedLw(null, win);
mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);
return mDisplayContent.getInsetsStateController().getControlsForDispatch(win);
}

View File

@@ -26,6 +26,8 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.os.Process.SYSTEM_UID;
import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES;
import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES;
@@ -347,6 +349,11 @@ class WindowTestsBase extends SystemServiceTestsBase {
LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
mNavBarWindow.mAttrs.privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
mNavBarWindow.mAttrs.providedInsets = new InsetsFrameProvider[] {
new InsetsFrameProvider(ITYPE_NAVIGATION_BAR),
new InsetsFrameProvider(ITYPE_BOTTOM_MANDATORY_GESTURES),
new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT)
};
for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
mNavBarWindow.mAttrs.paramsForRotation[rot] =
getNavBarLayoutParamsForRotation(rot);
@@ -400,6 +407,11 @@ class WindowTestsBase extends SystemServiceTestsBase {
lp.privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
lp.providedInsets = new InsetsFrameProvider[] {
new InsetsFrameProvider(ITYPE_NAVIGATION_BAR),
new InsetsFrameProvider(ITYPE_BOTTOM_MANDATORY_GESTURES),
new InsetsFrameProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT)
};
return lp;
}