Migrate SystemGesturePointerEventListener to WindowContext

Previously system context derived display context passed to
SystemGesturePointerEventListener.
After R, it threw IncorrectContextUsageViolation when initialization
because display context is not a UI context.

This CL changes to pass window context to fix the Violation.

Bug: 177650348
Test: atest WmTests
Test: atest DisplayPolicyTests#testDisplayPolicyNoCrash

Change-Id: I0d17327d8a8c14ec626c0dd9ad1a4e8529174598
This commit is contained in:
Charles Chen
2021-01-18 14:27:42 +08:00
parent caf9ae8b52
commit 68c3024767
4 changed files with 173 additions and 137 deletions

View File

@@ -67,6 +67,7 @@ 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;
import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
@@ -240,7 +241,7 @@ public class DisplayPolicy {
}
}
private final SystemGesturesPointerEventListener mSystemGestures;
private SystemGesturesPointerEventListener mSystemGestures;
private volatile int mLidState = LID_ABSENT;
private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
@@ -382,7 +383,7 @@ public class DisplayPolicy {
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
private GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
private final WindowManagerInternal.AppTransitionListener mAppTransitionListener;
@@ -446,119 +447,6 @@ public class DisplayPolicy {
final Looper looper = UiThread.getHandler().getLooper();
mHandler = new PolicyHandler(looper);
mSystemGestures = new SystemGesturesPointerEventListener(mContext, mHandler,
new SystemGesturesPointerEventListener.Callbacks() {
@Override
public void onSwipeFromTop() {
synchronized (mLock) {
if (mStatusBar != null) {
requestTransientBars(mStatusBar);
}
checkAltBarSwipeForTransientBars(ALT_BAR_TOP);
}
}
@Override
public void onSwipeFromBottom() {
synchronized (mLock) {
if (mNavigationBar != null
&& mNavigationBarPosition == NAV_BAR_BOTTOM) {
requestTransientBars(mNavigationBar);
}
checkAltBarSwipeForTransientBars(ALT_BAR_BOTTOM);
}
}
@Override
public void onSwipeFromRight() {
final Region excludedRegion = Region.obtain();
synchronized (mLock) {
mDisplayContent.calculateSystemGestureExclusion(
excludedRegion, null /* outUnrestricted */);
final boolean excluded =
mSystemGestures.currentGestureStartedInRegion(excludedRegion);
if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_RIGHT
|| !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
requestTransientBars(mNavigationBar);
}
checkAltBarSwipeForTransientBars(ALT_BAR_RIGHT);
}
excludedRegion.recycle();
}
@Override
public void onSwipeFromLeft() {
final Region excludedRegion = Region.obtain();
synchronized (mLock) {
mDisplayContent.calculateSystemGestureExclusion(
excludedRegion, null /* outUnrestricted */);
final boolean excluded =
mSystemGestures.currentGestureStartedInRegion(excludedRegion);
if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_LEFT
|| !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
requestTransientBars(mNavigationBar);
}
checkAltBarSwipeForTransientBars(ALT_BAR_LEFT);
}
excludedRegion.recycle();
}
@Override
public void onFling(int duration) {
if (mService.mPowerManagerInternal != null) {
mService.mPowerManagerInternal.setPowerBoost(
Boost.INTERACTION, duration);
}
}
@Override
public void onDebug() {
// no-op
}
private WindowOrientationListener getOrientationListener() {
final DisplayRotation rotation = mDisplayContent.getDisplayRotation();
return rotation != null ? rotation.getOrientationListener() : null;
}
@Override
public void onDown() {
final WindowOrientationListener listener = getOrientationListener();
if (listener != null) {
listener.onTouchStart();
}
}
@Override
public void onUpOrCancel() {
final WindowOrientationListener listener = getOrientationListener();
if (listener != null) {
listener.onTouchEnd();
}
}
@Override
public void onMouseHoverAtTop() {
mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
}
@Override
public void onMouseHoverAtBottom() {
mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
}
@Override
public void onMouseLeaveFromEdge() {
mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
}
});
displayContent.registerPointerEventListener(mSystemGestures);
mAppTransitionListener = new WindowManagerInternal.AppTransitionListener() {
private Runnable mAppTransitionPending = () -> {
@@ -614,7 +502,7 @@ public class DisplayPolicy {
mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext, looper,
mService.mVrModeEnabled);
// TODO: Make it can take screenshot on external display
// TODO(b/180986447): Make it can take screenshot on external display
mScreenshotHelper = displayContent.isDefaultDisplay
? new ScreenshotHelper(mContext) : null;
@@ -638,16 +526,6 @@ public class DisplayPolicy {
mRefreshRatePolicy = new RefreshRatePolicy(mService,
mDisplayContent.getDisplayInfo(),
mService.mHighRefreshRateDenylist);
mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(mHandler,
mContext, () -> {
synchronized (mLock) {
onConfigurationChanged();
mSystemGestures.onConfigurationChanged();
mDisplayContent.updateSystemGestureExclusion();
}
});
mHandler.post(mGestureNavigationSettingsObserver::register);
}
private void checkAltBarSwipeForTransientBars(@WindowManagerPolicy.AltBarPosition int pos) {
@@ -666,12 +544,154 @@ public class DisplayPolicy {
}
void systemReady() {
mSystemGestures.systemReady();
if (mService.mPointerLocationEnabled) {
setPointerLocationEnabled(true);
}
}
@NonNull
private GestureNavigationSettingsObserver getGestureNavigationSettingsObserver() {
if (mGestureNavigationSettingsObserver == null) {
mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(mHandler,
mContext, () -> {
synchronized (mLock) {
onConfigurationChanged();
getSystemGestures().onConfigurationChanged();
mDisplayContent.updateSystemGestureExclusion();
}
});
mHandler.post(mGestureNavigationSettingsObserver::register);
}
return mGestureNavigationSettingsObserver;
}
@NonNull
private SystemGesturesPointerEventListener getSystemGestures() {
if (mSystemGestures == null) {
final Context gestureContext = mUiContext.createWindowContext(
mDisplayContent.getDisplay(), TYPE_POINTER, null /* options */);
mSystemGestures = new SystemGesturesPointerEventListener(gestureContext, mHandler,
new SystemGesturesPointerEventListener.Callbacks() {
@Override
public void onSwipeFromTop() {
synchronized (mLock) {
if (mStatusBar != null) {
requestTransientBars(mStatusBar);
}
checkAltBarSwipeForTransientBars(ALT_BAR_TOP);
}
}
@Override
public void onSwipeFromBottom() {
synchronized (mLock) {
if (mNavigationBar != null
&& mNavigationBarPosition == NAV_BAR_BOTTOM) {
requestTransientBars(mNavigationBar);
}
checkAltBarSwipeForTransientBars(ALT_BAR_BOTTOM);
}
}
@Override
public void onSwipeFromRight() {
final Region excludedRegion = Region.obtain();
synchronized (mLock) {
mDisplayContent.calculateSystemGestureExclusion(
excludedRegion, null /* outUnrestricted */);
final boolean excluded = mSystemGestures
.currentGestureStartedInRegion(excludedRegion);
if (mNavigationBar != null
&& (mNavigationBarPosition == NAV_BAR_RIGHT
|| !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
requestTransientBars(mNavigationBar);
}
checkAltBarSwipeForTransientBars(ALT_BAR_RIGHT);
}
excludedRegion.recycle();
}
@Override
public void onSwipeFromLeft() {
final Region excludedRegion = Region.obtain();
synchronized (mLock) {
mDisplayContent.calculateSystemGestureExclusion(
excludedRegion, null /* outUnrestricted */);
final boolean excluded = mSystemGestures
.currentGestureStartedInRegion(excludedRegion);
if (mNavigationBar != null
&& (mNavigationBarPosition == NAV_BAR_LEFT
|| !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
requestTransientBars(mNavigationBar);
}
checkAltBarSwipeForTransientBars(ALT_BAR_LEFT);
}
excludedRegion.recycle();
}
@Override
public void onFling(int duration) {
if (mService.mPowerManagerInternal != null) {
mService.mPowerManagerInternal.setPowerBoost(
Boost.INTERACTION, duration);
}
}
@Override
public void onDebug() {
// no-op
}
private WindowOrientationListener getOrientationListener() {
final DisplayRotation rotation = mDisplayContent.getDisplayRotation();
return rotation != null ? rotation.getOrientationListener() : null;
}
@Override
public void onDown() {
final WindowOrientationListener listener = getOrientationListener();
if (listener != null) {
listener.onTouchStart();
}
}
@Override
public void onUpOrCancel() {
final WindowOrientationListener listener = getOrientationListener();
if (listener != null) {
listener.onTouchEnd();
}
}
@Override
public void onMouseHoverAtTop() {
mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
}
@Override
public void onMouseHoverAtBottom() {
mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
}
@Override
public void onMouseLeaveFromEdge() {
mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
}
});
mDisplayContent.registerPointerEventListener(getSystemGestures());
if (mService.mSystemReady) {
mSystemGestures.systemReady();
}
}
return mSystemGestures;
}
private int getDisplayId() {
return mDisplayContent.getDisplayId();
}
@@ -1447,8 +1467,7 @@ public class DisplayPolicy {
}
void onDisplayInfoChanged(DisplayInfo info) {
mSystemGestures.screenWidth = info.logicalWidth;
mSystemGestures.screenHeight = info.logicalHeight;
getSystemGestures().onDisplayInfoChanged(info);
}
private void layoutStatusBar(DisplayFrames displayFrames, Rect contentFrame) {
@@ -1961,7 +1980,7 @@ public class DisplayPolicy {
public void onOverlayChangedLw() {
updateCurrentUserResources();
onConfigurationChanged();
mSystemGestures.onConfigurationChanged();
getSystemGestures().onConfigurationChanged();
}
/**
@@ -2032,10 +2051,10 @@ public class DisplayPolicy {
}
mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode);
mLeftGestureInset = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
mRightGestureInset = mGestureNavigationSettingsObserver.getRightSensitivity(res);
mNavButtonForcedVisible =
mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
final GestureNavigationSettingsObserver observer = getGestureNavigationSettingsObserver();
mLeftGestureInset = observer.getLeftSensitivity(res);
mRightGestureInset = observer.getRightSensitivity(res);
mNavButtonForcedVisible = observer.areNavigationButtonForcedVisible();
mNavigationBarLetsThroughTaps = res.getBoolean(R.bool.config_navBarTapThrough);
mNavigationBarAlwaysShowOnSideGesture =
res.getBoolean(R.bool.config_navBarAlwaysShowOnSideEdgeGesture);
@@ -3047,7 +3066,7 @@ public class DisplayPolicy {
}
void release() {
mHandler.post(mGestureNavigationSettingsObserver::unregister);
mHandler.post(getGestureNavigationSettingsObserver()::unregister);
}
@VisibleForTesting

View File

@@ -126,11 +126,17 @@ class SystemGesturesPointerEventListener implements PointerEventListener {
Slog.w(TAG, "Cannot create GestureDetector, display removed:" + displayId);
return;
}
onDisplayInfoChanged(info);
mGestureDetector = new GestureDetector(mContext, new FlingGestureDetector(), mHandler) {
};
});
}
void onDisplayInfoChanged(DisplayInfo info) {
screenWidth = info.logicalWidth;
screenHeight = info.logicalHeight;
}
@Override
public void onPointerEvent(MotionEvent event) {
if (mGestureDetector != null && event.isTouchEvent()) {

View File

@@ -321,4 +321,16 @@ public class DisplayPolicyTests extends WindowTestsBase {
assertFalse(navBarSource.getFrame().isEmpty());
assertTrue(imeSource.getFrame().contains(navBarSource.getFrame()));
}
@UseTestDisplay
@Test
public void testDisplayPolicyNotCrash() {
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
// Verify if modules initialized after DisplayContent ctr throws NPE.
displayPolicy.onDisplayInfoChanged(mDisplayInfo);
displayPolicy.onConfigurationChanged();
displayPolicy.onOverlayChangedLw();
displayPolicy.release();
}
}

View File

@@ -538,9 +538,8 @@ class WindowTestsBase extends SystemServiceTestsBase {
/** Creates a {@link DisplayContent} and adds it to the system. */
private DisplayContent createNewDisplay(DisplayInfo info, @DisplayImePolicy int imePolicy) {
final DisplayContent display =
final DisplayContent dc =
new TestDisplayContent.Builder(mAtm, info).build();
final DisplayContent dc = display.mDisplayContent;
// this display can show IME.
dc.mWmService.mDisplayWindowSettings.setDisplayImePolicy(dc, imePolicy);
return dc;