diff options
| -rw-r--r-- | core/java/android/os/Vibrator.java | 23 | ||||
| -rw-r--r-- | core/res/res/values/config.xml | 9 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 3 | ||||
| -rw-r--r-- | services/core/java/com/android/server/VibratorService.java | 105 |
4 files changed, 106 insertions, 34 deletions
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java index f1f6f414eba8..d2d8f1e159e5 100644 --- a/core/java/android/os/Vibrator.java +++ b/core/java/android/os/Vibrator.java @@ -72,12 +72,23 @@ public abstract class Vibrator { public @interface VibrationIntensity{} private final String mPackageName; + // The default vibration intensity level for haptic feedback. + @VibrationIntensity + private final int mDefaultHapticFeedbackIntensity; + // The default vibration intensity level for notifications. + @VibrationIntensity + private final int mDefaultNotificationVibrationIntensity; /** * @hide to prevent subclassing from outside of the framework */ public Vibrator() { mPackageName = ActivityThread.currentPackageName(); + final Context ctx = ActivityThread.currentActivityThread().getSystemContext(); + mDefaultHapticFeedbackIntensity = loadDefaultIntensity(ctx, + com.android.internal.R.integer.config_defaultHapticFeedbackIntensity); + mDefaultNotificationVibrationIntensity = loadDefaultIntensity(ctx, + com.android.internal.R.integer.config_defaultNotificationVibrationIntensity); } /** @@ -85,6 +96,14 @@ public abstract class Vibrator { */ protected Vibrator(Context context) { mPackageName = context.getOpPackageName(); + mDefaultHapticFeedbackIntensity = loadDefaultIntensity(context, + com.android.internal.R.integer.config_defaultHapticFeedbackIntensity); + mDefaultNotificationVibrationIntensity = loadDefaultIntensity(context, + com.android.internal.R.integer.config_defaultNotificationVibrationIntensity); + } + + private int loadDefaultIntensity(Context ctx, int resId) { + return ctx != null ? ctx.getResources().getInteger(resId) : VIBRATION_INTENSITY_MEDIUM; } /** @@ -92,7 +111,7 @@ public abstract class Vibrator { * @hide */ public int getDefaultHapticFeedbackIntensity() { - return VIBRATION_INTENSITY_MEDIUM; + return mDefaultHapticFeedbackIntensity; } /** @@ -100,7 +119,7 @@ public abstract class Vibrator { * @hide */ public int getDefaultNotificationVibrationIntensity() { - return VIBRATION_INTENSITY_HIGH; + return mDefaultNotificationVibrationIntensity; } /** diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index b0ecb3ecf11d..c856ed81d575 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1108,6 +1108,15 @@ <string-array translatable="false" name="config_ringtoneEffectUris"> </string-array> + <!-- The default intensity level for haptic feedback. See + Settings.System.HAPTIC_FEEDBACK_INTENSITY more details on the constant values and + meanings. --> + <integer name="config_defaultHapticFeedbackIntensity">2</integer> + <!-- The default intensity level for notification vibrations. See + Settings.System.NOTIFICATION_VIBRATION_INTENSITY more details on the constant values and + meanings. --> + <integer name="config_defaultNotificationVibrationIntensity">2</integer> + <bool name="config_use_strict_phone_number_comparation">false</bool> <!-- Display low battery warning when battery level dips to this value. diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 8a045a07938c..faf9093c0fe9 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3386,4 +3386,7 @@ <java-symbol type="drawable" name="ic_lock_lockdown" /> <java-symbol type="drawable" name="ic_arrow_forward" /> <java-symbol type="drawable" name="ic_permission" /> + + <java-symbol type="integer" name="config_defaultHapticFeedbackIntensity" /> + <java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" /> </resources> diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index ede870fbf02e..95e55182f823 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -76,17 +76,35 @@ public class VibratorService extends IVibratorService.Stub private static final long[] DOUBLE_CLICK_EFFECT_FALLBACK_TIMINGS = { 0, 30, 100, 30 }; - private static final float GAMMA_SCALE_FACTOR_MINIMUM = 2.0f; - private static final float GAMMA_SCALE_FACTOR_LOW = 1.5f; - private static final float GAMMA_SCALE_FACTOR_HIGH = 0.5f; - private static final float GAMMA_SCALE_FACTOR_NONE = 1.0f; - - private static final int MAX_AMPLITUDE_MINIMUM_INTENSITY = 168; // 2/3 * 255 - private static final int MAX_AMPLITUDE_LOW_INTENSITY = 192; // 3/4 * 255 + // Scale levels. Each level is defined as the delta between the current setting and the default + // intensity for that type of vibration (i.e. current - default). + private static final int SCALE_VERY_LOW = -2; + private static final int SCALE_LOW = -1; + private static final int SCALE_NONE = 0; + private static final int SCALE_HIGH = 1; + private static final int SCALE_VERY_HIGH = 2; + + // Gamma adjustments for scale levels. + private static final float SCALE_VERY_LOW_GAMMA = 2.0f; + private static final float SCALE_LOW_GAMMA = 1.5f; + private static final float SCALE_NONE_GAMMA = 1.0f; + private static final float SCALE_HIGH_GAMMA = 0.5f; + private static final float SCALE_VERY_HIGH_GAMMA = 0.25f; + + // Max amplitudes for scale levels. If one is not listed, then the max amplitude is the default + // max amplitude. + private static final int SCALE_VERY_LOW_MAX_AMPLITUDE = 168; // 2/3 * 255 + private static final int SCALE_LOW_MAX_AMPLITUDE = 192; // 3/4 * 255 // If a vibration is playing for longer than 5s, it's probably not haptic feedback. private static final long MAX_HAPTIC_FEEDBACK_DURATION = 5000; + + // A mapping from the intensity adjustment to the scaling to apply, where the intensity + // adjustment is defined as the delta between the default intensity level and the user selected + // intensity level. It's important that we apply the scaling on the delta between the two so + // that the default intensity level applies no scaling to application provided effects. + private final SparseArray<ScaleLevel> mScaleLevels; private final LinkedList<VibrationInfo> mPreviousVibrations; private final int mPreviousVibrationsLimit; private final boolean mAllowPriorityVibrationsInLowPowerMode; @@ -180,6 +198,8 @@ public class VibratorService extends IVibratorService.Stub case VibrationEffect.EFFECT_DOUBLE_CLICK: case VibrationEffect.EFFECT_HEAVY_CLICK: case VibrationEffect.EFFECT_TICK: + case VibrationEffect.EFFECT_POP: + case VibrationEffect.EFFECT_THUD: return true; default: Slog.w(TAG, "Unknown prebaked vibration effect, " @@ -254,6 +274,25 @@ public class VibratorService extends IVibratorService.Stub } } + private static final class ScaleLevel { + public final float gamma; + public final int maxAmplitude; + + public ScaleLevel(float gamma) { + this(gamma, VibrationEffect.MAX_AMPLITUDE); + } + + public ScaleLevel(float gamma, int maxAmplitude) { + this.gamma = gamma; + this.maxAmplitude = maxAmplitude; + } + + @Override + public String toString() { + return "ScaleLevel{gamma=" + gamma + ", maxAmplitude=" + maxAmplitude + "}"; + } + } + VibratorService(Context context) { vibratorInit(); // Reset the hardware to a default state, in case this is a runtime @@ -295,11 +334,19 @@ public class VibratorService extends IVibratorService.Stub VibrationEffect tickEffect = createEffectFromResource( com.android.internal.R.array.config_clockTickVibePattern); - mFallbackEffects = new SparseArray<VibrationEffect>(); + mFallbackEffects = new SparseArray<>(); mFallbackEffects.put(VibrationEffect.EFFECT_CLICK, clickEffect); mFallbackEffects.put(VibrationEffect.EFFECT_DOUBLE_CLICK, doubleClickEffect); mFallbackEffects.put(VibrationEffect.EFFECT_TICK, tickEffect); mFallbackEffects.put(VibrationEffect.EFFECT_HEAVY_CLICK, heavyClickEffect); + + mScaleLevels = new SparseArray<>(); + mScaleLevels.put(SCALE_VERY_LOW, + new ScaleLevel(SCALE_VERY_LOW_GAMMA, SCALE_VERY_LOW_MAX_AMPLITUDE)); + mScaleLevels.put(SCALE_LOW, new ScaleLevel(SCALE_LOW_GAMMA, SCALE_LOW_MAX_AMPLITUDE)); + mScaleLevels.put(SCALE_NONE, new ScaleLevel(SCALE_NONE_GAMMA)); + mScaleLevels.put(SCALE_HIGH, new ScaleLevel(SCALE_HIGH_GAMMA)); + mScaleLevels.put(SCALE_VERY_HIGH, new ScaleLevel(SCALE_VERY_HIGH_GAMMA)); } private VibrationEffect createEffectFromResource(int resId) { @@ -675,41 +722,35 @@ public class VibratorService extends IVibratorService.Stub return; } - final float gamma; - final int maxAmplitude; + final int defaultIntensity; if (vib.isNotification() || vib.isRingtone()) { - if (intensity == Vibrator.VIBRATION_INTENSITY_LOW) { - gamma = GAMMA_SCALE_FACTOR_MINIMUM; - maxAmplitude = MAX_AMPLITUDE_MINIMUM_INTENSITY; - } else if (intensity == Vibrator.VIBRATION_INTENSITY_MEDIUM) { - gamma = GAMMA_SCALE_FACTOR_LOW; - maxAmplitude = MAX_AMPLITUDE_LOW_INTENSITY; - } else { - gamma = GAMMA_SCALE_FACTOR_NONE; - maxAmplitude = VibrationEffect.MAX_AMPLITUDE; - } + defaultIntensity = mVibrator.getDefaultNotificationVibrationIntensity(); + } else if (vib.isHapticFeedback()) { + defaultIntensity = mVibrator.getDefaultHapticFeedbackIntensity(); } else { - if (intensity == Vibrator.VIBRATION_INTENSITY_LOW) { - gamma = GAMMA_SCALE_FACTOR_LOW; - maxAmplitude = MAX_AMPLITUDE_LOW_INTENSITY; - } else if (intensity == Vibrator.VIBRATION_INTENSITY_HIGH) { - gamma = GAMMA_SCALE_FACTOR_HIGH; - maxAmplitude = VibrationEffect.MAX_AMPLITUDE; - } else { - gamma = GAMMA_SCALE_FACTOR_NONE; - maxAmplitude = VibrationEffect.MAX_AMPLITUDE; - } + // If we don't know what kind of vibration we're playing then just skip scaling for + // now. + return; + } + + final ScaleLevel scale = mScaleLevels.get(intensity - defaultIntensity); + if (scale == null) { + // We should have scaling levels for all cases, so not being able to scale because of a + // missing level is unexpected. + Slog.e(TAG, "No configured scaling level!" + + " (current=" + intensity + ", default= " + defaultIntensity + ")"); + return; } VibrationEffect scaledEffect = null; if (vib.effect instanceof VibrationEffect.OneShot) { VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.effect; oneShot = oneShot.resolve(mDefaultVibrationAmplitude); - scaledEffect = oneShot.scale(gamma, maxAmplitude); + scaledEffect = oneShot.scale(scale.gamma, scale.maxAmplitude); } else if (vib.effect instanceof VibrationEffect.Waveform) { VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.effect; waveform = waveform.resolve(mDefaultVibrationAmplitude); - scaledEffect = waveform.scale(gamma, maxAmplitude); + scaledEffect = waveform.scale(scale.gamma, scale.maxAmplitude); } else { Slog.w(TAG, "Unable to apply intensity scaling, unknown VibrationEffect type"); } |