From a3495a193c2c3c333f28855b07592bbe427e0562 Mon Sep 17 00:00:00 2001 From: Michael Mikhail Date: Thu, 8 Sep 2022 21:49:30 +0000 Subject: [PATCH] Apply falsing manager on seekbar Check false taps and touches on seekbar change listener whenever touch is finished. This ensures that all falsing actions are handled besides OnFling events that are handled. Bug: 243040927 Test: manual Test: atest SeekBarViewModelTest Change-Id: I60bcc3196cc2a4b3410c7851f798bfaf87d9e456 --- .../systemui/classifier/Classifier.java | 4 ++- .../classifier/DistanceClassifier.java | 2 ++ .../classifier/ProximityClassifier.java | 4 ++- .../systemui/classifier/TypeClassifier.java | 5 ++++ .../systemui/classifier/ZigZagClassifier.java | 2 ++ .../systemui/media/SeekBarViewModel.kt | 20 ++++++++++--- .../systemui/media/SeekBarViewModelTest.kt | 30 ++++++++++++++++--- 7 files changed, 57 insertions(+), 10 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java index c2922968b58ec..701df8981ca26 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java @@ -45,6 +45,7 @@ public abstract class Classifier { public static final int QS_SWIPE_SIDE = 15; public static final int BACK_GESTURE = 16; public static final int QS_SWIPE_NESTED = 17; + public static final int MEDIA_SEEKBAR = 18; @IntDef({ QUICK_SETTINGS, @@ -65,7 +66,8 @@ public abstract class Classifier { LOCK_ICON, QS_SWIPE_SIDE, QS_SWIPE_NESTED, - BACK_GESTURE + BACK_GESTURE, + MEDIA_SEEKBAR, }) @Retention(RetentionPolicy.SOURCE) public @interface InteractionType {} diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java index 5e4f149d3ca38..f8ee49add04b3 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java @@ -23,6 +23,7 @@ import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHT import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VERTICAL_FLING_THRESHOLD_IN; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_THRESHOLD_IN; import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER; +import static com.android.systemui.classifier.Classifier.MEDIA_SEEKBAR; import static com.android.systemui.classifier.Classifier.QS_COLLAPSE; import static com.android.systemui.classifier.Classifier.QS_SWIPE_NESTED; import static com.android.systemui.classifier.Classifier.SHADE_DRAG; @@ -153,6 +154,7 @@ class DistanceClassifier extends FalsingClassifier { @Classifier.InteractionType int interactionType, double historyBelief, double historyConfidence) { if (interactionType == BRIGHTNESS_SLIDER + || interactionType == MEDIA_SEEKBAR || interactionType == SHADE_DRAG || interactionType == QS_COLLAPSE || interactionType == Classifier.UDFPS_AUTHENTICATION diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java index 07f94e792a934..e8c83b1e49dda 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java @@ -18,6 +18,7 @@ package com.android.systemui.classifier; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD; import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER; +import static com.android.systemui.classifier.Classifier.MEDIA_SEEKBAR; import static com.android.systemui.classifier.Classifier.QS_COLLAPSE; import static com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE; import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; @@ -119,7 +120,8 @@ class ProximityClassifier extends FalsingClassifier { @Classifier.InteractionType int interactionType, double historyBelief, double historyConfidence) { if (interactionType == QUICK_SETTINGS || interactionType == BRIGHTNESS_SLIDER - || interactionType == QS_COLLAPSE || interactionType == QS_SWIPE_SIDE) { + || interactionType == QS_COLLAPSE || interactionType == QS_SWIPE_SIDE + || interactionType == MEDIA_SEEKBAR) { return Result.passed(0); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java index 776bc88ad6bfc..f576a5af8907b 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java @@ -20,6 +20,7 @@ package com.android.systemui.classifier; import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK; import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER; import static com.android.systemui.classifier.Classifier.LEFT_AFFORDANCE; +import static com.android.systemui.classifier.Classifier.MEDIA_SEEKBAR; import static com.android.systemui.classifier.Classifier.NOTIFICATION_DISMISS; import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN; import static com.android.systemui.classifier.Classifier.PULSE_EXPAND; @@ -93,6 +94,10 @@ public class TypeClassifier extends FalsingClassifier { case QS_SWIPE_NESTED: wrongDirection = !vertical; break; + case MEDIA_SEEKBAR: + confidence = 0; + wrongDirection = vertical; + break; default: wrongDirection = true; break; diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java index de2bdf7ded755..840982cbcc64d 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java @@ -22,6 +22,7 @@ import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHT import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_Y_SECONDARY_DEVIANCE; import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER; import static com.android.systemui.classifier.Classifier.LOCK_ICON; +import static com.android.systemui.classifier.Classifier.MEDIA_SEEKBAR; import static com.android.systemui.classifier.Classifier.SHADE_DRAG; import android.graphics.Point; @@ -91,6 +92,7 @@ class ZigZagClassifier extends FalsingClassifier { @Classifier.InteractionType int interactionType, double historyBelief, double historyConfidence) { if (interactionType == BRIGHTNESS_SLIDER + || interactionType == MEDIA_SEEKBAR || interactionType == SHADE_DRAG || interactionType == LOCK_ICON) { return Result.passed(0); diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt index 0359c6325749b..17ebfecdd1fa8 100644 --- a/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt @@ -30,7 +30,10 @@ import androidx.annotation.WorkerThread import androidx.core.view.GestureDetectorCompat import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import com.android.systemui.classifier.Classifier.MEDIA_SEEKBAR import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.plugins.FalsingManager +import com.android.systemui.plugins.FalsingManager.LOW_PENALTY import com.android.systemui.statusbar.NotificationMediaManager import com.android.systemui.util.concurrency.RepeatableExecutor import javax.inject.Inject @@ -72,7 +75,8 @@ private fun PlaybackState.computePosition(duration: Long): Long { /** ViewModel for seek bar in QS media player. */ class SeekBarViewModel @Inject constructor( - @Background private val bgExecutor: RepeatableExecutor + @Background private val bgExecutor: RepeatableExecutor, + private val falsingManager: FalsingManager, ) { private var _data = Progress(false, false, false, false, null, 0) set(value) { @@ -275,7 +279,7 @@ class SeekBarViewModel @Inject constructor( /** Gets a listener to attach to the seek bar to handle seeking. */ val seekBarListener: SeekBar.OnSeekBarChangeListener get() { - return SeekBarChangeListener(this) + return SeekBarChangeListener(this, falsingManager) } /** Attach touch handlers to the seek bar view. */ @@ -315,7 +319,8 @@ class SeekBarViewModel @Inject constructor( } private class SeekBarChangeListener( - val viewModel: SeekBarViewModel + val viewModel: SeekBarViewModel, + val falsingManager: FalsingManager, ) : SeekBar.OnSeekBarChangeListener { override fun onProgressChanged(bar: SeekBar, progress: Int, fromUser: Boolean) { if (fromUser) { @@ -328,6 +333,13 @@ class SeekBarViewModel @Inject constructor( } override fun onStopTrackingTouch(bar: SeekBar) { + // in addition to the normal functionality of both functions. + // isFalseTouch returns true if there is a real/false tap since it is not a move. + // isFalseTap returns true if there is a real/false move since it is not a tap. + if (falsingManager.isFalseTouch(MEDIA_SEEKBAR) && + falsingManager.isFalseTap(LOW_PENALTY)) { + viewModel.onSeekFalse() + } viewModel.onSeek(bar.progress.toLong()) } } @@ -340,7 +352,7 @@ class SeekBarViewModel @Inject constructor( */ private class SeekBarTouchListener( private val viewModel: SeekBarViewModel, - private val bar: SeekBar + private val bar: SeekBar, ) : View.OnTouchListener, GestureDetector.OnGestureListener { // Gesture detector helps decide which touch events to intercept. diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt index 82aa6123917e0..597334033895a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt @@ -26,13 +26,13 @@ import android.widget.SeekBar import androidx.arch.core.executor.ArchTaskExecutor import androidx.arch.core.executor.TaskExecutor import androidx.test.filters.SmallTest - import com.android.systemui.SysuiTestCase +import com.android.systemui.classifier.Classifier +import com.android.systemui.plugins.FalsingManager import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.concurrency.FakeRepeatableExecutor import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat - import org.junit.After import org.junit.Before import org.junit.Ignore @@ -47,8 +47,8 @@ import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify -import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever +import org.mockito.junit.MockitoJUnit @SmallTest @RunWith(AndroidTestingRunner::class) @@ -70,6 +70,8 @@ public class SeekBarViewModelTest : SysuiTestCase() { } @Mock private lateinit var mockController: MediaController @Mock private lateinit var mockTransport: MediaController.TransportControls + @Mock private lateinit var falsingManager: FalsingManager + @Mock private lateinit var mockBar: SeekBar private val token1 = MediaSession.Token(1, null) private val token2 = MediaSession.Token(2, null) @@ -78,9 +80,10 @@ public class SeekBarViewModelTest : SysuiTestCase() { @Before fun setUp() { fakeExecutor = FakeExecutor(FakeSystemClock()) - viewModel = SeekBarViewModel(FakeRepeatableExecutor(fakeExecutor)) + viewModel = SeekBarViewModel(FakeRepeatableExecutor(fakeExecutor), falsingManager) viewModel.logSeek = { } whenever(mockController.sessionToken).thenReturn(token1) + whenever(mockBar.context).thenReturn(context) // LiveData to run synchronously ArchTaskExecutor.getInstance().setDelegate(taskExecutor) @@ -453,6 +456,25 @@ public class SeekBarViewModelTest : SysuiTestCase() { verify(mockTransport).seekTo(eq(pos.toLong())) } + @Test + fun onFalseTapOrTouch() { + whenever(mockController.getTransportControls()).thenReturn(mockTransport) + whenever(falsingManager.isFalseTouch(Classifier.MEDIA_SEEKBAR)).thenReturn(true) + whenever(falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)).thenReturn(true) + viewModel.updateController(mockController) + val pos = 169 + + viewModel.attachTouchHandlers(mockBar) + with(viewModel.seekBarListener) { + onStartTrackingTouch(mockBar) + onProgressChanged(mockBar, pos, true) + onStopTrackingTouch(mockBar) + } + + // THEN transport controls should not be used + verify(mockTransport, never()).seekTo(pos.toLong()) + } + @Test fun queuePollTaskWhenPlaying() { // GIVEN that the track is playing