Allow in-progress touch sessions to continue outside resume.
Currently, touch sessions are terminated outside the resume lifecycle
state. This behavior causes issues when a touch behavior is directly
leading to another state, such as dragging down the notification shade.
This changelist allows in-progress touch sessions to continue until
the session is popped. Note that lifecycle states here are used
abstractly and do not correspond to Activity usage. Also, touch
sessions are still forcefully ended in the case of resetting the touch
monitor due to the destroy lifecycle state or from starting monitoring
again.
Test: atest DreamOverlayTouchMonitorTest#testPauseWithNoActiveSessions
atest DreamOverlayTouchMonitorTest#testDeferredPauseWithActiveSessions
atest DreamOverlayTouchMonitorTest#testDestroyWithActiveSessions
Bug: 267565290
Change-Id: Ibac6e94bcf6b8c4d751349edfbcb04b2fe53285a
This commit is contained in:
@@ -101,6 +101,10 @@ public class DreamOverlayTouchMonitor {
|
||||
|
||||
completer.set(predecessor);
|
||||
}
|
||||
|
||||
if (mActiveTouchSessions.isEmpty() && mStopMonitoringPending) {
|
||||
stopMonitoring(false);
|
||||
}
|
||||
});
|
||||
|
||||
return "DreamOverlayTouchMonitor::pop";
|
||||
@@ -214,7 +218,12 @@ public class DreamOverlayTouchMonitor {
|
||||
|
||||
@Override
|
||||
public void onPause(@NonNull LifecycleOwner owner) {
|
||||
stopMonitoring();
|
||||
stopMonitoring(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(LifecycleOwner owner) {
|
||||
stopMonitoring(true);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -222,7 +231,7 @@ public class DreamOverlayTouchMonitor {
|
||||
* When invoked, instantiates a new {@link InputSession} to monitor touch events.
|
||||
*/
|
||||
private void startMonitoring() {
|
||||
stopMonitoring();
|
||||
stopMonitoring(true);
|
||||
mCurrentInputSession = mInputSessionFactory.create(
|
||||
"dreamOverlay",
|
||||
mInputEventListener,
|
||||
@@ -234,11 +243,16 @@ public class DreamOverlayTouchMonitor {
|
||||
/**
|
||||
* Destroys any active {@link InputSession}.
|
||||
*/
|
||||
private void stopMonitoring() {
|
||||
private void stopMonitoring(boolean force) {
|
||||
if (mCurrentInputSession == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mActiveTouchSessions.isEmpty() && !force) {
|
||||
mStopMonitoringPending = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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 -> {
|
||||
@@ -250,6 +264,7 @@ public class DreamOverlayTouchMonitor {
|
||||
|
||||
mCurrentInputSession.dispose();
|
||||
mCurrentInputSession = null;
|
||||
mStopMonitoringPending = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -257,6 +272,8 @@ public class DreamOverlayTouchMonitor {
|
||||
private final Collection<DreamTouchHandler> mHandlers;
|
||||
private final DisplayHelper mDisplayHelper;
|
||||
|
||||
private boolean mStopMonitoringPending;
|
||||
|
||||
private InputChannelCompat.InputEventListener mInputEventListener =
|
||||
new InputChannelCompat.InputEventListener() {
|
||||
@Override
|
||||
|
||||
@@ -399,7 +399,21 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPause() {
|
||||
public void testPauseWithNoActiveSessions() {
|
||||
final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
|
||||
|
||||
final Environment environment = new Environment(Stream.of(touchHandler)
|
||||
.collect(Collectors.toCollection(HashSet::new)));
|
||||
|
||||
environment.updateLifecycle(observerOwnerPair -> {
|
||||
observerOwnerPair.first.onPause(observerOwnerPair.second);
|
||||
});
|
||||
|
||||
environment.verifyInputSessionDispose();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeferredPauseWithActiveSessions() {
|
||||
final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
|
||||
|
||||
final Environment environment = new Environment(Stream.of(touchHandler)
|
||||
@@ -417,13 +431,58 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase {
|
||||
environment.publishInputEvent(event);
|
||||
verify(eventListener).onInputEvent(eq(event));
|
||||
|
||||
final ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionArgumentCaptor =
|
||||
ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
|
||||
|
||||
verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
|
||||
|
||||
environment.updateLifecycle(observerOwnerPair -> {
|
||||
observerOwnerPair.first.onPause(observerOwnerPair.second);
|
||||
});
|
||||
|
||||
verify(environment.mInputSession, never()).dispose();
|
||||
|
||||
// End session
|
||||
touchSessionArgumentCaptor.getValue().pop();
|
||||
environment.executeAll();
|
||||
|
||||
// Check to make sure the input session is now disposed.
|
||||
environment.verifyInputSessionDispose();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDestroyWithActiveSessions() {
|
||||
final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class);
|
||||
|
||||
final Environment environment = new Environment(Stream.of(touchHandler)
|
||||
.collect(Collectors.toCollection(HashSet::new)));
|
||||
|
||||
final InputEvent initialEvent = Mockito.mock(InputEvent.class);
|
||||
environment.publishInputEvent(initialEvent);
|
||||
|
||||
// Ensure session started
|
||||
final InputChannelCompat.InputEventListener eventListener =
|
||||
registerInputEventListener(touchHandler);
|
||||
|
||||
// First event will be missed since we register after the execution loop,
|
||||
final InputEvent event = Mockito.mock(InputEvent.class);
|
||||
environment.publishInputEvent(event);
|
||||
verify(eventListener).onInputEvent(eq(event));
|
||||
|
||||
final ArgumentCaptor<DreamTouchHandler.TouchSession> touchSessionArgumentCaptor =
|
||||
ArgumentCaptor.forClass(DreamTouchHandler.TouchSession.class);
|
||||
|
||||
verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
|
||||
|
||||
environment.updateLifecycle(observerOwnerPair -> {
|
||||
observerOwnerPair.first.onDestroy(observerOwnerPair.second);
|
||||
});
|
||||
|
||||
// Check to make sure the input session is now disposed.
|
||||
environment.verifyInputSessionDispose();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPilfering() {
|
||||
final DreamTouchHandler touchHandler1 = Mockito.mock(DreamTouchHandler.class);
|
||||
@@ -476,7 +535,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase {
|
||||
environment.executeAll();
|
||||
|
||||
environment.updateLifecycle(observerOwnerPair -> {
|
||||
observerOwnerPair.first.onPause(observerOwnerPair.second);
|
||||
observerOwnerPair.first.onDestroy(observerOwnerPair.second);
|
||||
});
|
||||
|
||||
environment.executeAll();
|
||||
|
||||
Reference in New Issue
Block a user