Correct display dimensions considered.
This changelist makes sure the full screen size is considered when accounting for the dream overlay. Previously, insets would be subtracted from the overall dimensions. Test: atest DreamOverlayTouchMonitorTest#testReportedDisplayBounds Fixes: 267565290 Change-Id: I48c072491efc62c49385ae5f4684d99585a05895 Merged-In: I48c072491efc62c49385ae5f4684d99585a05895
This commit is contained in:
@@ -25,7 +25,6 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.InputEvent;
|
||||
@@ -89,8 +88,6 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
private final FlingAnimationUtils mFlingAnimationUtils;
|
||||
private final FlingAnimationUtils mFlingAnimationUtilsClosing;
|
||||
|
||||
private final DisplayMetrics mDisplayMetrics;
|
||||
|
||||
private Boolean mCapture;
|
||||
private Boolean mExpanded;
|
||||
|
||||
@@ -161,7 +158,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
// (0).
|
||||
final float dragDownAmount = e2.getY() - e1.getY();
|
||||
final float screenTravelPercentage = Math.abs(e1.getY() - e2.getY())
|
||||
/ mCentralSurfaces.get().getDisplayHeight();
|
||||
/ mTouchSession.getBounds().height();
|
||||
setPanelExpansion(mBouncerInitiallyShowing
|
||||
? screenTravelPercentage : 1 - screenTravelPercentage, dragDownAmount);
|
||||
return true;
|
||||
@@ -202,7 +199,6 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
|
||||
@Inject
|
||||
public BouncerSwipeTouchHandler(
|
||||
DisplayMetrics displayMetrics,
|
||||
ScrimManager scrimManager,
|
||||
Optional<CentralSurfaces> centralSurfaces,
|
||||
NotificationShadeWindowController notificationShadeWindowController,
|
||||
@@ -214,7 +210,6 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
FlingAnimationUtils flingAnimationUtilsClosing,
|
||||
@Named(SWIPE_TO_BOUNCER_START_REGION) float swipeRegionPercentage,
|
||||
UiEventLogger uiEventLogger) {
|
||||
mDisplayMetrics = displayMetrics;
|
||||
mCentralSurfaces = centralSurfaces;
|
||||
mScrimManager = scrimManager;
|
||||
mNotificationShadeWindowController = notificationShadeWindowController;
|
||||
@@ -227,19 +222,20 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getTouchInitiationRegion(Region region) {
|
||||
public void getTouchInitiationRegion(Rect bounds, Region region) {
|
||||
final int width = bounds.width();
|
||||
final int height = bounds.height();
|
||||
|
||||
if (mCentralSurfaces.map(CentralSurfaces::isBouncerShowing).orElse(false)) {
|
||||
region.op(new Rect(0, 0, mDisplayMetrics.widthPixels,
|
||||
region.op(new Rect(0, 0, width,
|
||||
Math.round(
|
||||
mDisplayMetrics.heightPixels * mBouncerZoneScreenPercentage)),
|
||||
height * mBouncerZoneScreenPercentage)),
|
||||
Region.Op.UNION);
|
||||
} else {
|
||||
region.op(new Rect(0,
|
||||
Math.round(
|
||||
mDisplayMetrics.heightPixels
|
||||
* (1 - mBouncerZoneScreenPercentage)),
|
||||
mDisplayMetrics.widthPixels,
|
||||
mDisplayMetrics.heightPixels),
|
||||
Math.round(height * (1 - mBouncerZoneScreenPercentage)),
|
||||
width,
|
||||
height),
|
||||
Region.Op.UNION);
|
||||
}
|
||||
}
|
||||
@@ -356,7 +352,7 @@ public class BouncerSwipeTouchHandler implements DreamTouchHandler {
|
||||
}
|
||||
|
||||
// The animation utils deal in pixel units, rather than expansion height.
|
||||
final float viewHeight = mCentralSurfaces.get().getDisplayHeight();
|
||||
final float viewHeight = mTouchSession.getBounds().height();
|
||||
final float currentHeight = viewHeight * mCurrentExpansion;
|
||||
final float targetHeight = viewHeight * expansion;
|
||||
final float expansionHeight = targetHeight - currentHeight;
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.systemui.dreams.touch;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.InputEvent;
|
||||
@@ -31,6 +34,7 @@ import androidx.lifecycle.LifecycleOwner;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dreams.touch.dagger.InputSessionComponent;
|
||||
import com.android.systemui.shared.system.InputChannelCompat;
|
||||
import com.android.systemui.util.display.DisplayHelper;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
@@ -69,7 +73,8 @@ public class DreamOverlayTouchMonitor {
|
||||
}
|
||||
|
||||
final TouchSessionImpl touchSession =
|
||||
new TouchSessionImpl(this, touchSessionImpl);
|
||||
new TouchSessionImpl(this, touchSessionImpl.getBounds(),
|
||||
touchSessionImpl);
|
||||
mActiveTouchSessions.add(touchSession);
|
||||
completer.set(touchSession);
|
||||
});
|
||||
@@ -120,10 +125,13 @@ public class DreamOverlayTouchMonitor {
|
||||
|
||||
private final TouchSessionImpl mPredecessor;
|
||||
private final DreamOverlayTouchMonitor mTouchMonitor;
|
||||
private final Rect mBounds;
|
||||
|
||||
TouchSessionImpl(DreamOverlayTouchMonitor touchMonitor, TouchSessionImpl predecessor) {
|
||||
TouchSessionImpl(DreamOverlayTouchMonitor touchMonitor, Rect bounds,
|
||||
TouchSessionImpl predecessor) {
|
||||
mPredecessor = predecessor;
|
||||
mTouchMonitor = touchMonitor;
|
||||
mBounds = bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -185,6 +193,11 @@ public class DreamOverlayTouchMonitor {
|
||||
private void onRemoved() {
|
||||
mCallbacks.forEach(callback -> callback.onRemoved());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect getBounds() {
|
||||
return mBounds;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -242,6 +255,7 @@ public class DreamOverlayTouchMonitor {
|
||||
|
||||
private final HashSet<TouchSessionImpl> mActiveTouchSessions = new HashSet<>();
|
||||
private final Collection<DreamTouchHandler> mHandlers;
|
||||
private final DisplayHelper mDisplayHelper;
|
||||
|
||||
private InputChannelCompat.InputEventListener mInputEventListener =
|
||||
new InputChannelCompat.InputEventListener() {
|
||||
@@ -253,8 +267,11 @@ public class DreamOverlayTouchMonitor {
|
||||
new HashMap<>();
|
||||
|
||||
for (DreamTouchHandler handler : mHandlers) {
|
||||
final Rect maxBounds = mDisplayHelper.getMaxBounds(ev.getDisplayId(),
|
||||
TYPE_APPLICATION_OVERLAY);
|
||||
|
||||
final Region initiationRegion = Region.obtain();
|
||||
handler.getTouchInitiationRegion(initiationRegion);
|
||||
handler.getTouchInitiationRegion(maxBounds, initiationRegion);
|
||||
|
||||
if (!initiationRegion.isEmpty()) {
|
||||
// Initiation regions require a motion event to determine pointer location
|
||||
@@ -272,8 +289,8 @@ public class DreamOverlayTouchMonitor {
|
||||
}
|
||||
}
|
||||
|
||||
final TouchSessionImpl sessionStack =
|
||||
new TouchSessionImpl(DreamOverlayTouchMonitor.this, null);
|
||||
final TouchSessionImpl sessionStack = new TouchSessionImpl(
|
||||
DreamOverlayTouchMonitor.this, maxBounds, null);
|
||||
mActiveTouchSessions.add(sessionStack);
|
||||
sessionMap.put(handler, sessionStack);
|
||||
}
|
||||
@@ -389,11 +406,13 @@ public class DreamOverlayTouchMonitor {
|
||||
@Main Executor executor,
|
||||
Lifecycle lifecycle,
|
||||
InputSessionComponent.Factory inputSessionFactory,
|
||||
DisplayHelper displayHelper,
|
||||
Set<DreamTouchHandler> handlers) {
|
||||
mHandlers = handlers;
|
||||
mInputSessionFactory = inputSessionFactory;
|
||||
mExecutor = executor;
|
||||
mLifecycle = lifecycle;
|
||||
mDisplayHelper = displayHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.dreams.touch;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.view.GestureDetector;
|
||||
|
||||
@@ -77,6 +78,11 @@ public interface DreamTouchHandler {
|
||||
* Returns the number of currently active sessions.
|
||||
*/
|
||||
int getActiveSessionCount();
|
||||
|
||||
/**
|
||||
* Returns the bounds of the display the touch region.
|
||||
*/
|
||||
Rect getBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,7 +90,7 @@ public interface DreamTouchHandler {
|
||||
* indicating the entire screen should be considered.
|
||||
* @param region A {@link Region} that is passed in to the target entry touch region.
|
||||
*/
|
||||
default void getTouchInitiationRegion(Region region) {
|
||||
default void getTouchInitiationRegion(Rect bounds, Region region) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.systemui.touch;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewRootImpl;
|
||||
|
||||
import androidx.concurrent.futures.CallbackToFutureAdapter;
|
||||
@@ -90,7 +91,9 @@ public class TouchInsetManager {
|
||||
|
||||
mTrackedViews.stream().forEach(view -> {
|
||||
final Rect boundaries = new Rect();
|
||||
view.getBoundsOnScreen(boundaries);
|
||||
view.getDrawingRect(boundaries);
|
||||
((ViewGroup) view.getRootView()).offsetDescendantRectToMyCoords(view, boundaries);
|
||||
|
||||
cumulativeRegion.op(boundaries, Region.Op.UNION);
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.systemui.util.display;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.view.Display;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Utility class for working with displays.
|
||||
*/
|
||||
public class DisplayHelper {
|
||||
private final Context mContext;
|
||||
private final DisplayManager mDisplayManager;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
@Inject
|
||||
public DisplayHelper(Context context, DisplayManager displayManager) {
|
||||
mContext = context;
|
||||
mDisplayManager = displayManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the maximum display bounds for the given window context type.
|
||||
*/
|
||||
public Rect getMaxBounds(int displayId, int windowContextType) {
|
||||
final Display display = mDisplayManager.getDisplay(displayId);
|
||||
WindowManager windowManager = mContext.createDisplayContext(display)
|
||||
.createWindowContext(windowContextType, null)
|
||||
.getSystemService(WindowManager.class);
|
||||
return windowManager.getMaximumWindowMetrics().getBounds();
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,6 @@ import android.animation.ValueAnimator;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.GestureDetector.OnGestureListener;
|
||||
import android.view.MotionEvent;
|
||||
@@ -101,20 +100,16 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
UiEventLogger mUiEventLogger;
|
||||
|
||||
final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
|
||||
|
||||
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 Rect SCREEN_BOUNDS = new Rect(0, 0, 1024, 100);
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mDisplayMetrics.widthPixels = SCREEN_WIDTH_PX;
|
||||
mDisplayMetrics.heightPixels = SCREEN_HEIGHT_PX;
|
||||
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTouchHandler = new BouncerSwipeTouchHandler(
|
||||
mDisplayMetrics,
|
||||
mScrimManager,
|
||||
Optional.of(mCentralSurfaces),
|
||||
mNotificationShadeWindowController,
|
||||
@@ -127,10 +122,10 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
|
||||
|
||||
when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
|
||||
when(mCentralSurfaces.isBouncerShowing()).thenReturn(false);
|
||||
when(mCentralSurfaces.getDisplayHeight()).thenReturn((float) SCREEN_HEIGHT_PX);
|
||||
when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
|
||||
when(mVelocityTrackerFactory.obtain()).thenReturn(mVelocityTracker);
|
||||
when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn(Float.MAX_VALUE);
|
||||
when(mTouchSession.getBounds()).thenReturn(SCREEN_BOUNDS);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,7 +134,7 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testSessionStart() {
|
||||
final Region region = Region.obtain();
|
||||
mTouchHandler.getTouchInitiationRegion(region);
|
||||
mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, region);
|
||||
|
||||
final Rect bounds = region.getBounds();
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -44,6 +45,7 @@ import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.dreams.touch.dagger.InputSessionComponent;
|
||||
import com.android.systemui.shared.system.InputChannelCompat;
|
||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||
import com.android.systemui.util.display.DisplayHelper;
|
||||
import com.android.systemui.util.time.FakeSystemClock;
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
@@ -79,7 +81,9 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase {
|
||||
private final DefaultLifecycleObserver mLifecycleObserver;
|
||||
private final InputChannelCompat.InputEventListener mEventListener;
|
||||
private final GestureDetector.OnGestureListener mGestureListener;
|
||||
private final DisplayHelper mDisplayHelper;
|
||||
private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
|
||||
private final Rect mDisplayBounds = Mockito.mock(Rect.class);
|
||||
|
||||
Environment(Set<DreamTouchHandler> handlers) {
|
||||
mLifecycle = Mockito.mock(Lifecycle.class);
|
||||
@@ -93,7 +97,11 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase {
|
||||
.thenReturn(inputComponent);
|
||||
when(inputComponent.getInputSession()).thenReturn(mInputSession);
|
||||
|
||||
mMonitor = new DreamOverlayTouchMonitor(mExecutor, mLifecycle, mInputFactory, handlers);
|
||||
mDisplayHelper = Mockito.mock(DisplayHelper.class);
|
||||
when(mDisplayHelper.getMaxBounds(anyInt(), anyInt()))
|
||||
.thenReturn(mDisplayBounds);
|
||||
mMonitor = new DreamOverlayTouchMonitor(mExecutor, mLifecycle, mInputFactory,
|
||||
mDisplayHelper, handlers);
|
||||
mMonitor.init();
|
||||
|
||||
final ArgumentCaptor<LifecycleObserver> lifecycleObserverCaptor =
|
||||
@@ -117,6 +125,10 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase {
|
||||
mGestureListener = gestureListenerCaptor.getValue();
|
||||
}
|
||||
|
||||
public Rect getDisplayBounds() {
|
||||
return mDisplayBounds;
|
||||
}
|
||||
|
||||
void executeAll() {
|
||||
mExecutor.runAllReady();
|
||||
}
|
||||
@@ -139,16 +151,38 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReportedDisplayBounds() {
|
||||
final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
|
||||
final Environment environment = new Environment(Stream.of(touchHandler)
|
||||
.collect(Collectors.toCollection(HashSet::new)));
|
||||
|
||||
final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
|
||||
when(initialEvent.getX()).thenReturn(0.0f);
|
||||
when(initialEvent.getY()).thenReturn(0.0f);
|
||||
environment.publishInputEvent(initialEvent);
|
||||
|
||||
// Verify display bounds passed into TouchHandler#getTouchInitiationRegion
|
||||
verify(touchHandler).getTouchInitiationRegion(eq(environment.getDisplayBounds()), any());
|
||||
final ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionArgumentCaptor =
|
||||
ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
|
||||
verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
|
||||
|
||||
// Verify that display bounds provided from TouchSession#getBounds
|
||||
assertThat(touchSessionArgumentCaptor.getValue().getBounds())
|
||||
.isEqualTo(environment.getDisplayBounds());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntryTouchZone() {
|
||||
final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
|
||||
final Rect touchArea = new Rect(4, 4, 8 , 8);
|
||||
|
||||
doAnswer(invocation -> {
|
||||
final Region region = (Region) invocation.getArguments()[0];
|
||||
final Region region = (Region) invocation.getArguments()[1];
|
||||
region.set(touchArea);
|
||||
return null;
|
||||
}).when(touchHandler).getTouchInitiationRegion(any());
|
||||
}).when(touchHandler).getTouchInitiationRegion(any(), any());
|
||||
|
||||
final Environment environment = new Environment(Stream.of(touchHandler)
|
||||
.collect(Collectors.toCollection(HashSet::new)));
|
||||
@@ -174,10 +208,10 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase {
|
||||
|
||||
final DreamTouchHandler unzonedTouchHandler = Mockito.mock(DreamTouchHandler.class);
|
||||
doAnswer(invocation -> {
|
||||
final Region region = (Region) invocation.getArguments()[0];
|
||||
final Region region = (Region) invocation.getArguments()[1];
|
||||
region.set(touchArea);
|
||||
return null;
|
||||
}).when(touchHandler).getTouchInitiationRegion(any());
|
||||
}).when(touchHandler).getTouchInitiationRegion(any(), any());
|
||||
|
||||
final Environment environment = new Environment(Stream.of(touchHandler, unzonedTouchHandler)
|
||||
.collect(Collectors.toCollection(HashSet::new)));
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewRootImpl;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -47,7 +48,7 @@ import org.mockito.MockitoAnnotations;
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class TouchInsetManagerTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private View mRootView;
|
||||
private ViewGroup mRootView;
|
||||
|
||||
@Mock
|
||||
private ViewRootImpl mRootViewImpl;
|
||||
@@ -193,6 +194,7 @@ public class TouchInsetManagerTest extends SysuiTestCase {
|
||||
private View createView(Rect bounds) {
|
||||
final Rect rect = new Rect(bounds);
|
||||
final View view = Mockito.mock(View.class);
|
||||
when(view.getRootView()).thenReturn(mRootView);
|
||||
doAnswer(invocation -> {
|
||||
((Rect) invocation.getArgument(0)).set(rect);
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user