Merge "Apply falsing manager on seekbar" into tm-qpr-dev am: 9d5386156a
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19902246 Change-Id: I55c8d51b477a4012a4df812837ed9d80ed54e59e Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -45,6 +45,7 @@ public abstract class Classifier {
|
|||||||
public static final int QS_SWIPE_SIDE = 15;
|
public static final int QS_SWIPE_SIDE = 15;
|
||||||
public static final int BACK_GESTURE = 16;
|
public static final int BACK_GESTURE = 16;
|
||||||
public static final int QS_SWIPE_NESTED = 17;
|
public static final int QS_SWIPE_NESTED = 17;
|
||||||
|
public static final int MEDIA_SEEKBAR = 18;
|
||||||
|
|
||||||
@IntDef({
|
@IntDef({
|
||||||
QUICK_SETTINGS,
|
QUICK_SETTINGS,
|
||||||
@@ -65,7 +66,8 @@ public abstract class Classifier {
|
|||||||
LOCK_ICON,
|
LOCK_ICON,
|
||||||
QS_SWIPE_SIDE,
|
QS_SWIPE_SIDE,
|
||||||
QS_SWIPE_NESTED,
|
QS_SWIPE_NESTED,
|
||||||
BACK_GESTURE
|
BACK_GESTURE,
|
||||||
|
MEDIA_SEEKBAR,
|
||||||
})
|
})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface InteractionType {}
|
public @interface InteractionType {}
|
||||||
|
|||||||
@@ -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_FLING_THRESHOLD_IN;
|
||||||
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_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.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_COLLAPSE;
|
||||||
import static com.android.systemui.classifier.Classifier.QS_SWIPE_NESTED;
|
import static com.android.systemui.classifier.Classifier.QS_SWIPE_NESTED;
|
||||||
import static com.android.systemui.classifier.Classifier.SHADE_DRAG;
|
import static com.android.systemui.classifier.Classifier.SHADE_DRAG;
|
||||||
@@ -153,6 +154,7 @@ class DistanceClassifier extends FalsingClassifier {
|
|||||||
@Classifier.InteractionType int interactionType,
|
@Classifier.InteractionType int interactionType,
|
||||||
double historyBelief, double historyConfidence) {
|
double historyBelief, double historyConfidence) {
|
||||||
if (interactionType == BRIGHTNESS_SLIDER
|
if (interactionType == BRIGHTNESS_SLIDER
|
||||||
|
|| interactionType == MEDIA_SEEKBAR
|
||||||
|| interactionType == SHADE_DRAG
|
|| interactionType == SHADE_DRAG
|
||||||
|| interactionType == QS_COLLAPSE
|
|| interactionType == QS_COLLAPSE
|
||||||
|| interactionType == Classifier.UDFPS_AUTHENTICATION
|
|| interactionType == Classifier.UDFPS_AUTHENTICATION
|
||||||
|
|||||||
@@ -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.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.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_COLLAPSE;
|
||||||
import static com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE;
|
import static com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE;
|
||||||
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
|
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
|
||||||
@@ -119,7 +120,8 @@ class ProximityClassifier extends FalsingClassifier {
|
|||||||
@Classifier.InteractionType int interactionType,
|
@Classifier.InteractionType int interactionType,
|
||||||
double historyBelief, double historyConfidence) {
|
double historyBelief, double historyConfidence) {
|
||||||
if (interactionType == QUICK_SETTINGS || interactionType == BRIGHTNESS_SLIDER
|
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);
|
return Result.passed(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.BOUNCER_UNLOCK;
|
||||||
import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
|
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.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_DISMISS;
|
||||||
import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN;
|
import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN;
|
||||||
import static com.android.systemui.classifier.Classifier.PULSE_EXPAND;
|
import static com.android.systemui.classifier.Classifier.PULSE_EXPAND;
|
||||||
@@ -93,6 +94,10 @@ public class TypeClassifier extends FalsingClassifier {
|
|||||||
case QS_SWIPE_NESTED:
|
case QS_SWIPE_NESTED:
|
||||||
wrongDirection = !vertical;
|
wrongDirection = !vertical;
|
||||||
break;
|
break;
|
||||||
|
case MEDIA_SEEKBAR:
|
||||||
|
confidence = 0;
|
||||||
|
wrongDirection = vertical;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
wrongDirection = true;
|
wrongDirection = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -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.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.BRIGHTNESS_SLIDER;
|
||||||
import static com.android.systemui.classifier.Classifier.LOCK_ICON;
|
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 static com.android.systemui.classifier.Classifier.SHADE_DRAG;
|
||||||
|
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
@@ -91,6 +92,7 @@ class ZigZagClassifier extends FalsingClassifier {
|
|||||||
@Classifier.InteractionType int interactionType,
|
@Classifier.InteractionType int interactionType,
|
||||||
double historyBelief, double historyConfidence) {
|
double historyBelief, double historyConfidence) {
|
||||||
if (interactionType == BRIGHTNESS_SLIDER
|
if (interactionType == BRIGHTNESS_SLIDER
|
||||||
|
|| interactionType == MEDIA_SEEKBAR
|
||||||
|| interactionType == SHADE_DRAG
|
|| interactionType == SHADE_DRAG
|
||||||
|| interactionType == LOCK_ICON) {
|
|| interactionType == LOCK_ICON) {
|
||||||
return Result.passed(0);
|
return Result.passed(0);
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ import androidx.annotation.WorkerThread
|
|||||||
import androidx.core.view.GestureDetectorCompat
|
import androidx.core.view.GestureDetectorCompat
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.android.systemui.classifier.Classifier.MEDIA_SEEKBAR
|
||||||
import com.android.systemui.dagger.qualifiers.Background
|
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.statusbar.NotificationMediaManager
|
||||||
import com.android.systemui.util.concurrency.RepeatableExecutor
|
import com.android.systemui.util.concurrency.RepeatableExecutor
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -72,7 +75,8 @@ private fun PlaybackState.computePosition(duration: Long): Long {
|
|||||||
|
|
||||||
/** ViewModel for seek bar in QS media player. */
|
/** ViewModel for seek bar in QS media player. */
|
||||||
class SeekBarViewModel @Inject constructor(
|
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)
|
private var _data = Progress(false, false, false, false, null, 0)
|
||||||
set(value) {
|
set(value) {
|
||||||
@@ -275,7 +279,7 @@ class SeekBarViewModel @Inject constructor(
|
|||||||
/** Gets a listener to attach to the seek bar to handle seeking. */
|
/** Gets a listener to attach to the seek bar to handle seeking. */
|
||||||
val seekBarListener: SeekBar.OnSeekBarChangeListener
|
val seekBarListener: SeekBar.OnSeekBarChangeListener
|
||||||
get() {
|
get() {
|
||||||
return SeekBarChangeListener(this)
|
return SeekBarChangeListener(this, falsingManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Attach touch handlers to the seek bar view. */
|
/** Attach touch handlers to the seek bar view. */
|
||||||
@@ -315,7 +319,8 @@ class SeekBarViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class SeekBarChangeListener(
|
private class SeekBarChangeListener(
|
||||||
val viewModel: SeekBarViewModel
|
val viewModel: SeekBarViewModel,
|
||||||
|
val falsingManager: FalsingManager,
|
||||||
) : SeekBar.OnSeekBarChangeListener {
|
) : SeekBar.OnSeekBarChangeListener {
|
||||||
override fun onProgressChanged(bar: SeekBar, progress: Int, fromUser: Boolean) {
|
override fun onProgressChanged(bar: SeekBar, progress: Int, fromUser: Boolean) {
|
||||||
if (fromUser) {
|
if (fromUser) {
|
||||||
@@ -328,6 +333,13 @@ class SeekBarViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onStopTrackingTouch(bar: SeekBar) {
|
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())
|
viewModel.onSeek(bar.progress.toLong())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -340,7 +352,7 @@ class SeekBarViewModel @Inject constructor(
|
|||||||
*/
|
*/
|
||||||
private class SeekBarTouchListener(
|
private class SeekBarTouchListener(
|
||||||
private val viewModel: SeekBarViewModel,
|
private val viewModel: SeekBarViewModel,
|
||||||
private val bar: SeekBar
|
private val bar: SeekBar,
|
||||||
) : View.OnTouchListener, GestureDetector.OnGestureListener {
|
) : View.OnTouchListener, GestureDetector.OnGestureListener {
|
||||||
|
|
||||||
// Gesture detector helps decide which touch events to intercept.
|
// Gesture detector helps decide which touch events to intercept.
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ import android.widget.SeekBar
|
|||||||
import androidx.arch.core.executor.ArchTaskExecutor
|
import androidx.arch.core.executor.ArchTaskExecutor
|
||||||
import androidx.arch.core.executor.TaskExecutor
|
import androidx.arch.core.executor.TaskExecutor
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
|
|
||||||
import com.android.systemui.SysuiTestCase
|
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.FakeExecutor
|
||||||
import com.android.systemui.util.concurrency.FakeRepeatableExecutor
|
import com.android.systemui.util.concurrency.FakeRepeatableExecutor
|
||||||
import com.android.systemui.util.time.FakeSystemClock
|
import com.android.systemui.util.time.FakeSystemClock
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Ignore
|
import org.junit.Ignore
|
||||||
@@ -47,8 +47,8 @@ import org.mockito.Mockito.mock
|
|||||||
import org.mockito.Mockito.never
|
import org.mockito.Mockito.never
|
||||||
import org.mockito.Mockito.times
|
import org.mockito.Mockito.times
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.junit.MockitoJUnit
|
|
||||||
import org.mockito.Mockito.`when` as whenever
|
import org.mockito.Mockito.`when` as whenever
|
||||||
|
import org.mockito.junit.MockitoJUnit
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
@@ -70,6 +70,8 @@ public class SeekBarViewModelTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
@Mock private lateinit var mockController: MediaController
|
@Mock private lateinit var mockController: MediaController
|
||||||
@Mock private lateinit var mockTransport: MediaController.TransportControls
|
@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 token1 = MediaSession.Token(1, null)
|
||||||
private val token2 = MediaSession.Token(2, null)
|
private val token2 = MediaSession.Token(2, null)
|
||||||
|
|
||||||
@@ -78,9 +80,10 @@ public class SeekBarViewModelTest : SysuiTestCase() {
|
|||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
fakeExecutor = FakeExecutor(FakeSystemClock())
|
fakeExecutor = FakeExecutor(FakeSystemClock())
|
||||||
viewModel = SeekBarViewModel(FakeRepeatableExecutor(fakeExecutor))
|
viewModel = SeekBarViewModel(FakeRepeatableExecutor(fakeExecutor), falsingManager)
|
||||||
viewModel.logSeek = { }
|
viewModel.logSeek = { }
|
||||||
whenever(mockController.sessionToken).thenReturn(token1)
|
whenever(mockController.sessionToken).thenReturn(token1)
|
||||||
|
whenever(mockBar.context).thenReturn(context)
|
||||||
|
|
||||||
// LiveData to run synchronously
|
// LiveData to run synchronously
|
||||||
ArchTaskExecutor.getInstance().setDelegate(taskExecutor)
|
ArchTaskExecutor.getInstance().setDelegate(taskExecutor)
|
||||||
@@ -453,6 +456,25 @@ public class SeekBarViewModelTest : SysuiTestCase() {
|
|||||||
verify(mockTransport).seekTo(eq(pos.toLong()))
|
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
|
@Test
|
||||||
fun queuePollTaskWhenPlaying() {
|
fun queuePollTaskWhenPlaying() {
|
||||||
// GIVEN that the track is playing
|
// GIVEN that the track is playing
|
||||||
|
|||||||
Reference in New Issue
Block a user