diff options
| author | 2024-02-08 18:15:25 +0000 | |
|---|---|---|
| committer | 2024-02-08 18:15:25 +0000 | |
| commit | 43b8ccaa3427d2cde5f7c0b202006ce89270ec89 (patch) | |
| tree | c0d3bdcac78402caa6761b71e19a09256c001214 | |
| parent | a3c870d1d6f15719a9ef6edb6650c3867c2c6137 (diff) | |
| parent | 0906c162a5b85fa9a535f2fdc5d2cfb7ea6b99e7 (diff) | |
Merge "Turn off glanceable hub touch handling on dream if disabled" into main
6 files changed, 160 insertions, 21 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java index 2a9bc4a1d80e..8dcf9032759b 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java @@ -18,15 +18,20 @@ package com.android.systemui.dreams.touch; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.view.GestureDetector; import android.view.MotionEvent; +import androidx.lifecycle.Lifecycle; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.kosmos.KosmosJavaAdapter; import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.statusbar.phone.CentralSurfaces; @@ -39,28 +44,60 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; @SmallTest @RunWith(AndroidJUnit4.class) public class CommunalTouchHandlerTest extends SysuiTestCase { + private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this); + @Mock CentralSurfaces mCentralSurfaces; @Mock DreamTouchHandler.TouchSession mTouchSession; CommunalTouchHandler mTouchHandler; + @Mock + Lifecycle mLifecycle; private static final int INITIATION_WIDTH = 20; @Before public void setup() { MockitoAnnotations.initMocks(this); + AtomicReference reference = new AtomicReference<>(null); + when(mLifecycle.getInternalScopeRef()).thenReturn(reference); + when(mLifecycle.getCurrentState()).thenReturn(Lifecycle.State.CREATED); mTouchHandler = new CommunalTouchHandler( Optional.of(mCentralSurfaces), - INITIATION_WIDTH); + INITIATION_WIDTH, + mKosmos.getCommunalInteractor(), + mLifecycle + ); + } + + @Test + public void communalTouchHandler_disabledByDefault() { + assertThat(mTouchHandler.isEnabled()).isFalse(); + } + + @Test + public void communalTouchHandler_disabled_whenCommunalUnavailable() { + mTouchHandler.mIsCommunalAvailableCallback.accept(false); + assertThat(mTouchHandler.isEnabled()).isFalse(); + + mTouchHandler.onSessionStart(mTouchSession); + verify(mTouchSession, never()).registerGestureListener(any()); + } + + @Test + public void communalTouchHandler_enabled_whenCommunalAvailable() { + mTouchHandler.mIsCommunalAvailableCallback.accept(true); + assertThat(mTouchHandler.isEnabled()).isTrue(); } @Test public void testEventPropagation() { + mTouchHandler.mIsCommunalAvailableCallback.accept(true); final MotionEvent motionEvent = Mockito.mock(MotionEvent.class); final ArgumentCaptor<InputChannelCompat.InputEventListener> @@ -75,6 +112,7 @@ public class CommunalTouchHandlerTest extends SysuiTestCase { @Test public void testTouchPilferingOnScroll() { + mTouchHandler.mIsCommunalAvailableCallback.accept(true); final MotionEvent motionEvent1 = Mockito.mock(MotionEvent.class); final MotionEvent motionEvent2 = Mockito.mock(MotionEvent.class); diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java index 05279fcdf51c..e5c705f608b9 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java @@ -17,15 +17,21 @@ package com.android.systemui.dreams.touch; import static com.android.systemui.dreams.touch.dagger.ShadeModule.COMMUNAL_GESTURE_INITIATION_WIDTH; +import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; import android.graphics.Rect; import android.graphics.Region; import android.view.GestureDetector; import android.view.MotionEvent; +import androidx.annotation.VisibleForTesting; +import androidx.lifecycle.Lifecycle; + +import com.android.systemui.communal.domain.interactor.CommunalInteractor; import com.android.systemui.statusbar.phone.CentralSurfaces; import java.util.Optional; +import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Named; @@ -34,17 +40,49 @@ import javax.inject.Named; public class CommunalTouchHandler implements DreamTouchHandler { private final int mInitiationWidth; private final Optional<CentralSurfaces> mCentralSurfaces; + private final Lifecycle mLifecycle; + private final CommunalInteractor mCommunalInteractor; + private Boolean mIsEnabled = false; + + @VisibleForTesting + final Consumer<Boolean> mIsCommunalAvailableCallback = + isAvailable -> { + setIsEnabled(isAvailable); + }; @Inject public CommunalTouchHandler( Optional<CentralSurfaces> centralSurfaces, - @Named(COMMUNAL_GESTURE_INITIATION_WIDTH) int initiationWidth) { + @Named(COMMUNAL_GESTURE_INITIATION_WIDTH) int initiationWidth, + CommunalInteractor communalInteractor, + Lifecycle lifecycle) { mInitiationWidth = initiationWidth; mCentralSurfaces = centralSurfaces; + mLifecycle = lifecycle; + mCommunalInteractor = communalInteractor; + + collectFlow( + mLifecycle, + mCommunalInteractor.isCommunalAvailable(), + mIsCommunalAvailableCallback + ); + } + + @Override + public Boolean isEnabled() { + return mIsEnabled; + } + + @Override + public void setIsEnabled(Boolean enabled) { + mIsEnabled = enabled; } @Override public void onSessionStart(TouchSession session) { + if (!mIsEnabled) { + return; + } mCentralSurfaces.ifPresent(surfaces -> handleSessionStart(surfaces, session)); } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java index aca621bd9e55..55a9c0c4de99 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java @@ -292,6 +292,9 @@ public class DreamOverlayTouchMonitor { new HashMap<>(); for (DreamTouchHandler handler : mHandlers) { + if (!handler.isEnabled()) { + continue; + } final Rect maxBounds = mDisplayHelper.getMaxBounds(ev.getDisplayId(), TYPE_APPLICATION_OVERLAY); diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamTouchHandler.java index b37010cfc07b..72ad45d1055c 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/DreamTouchHandler.java @@ -86,6 +86,20 @@ public interface DreamTouchHandler { } /** + * Returns whether the handler is enabled to handle touch on dream. + * @return isEnabled state. By default it's true. + */ + default Boolean isEnabled() { + return true; + } + + /** + * Sets whether to enable the handler to handle touch on dream. + * @param enabled new value to be set whether to enable the handler. + */ + default void setIsEnabled(Boolean enabled){} + + /** * Returns the region the touch handler is interested in. By default, no region is specified, * indicating the entire screen should be considered. * @param region A {@link Region} that is passed in to the target entry touch region. diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt index 0d0a6469d674..46ce5f2623de 100644 --- a/packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt @@ -18,6 +18,7 @@ package com.android.systemui.util.kotlin import android.view.View import androidx.lifecycle.Lifecycle +import androidx.lifecycle.coroutineScope import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application @@ -76,6 +77,23 @@ fun <T> collectFlow( } } +/** + * Collect information for the given [flow], calling [consumer] for each emitted event. Defaults to + * [LifeCycle.State.CREATED] which is mapped over from the equivalent definition for collecting the + * flow on a view. + */ +@JvmOverloads +fun <T> collectFlow( + lifecycle: Lifecycle, + flow: Flow<T>, + consumer: Consumer<T>, + state: Lifecycle.State = Lifecycle.State.CREATED, +) { + lifecycle.coroutineScope.launch { + lifecycle.repeatOnLifecycle(state) { flow.collect { consumer.accept(it) } } + } +} + fun <A, B, R> combineFlows(flow1: Flow<A>, flow2: Flow<B>, bifunction: (A, B) -> R): Flow<R> { return combine(flow1, flow2, bifunction) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java index 21397d97b578..1c6f25147a1e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitorTest.java @@ -153,7 +153,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testReportedDisplayBounds() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -175,7 +175,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testEntryTouchZone() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); final Rect touchArea = new Rect(4, 4, 8 , 8); doAnswer(invocation -> { @@ -203,10 +203,10 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testSessionCount() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); final Rect touchArea = new Rect(4, 4, 8 , 8); - final DreamTouchHandler unzonedTouchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler unzonedTouchHandler = createTouchHandler(); doAnswer(invocation -> { final Region region = (Region) invocation.getArguments()[1]; region.set(touchArea); @@ -248,9 +248,28 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { } } + @Test - public void testInputEventPropagation() { + public void testNoActiveSessionWhenHandlerDisabled() { final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + // disable the handler + when(touchHandler.isEnabled()).thenReturn(false); + + final Environment environment = new Environment(Stream.of(touchHandler) + .collect(Collectors.toCollection(HashSet::new))); + final MotionEvent initialEvent = Mockito.mock(MotionEvent.class); + when(initialEvent.getX()).thenReturn(5.0f); + when(initialEvent.getY()).thenReturn(5.0f); + environment.publishInputEvent(initialEvent); + + // Make sure there is no active session. + verify(touchHandler, never()).onSessionStart(any()); + verify(touchHandler, never()).getTouchInitiationRegion(any(), any()); + } + + @Test + public void testInputEventPropagation() { + final DreamTouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -270,7 +289,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testInputEventPropagationAfterRemoval() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -294,7 +313,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testInputGesturePropagation() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -313,7 +332,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testGestureConsumption() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -336,8 +355,9 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testBroadcast() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); - final DreamTouchHandler touchHandler2 = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); + final DreamTouchHandler touchHandler2 = createTouchHandler(); + when(touchHandler2.isEnabled()).thenReturn(true); final Environment environment = new Environment(Stream.of(touchHandler, touchHandler2) .collect(Collectors.toCollection(HashSet::new))); @@ -361,7 +381,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testPush() throws InterruptedException, ExecutionException { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -404,7 +424,8 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testPop() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); + final DreamTouchHandler.TouchSession.Callback callback = Mockito.mock(DreamTouchHandler.TouchSession.Callback.class); @@ -424,7 +445,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testPauseWithNoActiveSessions() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -438,7 +459,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testDeferredPauseWithActiveSessions() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -476,7 +497,7 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testDestroyWithActiveSessions() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler) .collect(Collectors.toCollection(HashSet::new))); @@ -509,9 +530,8 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testPilfering() { - final DreamTouchHandler touchHandler1 = Mockito.mock(DreamTouchHandler.class); - final DreamTouchHandler touchHandler2 = Mockito.mock(DreamTouchHandler.class); - + final DreamTouchHandler touchHandler1 = createTouchHandler(); + final DreamTouchHandler touchHandler2 = createTouchHandler(); final Environment environment = new Environment(Stream.of(touchHandler1, touchHandler2) .collect(Collectors.toCollection(HashSet::new))); @@ -543,7 +563,8 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { @Test public void testOnRemovedCallbackOnStopMonitoring() { - final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + final DreamTouchHandler touchHandler = createTouchHandler(); + final DreamTouchHandler.TouchSession.Callback callback = Mockito.mock(DreamTouchHandler.TouchSession.Callback.class); @@ -607,4 +628,11 @@ public class DreamOverlayTouchMonitorTest extends SysuiTestCase { DreamTouchHandler handler) { return registerInputEventListener(captureSession(handler)); } + + private DreamTouchHandler createTouchHandler() { + final DreamTouchHandler touchHandler = Mockito.mock(DreamTouchHandler.class); + // enable the handler by default + when(touchHandler.isEnabled()).thenReturn(true); + return touchHandler; + } } |