Files
Lawnchair/src/com/android/launcher3/util/VibratorWrapper.java
T
Anushree Ganjam 87ea411e97 Make VibratorWrapper injected by dagger (14/n)
Bug: 361850561
Test: Manual
Flag: NONE Dagger Integration
Change-Id: I57047122b35731d83674a5607e1ac980b86aebca
2024-11-04 11:33:34 -08:00

139 lines
5.3 KiB
Java

/*
* Copyright (C) 2021 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.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.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.annotation.SuppressLint;
import android.content.Context;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.dagger.ApplicationContext;
import com.android.launcher3.dagger.LauncherAppSingleton;
import com.android.launcher3.dagger.LauncherBaseAppComponent;
import javax.inject.Inject;
/**
* Wrapper around {@link Vibrator} to easily perform haptic feedback where necessary.
*/
@LauncherAppSingleton
public class VibratorWrapper {
public static final DaggerSingletonObject<VibratorWrapper> INSTANCE =
new DaggerSingletonObject<>(LauncherBaseAppComponent::getVibratorWrapper);
public static final AudioAttributes VIBRATION_ATTRS = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
public static final VibrationEffect EFFECT_CLICK =
createPredefined(VibrationEffect.EFFECT_CLICK);
@VisibleForTesting
static final Uri HAPTIC_FEEDBACK_URI = Settings.System.getUriFor(HAPTIC_FEEDBACK_ENABLED);
@VisibleForTesting static final float LOW_TICK_SCALE = 0.9f;
/**
* Haptic when entering overview.
*/
public static final VibrationEffect OVERVIEW_HAPTIC = EFFECT_CLICK;
private final Vibrator mVibrator;
private final boolean mHasVibrator;
@VisibleForTesting
final SettingsCache.OnChangeListener mHapticChangeListener =
isEnabled -> mIsHapticFeedbackEnabled = isEnabled;
private boolean mIsHapticFeedbackEnabled;
@Inject
public VibratorWrapper(@ApplicationContext Context context, SettingsCache settingsCache,
DaggerSingletonTracker tracker) {
mVibrator = context.getSystemService(Vibrator.class);
mHasVibrator = mVibrator.hasVibrator();
if (mHasVibrator) {
MAIN_EXECUTOR.execute(
() -> settingsCache.register(HAPTIC_FEEDBACK_URI, mHapticChangeListener));
mIsHapticFeedbackEnabled = settingsCache.getValue(HAPTIC_FEEDBACK_URI, 0);
tracker.addCloseable(
() -> settingsCache.unregister(HAPTIC_FEEDBACK_URI, mHapticChangeListener));
} else {
mIsHapticFeedbackEnabled = false;
}
}
/**
* 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.
*/
public void cancelVibrate() {
UI_HELPER_EXECUTOR.execute(mVibrator::cancel);
}
/** Vibrates with the given effect if haptic feedback is available and enabled. */
public void vibrate(VibrationEffect vibrationEffect) {
if (mHasVibrator && mIsHapticFeedbackEnabled) {
UI_HELPER_EXECUTOR.execute(() -> mVibrator.vibrate(vibrationEffect, VIBRATION_ATTRS));
}
}
/**
* Vibrates with a single primitive, if supported, or use a fallback effect instead. This only
* vibrates if haptic feedback is available and enabled.
*/
@SuppressLint("NewApi")
public void vibrate(int primitiveId, float primitiveScale, VibrationEffect fallbackEffect) {
if (mHasVibrator && mIsHapticFeedbackEnabled) {
UI_HELPER_EXECUTOR.execute(() -> {
if (primitiveId >= 0 && mVibrator.areAllPrimitivesSupported(primitiveId)) {
mVibrator.vibrate(VibrationEffect.startComposition()
.addPrimitive(primitiveId, primitiveScale)
.compose(), VIBRATION_ATTRS);
} else {
mVibrator.vibrate(fallbackEffect, VIBRATION_ATTRS);
}
});
}
}
/** Indicates that Taskbar has been invoked. */
public void vibrateForTaskbarUnstash() {
if (mVibrator.areAllPrimitivesSupported(PRIMITIVE_LOW_TICK)) {
VibrationEffect primitiveLowTickEffect = VibrationEffect
.startComposition()
.addPrimitive(PRIMITIVE_LOW_TICK, LOW_TICK_SCALE)
.compose();
vibrate(primitiveLowTickEffect);
}
}
}