Loading packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java +83 −3 Original line number Diff line number Diff line Loading @@ -63,7 +63,6 @@ import org.mockito.MockitoAnnotations; import java.util.Collections; import java.util.Optional; @SmallTest @RunWith(AndroidJUnit4.class) public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { Loading Loading @@ -119,6 +118,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { private static final float TOUCH_REGION = .3f; private static final int SCREEN_WIDTH_PX = 1024; private static final int SCREEN_HEIGHT_PX = 100; private static final float MIN_BOUNCER_HEIGHT = .05f; private static final Rect SCREEN_BOUNDS = new Rect(0, 0, 1024, 100); private static final UserInfo CURRENT_USER_INFO = new UserInfo( Loading @@ -142,6 +142,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { mFlingAnimationUtils, mFlingAnimationUtilsClosing, TOUCH_REGION, MIN_BOUNCER_HEIGHT, mUiEventLogger); when(mScrimManager.getCurrentController()).thenReturn(mScrimController); Loading @@ -160,9 +161,9 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { */ @Test public void testSessionStart() { mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion); mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, null); verify(mRegion).op(mRectCaptor.capture(), eq(Region.Op.UNION)); verify(mRegion).union(mRectCaptor.capture()); final Rect bounds = mRectCaptor.getValue(); final Rect expected = new Rect(); Loading Loading @@ -194,6 +195,85 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { UP, } @Test public void testSwipeUp_whenBouncerInitiallyShowing_reduceHeightWithExclusionRects() { mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, new Rect(0, 0, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX)); verify(mRegion).union(mRectCaptor.capture()); final Rect bounds = mRectCaptor.getValue(); final Rect expected = new Rect(); final float minBouncerHeight = SCREEN_HEIGHT_PX * MIN_BOUNCER_HEIGHT; final int minAllowableBottom = SCREEN_HEIGHT_PX - Math.round(minBouncerHeight); expected.set(0, minAllowableBottom , SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX); assertThat(bounds).isEqualTo(expected); onSessionStartHelper(mTouchHandler, mTouchSession, mNotificationShadeWindowController); } @Test public void testSwipeUp_exclusionRectAtTop_doesNotIntersectGestureArea() { mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, new Rect(0, 0, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX / 4)); verify(mRegion).union(mRectCaptor.capture()); final Rect bounds = mRectCaptor.getValue(); final Rect expected = new Rect(); final int gestureAreaTop = SCREEN_HEIGHT_PX - Math.round(SCREEN_HEIGHT_PX * TOUCH_REGION); expected.set(0, gestureAreaTop, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX); assertThat(bounds).isEqualTo(expected); onSessionStartHelper(mTouchHandler, mTouchSession, mNotificationShadeWindowController); } @Test public void testSwipeUp_exclusionRectBetweenNormalAndMinimumSwipeArea() { final int normalSwipeAreaTop = SCREEN_HEIGHT_PX - Math.round(SCREEN_HEIGHT_PX * TOUCH_REGION); final int minimumSwipeAreaTop = SCREEN_HEIGHT_PX - Math.round(SCREEN_HEIGHT_PX * MIN_BOUNCER_HEIGHT); Rect exclusionRect = new Rect(0, 0, SCREEN_WIDTH_PX, (normalSwipeAreaTop + minimumSwipeAreaTop) / 2); mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, exclusionRect); verify(mRegion).union(mRectCaptor.capture()); final Rect bounds = mRectCaptor.getValue(); final Rect expected = new Rect(); final int expectedSwipeAreaBottom = exclusionRect.bottom; expected.set(0, expectedSwipeAreaBottom, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX); assertThat(bounds).isEqualTo(expected); onSessionStartHelper(mTouchHandler, mTouchSession, mNotificationShadeWindowController); } private static void onSessionStartHelper(BouncerSwipeTouchHandler touchHandler, DreamTouchHandler.TouchSession touchSession, NotificationShadeWindowController notificationShadeWindowController) { touchHandler.onSessionStart(touchSession); verify(notificationShadeWindowController).setForcePluginOpen(eq(true), any()); ArgumentCaptor<InputChannelCompat.InputEventListener> eventListenerCaptor = ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class); ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor = ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class); verify(touchSession).registerGestureListener(gestureListenerCaptor.capture()); verify(touchSession).registerInputListener(eventListenerCaptor.capture()); // A touch within range at the bottom of the screen should trigger listening assertThat(gestureListenerCaptor.getValue() .onScroll(Mockito.mock(MotionEvent.class), Mockito.mock(MotionEvent.class), 1, 2)).isTrue(); } /** * Makes sure swiping up when bouncer initially showing doesn't change the expansion amount. */ Loading packages/SystemUI/res/values/dimens.xml +4 −0 Original line number Diff line number Diff line Loading @@ -1867,6 +1867,10 @@ .2 </item> <item name="dream_overlay_bouncer_min_region_screen_percentage" format="float" type="dimen"> .05 </item> <!-- The padding applied to the dream overlay container --> <dimen name="dream_overlay_container_padding_start">0dp</dimen> <dimen name="dream_overlay_container_padding_end">0dp</dimen> Loading packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java +20 −13 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.dreams.touch; import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING; import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING; import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_START_REGION; import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; Loading Loading @@ -81,6 +82,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { private final LockPatternUtils mLockPatternUtils; private final UserTracker mUserTracker; private final float mBouncerZoneScreenPercentage; private final float mMinBouncerZoneScreenPercentage; private final ScrimManager mScrimManager; private ScrimController mCurrentScrimController; Loading Loading @@ -222,6 +224,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING) FlingAnimationUtils flingAnimationUtilsClosing, @Named(SWIPE_TO_BOUNCER_START_REGION) float swipeRegionPercentage, @Named(MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE) float minRegionPercentage, UiEventLogger uiEventLogger) { mCentralSurfaces = centralSurfaces; mScrimManager = scrimManager; Loading @@ -229,6 +232,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { mLockPatternUtils = lockPatternUtils; mUserTracker = userTracker; mBouncerZoneScreenPercentage = swipeRegionPercentage; mMinBouncerZoneScreenPercentage = minRegionPercentage; mFlingAnimationUtils = flingAnimationUtils; mFlingAnimationUtilsClosing = flingAnimationUtilsClosing; mValueAnimatorCreator = valueAnimatorCreator; Loading @@ -237,24 +241,27 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { } @Override public void getTouchInitiationRegion(Rect bounds, Region region) { public void getTouchInitiationRegion(Rect bounds, Region region, Rect exclusionRect) { final int width = bounds.width(); final int height = bounds.height(); final float minBouncerHeight = height * mMinBouncerZoneScreenPercentage; final int minAllowableBottom = Math.round(height * (1 - mMinBouncerZoneScreenPercentage)); if (mCentralSurfaces.map(CentralSurfaces::isBouncerShowing).orElse(false)) { region.op(new Rect(0, 0, width, Math.round( height * mBouncerZoneScreenPercentage)), Region.Op.UNION); } else { region.op(new Rect(0, Math.round(height * (1 - mBouncerZoneScreenPercentage)), width, height), Region.Op.UNION); final boolean isBouncerShowing = mCentralSurfaces.map(CentralSurfaces::isBouncerShowing).orElse(false); final Rect normalRegion = isBouncerShowing ? new Rect(0, 0, width, Math.round(height * mBouncerZoneScreenPercentage)) : new Rect(0, Math.round(height * (1 - mBouncerZoneScreenPercentage)), width, height); if (!isBouncerShowing && exclusionRect != null) { int lowestBottom = Math.min(Math.max(0, exclusionRect.bottom), minAllowableBottom); normalRegion.top = Math.max(normalRegion.top, lowestBottom); } region.union(normalRegion); } @Override public void onSessionStart(TouchSession session) { mVelocityTracker = mVelocityTrackerFactory.obtain(); Loading packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java +1 −1 Original line number Diff line number Diff line Loading @@ -87,7 +87,7 @@ public class CommunalTouchHandler implements DreamTouchHandler { } @Override public void getTouchInitiationRegion(Rect bounds, Region region) { public void getTouchInitiationRegion(Rect bounds, Region region, Rect exclusionRect) { final Rect outBounds = new Rect(bounds); outBounds.inset(outBounds.width() - mInitiationWidth, 0, 0, 0); region.op(outBounds, Region.Op.UNION); Loading packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java +73 −11 Original line number Diff line number Diff line Loading @@ -18,9 +18,15 @@ package com.android.systemui.dreams.touch; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.android.systemui.shared.Flags.bouncerAreaExclusion; import android.graphics.Rect; import android.graphics.Region; import android.os.RemoteException; import android.util.Log; import android.view.GestureDetector; import android.view.ISystemGestureExclusionListener; import android.view.IWindowManager; import android.view.InputEvent; import android.view.MotionEvent; Loading @@ -31,6 +37,8 @@ import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.LifecycleOwner; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.DisplayId; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.touch.dagger.InputSessionComponent; import com.android.systemui.shared.system.InputChannelCompat; Loading Loading @@ -58,8 +66,23 @@ import javax.inject.Inject; public class DreamOverlayTouchMonitor { // This executor is used to protect {@code mActiveTouchSessions} from being modified // concurrently. Any operation that adds or removes values should use this executor. private final Executor mExecutor; public String TAG = "DreamOverlayTouchMonitor"; private final Executor mMainExecutor; private final Executor mBackgroundExecutor; private final Lifecycle mLifecycle; private Rect mExclusionRect = null; private ISystemGestureExclusionListener mGestureExclusionListener = new ISystemGestureExclusionListener.Stub() { @Override public void onSystemGestureExclusionChanged(int displayId, Region systemGestureExclusion, Region systemGestureExclusionUnrestricted) { mExclusionRect = systemGestureExclusion.getBounds(); } }; /** * Adds a new {@link TouchSessionImpl} to participate in receiving future touches and gestures. Loading @@ -67,7 +90,7 @@ public class DreamOverlayTouchMonitor { private ListenableFuture<DreamTouchHandler.TouchSession> push( TouchSessionImpl touchSessionImpl) { return CallbackToFutureAdapter.getFuture(completer -> { mExecutor.execute(() -> { mMainExecutor.execute(() -> { if (!mActiveTouchSessions.remove(touchSessionImpl)) { completer.set(null); return; Loading @@ -90,7 +113,7 @@ public class DreamOverlayTouchMonitor { private ListenableFuture<DreamTouchHandler.TouchSession> pop( TouchSessionImpl touchSessionImpl) { return CallbackToFutureAdapter.getFuture(completer -> { mExecutor.execute(() -> { mMainExecutor.execute(() -> { if (mActiveTouchSessions.remove(touchSessionImpl)) { touchSessionImpl.onRemoved(); Loading Loading @@ -240,6 +263,17 @@ public class DreamOverlayTouchMonitor { */ private void startMonitoring() { stopMonitoring(true); if (bouncerAreaExclusion()) { mBackgroundExecutor.execute(() -> { try { mWindowManagerService.registerSystemGestureExclusionListener( mGestureExclusionListener, mDisplayId); } catch (RemoteException e) { // Handle the exception Log.e(TAG, "Failed to register gesture exclusion listener", e); } }); } mCurrentInputSession = mInputSessionFactory.create( "dreamOverlay", mInputEventListener, Loading @@ -252,6 +286,18 @@ public class DreamOverlayTouchMonitor { * Destroys any active {@link InputSession}. */ private void stopMonitoring(boolean force) { mExclusionRect = null; if (bouncerAreaExclusion()) { mBackgroundExecutor.execute(() -> { try { mWindowManagerService.unregisterSystemGestureExclusionListener( mGestureExclusionListener, mDisplayId); } catch (RemoteException e) { // Handle the exception Log.e(TAG, "unregisterSystemGestureExclusionListener: failed", e); } }); } if (mCurrentInputSession == null) { return; } Loading @@ -263,7 +309,7 @@ public class DreamOverlayTouchMonitor { // When we stop monitoring touches, we must ensure that all active touch sessions and // descendants informed of the removal so any cleanup for active tracking can proceed. mExecutor.execute(() -> mActiveTouchSessions.forEach(touchSession -> { mMainExecutor.execute(() -> mActiveTouchSessions.forEach(touchSession -> { while (touchSession != null) { touchSession.onRemoved(); touchSession = touchSession.getPredecessor(); Loading Loading @@ -297,9 +343,13 @@ public class DreamOverlayTouchMonitor { } final Rect maxBounds = mDisplayHelper.getMaxBounds(ev.getDisplayId(), TYPE_APPLICATION_OVERLAY); final Region initiationRegion = Region.obtain(); handler.getTouchInitiationRegion(maxBounds, initiationRegion); Rect exclusionRect = null; if (bouncerAreaExclusion()) { exclusionRect = getCurrentExclusionRect(); } handler.getTouchInitiationRegion( maxBounds, initiationRegion, exclusionRect); if (!initiationRegion.isEmpty()) { // Initiation regions require a motion event to determine pointer location Loading Loading @@ -335,6 +385,9 @@ public class DreamOverlayTouchMonitor { .flatMap(Collection::stream) .forEach(inputEventListener -> inputEventListener.onInputEvent(ev)); } private Rect getCurrentExclusionRect() { return mExclusionRect; } }; /** Loading Loading @@ -416,6 +469,9 @@ public class DreamOverlayTouchMonitor { private InputSessionComponent.Factory mInputSessionFactory; private InputSession mCurrentInputSession; private final int mDisplayId; private final IWindowManager mWindowManagerService; /** * Designated constructor for {@link DreamOverlayTouchMonitor} Loading @@ -432,15 +488,21 @@ public class DreamOverlayTouchMonitor { @Inject public DreamOverlayTouchMonitor( @Main Executor executor, @Background Executor backgroundExecutor, Lifecycle lifecycle, InputSessionComponent.Factory inputSessionFactory, DisplayHelper displayHelper, Set<DreamTouchHandler> handlers) { Set<DreamTouchHandler> handlers, IWindowManager windowManagerService, @DisplayId int displayId) { mDisplayId = displayId; mHandlers = handlers; mInputSessionFactory = inputSessionFactory; mExecutor = executor; mMainExecutor = executor; mBackgroundExecutor = backgroundExecutor; mLifecycle = lifecycle; mDisplayHelper = displayHelper; mWindowManagerService = windowManagerService; } /** Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java +83 −3 Original line number Diff line number Diff line Loading @@ -63,7 +63,6 @@ import org.mockito.MockitoAnnotations; import java.util.Collections; import java.util.Optional; @SmallTest @RunWith(AndroidJUnit4.class) public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { Loading Loading @@ -119,6 +118,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { private static final float TOUCH_REGION = .3f; private static final int SCREEN_WIDTH_PX = 1024; private static final int SCREEN_HEIGHT_PX = 100; private static final float MIN_BOUNCER_HEIGHT = .05f; private static final Rect SCREEN_BOUNDS = new Rect(0, 0, 1024, 100); private static final UserInfo CURRENT_USER_INFO = new UserInfo( Loading @@ -142,6 +142,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { mFlingAnimationUtils, mFlingAnimationUtilsClosing, TOUCH_REGION, MIN_BOUNCER_HEIGHT, mUiEventLogger); when(mScrimManager.getCurrentController()).thenReturn(mScrimController); Loading @@ -160,9 +161,9 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { */ @Test public void testSessionStart() { mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion); mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, null); verify(mRegion).op(mRectCaptor.capture(), eq(Region.Op.UNION)); verify(mRegion).union(mRectCaptor.capture()); final Rect bounds = mRectCaptor.getValue(); final Rect expected = new Rect(); Loading Loading @@ -194,6 +195,85 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase { UP, } @Test public void testSwipeUp_whenBouncerInitiallyShowing_reduceHeightWithExclusionRects() { mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, new Rect(0, 0, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX)); verify(mRegion).union(mRectCaptor.capture()); final Rect bounds = mRectCaptor.getValue(); final Rect expected = new Rect(); final float minBouncerHeight = SCREEN_HEIGHT_PX * MIN_BOUNCER_HEIGHT; final int minAllowableBottom = SCREEN_HEIGHT_PX - Math.round(minBouncerHeight); expected.set(0, minAllowableBottom , SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX); assertThat(bounds).isEqualTo(expected); onSessionStartHelper(mTouchHandler, mTouchSession, mNotificationShadeWindowController); } @Test public void testSwipeUp_exclusionRectAtTop_doesNotIntersectGestureArea() { mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, new Rect(0, 0, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX / 4)); verify(mRegion).union(mRectCaptor.capture()); final Rect bounds = mRectCaptor.getValue(); final Rect expected = new Rect(); final int gestureAreaTop = SCREEN_HEIGHT_PX - Math.round(SCREEN_HEIGHT_PX * TOUCH_REGION); expected.set(0, gestureAreaTop, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX); assertThat(bounds).isEqualTo(expected); onSessionStartHelper(mTouchHandler, mTouchSession, mNotificationShadeWindowController); } @Test public void testSwipeUp_exclusionRectBetweenNormalAndMinimumSwipeArea() { final int normalSwipeAreaTop = SCREEN_HEIGHT_PX - Math.round(SCREEN_HEIGHT_PX * TOUCH_REGION); final int minimumSwipeAreaTop = SCREEN_HEIGHT_PX - Math.round(SCREEN_HEIGHT_PX * MIN_BOUNCER_HEIGHT); Rect exclusionRect = new Rect(0, 0, SCREEN_WIDTH_PX, (normalSwipeAreaTop + minimumSwipeAreaTop) / 2); mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion, exclusionRect); verify(mRegion).union(mRectCaptor.capture()); final Rect bounds = mRectCaptor.getValue(); final Rect expected = new Rect(); final int expectedSwipeAreaBottom = exclusionRect.bottom; expected.set(0, expectedSwipeAreaBottom, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX); assertThat(bounds).isEqualTo(expected); onSessionStartHelper(mTouchHandler, mTouchSession, mNotificationShadeWindowController); } private static void onSessionStartHelper(BouncerSwipeTouchHandler touchHandler, DreamTouchHandler.TouchSession touchSession, NotificationShadeWindowController notificationShadeWindowController) { touchHandler.onSessionStart(touchSession); verify(notificationShadeWindowController).setForcePluginOpen(eq(true), any()); ArgumentCaptor<InputChannelCompat.InputEventListener> eventListenerCaptor = ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class); ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor = ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class); verify(touchSession).registerGestureListener(gestureListenerCaptor.capture()); verify(touchSession).registerInputListener(eventListenerCaptor.capture()); // A touch within range at the bottom of the screen should trigger listening assertThat(gestureListenerCaptor.getValue() .onScroll(Mockito.mock(MotionEvent.class), Mockito.mock(MotionEvent.class), 1, 2)).isTrue(); } /** * Makes sure swiping up when bouncer initially showing doesn't change the expansion amount. */ Loading
packages/SystemUI/res/values/dimens.xml +4 −0 Original line number Diff line number Diff line Loading @@ -1867,6 +1867,10 @@ .2 </item> <item name="dream_overlay_bouncer_min_region_screen_percentage" format="float" type="dimen"> .05 </item> <!-- The padding applied to the dream overlay container --> <dimen name="dream_overlay_container_padding_start">0dp</dimen> <dimen name="dream_overlay_container_padding_end">0dp</dimen> Loading
packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java +20 −13 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.dreams.touch; import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING; import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING; import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_START_REGION; import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; Loading Loading @@ -81,6 +82,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { private final LockPatternUtils mLockPatternUtils; private final UserTracker mUserTracker; private final float mBouncerZoneScreenPercentage; private final float mMinBouncerZoneScreenPercentage; private final ScrimManager mScrimManager; private ScrimController mCurrentScrimController; Loading Loading @@ -222,6 +224,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING) FlingAnimationUtils flingAnimationUtilsClosing, @Named(SWIPE_TO_BOUNCER_START_REGION) float swipeRegionPercentage, @Named(MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE) float minRegionPercentage, UiEventLogger uiEventLogger) { mCentralSurfaces = centralSurfaces; mScrimManager = scrimManager; Loading @@ -229,6 +232,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { mLockPatternUtils = lockPatternUtils; mUserTracker = userTracker; mBouncerZoneScreenPercentage = swipeRegionPercentage; mMinBouncerZoneScreenPercentage = minRegionPercentage; mFlingAnimationUtils = flingAnimationUtils; mFlingAnimationUtilsClosing = flingAnimationUtilsClosing; mValueAnimatorCreator = valueAnimatorCreator; Loading @@ -237,24 +241,27 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler { } @Override public void getTouchInitiationRegion(Rect bounds, Region region) { public void getTouchInitiationRegion(Rect bounds, Region region, Rect exclusionRect) { final int width = bounds.width(); final int height = bounds.height(); final float minBouncerHeight = height * mMinBouncerZoneScreenPercentage; final int minAllowableBottom = Math.round(height * (1 - mMinBouncerZoneScreenPercentage)); if (mCentralSurfaces.map(CentralSurfaces::isBouncerShowing).orElse(false)) { region.op(new Rect(0, 0, width, Math.round( height * mBouncerZoneScreenPercentage)), Region.Op.UNION); } else { region.op(new Rect(0, Math.round(height * (1 - mBouncerZoneScreenPercentage)), width, height), Region.Op.UNION); final boolean isBouncerShowing = mCentralSurfaces.map(CentralSurfaces::isBouncerShowing).orElse(false); final Rect normalRegion = isBouncerShowing ? new Rect(0, 0, width, Math.round(height * mBouncerZoneScreenPercentage)) : new Rect(0, Math.round(height * (1 - mBouncerZoneScreenPercentage)), width, height); if (!isBouncerShowing && exclusionRect != null) { int lowestBottom = Math.min(Math.max(0, exclusionRect.bottom), minAllowableBottom); normalRegion.top = Math.max(normalRegion.top, lowestBottom); } region.union(normalRegion); } @Override public void onSessionStart(TouchSession session) { mVelocityTracker = mVelocityTrackerFactory.obtain(); Loading
packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java +1 −1 Original line number Diff line number Diff line Loading @@ -87,7 +87,7 @@ public class CommunalTouchHandler implements DreamTouchHandler { } @Override public void getTouchInitiationRegion(Rect bounds, Region region) { public void getTouchInitiationRegion(Rect bounds, Region region, Rect exclusionRect) { final Rect outBounds = new Rect(bounds); outBounds.inset(outBounds.width() - mInitiationWidth, 0, 0, 0); region.op(outBounds, Region.Op.UNION); Loading
packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java +73 −11 Original line number Diff line number Diff line Loading @@ -18,9 +18,15 @@ package com.android.systemui.dreams.touch; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.android.systemui.shared.Flags.bouncerAreaExclusion; import android.graphics.Rect; import android.graphics.Region; import android.os.RemoteException; import android.util.Log; import android.view.GestureDetector; import android.view.ISystemGestureExclusionListener; import android.view.IWindowManager; import android.view.InputEvent; import android.view.MotionEvent; Loading @@ -31,6 +37,8 @@ import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.LifecycleOwner; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.DisplayId; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dreams.touch.dagger.InputSessionComponent; import com.android.systemui.shared.system.InputChannelCompat; Loading Loading @@ -58,8 +66,23 @@ import javax.inject.Inject; public class DreamOverlayTouchMonitor { // This executor is used to protect {@code mActiveTouchSessions} from being modified // concurrently. Any operation that adds or removes values should use this executor. private final Executor mExecutor; public String TAG = "DreamOverlayTouchMonitor"; private final Executor mMainExecutor; private final Executor mBackgroundExecutor; private final Lifecycle mLifecycle; private Rect mExclusionRect = null; private ISystemGestureExclusionListener mGestureExclusionListener = new ISystemGestureExclusionListener.Stub() { @Override public void onSystemGestureExclusionChanged(int displayId, Region systemGestureExclusion, Region systemGestureExclusionUnrestricted) { mExclusionRect = systemGestureExclusion.getBounds(); } }; /** * Adds a new {@link TouchSessionImpl} to participate in receiving future touches and gestures. Loading @@ -67,7 +90,7 @@ public class DreamOverlayTouchMonitor { private ListenableFuture<DreamTouchHandler.TouchSession> push( TouchSessionImpl touchSessionImpl) { return CallbackToFutureAdapter.getFuture(completer -> { mExecutor.execute(() -> { mMainExecutor.execute(() -> { if (!mActiveTouchSessions.remove(touchSessionImpl)) { completer.set(null); return; Loading @@ -90,7 +113,7 @@ public class DreamOverlayTouchMonitor { private ListenableFuture<DreamTouchHandler.TouchSession> pop( TouchSessionImpl touchSessionImpl) { return CallbackToFutureAdapter.getFuture(completer -> { mExecutor.execute(() -> { mMainExecutor.execute(() -> { if (mActiveTouchSessions.remove(touchSessionImpl)) { touchSessionImpl.onRemoved(); Loading Loading @@ -240,6 +263,17 @@ public class DreamOverlayTouchMonitor { */ private void startMonitoring() { stopMonitoring(true); if (bouncerAreaExclusion()) { mBackgroundExecutor.execute(() -> { try { mWindowManagerService.registerSystemGestureExclusionListener( mGestureExclusionListener, mDisplayId); } catch (RemoteException e) { // Handle the exception Log.e(TAG, "Failed to register gesture exclusion listener", e); } }); } mCurrentInputSession = mInputSessionFactory.create( "dreamOverlay", mInputEventListener, Loading @@ -252,6 +286,18 @@ public class DreamOverlayTouchMonitor { * Destroys any active {@link InputSession}. */ private void stopMonitoring(boolean force) { mExclusionRect = null; if (bouncerAreaExclusion()) { mBackgroundExecutor.execute(() -> { try { mWindowManagerService.unregisterSystemGestureExclusionListener( mGestureExclusionListener, mDisplayId); } catch (RemoteException e) { // Handle the exception Log.e(TAG, "unregisterSystemGestureExclusionListener: failed", e); } }); } if (mCurrentInputSession == null) { return; } Loading @@ -263,7 +309,7 @@ public class DreamOverlayTouchMonitor { // When we stop monitoring touches, we must ensure that all active touch sessions and // descendants informed of the removal so any cleanup for active tracking can proceed. mExecutor.execute(() -> mActiveTouchSessions.forEach(touchSession -> { mMainExecutor.execute(() -> mActiveTouchSessions.forEach(touchSession -> { while (touchSession != null) { touchSession.onRemoved(); touchSession = touchSession.getPredecessor(); Loading Loading @@ -297,9 +343,13 @@ public class DreamOverlayTouchMonitor { } final Rect maxBounds = mDisplayHelper.getMaxBounds(ev.getDisplayId(), TYPE_APPLICATION_OVERLAY); final Region initiationRegion = Region.obtain(); handler.getTouchInitiationRegion(maxBounds, initiationRegion); Rect exclusionRect = null; if (bouncerAreaExclusion()) { exclusionRect = getCurrentExclusionRect(); } handler.getTouchInitiationRegion( maxBounds, initiationRegion, exclusionRect); if (!initiationRegion.isEmpty()) { // Initiation regions require a motion event to determine pointer location Loading Loading @@ -335,6 +385,9 @@ public class DreamOverlayTouchMonitor { .flatMap(Collection::stream) .forEach(inputEventListener -> inputEventListener.onInputEvent(ev)); } private Rect getCurrentExclusionRect() { return mExclusionRect; } }; /** Loading Loading @@ -416,6 +469,9 @@ public class DreamOverlayTouchMonitor { private InputSessionComponent.Factory mInputSessionFactory; private InputSession mCurrentInputSession; private final int mDisplayId; private final IWindowManager mWindowManagerService; /** * Designated constructor for {@link DreamOverlayTouchMonitor} Loading @@ -432,15 +488,21 @@ public class DreamOverlayTouchMonitor { @Inject public DreamOverlayTouchMonitor( @Main Executor executor, @Background Executor backgroundExecutor, Lifecycle lifecycle, InputSessionComponent.Factory inputSessionFactory, DisplayHelper displayHelper, Set<DreamTouchHandler> handlers) { Set<DreamTouchHandler> handlers, IWindowManager windowManagerService, @DisplayId int displayId) { mDisplayId = displayId; mHandlers = handlers; mInputSessionFactory = inputSessionFactory; mExecutor = executor; mMainExecutor = executor; mBackgroundExecutor = backgroundExecutor; mLifecycle = lifecycle; mDisplayHelper = displayHelper; mWindowManagerService = windowManagerService; } /** Loading