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:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user