diff options
4 files changed, 376 insertions, 212 deletions
diff --git a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt index 66fdf538e284..933ddb5739e9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt @@ -16,25 +16,22 @@ package com.android.systemui.haptics.slider -import android.os.VibrationAttributes import android.os.VibrationEffect import android.view.VelocityTracker import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase -import com.android.systemui.statusbar.VibratorHelper -import com.android.systemui.util.mockito.any -import com.android.systemui.util.mockito.eq +import com.android.systemui.haptics.vibratorHelper +import com.android.systemui.testKosmos import com.android.systemui.util.mockito.whenever -import com.android.systemui.util.time.FakeSystemClock +import com.android.systemui.util.time.fakeSystemClock import kotlin.math.max import kotlin.test.assertEquals +import kotlin.test.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock -import org.mockito.Mockito.times -import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @SmallTest @@ -42,10 +39,10 @@ import org.mockito.MockitoAnnotations class SliderHapticFeedbackProviderTest : SysuiTestCase() { @Mock private lateinit var velocityTracker: VelocityTracker - @Mock private lateinit var vibratorHelper: VibratorHelper + + private val kosmos = testKosmos() private val config = SliderHapticFeedbackConfig() - private val clock = FakeSystemClock() private val lowTickDuration = 12 // Mocked duration of a low tick private val dragTextureThresholdMillis = @@ -55,250 +52,278 @@ class SliderHapticFeedbackProviderTest : SysuiTestCase() { @Before fun setup() { MockitoAnnotations.initMocks(this) - whenever(vibratorHelper.getPrimitiveDurations(any())) - .thenReturn(intArrayOf(lowTickDuration)) whenever(velocityTracker.isAxisSupported(config.velocityAxis)).thenReturn(true) whenever(velocityTracker.getAxisVelocity(config.velocityAxis)) .thenReturn(config.maxVelocityToScale) + + kosmos.vibratorHelper.primitiveDurations[VibrationEffect.Composition.PRIMITIVE_LOW_TICK] = + lowTickDuration sliderHapticFeedbackProvider = - SliderHapticFeedbackProvider(vibratorHelper, velocityTracker, config, clock) + SliderHapticFeedbackProvider( + kosmos.vibratorHelper, + velocityTracker, + config, + kosmos.fakeSystemClock, + ) } @Test - fun playHapticAtLowerBookend_playsClick() { - val vibration = - VibrationEffect.startComposition() - .addPrimitive( - VibrationEffect.Composition.PRIMITIVE_CLICK, - sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale), - ) - .compose() - - sliderHapticFeedbackProvider.onLowerBookend() - - verify(vibratorHelper).vibrate(eq(vibration), any(VibrationAttributes::class.java)) - } + fun playHapticAtLowerBookend_playsClick() = + with(kosmos) { + val vibration = + VibrationEffect.startComposition() + .addPrimitive( + VibrationEffect.Composition.PRIMITIVE_CLICK, + sliderHapticFeedbackProvider.scaleOnEdgeCollision( + config.maxVelocityToScale + ), + ) + .compose() + + sliderHapticFeedbackProvider.onLowerBookend() + + assertTrue(vibratorHelper.hasVibratedWithEffects(vibration)) + } @Test - fun playHapticAtLowerBookend_twoTimes_playsClickOnlyOnce() { - val vibration = - VibrationEffect.startComposition() - .addPrimitive( - VibrationEffect.Composition.PRIMITIVE_CLICK, - sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale) - ) - .compose() - - sliderHapticFeedbackProvider.onLowerBookend() - sliderHapticFeedbackProvider.onLowerBookend() - - verify(vibratorHelper).vibrate(eq(vibration), any(VibrationAttributes::class.java)) - } + fun playHapticAtLowerBookend_twoTimes_playsClickOnlyOnce() = + with(kosmos) { + val vibration = + VibrationEffect.startComposition() + .addPrimitive( + VibrationEffect.Composition.PRIMITIVE_CLICK, + sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale) + ) + .compose() + + sliderHapticFeedbackProvider.onLowerBookend() + sliderHapticFeedbackProvider.onLowerBookend() + + assertTrue(vibratorHelper.hasVibratedWithEffects(vibration)) + } @Test - fun playHapticAtUpperBookend_playsClick() { - val vibration = - VibrationEffect.startComposition() - .addPrimitive( - VibrationEffect.Composition.PRIMITIVE_CLICK, - sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale), - ) - .compose() - - sliderHapticFeedbackProvider.onUpperBookend() + fun playHapticAtUpperBookend_playsClick() = + with(kosmos) { + val vibration = + VibrationEffect.startComposition() + .addPrimitive( + VibrationEffect.Composition.PRIMITIVE_CLICK, + sliderHapticFeedbackProvider.scaleOnEdgeCollision( + config.maxVelocityToScale + ), + ) + .compose() + + sliderHapticFeedbackProvider.onUpperBookend() + + assertTrue(vibratorHelper.hasVibratedWithEffects(vibration)) + } - verify(vibratorHelper).vibrate(eq(vibration), any(VibrationAttributes::class.java)) - } + @Test + fun playHapticAtUpperBookend_twoTimes_playsClickOnlyOnce() = + with(kosmos) { + val vibration = + VibrationEffect.startComposition() + .addPrimitive( + VibrationEffect.Composition.PRIMITIVE_CLICK, + sliderHapticFeedbackProvider.scaleOnEdgeCollision( + config.maxVelocityToScale + ), + ) + .compose() + + sliderHapticFeedbackProvider.onUpperBookend() + sliderHapticFeedbackProvider.onUpperBookend() + + assertEquals(/* expected=*/ 1, vibratorHelper.timesVibratedWithEffect(vibration)) + } @Test - fun playHapticAtUpperBookend_twoTimes_playsClickOnlyOnce() { - val vibration = - VibrationEffect.startComposition() - .addPrimitive( - VibrationEffect.Composition.PRIMITIVE_CLICK, - sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale), + fun playHapticAtProgress_onQuickSuccession_playsLowTicksOnce() = + with(kosmos) { + // GIVEN max velocity and slider progress + val progress = 1f + val expectedScale = + sliderHapticFeedbackProvider.scaleOnDragTexture( + config.maxVelocityToScale, + progress, ) - .compose() + val ticks = VibrationEffect.startComposition() + repeat(config.numberOfLowTicks) { + ticks.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, expectedScale) + } - sliderHapticFeedbackProvider.onUpperBookend() - sliderHapticFeedbackProvider.onUpperBookend() + // GIVEN system running for 1s + fakeSystemClock.advanceTime(1000) - verify(vibratorHelper, times(1)) - .vibrate(eq(vibration), any(VibrationAttributes::class.java)) - } + // WHEN two calls to play occur immediately + sliderHapticFeedbackProvider.onProgress(progress) + sliderHapticFeedbackProvider.onProgress(progress) - @Test - fun playHapticAtProgress_onQuickSuccession_playsLowTicksOnce() { - // GIVEN max velocity and slider progress - val progress = 1f - val expectedScale = - sliderHapticFeedbackProvider.scaleOnDragTexture( - config.maxVelocityToScale, - progress, - ) - val ticks = VibrationEffect.startComposition() - repeat(config.numberOfLowTicks) { - ticks.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, expectedScale) + // THEN the correct composition only plays once + assertEquals(/* expected=*/ 1, vibratorHelper.timesVibratedWithEffect(ticks.compose())) } - // GIVEN system running for 1s - clock.advanceTime(1000) - - // WHEN two calls to play occur immediately - sliderHapticFeedbackProvider.onProgress(progress) - sliderHapticFeedbackProvider.onProgress(progress) - - // THEN the correct composition only plays once - verify(vibratorHelper, times(1)) - .vibrate(eq(ticks.compose()), any(VibrationAttributes::class.java)) - } - @Test - fun playHapticAtProgress_beforeNextDragThreshold_playsLowTicksOnce() { - // GIVEN max velocity and a slider progress at half progress - val firstProgress = 0.5f - val firstTicks = generateTicksComposition(config.maxVelocityToScale, firstProgress) - - // Given a second slider progress event smaller than the progress threshold - val secondProgress = firstProgress + max(0f, config.deltaProgressForDragThreshold - 0.01f) - - // GIVEN system running for 1s - clock.advanceTime(1000) - - // WHEN two calls to play occur with the required threshold separation (time and progress) - sliderHapticFeedbackProvider.onProgress(firstProgress) - clock.advanceTime(dragTextureThresholdMillis.toLong()) - sliderHapticFeedbackProvider.onProgress(secondProgress) - - // THEN Only the first compositions plays - verify(vibratorHelper, times(1)) - .vibrate(eq(firstTicks), any(VibrationAttributes::class.java)) - verify(vibratorHelper, times(1)) - .vibrate(any(VibrationEffect::class.java), any(VibrationAttributes::class.java)) - } + fun playHapticAtProgress_beforeNextDragThreshold_playsLowTicksOnce() = + with(kosmos) { + // GIVEN max velocity and a slider progress at half progress + val firstProgress = 0.5f + val firstTicks = generateTicksComposition(config.maxVelocityToScale, firstProgress) + + // Given a second slider progress event smaller than the progress threshold + val secondProgress = + firstProgress + max(0f, config.deltaProgressForDragThreshold - 0.01f) + + // GIVEN system running for 1s + fakeSystemClock.advanceTime(1000) + + // WHEN two calls to play occur with the required threshold separation (time and + // progress) + sliderHapticFeedbackProvider.onProgress(firstProgress) + fakeSystemClock.advanceTime(dragTextureThresholdMillis.toLong()) + sliderHapticFeedbackProvider.onProgress(secondProgress) + + // THEN Only the first compositions plays + assertEquals(/* expected= */ 1, vibratorHelper.timesVibratedWithEffect(firstTicks)) + assertEquals(/* expected= */ 1, vibratorHelper.totalVibrations) + } @Test - fun playHapticAtProgress_afterNextDragThreshold_playsLowTicksTwice() { - // GIVEN max velocity and a slider progress at half progress - val firstProgress = 0.5f - val firstTicks = generateTicksComposition(config.maxVelocityToScale, firstProgress) - - // Given a second slider progress event beyond progress threshold - val secondProgress = firstProgress + config.deltaProgressForDragThreshold + 0.01f - val secondTicks = generateTicksComposition(config.maxVelocityToScale, secondProgress) - - // GIVEN system running for 1s - clock.advanceTime(1000) - - // WHEN two calls to play occur with the required threshold separation (time and progress) - sliderHapticFeedbackProvider.onProgress(firstProgress) - clock.advanceTime(dragTextureThresholdMillis.toLong()) - sliderHapticFeedbackProvider.onProgress(secondProgress) - - // THEN the correct compositions play - verify(vibratorHelper, times(1)) - .vibrate(eq(firstTicks), any(VibrationAttributes::class.java)) - verify(vibratorHelper, times(1)) - .vibrate(eq(secondTicks), any(VibrationAttributes::class.java)) - } + fun playHapticAtProgress_afterNextDragThreshold_playsLowTicksTwice() = + with(kosmos) { + // GIVEN max velocity and a slider progress at half progress + val firstProgress = 0.5f + val firstTicks = generateTicksComposition(config.maxVelocityToScale, firstProgress) + + // Given a second slider progress event beyond progress threshold + val secondProgress = firstProgress + config.deltaProgressForDragThreshold + 0.01f + val secondTicks = generateTicksComposition(config.maxVelocityToScale, secondProgress) + + // GIVEN system running for 1s + fakeSystemClock.advanceTime(1000) + + // WHEN two calls to play occur with the required threshold separation (time and + // progress) + sliderHapticFeedbackProvider.onProgress(firstProgress) + fakeSystemClock.advanceTime(dragTextureThresholdMillis.toLong()) + sliderHapticFeedbackProvider.onProgress(secondProgress) + + // THEN the correct compositions play + assertEquals(/* expected= */ 1, vibratorHelper.timesVibratedWithEffect(firstTicks)) + assertEquals(/* expected= */ 1, vibratorHelper.timesVibratedWithEffect(secondTicks)) + } @Test - fun playHapticAtLowerBookend_afterPlayingAtProgress_playsTwice() { - // GIVEN max velocity and slider progress - val progress = 1f - val expectedScale = - sliderHapticFeedbackProvider.scaleOnDragTexture( - config.maxVelocityToScale, - progress, + fun playHapticAtLowerBookend_afterPlayingAtProgress_playsTwice() = + with(kosmos) { + // GIVEN max velocity and slider progress + val progress = 1f + val expectedScale = + sliderHapticFeedbackProvider.scaleOnDragTexture( + config.maxVelocityToScale, + progress, + ) + val ticks = VibrationEffect.startComposition() + repeat(config.numberOfLowTicks) { + ticks.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, expectedScale) + } + val bookendVibration = + VibrationEffect.startComposition() + .addPrimitive( + VibrationEffect.Composition.PRIMITIVE_CLICK, + sliderHapticFeedbackProvider.scaleOnEdgeCollision( + config.maxVelocityToScale + ), + ) + .compose() + + // GIVEN a vibration at the lower bookend followed by a request to vibrate at progress + sliderHapticFeedbackProvider.onLowerBookend() + sliderHapticFeedbackProvider.onProgress(progress) + + // WHEN a vibration is to trigger again at the lower bookend + sliderHapticFeedbackProvider.onLowerBookend() + + // THEN there are two bookend vibrations + assertEquals( + /* expected= */ 2, + vibratorHelper.timesVibratedWithEffect(bookendVibration) ) - val ticks = VibrationEffect.startComposition() - repeat(config.numberOfLowTicks) { - ticks.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, expectedScale) } - val bookendVibration = - VibrationEffect.startComposition() - .addPrimitive( - VibrationEffect.Composition.PRIMITIVE_CLICK, - sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale), - ) - .compose() - - // GIVEN a vibration at the lower bookend followed by a request to vibrate at progress - sliderHapticFeedbackProvider.onLowerBookend() - sliderHapticFeedbackProvider.onProgress(progress) - - // WHEN a vibration is to trigger again at the lower bookend - sliderHapticFeedbackProvider.onLowerBookend() - - // THEN there are two bookend vibrations - verify(vibratorHelper, times(2)) - .vibrate(eq(bookendVibration), any(VibrationAttributes::class.java)) - } @Test - fun playHapticAtUpperBookend_afterPlayingAtProgress_playsTwice() { - // GIVEN max velocity and slider progress - val progress = 1f - val expectedScale = - sliderHapticFeedbackProvider.scaleOnDragTexture( - config.maxVelocityToScale, - progress, + fun playHapticAtUpperBookend_afterPlayingAtProgress_playsTwice() = + with(kosmos) { + // GIVEN max velocity and slider progress + val progress = 1f + val expectedScale = + sliderHapticFeedbackProvider.scaleOnDragTexture( + config.maxVelocityToScale, + progress, + ) + val ticks = VibrationEffect.startComposition() + repeat(config.numberOfLowTicks) { + ticks.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, expectedScale) + } + val bookendVibration = + VibrationEffect.startComposition() + .addPrimitive( + VibrationEffect.Composition.PRIMITIVE_CLICK, + sliderHapticFeedbackProvider.scaleOnEdgeCollision( + config.maxVelocityToScale + ), + ) + .compose() + + // GIVEN a vibration at the upper bookend followed by a request to vibrate at progress + sliderHapticFeedbackProvider.onUpperBookend() + sliderHapticFeedbackProvider.onProgress(progress) + + // WHEN a vibration is to trigger again at the upper bookend + sliderHapticFeedbackProvider.onUpperBookend() + + // THEN there are two bookend vibrations + assertEquals( + /* expected= */ 2, + vibratorHelper.timesVibratedWithEffect(bookendVibration) ) - val ticks = VibrationEffect.startComposition() - repeat(config.numberOfLowTicks) { - ticks.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, expectedScale) } - val bookendVibration = - VibrationEffect.startComposition() - .addPrimitive( - VibrationEffect.Composition.PRIMITIVE_CLICK, - sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale), - ) - .compose() - - // GIVEN a vibration at the upper bookend followed by a request to vibrate at progress - sliderHapticFeedbackProvider.onUpperBookend() - sliderHapticFeedbackProvider.onProgress(progress) - // WHEN a vibration is to trigger again at the upper bookend - sliderHapticFeedbackProvider.onUpperBookend() + fun dragTextureLastProgress_afterDragTextureHaptics_keepsLastDragTextureProgress() = + with(kosmos) { + // GIVEN max velocity and a slider progress at half progress + val progress = 0.5f - // THEN there are two bookend vibrations - verify(vibratorHelper, times(2)) - .vibrate(eq(bookendVibration), any(VibrationAttributes::class.java)) - } + // GIVEN system running for 1s + fakeSystemClock.advanceTime(1000) - fun dragTextureLastProgress_afterDragTextureHaptics_keepsLastDragTextureProgress() { - // GIVEN max velocity and a slider progress at half progress - val progress = 0.5f + // WHEN a drag texture plays + sliderHapticFeedbackProvider.onProgress(progress) - // GIVEN system running for 1s - clock.advanceTime(1000) - - // WHEN a drag texture plays - sliderHapticFeedbackProvider.onProgress(progress) - - // THEN the dragTextureLastProgress remembers the latest progress - assertEquals(progress, sliderHapticFeedbackProvider.dragTextureLastProgress) - } + // THEN the dragTextureLastProgress remembers the latest progress + assertEquals(progress, sliderHapticFeedbackProvider.dragTextureLastProgress) + } @Test - fun dragTextureLastProgress_afterDragTextureHaptics_resetsOnHandleReleased() { - // GIVEN max velocity and a slider progress at half progress - val progress = 0.5f + fun dragTextureLastProgress_afterDragTextureHaptics_resetsOnHandleReleased() = + with(kosmos) { + // GIVEN max velocity and a slider progress at half progress + val progress = 0.5f - // GIVEN system running for 1s - clock.advanceTime(1000) + // GIVEN system running for 1s + fakeSystemClock.advanceTime(1000) - // WHEN a drag texture plays - sliderHapticFeedbackProvider.onProgress(progress) + // WHEN a drag texture plays + sliderHapticFeedbackProvider.onProgress(progress) - // WHEN the handle is released - sliderHapticFeedbackProvider.onHandleReleasedFromTouch() + // WHEN the handle is released + sliderHapticFeedbackProvider.onHandleReleasedFromTouch() - // THEN the dragTextureLastProgress tracker is reset - assertEquals(-1f, sliderHapticFeedbackProvider.dragTextureLastProgress) - } + // THEN the dragTextureLastProgress tracker is reset + assertEquals(-1f, sliderHapticFeedbackProvider.dragTextureLastProgress) + } private fun generateTicksComposition(velocity: Float, progress: Float): VibrationEffect { val ticks = VibrationEffect.startComposition() diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/EmptyVibrator.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/EmptyVibrator.kt new file mode 100644 index 000000000000..875f6ed8d4a8 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/EmptyVibrator.kt @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.haptics + +import android.os.VibrationAttributes +import android.os.VibrationEffect +import android.os.Vibrator + +/** A simple empty vibrator required for the [FakeVibratorHelper] */ +class EmptyVibrator : Vibrator() { + override fun cancel() {} + + override fun cancel(usageFilter: Int) {} + + override fun hasAmplitudeControl(): Boolean = true + + override fun hasVibrator(): Boolean = true + + override fun vibrate( + uid: Int, + opPkg: String, + vibe: VibrationEffect, + reason: String, + attributes: VibrationAttributes, + ) {} +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/FakeVibratorHelper.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/FakeVibratorHelper.kt new file mode 100644 index 000000000000..4c0b132210f1 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/FakeVibratorHelper.kt @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.haptics + +import android.annotation.SuppressLint +import android.media.AudioAttributes +import android.os.VibrationAttributes +import android.os.VibrationEffect +import com.android.systemui.statusbar.VibratorHelper +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.time.FakeSystemClock + +/** A fake [VibratorHelper] that only keeps track of the latest vibration effects delivered */ +@SuppressLint("VisibleForTests") +class FakeVibratorHelper : VibratorHelper(EmptyVibrator(), FakeExecutor(FakeSystemClock())) { + + /** A customizable map of primitive ids and their durations in ms */ + val primitiveDurations: HashMap<Int, Int> = ALL_PRIMITIVE_DURATIONS + + private val vibrationEffectHistory = ArrayList<VibrationEffect>() + + val totalVibrations: Int + get() = vibrationEffectHistory.size + + override fun vibrate(effect: VibrationEffect) { + vibrationEffectHistory.add(effect) + } + + override fun vibrate(effect: VibrationEffect, attributes: VibrationAttributes) = vibrate(effect) + + override fun vibrate(effect: VibrationEffect, attributes: AudioAttributes) = vibrate(effect) + + override fun vibrate( + uid: Int, + opPkg: String?, + vibe: VibrationEffect, + reason: String?, + attributes: VibrationAttributes, + ) = vibrate(vibe) + + override fun getPrimitiveDurations(vararg primitiveIds: Int): IntArray = + primitiveIds.map { primitiveDurations[it] ?: 0 }.toIntArray() + + fun hasVibratedWithEffects(vararg effects: VibrationEffect): Boolean = + vibrationEffectHistory.containsAll(effects.toList()) + + fun timesVibratedWithEffect(effect: VibrationEffect): Int = + vibrationEffectHistory.count { it == effect } + + companion object { + val ALL_PRIMITIVE_DURATIONS = + hashMapOf( + VibrationEffect.Composition.PRIMITIVE_NOOP to 0, + VibrationEffect.Composition.PRIMITIVE_CLICK to 12, + VibrationEffect.Composition.PRIMITIVE_THUD to 300, + VibrationEffect.Composition.PRIMITIVE_SPIN to 133, + VibrationEffect.Composition.PRIMITIVE_QUICK_RISE to 150, + VibrationEffect.Composition.PRIMITIVE_SLOW_RISE to 500, + VibrationEffect.Composition.PRIMITIVE_QUICK_FALL to 100, + VibrationEffect.Composition.PRIMITIVE_TICK to 5, + VibrationEffect.Composition.PRIMITIVE_LOW_TICK to 12, + ) + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/VibratorHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/VibratorHelperKosmos.kt new file mode 100644 index 000000000000..434953fb2f43 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/VibratorHelperKosmos.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.haptics + +import com.android.systemui.kosmos.Kosmos + +var Kosmos.vibratorHelper by Kosmos.Fixture { FakeVibratorHelper() } |