Loading packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java +39 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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> Loading @@ -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); Loading packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java +39 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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)); } Loading packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java +3 −0 Original line number Diff line number Diff line Loading @@ -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); Loading packages/SystemUI/src/com/android/systemui/dreams/touch/DreamTouchHandler.java +14 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,20 @@ public interface DreamTouchHandler { Rect getBounds(); } /** * 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. Loading packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt +18 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java +39 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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> Loading @@ -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); Loading
packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java +39 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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)); } Loading
packages/SystemUI/src/com/android/systemui/dreams/touch/DreamOverlayTouchMonitor.java +3 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
packages/SystemUI/src/com/android/systemui/dreams/touch/DreamTouchHandler.java +14 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,20 @@ public interface DreamTouchHandler { Rect getBounds(); } /** * 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. Loading
packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt +18 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) }