Introduce Client Transient flag (1/n)
This is a feature flag to develop transient related features on the system UI side. Currently it's handled by the system server. This change introduced the flag and set it by default to false, in the meanwhile, wrapped existing server side logic with the flag to make the future clean-up easier. If the flag is flipped without system UI side feature complete, the transient animation will not work. Other insets related functionality will not be affected. SystemGesturesPointerEventListener should be simplified or changed to a class instead of an interface with the feature development. Bug: 277290737 Test: DisplayPolicyTests Test: DisplayPolicyInsetsTests Change-Id: I243407d233d71b40807d29660090e674b8dd5d31
This commit is contained in:
@@ -300,6 +300,14 @@ public final class ViewRootImpl implements ViewParent,
|
||||
public static final boolean CAPTION_ON_SHELL =
|
||||
SystemProperties.getBoolean("persist.wm.debug.caption_on_shell", true);
|
||||
|
||||
/**
|
||||
* Whether the client (system UI) is handling the transient gesture and the corresponding
|
||||
* animation.
|
||||
* @hide
|
||||
*/
|
||||
public static final boolean CLIENT_TRANSIENT =
|
||||
SystemProperties.getBoolean("persist.wm.debug.client_transient", false);
|
||||
|
||||
/**
|
||||
* Whether the client should compute the window frame on its own.
|
||||
* @hide
|
||||
|
||||
@@ -22,6 +22,7 @@ import static android.view.InsetsFrameProvider.SOURCE_ARBITRARY_RECTANGLE;
|
||||
import static android.view.InsetsFrameProvider.SOURCE_CONTAINER_BOUNDS;
|
||||
import static android.view.InsetsFrameProvider.SOURCE_DISPLAY;
|
||||
import static android.view.InsetsFrameProvider.SOURCE_FRAME;
|
||||
import static android.view.ViewRootImpl.CLIENT_TRANSIENT;
|
||||
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
|
||||
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
|
||||
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
|
||||
@@ -214,7 +215,8 @@ public class DisplayPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
private final SystemGesturesPointerEventListener mSystemGestures;
|
||||
// Will be null in client transient mode.
|
||||
private SystemGesturesPointerEventListener mSystemGestures;
|
||||
|
||||
final DecorInsets mDecorInsets;
|
||||
|
||||
@@ -411,158 +413,162 @@ public class DisplayPolicy {
|
||||
final Looper looper = UiThread.getHandler().getLooper();
|
||||
mHandler = new PolicyHandler(looper);
|
||||
// TODO(b/181821798) Migrate SystemGesturesPointerEventListener to use window context.
|
||||
mSystemGestures = new SystemGesturesPointerEventListener(mUiContext, mHandler,
|
||||
new SystemGesturesPointerEventListener.Callbacks() {
|
||||
if (!CLIENT_TRANSIENT) {
|
||||
SystemGesturesPointerEventListener.Callbacks gesturesPointerEventCallbacks =
|
||||
new SystemGesturesPointerEventListener.Callbacks() {
|
||||
|
||||
private static final long MOUSE_GESTURE_DELAY_MS = 500;
|
||||
private static final long MOUSE_GESTURE_DELAY_MS = 500;
|
||||
|
||||
private Runnable mOnSwipeFromLeft = this::onSwipeFromLeft;
|
||||
private Runnable mOnSwipeFromTop = this::onSwipeFromTop;
|
||||
private Runnable mOnSwipeFromRight = this::onSwipeFromRight;
|
||||
private Runnable mOnSwipeFromBottom = this::onSwipeFromBottom;
|
||||
private Runnable mOnSwipeFromLeft = this::onSwipeFromLeft;
|
||||
private Runnable mOnSwipeFromTop = this::onSwipeFromTop;
|
||||
private Runnable mOnSwipeFromRight = this::onSwipeFromRight;
|
||||
private Runnable mOnSwipeFromBottom = this::onSwipeFromBottom;
|
||||
|
||||
private Insets getControllableInsets(WindowState win) {
|
||||
if (win == null) {
|
||||
return Insets.NONE;
|
||||
}
|
||||
final InsetsSourceProvider provider = win.getControllableInsetProvider();
|
||||
if (provider == null) {
|
||||
return Insets.NONE;
|
||||
}
|
||||
return provider.getSource().calculateInsets(win.getBounds(),
|
||||
true /* ignoreVisibility */);
|
||||
private Insets getControllableInsets(WindowState win) {
|
||||
if (win == null) {
|
||||
return Insets.NONE;
|
||||
}
|
||||
final InsetsSourceProvider provider = win.getControllableInsetProvider();
|
||||
if (provider == null) {
|
||||
return Insets.NONE;
|
||||
}
|
||||
return provider.getSource().calculateInsets(win.getBounds(),
|
||||
true /* ignoreVisibility */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwipeFromTop() {
|
||||
synchronized (mLock) {
|
||||
requestTransientBars(mTopGestureHost,
|
||||
getControllableInsets(mTopGestureHost).top > 0);
|
||||
@Override
|
||||
public void onSwipeFromTop() {
|
||||
synchronized (mLock) {
|
||||
requestTransientBars(mTopGestureHost,
|
||||
getControllableInsets(mTopGestureHost).top > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwipeFromBottom() {
|
||||
synchronized (mLock) {
|
||||
requestTransientBars(mBottomGestureHost,
|
||||
getControllableInsets(mBottomGestureHost).bottom > 0);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean allowsSideSwipe(Region excludedRegion) {
|
||||
return mNavigationBarAlwaysShowOnSideGesture
|
||||
&& !mSystemGestures.currentGestureStartedInRegion(excludedRegion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwipeFromRight() {
|
||||
final Region excludedRegion = Region.obtain();
|
||||
synchronized (mLock) {
|
||||
mDisplayContent.calculateSystemGestureExclusion(
|
||||
excludedRegion, null /* outUnrestricted */);
|
||||
final boolean hasWindow =
|
||||
getControllableInsets(mRightGestureHost).right > 0;
|
||||
if (hasWindow || allowsSideSwipe(excludedRegion)) {
|
||||
requestTransientBars(mRightGestureHost, hasWindow);
|
||||
}
|
||||
}
|
||||
excludedRegion.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwipeFromBottom() {
|
||||
synchronized (mLock) {
|
||||
requestTransientBars(mBottomGestureHost,
|
||||
getControllableInsets(mBottomGestureHost).bottom > 0);
|
||||
@Override
|
||||
public void onSwipeFromLeft() {
|
||||
final Region excludedRegion = Region.obtain();
|
||||
synchronized (mLock) {
|
||||
mDisplayContent.calculateSystemGestureExclusion(
|
||||
excludedRegion, null /* outUnrestricted */);
|
||||
final boolean hasWindow =
|
||||
getControllableInsets(mLeftGestureHost).left > 0;
|
||||
if (hasWindow || allowsSideSwipe(excludedRegion)) {
|
||||
requestTransientBars(mLeftGestureHost, hasWindow);
|
||||
}
|
||||
}
|
||||
excludedRegion.recycle();
|
||||
}
|
||||
|
||||
private boolean allowsSideSwipe(Region excludedRegion) {
|
||||
return mNavigationBarAlwaysShowOnSideGesture
|
||||
&& !mSystemGestures.currentGestureStartedInRegion(excludedRegion);
|
||||
@Override
|
||||
public void onFling(int duration) {
|
||||
if (mService.mPowerManagerInternal != null) {
|
||||
mService.mPowerManagerInternal.setPowerBoost(
|
||||
Boost.INTERACTION, duration);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwipeFromRight() {
|
||||
final Region excludedRegion = Region.obtain();
|
||||
synchronized (mLock) {
|
||||
mDisplayContent.calculateSystemGestureExclusion(
|
||||
excludedRegion, null /* outUnrestricted */);
|
||||
final boolean hasWindow =
|
||||
getControllableInsets(mRightGestureHost).right > 0;
|
||||
if (hasWindow || allowsSideSwipe(excludedRegion)) {
|
||||
requestTransientBars(mRightGestureHost, hasWindow);
|
||||
}
|
||||
}
|
||||
excludedRegion.recycle();
|
||||
}
|
||||
@Override
|
||||
public void onDebug() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwipeFromLeft() {
|
||||
final Region excludedRegion = Region.obtain();
|
||||
synchronized (mLock) {
|
||||
mDisplayContent.calculateSystemGestureExclusion(
|
||||
excludedRegion, null /* outUnrestricted */);
|
||||
final boolean hasWindow =
|
||||
getControllableInsets(mLeftGestureHost).left > 0;
|
||||
if (hasWindow || allowsSideSwipe(excludedRegion)) {
|
||||
requestTransientBars(mLeftGestureHost, hasWindow);
|
||||
}
|
||||
}
|
||||
excludedRegion.recycle();
|
||||
}
|
||||
private WindowOrientationListener getOrientationListener() {
|
||||
final DisplayRotation rotation = mDisplayContent.getDisplayRotation();
|
||||
return rotation != null ? rotation.getOrientationListener() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFling(int duration) {
|
||||
if (mService.mPowerManagerInternal != null) {
|
||||
mService.mPowerManagerInternal.setPowerBoost(
|
||||
Boost.INTERACTION, duration);
|
||||
}
|
||||
@Override
|
||||
public void onDown() {
|
||||
final WindowOrientationListener listener = getOrientationListener();
|
||||
if (listener != null) {
|
||||
listener.onTouchStart();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDebug() {
|
||||
// no-op
|
||||
@Override
|
||||
public void onUpOrCancel() {
|
||||
final WindowOrientationListener listener = getOrientationListener();
|
||||
if (listener != null) {
|
||||
listener.onTouchEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private WindowOrientationListener getOrientationListener() {
|
||||
final DisplayRotation rotation = mDisplayContent.getDisplayRotation();
|
||||
return rotation != null ? rotation.getOrientationListener() : null;
|
||||
}
|
||||
@Override
|
||||
public void onMouseHoverAtLeft() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromLeft);
|
||||
mHandler.postDelayed(mOnSwipeFromLeft, MOUSE_GESTURE_DELAY_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDown() {
|
||||
final WindowOrientationListener listener = getOrientationListener();
|
||||
if (listener != null) {
|
||||
listener.onTouchStart();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onMouseHoverAtTop() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromTop);
|
||||
mHandler.postDelayed(mOnSwipeFromTop, MOUSE_GESTURE_DELAY_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpOrCancel() {
|
||||
final WindowOrientationListener listener = getOrientationListener();
|
||||
if (listener != null) {
|
||||
listener.onTouchEnd();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onMouseHoverAtRight() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromRight);
|
||||
mHandler.postDelayed(mOnSwipeFromRight, MOUSE_GESTURE_DELAY_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseHoverAtLeft() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromLeft);
|
||||
mHandler.postDelayed(mOnSwipeFromLeft, MOUSE_GESTURE_DELAY_MS);
|
||||
}
|
||||
@Override
|
||||
public void onMouseHoverAtBottom() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromBottom);
|
||||
mHandler.postDelayed(mOnSwipeFromBottom, MOUSE_GESTURE_DELAY_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseHoverAtTop() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromTop);
|
||||
mHandler.postDelayed(mOnSwipeFromTop, MOUSE_GESTURE_DELAY_MS);
|
||||
}
|
||||
@Override
|
||||
public void onMouseLeaveFromLeft() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromLeft);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseHoverAtRight() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromRight);
|
||||
mHandler.postDelayed(mOnSwipeFromRight, MOUSE_GESTURE_DELAY_MS);
|
||||
}
|
||||
@Override
|
||||
public void onMouseLeaveFromTop() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromTop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseHoverAtBottom() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromBottom);
|
||||
mHandler.postDelayed(mOnSwipeFromBottom, MOUSE_GESTURE_DELAY_MS);
|
||||
}
|
||||
@Override
|
||||
public void onMouseLeaveFromRight() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromRight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseLeaveFromLeft() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromLeft);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseLeaveFromTop() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromTop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseLeaveFromRight() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromRight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseLeaveFromBottom() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromBottom);
|
||||
}
|
||||
});
|
||||
displayContent.registerPointerEventListener(mSystemGestures);
|
||||
@Override
|
||||
public void onMouseLeaveFromBottom() {
|
||||
mHandler.removeCallbacks(mOnSwipeFromBottom);
|
||||
}
|
||||
};
|
||||
mSystemGestures = new SystemGesturesPointerEventListener(mUiContext, mHandler,
|
||||
gesturesPointerEventCallbacks);
|
||||
displayContent.registerPointerEventListener(mSystemGestures);
|
||||
}
|
||||
mAppTransitionListener = new WindowManagerInternal.AppTransitionListener() {
|
||||
|
||||
private Runnable mAppTransitionPending = () -> {
|
||||
@@ -648,7 +654,9 @@ public class DisplayPolicy {
|
||||
mContext, () -> {
|
||||
synchronized (mLock) {
|
||||
onConfigurationChanged();
|
||||
mSystemGestures.onConfigurationChanged();
|
||||
if (!CLIENT_TRANSIENT) {
|
||||
mSystemGestures.onConfigurationChanged();
|
||||
}
|
||||
mDisplayContent.updateSystemGestureExclusion();
|
||||
}
|
||||
});
|
||||
@@ -670,7 +678,9 @@ public class DisplayPolicy {
|
||||
}
|
||||
|
||||
void systemReady() {
|
||||
mSystemGestures.systemReady();
|
||||
if (!CLIENT_TRANSIENT) {
|
||||
mSystemGestures.systemReady();
|
||||
}
|
||||
if (mService.mPointerLocationEnabled) {
|
||||
setPointerLocationEnabled(true);
|
||||
}
|
||||
@@ -1317,7 +1327,9 @@ public class DisplayPolicy {
|
||||
}
|
||||
|
||||
void onDisplayInfoChanged(DisplayInfo info) {
|
||||
mSystemGestures.onDisplayInfoChanged(info);
|
||||
if (!CLIENT_TRANSIENT) {
|
||||
mSystemGestures.onDisplayInfoChanged(info);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1690,7 +1702,9 @@ public class DisplayPolicy {
|
||||
// Update the latest display size, cutout.
|
||||
mDisplayContent.updateDisplayInfo();
|
||||
onConfigurationChanged();
|
||||
mSystemGestures.onConfigurationChanged();
|
||||
if (!CLIENT_TRANSIENT) {
|
||||
mSystemGestures.onConfigurationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1963,6 +1977,9 @@ public class DisplayPolicy {
|
||||
|
||||
@VisibleForTesting
|
||||
void requestTransientBars(WindowState swipeTarget, boolean isGestureOnSystemBar) {
|
||||
if (CLIENT_TRANSIENT) {
|
||||
return;
|
||||
}
|
||||
if (swipeTarget == null || !mService.mPolicy.isUserSetupComplete()) {
|
||||
// Swipe-up for navigation bar is disabled during setup
|
||||
return;
|
||||
@@ -2613,7 +2630,9 @@ public class DisplayPolicy {
|
||||
final DecorInsets.Info info = mDecorInsets.mInfoForRotation[rotation];
|
||||
pw.println(prefixInner + Surface.rotationToString(rotation) + "=" + info);
|
||||
}
|
||||
mSystemGestures.dump(pw, prefix);
|
||||
if (!CLIENT_TRANSIENT) {
|
||||
mSystemGestures.dump(pw, prefix);
|
||||
}
|
||||
|
||||
pw.print(prefix); pw.println("Looper state:");
|
||||
mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + " ");
|
||||
|
||||
@@ -22,6 +22,7 @@ import static android.view.RoundedCorners.NO_ROUNDED_CORNERS;
|
||||
import static android.view.Surface.ROTATION_0;
|
||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
import static android.view.ViewRootImpl.CLIENT_TRANSIENT;
|
||||
import static android.view.WindowInsets.Type.navigationBars;
|
||||
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
|
||||
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
|
||||
@@ -61,6 +62,7 @@ import android.view.WindowManager;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@@ -379,6 +381,7 @@ public class DisplayPolicyTests extends WindowTestsBase {
|
||||
@SetupWindows(addWindows = { W_ACTIVITY, W_NAVIGATION_BAR })
|
||||
@Test
|
||||
public void testCanSystemBarsBeShownByUser() {
|
||||
Assume.assumeFalse(CLIENT_TRANSIENT);
|
||||
((TestWindowManagerPolicy) mWm.mPolicy).mIsUserSetupComplete = true;
|
||||
mAppWindow.mAttrs.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
|
||||
mAppWindow.setRequestedVisibleTypes(0, navigationBars());
|
||||
@@ -400,6 +403,7 @@ public class DisplayPolicyTests extends WindowTestsBase {
|
||||
@UseTestDisplay(addWindows = { W_NAVIGATION_BAR })
|
||||
@Test
|
||||
public void testTransientBarsSuppressedOnDreams() {
|
||||
Assume.assumeFalse(CLIENT_TRANSIENT);
|
||||
final WindowState win = createDreamWindow();
|
||||
|
||||
((TestWindowManagerPolicy) mWm.mPolicy).mIsUserSetupComplete = true;
|
||||
|
||||
Reference in New Issue
Block a user