summaryrefslogtreecommitdiff
path: root/src/com/android/launcher3/util/VibratorWrapper.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3/util/VibratorWrapper.java')
-rw-r--r--src/com/android/launcher3/util/VibratorWrapper.java109
1 files changed, 83 insertions, 26 deletions
diff --git a/src/com/android/launcher3/util/VibratorWrapper.java b/src/com/android/launcher3/util/VibratorWrapper.java
index 91945caa15..4f20bbcf44 100644
--- a/src/com/android/launcher3/util/VibratorWrapper.java
+++ b/src/com/android/launcher3/util/VibratorWrapper.java
@@ -15,9 +15,15 @@
*/
package com.android.launcher3.util;
+import static android.os.VibrationEffect.Composition.PRIMITIVE_LOW_TICK;
import static android.os.VibrationEffect.createPredefined;
import static android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_DELAY;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_END_SCALE_PERCENT;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_ITERATIONS;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_SCALE_EXPONENT;
+import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_START_SCALE_PERCENT;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
@@ -35,10 +41,9 @@ import android.provider.Settings;
import androidx.annotation.Nullable;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.PendingAnimation;
-
-import java.util.function.Consumer;
+import com.android.launcher3.config.FeatureFlags;
/**
* Wrapper around {@link Vibrator} to easily perform haptic feedback where necessary.
@@ -57,6 +62,7 @@ public class VibratorWrapper {
public static final VibrationEffect EFFECT_CLICK =
createPredefined(VibrationEffect.EFFECT_CLICK);
+ private static final float LOW_TICK_SCALE = 0.9f;
private static final float DRAG_TEXTURE_SCALE = 0.03f;
private static final float DRAG_COMMIT_SCALE = 0.5f;
private static final float DRAG_BUMP_SCALE = 0.4f;
@@ -70,7 +76,7 @@ public class VibratorWrapper {
private final VibrationEffect mBumpEffect;
@Nullable
- private final VibrationEffect mAssistEffect;
+ private final VibrationEffect mSearchEffect;
private long mLastDragTime;
private final int mThresholdUntilNextDragCallMillis;
@@ -80,12 +86,14 @@ public class VibratorWrapper {
*/
public static final VibrationEffect OVERVIEW_HAPTIC = EFFECT_CLICK;
+ private final Context mContext;
private final Vibrator mVibrator;
private final boolean mHasVibrator;
private boolean mIsHapticFeedbackEnabled;
private VibratorWrapper(Context context) {
+ mContext = context;
mVibrator = context.getSystemService(Vibrator.class);
mHasVibrator = mVibrator.hasVibrator();
if (mHasVibrator) {
@@ -104,22 +112,22 @@ public class VibratorWrapper {
}
if (Utilities.ATLEAST_S && mVibrator.areAllPrimitivesSupported(
- VibrationEffect.Composition.PRIMITIVE_LOW_TICK)) {
+ PRIMITIVE_LOW_TICK)) {
// Drag texture, Commit, and Bump should only be used for premium phones.
// Before using these haptics make sure check if the device can use it
VibrationEffect.Composition dragEffect = VibrationEffect.startComposition();
for (int i = 0; i < DRAG_TEXTURE_EFFECT_SIZE; i++) {
dragEffect.addPrimitive(
- VibrationEffect.Composition.PRIMITIVE_LOW_TICK, DRAG_TEXTURE_SCALE);
+ PRIMITIVE_LOW_TICK, DRAG_TEXTURE_SCALE);
}
mDragEffect = dragEffect.compose();
mCommitEffect = VibrationEffect.startComposition().addPrimitive(
VibrationEffect.Composition.PRIMITIVE_TICK, DRAG_COMMIT_SCALE).compose();
mBumpEffect = VibrationEffect.startComposition().addPrimitive(
- VibrationEffect.Composition.PRIMITIVE_LOW_TICK, DRAG_BUMP_SCALE).compose();
+ PRIMITIVE_LOW_TICK, DRAG_BUMP_SCALE).compose();
int primitiveDuration = mVibrator.getPrimitiveDurations(
- VibrationEffect.Composition.PRIMITIVE_LOW_TICK)[0];
+ PRIMITIVE_LOW_TICK)[0];
mThresholdUntilNextDragCallMillis =
DRAG_TEXTURE_EFFECT_SIZE * primitiveDuration + 100;
@@ -133,14 +141,20 @@ public class VibratorWrapper {
if (Utilities.ATLEAST_R && mVibrator.areAllPrimitivesSupported(
VibrationEffect.Composition.PRIMITIVE_QUICK_RISE,
VibrationEffect.Composition.PRIMITIVE_TICK)) {
- // quiet ramp, short pause, then sharp tick
- mAssistEffect = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.25f)
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f, 50)
- .compose();
+ if (FeatureFlags.ENABLE_SEARCH_HAPTIC_HINT.get()) {
+ mSearchEffect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f)
+ .compose();
+ } else {
+ // quiet ramp, short pause, then sharp tick
+ mSearchEffect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.25f)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f, 50)
+ .compose();
+ }
} else {
// fallback for devices without composition support
- mAssistEffect = VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK);
+ mSearchEffect = VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK);
}
}
@@ -184,20 +198,10 @@ public class VibratorWrapper {
}
/**
- * The assist haptic is used to be called when an assistant is invoked
- */
- public void vibrateForAssist() {
- if (mAssistEffect != null) {
- vibrate(mAssistEffect);
- }
- }
-
- /**
* This should be used to cancel a haptic in case where the haptic shouldn't be vibrating. For
- * example, when no animation is happening but a vibrator happens to be vibrating still. Need
- * boolean parameter for {@link PendingAnimation#addEndListener(Consumer)}.
+ * example, when no animation is happening but a vibrator happens to be vibrating still.
*/
- public void cancelVibrate(boolean unused) {
+ public void cancelVibrate() {
UI_HELPER_EXECUTOR.execute(mVibrator::cancel);
// reset dragTexture timestamp to be able to play dragTexture again whenever cancelled
mLastDragTime = 0;
@@ -233,4 +237,57 @@ public class VibratorWrapper {
});
}
}
+
+ /** Indicates that search has been invoked. */
+ public void vibrateForSearch() {
+ if (mSearchEffect != null) {
+ vibrate(mSearchEffect);
+ }
+ }
+
+ /** Indicates that Taskbar has been invoked. */
+ public void vibrateForTaskbarUnstash() {
+ if (Utilities.ATLEAST_S && mVibrator.areAllPrimitivesSupported(PRIMITIVE_LOW_TICK)) {
+ VibrationEffect primitiveLowTickEffect = VibrationEffect
+ .startComposition()
+ .addPrimitive(PRIMITIVE_LOW_TICK, LOW_TICK_SCALE)
+ .compose();
+
+ vibrate(primitiveLowTickEffect);
+ }
+ }
+
+ /** Indicates that search will be invoked if the current gesture is maintained. */
+ public void vibrateForSearchHint() {
+ if (FeatureFlags.ENABLE_SEARCH_HAPTIC_HINT.get() && Utilities.ATLEAST_S
+ && mVibrator.areAllPrimitivesSupported(PRIMITIVE_LOW_TICK)) {
+ LauncherPrefs launcherPrefs = LauncherPrefs.get(mContext);
+ float startScale = launcherPrefs.get(
+ LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_START_SCALE_PERCENT) / 100f;
+ float endScale = launcherPrefs.get(
+ LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_END_SCALE_PERCENT) / 100f;
+ int scaleExponent = launcherPrefs.get(
+ LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_SCALE_EXPONENT);
+ int iterations = launcherPrefs.get(
+ LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_ITERATIONS);
+ int delayMs = launcherPrefs.get(
+ LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_DELAY);
+
+ VibrationEffect.Composition composition = VibrationEffect.startComposition();
+ for (int i = 0; i < iterations; i++) {
+ float t = i / (iterations - 1f);
+ float scale = (float) Math.pow((1 - t) * startScale + t * endScale,
+ scaleExponent);
+ if (i == 0) {
+ // Adds a delay before the ramp starts
+ composition.addPrimitive(PRIMITIVE_LOW_TICK, scale,
+ delayMs);
+ } else {
+ composition.addPrimitive(PRIMITIVE_LOW_TICK, scale);
+ }
+ }
+
+ vibrate(composition.compose());
+ }
+ }
}