Loading core/java/android/os/Vibrator.java +21 −2 Original line number Diff line number Diff line Loading @@ -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); } /** Loading @@ -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; } /** Loading @@ -92,7 +111,7 @@ public abstract class Vibrator { * @hide */ public int getDefaultHapticFeedbackIntensity() { return VIBRATION_INTENSITY_MEDIUM; return mDefaultHapticFeedbackIntensity; } /** Loading @@ -100,7 +119,7 @@ public abstract class Vibrator { * @hide */ public int getDefaultNotificationVibrationIntensity() { return VIBRATION_INTENSITY_HIGH; return mDefaultNotificationVibrationIntensity; } /** Loading core/res/res/values/config.xml +9 −0 Original line number Diff line number Diff line Loading @@ -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. Loading core/res/res/values/symbols.xml +3 −0 Original line number Diff line number Diff line Loading @@ -3392,4 +3392,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> services/core/java/com/android/server/VibratorService.java +73 −32 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, " Loading Loading @@ -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 Loading Loading @@ -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) { Loading Loading @@ -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; } } 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; defaultIntensity = mVibrator.getDefaultNotificationVibrationIntensity(); } else if (vib.isHapticFeedback()) { defaultIntensity = mVibrator.getDefaultHapticFeedbackIntensity(); } 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"); } Loading Loading
core/java/android/os/Vibrator.java +21 −2 Original line number Diff line number Diff line Loading @@ -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); } /** Loading @@ -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; } /** Loading @@ -92,7 +111,7 @@ public abstract class Vibrator { * @hide */ public int getDefaultHapticFeedbackIntensity() { return VIBRATION_INTENSITY_MEDIUM; return mDefaultHapticFeedbackIntensity; } /** Loading @@ -100,7 +119,7 @@ public abstract class Vibrator { * @hide */ public int getDefaultNotificationVibrationIntensity() { return VIBRATION_INTENSITY_HIGH; return mDefaultNotificationVibrationIntensity; } /** Loading
core/res/res/values/config.xml +9 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
core/res/res/values/symbols.xml +3 −0 Original line number Diff line number Diff line Loading @@ -3392,4 +3392,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>
services/core/java/com/android/server/VibratorService.java +73 −32 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, " Loading Loading @@ -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 Loading Loading @@ -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) { Loading Loading @@ -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; } } 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; defaultIntensity = mVibrator.getDefaultNotificationVibrationIntensity(); } else if (vib.isHapticFeedback()) { defaultIntensity = mVibrator.getDefaultHapticFeedbackIntensity(); } 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"); } Loading