Using performHapticFeedback on NotificationPanelViewController
Migration towards the new one-way API that can trigger haptic feedback from the UI thread. Calls to the vibrate method of the VibratorHelper are replaced by performHapticFeedback with haptic constants that represent interfactions. A GESTURE_START vibration is delivered upon swipe down events and a REJECT vibration when a second tap is required due to falsing. The migration is controlled by a feature flag at the moment. Test: Vibration calls were tested in the NotificationPanelViewControllerWithCoroutinesTest class. Manual verification of vibration was performed in the event of swiping down the notification panel. The vibrations were verified when the feature flag was on and off. Bug: 245528624 Change-Id: I55c3e7a0627358cf5ac0c6e221a6e8bb9a8f8404
This commit is contained in:
@@ -28,6 +28,7 @@ import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK;
|
||||
import static com.android.systemui.classifier.Classifier.GENERIC;
|
||||
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
|
||||
import static com.android.systemui.classifier.Classifier.UNLOCK;
|
||||
import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION;
|
||||
import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadScroll;
|
||||
import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadThreeFingerSwipe;
|
||||
import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_CLOSED;
|
||||
@@ -70,6 +71,7 @@ import android.provider.Settings;
|
||||
import android.util.IndentingPrintWriter;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.InputDevice;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
@@ -2632,12 +2634,16 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
|
||||
}
|
||||
|
||||
if (!mStatusBarStateController.isDozing()) {
|
||||
mVibratorHelper.vibrate(
|
||||
Process.myUid(),
|
||||
mView.getContext().getPackageName(),
|
||||
ADDITIONAL_TAP_REQUIRED_VIBRATION_EFFECT,
|
||||
"falsing-additional-tap-required",
|
||||
TOUCH_VIBRATION_ATTRIBUTES);
|
||||
if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) {
|
||||
mVibratorHelper.performHapticFeedback(mView, HapticFeedbackConstants.REJECT);
|
||||
} else {
|
||||
mVibratorHelper.vibrate(
|
||||
Process.myUid(),
|
||||
mView.getContext().getPackageName(),
|
||||
ADDITIONAL_TAP_REQUIRED_VIBRATION_EFFECT,
|
||||
"falsing-additional-tap-required",
|
||||
TOUCH_VIBRATION_ATTRIBUTES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3504,7 +3510,14 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
|
||||
private void maybeVibrateOnOpening(boolean openingWithTouch) {
|
||||
if (mVibrateOnOpening && mBarState != KEYGUARD && mBarState != SHADE_LOCKED) {
|
||||
if (!openingWithTouch || !mHasVibratedOnOpen) {
|
||||
mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
|
||||
if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) {
|
||||
mVibratorHelper.performHapticFeedback(
|
||||
mView,
|
||||
HapticFeedbackConstants.GESTURE_START
|
||||
);
|
||||
} else {
|
||||
mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
|
||||
}
|
||||
mHasVibratedOnOpen = true;
|
||||
mShadeLog.v("Vibrating on opening, mHasVibratedOnOpen=true");
|
||||
}
|
||||
|
||||
@@ -16,17 +16,23 @@
|
||||
|
||||
package com.android.systemui.shade
|
||||
|
||||
import android.os.VibrationEffect
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import android.view.HapticFeedbackConstants
|
||||
import android.view.View
|
||||
import android.view.ViewStub
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.internal.util.CollectionUtils
|
||||
import com.android.keyguard.KeyguardClockSwitch.LARGE
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION
|
||||
import com.android.systemui.statusbar.StatusBarState.KEYGUARD
|
||||
import com.android.systemui.statusbar.StatusBarState.SHADE
|
||||
import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
|
||||
import com.android.systemui.statusbar.VibratorHelper
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.eq
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -55,6 +61,9 @@ class NotificationPanelViewControllerWithCoroutinesTest :
|
||||
|
||||
override fun getMainDispatcher() = Dispatchers.Main.immediate
|
||||
|
||||
private val ADDITIONAL_TAP_REQUIRED_VIBRATION_EFFECT =
|
||||
VibrationEffect.get(VibrationEffect.EFFECT_STRENGTH_MEDIUM, false)
|
||||
|
||||
@Test
|
||||
fun testDisableUserSwitcherAfterEnabling_returnsViewStubToTheViewHierarchy() = runTest {
|
||||
launch(Dispatchers.Main.immediate) { givenViewAttached() }
|
||||
@@ -147,6 +156,43 @@ class NotificationPanelViewControllerWithCoroutinesTest :
|
||||
advanceUntilIdle()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doubleTapRequired_onKeyguard_oneWayHapticsDisabled_usesOldVibrate() = runTest {
|
||||
launch(Dispatchers.Main.immediate) {
|
||||
whenever(mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)).thenReturn(false)
|
||||
val listener = getFalsingTapListener()
|
||||
mStatusBarStateController.setState(KEYGUARD)
|
||||
|
||||
listener.onAdditionalTapRequired()
|
||||
val packageName = mView.context.packageName
|
||||
verify(mKeyguardIndicationController).showTransientIndication(anyInt())
|
||||
verify(mVibratorHelper)
|
||||
.vibrate(
|
||||
any(),
|
||||
eq(packageName),
|
||||
eq(ADDITIONAL_TAP_REQUIRED_VIBRATION_EFFECT),
|
||||
eq("falsing-additional-tap-required"),
|
||||
eq(VibratorHelper.TOUCH_VIBRATION_ATTRIBUTES)
|
||||
)
|
||||
}
|
||||
advanceUntilIdle()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doubleTapRequired_onKeyguard_oneWayHapticsEnabled_usesPerformHapticFeedback() = runTest {
|
||||
launch(Dispatchers.Main.immediate) {
|
||||
whenever(mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)).thenReturn(true)
|
||||
val listener = getFalsingTapListener()
|
||||
mStatusBarStateController.setState(KEYGUARD)
|
||||
|
||||
listener.onAdditionalTapRequired()
|
||||
verify(mKeyguardIndicationController).showTransientIndication(anyInt())
|
||||
verify(mVibratorHelper)
|
||||
.performHapticFeedback(eq(mView), eq(HapticFeedbackConstants.REJECT))
|
||||
}
|
||||
advanceUntilIdle()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDoubleTapRequired_ShadeLocked() = runTest {
|
||||
launch(Dispatchers.Main.immediate) {
|
||||
@@ -160,6 +206,45 @@ class NotificationPanelViewControllerWithCoroutinesTest :
|
||||
advanceUntilIdle()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doubleTapRequired_shadeLocked_oneWayHapticsDisabled_usesOldVibrate() = runTest {
|
||||
launch(Dispatchers.Main.immediate) {
|
||||
whenever(mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)).thenReturn(false)
|
||||
val listener = getFalsingTapListener()
|
||||
val packageName = mView.context.packageName
|
||||
mStatusBarStateController.setState(SHADE_LOCKED)
|
||||
|
||||
listener.onAdditionalTapRequired()
|
||||
verify(mVibratorHelper)
|
||||
.vibrate(
|
||||
any(),
|
||||
eq(packageName),
|
||||
eq(ADDITIONAL_TAP_REQUIRED_VIBRATION_EFFECT),
|
||||
eq("falsing-additional-tap-required"),
|
||||
eq(VibratorHelper.TOUCH_VIBRATION_ATTRIBUTES)
|
||||
)
|
||||
|
||||
verify(mTapAgainViewController).show()
|
||||
}
|
||||
advanceUntilIdle()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doubleTapRequired_shadeLocked_oneWayHapticsEnabled_usesPerformHapticFeedback() = runTest {
|
||||
launch(Dispatchers.Main.immediate) {
|
||||
whenever(mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)).thenReturn(true)
|
||||
val listener = getFalsingTapListener()
|
||||
mStatusBarStateController.setState(SHADE_LOCKED)
|
||||
|
||||
listener.onAdditionalTapRequired()
|
||||
verify(mVibratorHelper)
|
||||
.performHapticFeedback(eq(mView), eq(HapticFeedbackConstants.REJECT))
|
||||
|
||||
verify(mTapAgainViewController).show()
|
||||
}
|
||||
advanceUntilIdle()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnAttachRefreshStatusBarState() = runTest {
|
||||
launch(Dispatchers.Main.immediate) {
|
||||
|
||||
Reference in New Issue
Block a user