diff options
| author | 2024-08-08 16:07:49 +0000 | |
|---|---|---|
| committer | 2024-08-08 16:07:49 +0000 | |
| commit | 814d28df97f105027d5ad194d6e7c9aee0485edd (patch) | |
| tree | 7af6ea3d38f55e0f9f59956b5054239817c56efc | |
| parent | 92414fd866340ae833ded507cf245f93cafa559a (diff) | |
| parent | 680034b3f0fb30aa50c7aeaf9eba660d4c29f2c9 (diff) | |
Merge "Update haptics scaling" into main
13 files changed, 385 insertions, 129 deletions
diff --git a/core/java/android/os/ExternalVibrationScale.aidl b/core/java/android/os/ExternalVibrationScale.aidl index cf6f8ed52f7d..644beced2091 100644 --- a/core/java/android/os/ExternalVibrationScale.aidl +++ b/core/java/android/os/ExternalVibrationScale.aidl @@ -33,12 +33,24 @@ parcelable ExternalVibrationScale { SCALE_VERY_HIGH = 2 } + // TODO(b/345186129): remove this once we finish migrating to scale factor. /** * The scale level that will be applied to external vibrations. */ ScaleLevel scaleLevel = ScaleLevel.SCALE_NONE; /** + * The scale factor that will be applied to external vibrations. + * + * Values in (0,1) will scale down the vibrations, values > 1 will scale up vibrations within + * hardware limits. A zero scale factor indicates the external vibration should be muted. + * + * TODO(b/345186129): update this once we finish migrating, negative should not be expected. + * Negative values should be ignored in favour of the legacy ScaleLevel. + */ + float scaleFactor = -1f; // undefined + + /** * The adaptive haptics scale that will be applied to external vibrations. */ float adaptiveHapticsScale = 1f; diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index f3ef9e15b8f0..e68b74683292 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -663,6 +663,15 @@ public abstract class VibrationEffect implements Parcelable { * @hide */ public static float scale(float intensity, float scaleFactor) { + if (Flags.hapticsScaleV2Enabled()) { + if (Float.compare(scaleFactor, 1) <= 0 || Float.compare(intensity, 0) == 0) { + // Scaling down or scaling zero intensity is straightforward. + return scaleFactor * intensity; + } + // Using S * x / (1 + (S - 1) * x^2) as the scale up function to converge to 1.0. + return (scaleFactor * intensity) / (1 + (scaleFactor - 1) * intensity * intensity); + } + // Applying gamma correction to the scale factor, which is the same as encoding the input // value, scaling it, then decoding the scaled value. float scale = MathUtils.pow(scaleFactor, 1f / SCALE_GAMMA); diff --git a/core/java/android/os/vibrator/VibrationConfig.java b/core/java/android/os/vibrator/VibrationConfig.java index a4164e9f204c..e6e5a27bd731 100644 --- a/core/java/android/os/vibrator/VibrationConfig.java +++ b/core/java/android/os/vibrator/VibrationConfig.java @@ -49,8 +49,22 @@ import java.util.Arrays; */ public class VibrationConfig { + /** + * Hardcoded default scale level gain to be applied between each scale level to define their + * scale factor value. + * + * <p>Default gain defined as 3 dBs. + */ + private static final float DEFAULT_SCALE_LEVEL_GAIN = 1.4f; + + /** + * Hardcoded default amplitude to be used when device config is invalid, i.e. not in [1,255]. + */ + private static final int DEFAULT_AMPLITUDE = 255; + // TODO(b/191150049): move these to vibrator static config file private final float mHapticChannelMaxVibrationAmplitude; + private final int mDefaultVibrationAmplitude; private final int mRampStepDurationMs; private final int mRampDownDurationMs; private final int mRequestVibrationParamsTimeoutMs; @@ -75,8 +89,10 @@ public class VibrationConfig { /** @hide */ public VibrationConfig(@Nullable Resources resources) { + mDefaultVibrationAmplitude = resources.getInteger( + com.android.internal.R.integer.config_defaultVibrationAmplitude); mHapticChannelMaxVibrationAmplitude = loadFloat(resources, - com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude, 0); + com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude); mRampDownDurationMs = loadInteger(resources, com.android.internal.R.integer.config_vibrationWaveformRampDownDuration, 0); mRampStepDurationMs = loadInteger(resources, @@ -87,9 +103,9 @@ public class VibrationConfig { com.android.internal.R.array.config_requestVibrationParamsForUsages); mIgnoreVibrationsOnWirelessCharger = loadBoolean(resources, - com.android.internal.R.bool.config_ignoreVibrationsOnWirelessCharger, false); + com.android.internal.R.bool.config_ignoreVibrationsOnWirelessCharger); mKeyboardVibrationSettingsSupported = loadBoolean(resources, - com.android.internal.R.bool.config_keyboardVibrationSettingsSupported, false); + com.android.internal.R.bool.config_keyboardVibrationSettingsSupported); mDefaultAlarmVibrationIntensity = loadDefaultIntensity(resources, com.android.internal.R.integer.config_defaultAlarmVibrationIntensity); @@ -115,16 +131,16 @@ public class VibrationConfig { return value; } - private static float loadFloat(@Nullable Resources res, int resId, float defaultValue) { - return res != null ? res.getFloat(resId) : defaultValue; + private static float loadFloat(@Nullable Resources res, int resId) { + return res != null ? res.getFloat(resId) : 0f; } private static int loadInteger(@Nullable Resources res, int resId, int defaultValue) { return res != null ? res.getInteger(resId) : defaultValue; } - private static boolean loadBoolean(@Nullable Resources res, int resId, boolean defaultValue) { - return res != null ? res.getBoolean(resId) : defaultValue; + private static boolean loadBoolean(@Nullable Resources res, int resId) { + return res != null && res.getBoolean(resId); } private static int[] loadIntArray(@Nullable Resources res, int resId) { @@ -145,6 +161,26 @@ public class VibrationConfig { } /** + * Return the device default vibration amplitude value to replace the + * {@link android.os.VibrationEffect#DEFAULT_AMPLITUDE} constant. + */ + public int getDefaultVibrationAmplitude() { + if (mDefaultVibrationAmplitude < 1 || mDefaultVibrationAmplitude > 255) { + return DEFAULT_AMPLITUDE; + } + return mDefaultVibrationAmplitude; + } + + /** + * Return the device default gain to be applied between scale levels to define the scale factor + * for each level. + */ + public float getDefaultVibrationScaleLevelGain() { + // TODO(b/356407380): add device config for this + return DEFAULT_SCALE_LEVEL_GAIN; + } + + /** * The duration, in milliseconds, that should be applied to the ramp to turn off the vibrator * when a vibration is cancelled or finished at non-zero amplitude. */ @@ -233,6 +269,7 @@ public class VibrationConfig { public String toString() { return "VibrationConfig{" + "mIgnoreVibrationsOnWirelessCharger=" + mIgnoreVibrationsOnWirelessCharger + + ", mDefaultVibrationAmplitude=" + mDefaultVibrationAmplitude + ", mHapticChannelMaxVibrationAmplitude=" + mHapticChannelMaxVibrationAmplitude + ", mRampStepDurationMs=" + mRampStepDurationMs + ", mRampDownDurationMs=" + mRampDownDurationMs @@ -258,6 +295,7 @@ public class VibrationConfig { pw.println("VibrationConfig:"); pw.increaseIndent(); pw.println("ignoreVibrationsOnWirelessCharger = " + mIgnoreVibrationsOnWirelessCharger); + pw.println("defaultVibrationAmplitude = " + mDefaultVibrationAmplitude); pw.println("hapticChannelMaxAmplitude = " + mHapticChannelMaxVibrationAmplitude); pw.println("rampStepDurationMs = " + mRampStepDurationMs); pw.println("rampDownDurationMs = " + mRampDownDurationMs); diff --git a/core/java/android/os/vibrator/flags.aconfig b/core/java/android/os/vibrator/flags.aconfig index 1a19bb28fc71..53a1a67dfc58 100644 --- a/core/java/android/os/vibrator/flags.aconfig +++ b/core/java/android/os/vibrator/flags.aconfig @@ -103,3 +103,13 @@ flag { purpose: PURPOSE_FEATURE } } + +flag { + namespace: "haptics" + name: "haptics_scale_v2_enabled" + description: "Enables new haptics scaling function across all usages" + bug: "345186129" + metadata { + purpose: PURPOSE_FEATURE + } +} diff --git a/core/tests/vibrator/src/android/os/vibrator/PrimitiveSegmentTest.java b/core/tests/vibrator/src/android/os/vibrator/PrimitiveSegmentTest.java index e9a08aef4856..97f1d5e77ddb 100644 --- a/core/tests/vibrator/src/android/os/vibrator/PrimitiveSegmentTest.java +++ b/core/tests/vibrator/src/android/os/vibrator/PrimitiveSegmentTest.java @@ -27,7 +27,11 @@ import android.hardware.vibrator.IVibrator; import android.os.Parcel; import android.os.VibrationEffect; import android.os.VibratorInfo; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -36,6 +40,9 @@ import org.junit.runners.JUnit4; public class PrimitiveSegmentTest { private static final float TOLERANCE = 1e-2f; + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Test public void testCreation() { PrimitiveSegment primitive = new PrimitiveSegment( @@ -87,7 +94,8 @@ public class PrimitiveSegmentTest { } @Test - public void testScale_fullPrimitiveScaleValue() { + @DisableFlags(Flags.FLAG_HAPTICS_SCALE_V2_ENABLED) + public void testScale_withLegacyScaling_fullPrimitiveScaleValue() { PrimitiveSegment initial = new PrimitiveSegment( VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0); @@ -102,7 +110,24 @@ public class PrimitiveSegmentTest { } @Test - public void testScale_halfPrimitiveScaleValue() { + @EnableFlags(Flags.FLAG_HAPTICS_SCALE_V2_ENABLED) + public void testScale_withScalingV2_fullPrimitiveScaleValue() { + PrimitiveSegment initial = new PrimitiveSegment( + VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 0); + + assertEquals(1f, initial.scale(1).getScale(), TOLERANCE); + assertEquals(0.5f, initial.scale(0.5f).getScale(), TOLERANCE); + // The original value was not scaled up, so this only scales it down. + assertEquals(1f, initial.scale(1.5f).getScale(), TOLERANCE); + assertEquals(2 / 3f, initial.scale(1.5f).scale(2 / 3f).getScale(), TOLERANCE); + // Does not restore to the exact original value because scale up is a bit offset. + assertEquals(0.8f, initial.scale(0.8f).getScale(), TOLERANCE); + assertEquals(0.86f, initial.scale(0.8f).scale(1.25f).getScale(), TOLERANCE); + } + + @Test + @DisableFlags(Flags.FLAG_HAPTICS_SCALE_V2_ENABLED) + public void testScale_withLegacyScaling_halfPrimitiveScaleValue() { PrimitiveSegment initial = new PrimitiveSegment( VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 0); @@ -117,6 +142,22 @@ public class PrimitiveSegmentTest { } @Test + @EnableFlags(Flags.FLAG_HAPTICS_SCALE_V2_ENABLED) + public void testScale_withScalingV2_halfPrimitiveScaleValue() { + PrimitiveSegment initial = new PrimitiveSegment( + VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 0); + + assertEquals(0.5f, initial.scale(1).getScale(), TOLERANCE); + assertEquals(0.25f, initial.scale(0.5f).getScale(), TOLERANCE); + // The original value was not scaled up, so this only scales it down. + assertEquals(0.66f, initial.scale(1.5f).getScale(), TOLERANCE); + assertEquals(0.44f, initial.scale(1.5f).scale(2 / 3f).getScale(), TOLERANCE); + // Does not restore to the exact original value because scale up is a bit offset. + assertEquals(0.4f, initial.scale(0.8f).getScale(), TOLERANCE); + assertEquals(0.48f, initial.scale(0.8f).scale(1.25f).getScale(), TOLERANCE); + } + + @Test public void testScale_zeroPrimitiveScaleValue() { PrimitiveSegment initial = new PrimitiveSegment( VibrationEffect.Composition.PRIMITIVE_CLICK, 0, 0); diff --git a/core/tests/vibrator/src/android/os/vibrator/RampSegmentTest.java b/core/tests/vibrator/src/android/os/vibrator/RampSegmentTest.java index 01013ab69f85..bea82931dda7 100644 --- a/core/tests/vibrator/src/android/os/vibrator/RampSegmentTest.java +++ b/core/tests/vibrator/src/android/os/vibrator/RampSegmentTest.java @@ -29,7 +29,11 @@ import android.hardware.vibrator.IVibrator; import android.os.Parcel; import android.os.VibrationEffect; import android.os.VibratorInfo; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -38,6 +42,9 @@ import org.junit.runners.JUnit4; public class RampSegmentTest { private static final float TOLERANCE = 1e-2f; + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Test public void testCreation() { RampSegment ramp = new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0, @@ -97,14 +104,18 @@ public class RampSegmentTest { } @Test - public void testScale() { - RampSegment initial = new RampSegment(0, 1, 0, 0, 0); + @DisableFlags(Flags.FLAG_HAPTICS_SCALE_V2_ENABLED) + public void testScale_withLegacyScaling_halfAndFullAmplitudes() { + RampSegment initial = new RampSegment(0.5f, 1, 0, 0, 0); - assertEquals(0f, initial.scale(1).getStartAmplitude(), TOLERANCE); - assertEquals(0f, initial.scale(0.5f).getStartAmplitude(), TOLERANCE); - assertEquals(0f, initial.scale(1.5f).getStartAmplitude(), TOLERANCE); - assertEquals(0f, initial.scale(1.5f).scale(2 / 3f).getStartAmplitude(), TOLERANCE); - assertEquals(0f, initial.scale(0.8f).scale(1.25f).getStartAmplitude(), TOLERANCE); + assertEquals(0.5f, initial.scale(1).getStartAmplitude(), TOLERANCE); + assertEquals(0.17f, initial.scale(0.5f).getStartAmplitude(), TOLERANCE); + // The original value was not scaled up, so this only scales it down. + assertEquals(0.86f, initial.scale(1.5f).getStartAmplitude(), TOLERANCE); + assertEquals(0.47f, initial.scale(1.5f).scale(2 / 3f).getStartAmplitude(), TOLERANCE); + // Does not restore to the exact original value because scale up is a bit offset. + assertEquals(0.35f, initial.scale(0.8f).getStartAmplitude(), TOLERANCE); + assertEquals(0.5f, initial.scale(0.8f).scale(1.25f).getStartAmplitude(), TOLERANCE); assertEquals(1f, initial.scale(1).getEndAmplitude(), TOLERANCE); assertEquals(0.34f, initial.scale(0.5f).getEndAmplitude(), TOLERANCE); @@ -117,17 +128,38 @@ public class RampSegmentTest { } @Test - public void testScale_halfPrimitiveScaleValue() { + @EnableFlags(Flags.FLAG_HAPTICS_SCALE_V2_ENABLED) + public void testScale_withScalingV2_halfAndFullAmplitudes() { RampSegment initial = new RampSegment(0.5f, 1, 0, 0, 0); assertEquals(0.5f, initial.scale(1).getStartAmplitude(), TOLERANCE); - assertEquals(0.17f, initial.scale(0.5f).getStartAmplitude(), TOLERANCE); + assertEquals(0.25f, initial.scale(0.5f).getStartAmplitude(), TOLERANCE); + // The original value was not scaled up, so this only scales it down. + assertEquals(0.66f, initial.scale(1.5f).getStartAmplitude(), TOLERANCE); + assertEquals(0.44f, initial.scale(1.5f).scale(2 / 3f).getStartAmplitude(), TOLERANCE); // Does not restore to the exact original value because scale up is a bit offset. - assertEquals(0.86f, initial.scale(1.5f).getStartAmplitude(), TOLERANCE); - assertEquals(0.47f, initial.scale(1.5f).scale(2 / 3f).getStartAmplitude(), TOLERANCE); + assertEquals(0.4f, initial.scale(0.8f).getStartAmplitude(), TOLERANCE); + assertEquals(0.48f, initial.scale(0.8f).scale(1.25f).getStartAmplitude(), TOLERANCE); + + assertEquals(1f, initial.scale(1).getEndAmplitude(), TOLERANCE); + assertEquals(0.5f, initial.scale(0.5f).getEndAmplitude(), TOLERANCE); + // The original value was not scaled up, so this only scales it down. + assertEquals(1f, initial.scale(1.5f).getEndAmplitude(), TOLERANCE); + assertEquals(2 / 3f, initial.scale(1.5f).scale(2 / 3f).getEndAmplitude(), TOLERANCE); // Does not restore to the exact original value because scale up is a bit offset. - assertEquals(0.35f, initial.scale(0.8f).getStartAmplitude(), TOLERANCE); - assertEquals(0.5f, initial.scale(0.8f).scale(1.25f).getStartAmplitude(), TOLERANCE); + assertEquals(0.81f, initial.scale(0.8f).getEndAmplitude(), TOLERANCE); + assertEquals(0.86f, initial.scale(0.8f).scale(1.25f).getEndAmplitude(), TOLERANCE); + } + + @Test + public void testScale_zeroAmplitude() { + RampSegment initial = new RampSegment(0, 1, 0, 0, 0); + + assertEquals(0f, initial.scale(1).getStartAmplitude(), TOLERANCE); + assertEquals(0f, initial.scale(0.5f).getStartAmplitude(), TOLERANCE); + assertEquals(0f, initial.scale(1.5f).getStartAmplitude(), TOLERANCE); + assertEquals(0f, initial.scale(1.5f).scale(2 / 3f).getStartAmplitude(), TOLERANCE); + assertEquals(0f, initial.scale(0.8f).scale(1.25f).getStartAmplitude(), TOLERANCE); } @Test diff --git a/core/tests/vibrator/src/android/os/vibrator/StepSegmentTest.java b/core/tests/vibrator/src/android/os/vibrator/StepSegmentTest.java index 40776abc0291..411074a75e2e 100644 --- a/core/tests/vibrator/src/android/os/vibrator/StepSegmentTest.java +++ b/core/tests/vibrator/src/android/os/vibrator/StepSegmentTest.java @@ -27,7 +27,11 @@ import android.hardware.vibrator.IVibrator; import android.os.Parcel; import android.os.VibrationEffect; import android.os.VibratorInfo; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -35,6 +39,10 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class StepSegmentTest { private static final float TOLERANCE = 1e-2f; + + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Test public void testCreation() { StepSegment step = new StepSegment(/* amplitude= */ 1f, /* frequencyHz= */ 1f, @@ -93,7 +101,8 @@ public class StepSegmentTest { } @Test - public void testScale_fullAmplitude() { + @DisableFlags(Flags.FLAG_HAPTICS_SCALE_V2_ENABLED) + public void testScale_withLegacyScaling_fullAmplitude() { StepSegment initial = new StepSegment(1f, 0, 0); assertEquals(1f, initial.scale(1).getAmplitude(), TOLERANCE); @@ -107,7 +116,23 @@ public class StepSegmentTest { } @Test - public void testScale_halfAmplitude() { + @EnableFlags(Flags.FLAG_HAPTICS_SCALE_V2_ENABLED) + public void testScale_withScalingV2_fullAmplitude() { + StepSegment initial = new StepSegment(1f, 0, 0); + + assertEquals(1f, initial.scale(1).getAmplitude(), TOLERANCE); + assertEquals(0.5f, initial.scale(0.5f).getAmplitude(), TOLERANCE); + // The original value was not scaled up, so this only scales it down. + assertEquals(1f, initial.scale(1.5f).getAmplitude(), TOLERANCE); + assertEquals(2 / 3f, initial.scale(1.5f).scale(2 / 3f).getAmplitude(), TOLERANCE); + // Does not restore to the exact original value because scale up is a bit offset. + assertEquals(0.8f, initial.scale(0.8f).getAmplitude(), TOLERANCE); + assertEquals(0.86f, initial.scale(0.8f).scale(1.25f).getAmplitude(), TOLERANCE); + } + + @Test + @DisableFlags(Flags.FLAG_HAPTICS_SCALE_V2_ENABLED) + public void testScale_withLegacyScaling_halfAmplitude() { StepSegment initial = new StepSegment(0.5f, 0, 0); assertEquals(0.5f, initial.scale(1).getAmplitude(), TOLERANCE); @@ -121,6 +146,21 @@ public class StepSegmentTest { } @Test + @EnableFlags(Flags.FLAG_HAPTICS_SCALE_V2_ENABLED) + public void testScale_withScalingV2_halfAmplitude() { + StepSegment initial = new StepSegment(0.5f, 0, 0); + + assertEquals(0.5f, initial.scale(1).getAmplitude(), TOLERANCE); + assertEquals(0.25f, initial.scale(0.5f).getAmplitude(), TOLERANCE); + // The original value was not scaled up, so this only scales it down. + assertEquals(0.66f, initial.scale(1.5f).getAmplitude(), TOLERANCE); + assertEquals(0.44f, initial.scale(1.5f).scale(2 / 3f).getAmplitude(), TOLERANCE); + // Does not restore to the exact original value because scale up is a bit offset. + assertEquals(0.4f, initial.scale(0.8f).getAmplitude(), TOLERANCE); + assertEquals(0.48f, initial.scale(0.8f).scale(1.25f).getAmplitude(), TOLERANCE); + } + + @Test public void testScale_zeroAmplitude() { StepSegment initial = new StepSegment(0, 0, 0); diff --git a/services/core/java/com/android/server/vibrator/VibrationScaler.java b/services/core/java/com/android/server/vibrator/VibrationScaler.java index 39337594ff64..a74c4e07c9ed 100644 --- a/services/core/java/com/android/server/vibrator/VibrationScaler.java +++ b/services/core/java/com/android/server/vibrator/VibrationScaler.java @@ -17,7 +17,6 @@ package com.android.server.vibrator; import android.annotation.NonNull; -import android.content.Context; import android.hardware.vibrator.V1_0.EffectStrength; import android.os.ExternalVibrationScale; import android.os.VibrationAttributes; @@ -25,6 +24,7 @@ import android.os.VibrationEffect; import android.os.Vibrator; import android.os.vibrator.Flags; import android.os.vibrator.PrebakedSegment; +import android.os.vibrator.VibrationConfig; import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.SparseArray; @@ -37,8 +37,11 @@ import java.util.Locale; final class VibrationScaler { private static final String TAG = "VibrationScaler"; + // TODO(b/345186129): remove this once we finish migrating to scale factor and clean up flags. // Scale levels. Each level, except MUTE, is defined as the delta between the current setting // and the default intensity for that type of vibration (i.e. current - default). + // 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. static final int SCALE_VERY_LOW = ExternalVibrationScale.ScaleLevel.SCALE_VERY_LOW; // -2 static final int SCALE_LOW = ExternalVibrationScale.ScaleLevel.SCALE_LOW; // -1 static final int SCALE_NONE = ExternalVibrationScale.ScaleLevel.SCALE_NONE; // 0 @@ -53,35 +56,15 @@ final class VibrationScaler { private static final float SCALE_FACTOR_HIGH = 1.2f; private static final float SCALE_FACTOR_VERY_HIGH = 1.4f; - private static final ScaleLevel SCALE_LEVEL_NONE = new ScaleLevel(SCALE_FACTOR_NONE); - - // 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 VibrationSettings mSettingsController; private final int mDefaultVibrationAmplitude; + private final float mDefaultVibrationScaleLevelGain; private final SparseArray<Float> mAdaptiveHapticsScales = new SparseArray<>(); - VibrationScaler(Context context, VibrationSettings settingsController) { + VibrationScaler(VibrationConfig config, VibrationSettings settingsController) { mSettingsController = settingsController; - mDefaultVibrationAmplitude = context.getResources().getInteger( - com.android.internal.R.integer.config_defaultVibrationAmplitude); - - mScaleLevels = new SparseArray<>(); - mScaleLevels.put(SCALE_VERY_LOW, new ScaleLevel(SCALE_FACTOR_VERY_LOW)); - mScaleLevels.put(SCALE_LOW, new ScaleLevel(SCALE_FACTOR_LOW)); - mScaleLevels.put(SCALE_NONE, SCALE_LEVEL_NONE); - mScaleLevels.put(SCALE_HIGH, new ScaleLevel(SCALE_FACTOR_HIGH)); - mScaleLevels.put(SCALE_VERY_HIGH, new ScaleLevel(SCALE_FACTOR_VERY_HIGH)); - } - - /** - * Returns the default vibration amplitude configured for this device, value in [1,255]. - */ - public int getDefaultVibrationAmplitude() { - return mDefaultVibrationAmplitude; + mDefaultVibrationAmplitude = config.getDefaultVibrationAmplitude(); + mDefaultVibrationScaleLevelGain = config.getDefaultVibrationScaleLevelGain(); } /** @@ -111,6 +94,16 @@ final class VibrationScaler { } /** + * Calculates the scale factor to be applied to a vibration with given usage. + * + * @param usageHint one of VibrationAttributes.USAGE_* + * @return The scale factor. + */ + public float getScaleFactor(int usageHint) { + return scaleLevelToScaleFactor(getScaleLevel(usageHint)); + } + + /** * Returns the adaptive haptics scale that should be applied to the vibrations with * the given usage. When no adaptive scales are available for the usages, then returns 1 * indicating no scaling will be applied @@ -135,20 +128,12 @@ final class VibrationScaler { @NonNull public VibrationEffect scale(@NonNull VibrationEffect effect, int usageHint) { int newEffectStrength = getEffectStrength(usageHint); - ScaleLevel scaleLevel = mScaleLevels.get(getScaleLevel(usageHint)); + float scaleFactor = getScaleFactor(usageHint); float adaptiveScale = getAdaptiveHapticsScale(usageHint); - if (scaleLevel == null) { - // Something about our scaling has gone wrong, so just play with no scaling. - Slog.e(TAG, "No configured scaling level found! (current=" - + mSettingsController.getCurrentIntensity(usageHint) + ", default= " - + mSettingsController.getDefaultIntensity(usageHint) + ")"); - scaleLevel = SCALE_LEVEL_NONE; - } - return effect.resolve(mDefaultVibrationAmplitude) .applyEffectStrength(newEffectStrength) - .scale(scaleLevel.factor) + .scale(scaleFactor) .scaleLinearly(adaptiveScale); } @@ -192,14 +177,11 @@ final class VibrationScaler { void dump(IndentingPrintWriter pw) { pw.println("VibrationScaler:"); pw.increaseIndent(); - pw.println("defaultVibrationAmplitude = " + mDefaultVibrationAmplitude); pw.println("ScaleLevels:"); pw.increaseIndent(); - for (int i = 0; i < mScaleLevels.size(); i++) { - int scaleLevelKey = mScaleLevels.keyAt(i); - ScaleLevel scaleLevel = mScaleLevels.valueAt(i); - pw.println(scaleLevelToString(scaleLevelKey) + " = " + scaleLevel); + for (int level = SCALE_VERY_LOW; level <= SCALE_VERY_HIGH; level++) { + pw.println(scaleLevelToString(level) + " = " + scaleLevelToScaleFactor(level)); } pw.decreaseIndent(); @@ -224,16 +206,24 @@ final class VibrationScaler { @Override public String toString() { + StringBuilder scaleLevelsStr = new StringBuilder("{"); + for (int level = SCALE_VERY_LOW; level <= SCALE_VERY_HIGH; level++) { + scaleLevelsStr.append(scaleLevelToString(level)) + .append("=").append(scaleLevelToScaleFactor(level)); + if (level < SCALE_FACTOR_VERY_HIGH) { + scaleLevelsStr.append(", "); + } + } + scaleLevelsStr.append("}"); + return "VibrationScaler{" - + "mScaleLevels=" + mScaleLevels - + ", mDefaultVibrationAmplitude=" + mDefaultVibrationAmplitude + + "mScaleLevels=" + scaleLevelsStr + ", mAdaptiveHapticsScales=" + mAdaptiveHapticsScales + '}'; } private int getEffectStrength(int usageHint) { int currentIntensity = mSettingsController.getCurrentIntensity(usageHint); - if (currentIntensity == Vibrator.VIBRATION_INTENSITY_OFF) { // Bypassing user settings, or it has changed between checking and scaling. Use default. currentIntensity = mSettingsController.getDefaultIntensity(usageHint); @@ -244,17 +234,44 @@ final class VibrationScaler { /** Mapping of Vibrator.VIBRATION_INTENSITY_* values to {@link EffectStrength}. */ private static int intensityToEffectStrength(int intensity) { - switch (intensity) { - case Vibrator.VIBRATION_INTENSITY_LOW: - return EffectStrength.LIGHT; - case Vibrator.VIBRATION_INTENSITY_MEDIUM: - return EffectStrength.MEDIUM; - case Vibrator.VIBRATION_INTENSITY_HIGH: - return EffectStrength.STRONG; - default: + return switch (intensity) { + case Vibrator.VIBRATION_INTENSITY_LOW -> EffectStrength.LIGHT; + case Vibrator.VIBRATION_INTENSITY_MEDIUM -> EffectStrength.MEDIUM; + case Vibrator.VIBRATION_INTENSITY_HIGH -> EffectStrength.STRONG; + default -> { Slog.w(TAG, "Got unexpected vibration intensity: " + intensity); - return EffectStrength.STRONG; + yield EffectStrength.STRONG; + } + }; + } + + /** Mapping of ExternalVibrationScale.ScaleLevel.SCALE_* values to scale factor. */ + private float scaleLevelToScaleFactor(int level) { + if (Flags.hapticsScaleV2Enabled()) { + if (level == SCALE_NONE || level < SCALE_VERY_LOW || level > SCALE_VERY_HIGH) { + // Scale set to none or to a bad value, use default factor for no scaling. + return SCALE_FACTOR_NONE; + } + float scaleFactor = (float) Math.pow(mDefaultVibrationScaleLevelGain, level); + if (scaleFactor <= 0) { + // Something about our scaling has gone wrong, so just play with no scaling. + Slog.wtf(TAG, String.format(Locale.ROOT, "Error in scaling calculations, ended up" + + " with invalid scale factor %.2f for scale level %s and default" + + " level gain of %.2f", scaleFactor, scaleLevelToString(level), + mDefaultVibrationScaleLevelGain)); + scaleFactor = SCALE_FACTOR_NONE; + } + return scaleFactor; } + + return switch (level) { + case SCALE_VERY_LOW -> SCALE_FACTOR_VERY_LOW; + case SCALE_LOW -> SCALE_FACTOR_LOW; + case SCALE_HIGH -> SCALE_FACTOR_HIGH; + case SCALE_VERY_HIGH -> SCALE_FACTOR_VERY_HIGH; + // Scale set to none or to a bad value, use default factor for no scaling. + default -> SCALE_FACTOR_NONE; + }; } static String scaleLevelToString(int scaleLevel) { @@ -267,18 +284,4 @@ final class VibrationScaler { default -> String.valueOf(scaleLevel); }; } - - /** Represents the scale that must be applied to a vibration effect intensity. */ - private static final class ScaleLevel { - public final float factor; - - ScaleLevel(float factor) { - this.factor = factor; - } - - @Override - public String toString() { - return "ScaleLevel{factor=" + factor + "}"; - } - } } diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index 76872cf1274c..f2ad5b95fe5e 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -57,6 +57,7 @@ import android.os.VibrationEffect; import android.os.VibratorInfo; import android.os.vibrator.Flags; import android.os.vibrator.PrebakedSegment; +import android.os.vibrator.VibrationConfig; import android.os.vibrator.VibrationEffectSegment; import android.os.vibrator.VibratorInfoFactory; import android.os.vibrator.persistence.ParsedVibration; @@ -251,8 +252,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mHandler = injector.createHandler(Looper.myLooper()); mFrameworkStatsLogger = injector.getFrameworkStatsLogger(mHandler); - mVibrationSettings = new VibrationSettings(mContext, mHandler); - mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings); + VibrationConfig vibrationConfig = new VibrationConfig(context.getResources()); + mVibrationSettings = new VibrationSettings(mContext, mHandler, vibrationConfig); + mVibrationScaler = new VibrationScaler(vibrationConfig, mVibrationSettings); mVibratorControlService = new VibratorControlService(mContext, injector.createVibratorControllerHolder(), mVibrationScaler, mVibrationSettings, mFrameworkStatsLogger, mLock); @@ -1698,7 +1700,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { IBinder.DeathRecipient { public final ExternalVibration externalVibration; - public ExternalVibrationScale scale = new ExternalVibrationScale(); + public final ExternalVibrationScale scale = new ExternalVibrationScale(); private Vibration.Status mStatus; @@ -1712,8 +1714,18 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { mStatus = Vibration.Status.RUNNING; } + public void muteScale() { + scale.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE; + if (Flags.hapticsScaleV2Enabled()) { + scale.scaleFactor = 0; + } + } + public void scale(VibrationScaler scaler, int usage) { scale.scaleLevel = scaler.getScaleLevel(usage); + if (Flags.hapticsScaleV2Enabled()) { + scale.scaleFactor = scaler.getScaleFactor(usage); + } scale.adaptiveHapticsScale = scaler.getAdaptiveHapticsScale(usage); stats.reportAdaptiveScale(scale.adaptiveHapticsScale); } @@ -2047,7 +2059,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { // Create Vibration.Stats as close to the received request as possible, for tracking. ExternalVibrationHolder vibHolder = new ExternalVibrationHolder(vib); // Mute the request until we run all the checks and accept the vibration. - vibHolder.scale.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE; + vibHolder.muteScale(); boolean alreadyUnderExternalControl = false; boolean waitForCompletion = false; @@ -2146,7 +2158,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_CANCELLING), /* continueExternalControl= */ false); // Mute the request, vibration will be ignored. - vibHolder.scale.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE; + vibHolder.muteScale(); } return vibHolder.scale; } diff --git a/services/tests/vibrator/src/com/android/server/vibrator/DeviceAdapterTest.java b/services/tests/vibrator/src/com/android/server/vibrator/DeviceAdapterTest.java index 59d557777f3b..1493253a50d4 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/DeviceAdapterTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/DeviceAdapterTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.when; import android.content.ComponentName; +import android.content.Context; import android.content.pm.PackageManagerInternal; import android.hardware.vibrator.IVibrator; import android.os.CombinedVibration; @@ -32,11 +33,12 @@ import android.os.vibrator.PrebakedSegment; import android.os.vibrator.PrimitiveSegment; import android.os.vibrator.RampSegment; import android.os.vibrator.StepSegment; +import android.os.vibrator.VibrationConfig; import android.os.vibrator.VibrationEffectSegment; import android.platform.test.annotations.RequiresFlagsEnabled; import android.util.SparseArray; -import androidx.test.InstrumentationRegistry; +import androidx.test.core.app.ApplicationProvider; import com.android.server.LocalServices; @@ -76,9 +78,10 @@ public class DeviceAdapterTest { LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock); + Context context = ApplicationProvider.getApplicationContext(); mTestLooper = new TestLooper(); - mVibrationSettings = new VibrationSettings( - InstrumentationRegistry.getContext(), new Handler(mTestLooper.getLooper())); + mVibrationSettings = new VibrationSettings(context, new Handler(mTestLooper.getLooper()), + new VibrationConfig(context.getResources())); SparseArray<VibratorController> vibrators = new SparseArray<>(); vibrators.put(EMPTY_VIBRATOR_ID, createEmptyVibratorController(EMPTY_VIBRATOR_ID)); diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java index 9ebeaa8eb3fd..470469114dfa 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationScalerTest.java @@ -50,10 +50,9 @@ import android.os.vibrator.PrimitiveSegment; import android.os.vibrator.StepSegment; import android.os.vibrator.VibrationConfig; import android.os.vibrator.VibrationEffectSegment; -import android.platform.test.annotations.RequiresFlagsDisabled; -import android.platform.test.annotations.RequiresFlagsEnabled; -import android.platform.test.flag.junit.CheckFlagsRule; -import android.platform.test.flag.junit.DeviceFlagsValueProvider; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import androidx.test.InstrumentationRegistry; @@ -71,12 +70,13 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; public class VibrationScalerTest { + private static final float TOLERANCE = 1e-2f; + private static final int TEST_DEFAULT_AMPLITUDE = 255; + private static final float TEST_DEFAULT_SCALE_LEVEL_GAIN = 1.4f; @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); - @Rule - public final CheckFlagsRule mCheckFlagsRule = - DeviceFlagsValueProvider.createCheckFlagsRule(); + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private PowerManagerInternal mPowerManagerInternalMock; @Mock private PackageManagerInternal mPackageManagerInternalMock; @@ -96,6 +96,10 @@ public class VibrationScalerTest { when(mContextSpy.getContentResolver()).thenReturn(contentResolver); when(mPackageManagerInternalMock.getSystemUiServiceComponent()) .thenReturn(new ComponentName("", "")); + when(mVibrationConfigMock.getDefaultVibrationAmplitude()) + .thenReturn(TEST_DEFAULT_AMPLITUDE); + when(mVibrationConfigMock.getDefaultVibrationScaleLevelGain()) + .thenReturn(TEST_DEFAULT_SCALE_LEVEL_GAIN); LocalServices.removeServiceForTest(PackageManagerInternal.class); LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock); @@ -107,7 +111,7 @@ public class VibrationScalerTest { mVibrationSettings = new VibrationSettings( mContextSpy, new Handler(mTestLooper.getLooper()), mVibrationConfigMock); - mVibrationScaler = new VibrationScaler(mContextSpy, mVibrationSettings); + mVibrationScaler = new VibrationScaler(mVibrationConfigMock, mVibrationSettings); mVibrationSettings.onSystemReady(); } @@ -147,33 +151,76 @@ public class VibrationScalerTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) - public void testAdaptiveHapticsScale_withAdaptiveHapticsAvailable() { + @DisableFlags(Flags.FLAG_HAPTICS_SCALE_V2_ENABLED) + public void testGetScaleFactor_withLegacyScaling() { + // Default scale gain will be ignored. + when(mVibrationConfigMock.getDefaultVibrationScaleLevelGain()).thenReturn(1.4f); + mVibrationScaler = new VibrationScaler(mVibrationConfigMock, mVibrationSettings); + setDefaultIntensity(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_LOW); - setDefaultIntensity(USAGE_RINGTONE, Vibrator.VIBRATION_INTENSITY_LOW); setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH); - setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH); + assertEquals(1.4f, mVibrationScaler.getScaleFactor(USAGE_TOUCH), TOLERANCE); // VERY_HIGH + + setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_MEDIUM); + assertEquals(1.2f, mVibrationScaler.getScaleFactor(USAGE_TOUCH), TOLERANCE); // HIGH + + setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_LOW); + assertEquals(1f, mVibrationScaler.getScaleFactor(USAGE_TOUCH), TOLERANCE); // NONE + + setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_MEDIUM); + assertEquals(0.8f, mVibrationScaler.getScaleFactor(USAGE_TOUCH), TOLERANCE); // LOW + + setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_HIGH); + assertEquals(0.6f, mVibrationScaler.getScaleFactor(USAGE_TOUCH), TOLERANCE); // VERY_LOW + + setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF); + // Vibration setting being bypassed will use default setting and not scale. + assertEquals(1f, mVibrationScaler.getScaleFactor(USAGE_TOUCH), TOLERANCE); // NONE + } + + @Test + @EnableFlags(Flags.FLAG_HAPTICS_SCALE_V2_ENABLED) + public void testGetScaleFactor_withScalingV2() { + // Test scale factors for a default gain of 1.4 + when(mVibrationConfigMock.getDefaultVibrationScaleLevelGain()).thenReturn(1.4f); + mVibrationScaler = new VibrationScaler(mVibrationConfigMock, mVibrationSettings); + + setDefaultIntensity(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_LOW); + setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH); + assertEquals(1.95f, mVibrationScaler.getScaleFactor(USAGE_TOUCH), TOLERANCE); // VERY_HIGH + setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_MEDIUM); + assertEquals(1.4f, mVibrationScaler.getScaleFactor(USAGE_TOUCH), TOLERANCE); // HIGH + + setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_LOW); + assertEquals(1f, mVibrationScaler.getScaleFactor(USAGE_TOUCH), TOLERANCE); // NONE + + setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_MEDIUM); + assertEquals(0.71f, mVibrationScaler.getScaleFactor(USAGE_TOUCH), TOLERANCE); // LOW + + setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_HIGH); + assertEquals(0.51f, mVibrationScaler.getScaleFactor(USAGE_TOUCH), TOLERANCE); // VERY_LOW + + setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF); + // Vibration setting being bypassed will use default setting and not scale. + assertEquals(1f, mVibrationScaler.getScaleFactor(USAGE_TOUCH), TOLERANCE); // NONE + } + + @Test + @EnableFlags(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) + public void testAdaptiveHapticsScale_withAdaptiveHapticsAvailable() { mVibrationScaler.updateAdaptiveHapticsScale(USAGE_TOUCH, 0.5f); mVibrationScaler.updateAdaptiveHapticsScale(USAGE_RINGTONE, 0.2f); assertEquals(0.5f, mVibrationScaler.getAdaptiveHapticsScale(USAGE_TOUCH)); assertEquals(0.2f, mVibrationScaler.getAdaptiveHapticsScale(USAGE_RINGTONE)); assertEquals(1f, mVibrationScaler.getAdaptiveHapticsScale(USAGE_NOTIFICATION)); - - setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF); - // Vibration setting being bypassed will apply adaptive haptics scales. assertEquals(0.2f, mVibrationScaler.getAdaptiveHapticsScale(USAGE_RINGTONE)); } @Test - @RequiresFlagsDisabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) + @DisableFlags(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) public void testAdaptiveHapticsScale_flagDisabled_adaptiveHapticScaleAlwaysNone() { - setDefaultIntensity(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_LOW); - setDefaultIntensity(USAGE_RINGTONE, Vibrator.VIBRATION_INTENSITY_LOW); - setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH); - setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH); - mVibrationScaler.updateAdaptiveHapticsScale(USAGE_TOUCH, 0.5f); mVibrationScaler.updateAdaptiveHapticsScale(USAGE_RINGTONE, 0.2f); @@ -233,7 +280,7 @@ public class VibrationScalerTest { } @Test - @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS) + @EnableFlags(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS) public void scale_withVendorEffect_setsEffectStrengthBasedOnSettings() { setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_LOW); setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH); @@ -269,13 +316,13 @@ public class VibrationScalerTest { StepSegment resolved = getFirstSegment(mVibrationScaler.scale( VibrationEffect.createOneShot(10, VibrationEffect.DEFAULT_AMPLITUDE), USAGE_RINGTONE)); - assertTrue(resolved.getAmplitude() > 0); + assertEquals(TEST_DEFAULT_AMPLITUDE / 255f, resolved.getAmplitude(), TOLERANCE); resolved = getFirstSegment(mVibrationScaler.scale( VibrationEffect.createWaveform(new long[]{10}, new int[]{VibrationEffect.DEFAULT_AMPLITUDE}, -1), USAGE_RINGTONE)); - assertTrue(resolved.getAmplitude() > 0); + assertEquals(TEST_DEFAULT_AMPLITUDE / 255f, resolved.getAmplitude(), TOLERANCE); } @Test @@ -330,7 +377,7 @@ public class VibrationScalerTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) + @EnableFlags(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) public void scale_withAdaptiveHaptics_scalesVibrationsCorrectly() { setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_HIGH); setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_HIGH); @@ -351,7 +398,7 @@ public class VibrationScalerTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) + @EnableFlags(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) public void scale_clearAdaptiveHapticsScales_clearsAllCachedScales() { setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_HIGH); setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_HIGH); @@ -373,7 +420,7 @@ public class VibrationScalerTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) + @EnableFlags(Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED) public void scale_removeAdaptiveHapticsScale_removesCachedScale() { setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_HIGH); setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_HIGH); @@ -395,7 +442,7 @@ public class VibrationScalerTest { } @Test - @RequiresFlagsEnabled({ + @EnableFlags({ android.os.vibrator.Flags.FLAG_ADAPTIVE_HAPTICS_ENABLED, android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS, }) diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java index 3bd56deb32f4..0fbdce4ce61a 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java @@ -102,6 +102,8 @@ public class VibrationThreadTest { private static final String PACKAGE_NAME = "package"; private static final VibrationAttributes ATTRS = new VibrationAttributes.Builder().build(); private static final int TEST_RAMP_STEP_DURATION = 5; + private static final int TEST_DEFAULT_AMPLITUDE = 255; + private static final float TEST_DEFAULT_SCALE_LEVEL_GAIN = 1.4f; @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule @@ -133,6 +135,10 @@ public class VibrationThreadTest { when(mVibrationConfigMock.getDefaultVibrationIntensity(anyInt())) .thenReturn(Vibrator.VIBRATION_INTENSITY_MEDIUM); when(mVibrationConfigMock.getRampStepDurationMs()).thenReturn(TEST_RAMP_STEP_DURATION); + when(mVibrationConfigMock.getDefaultVibrationAmplitude()) + .thenReturn(TEST_DEFAULT_AMPLITUDE); + when(mVibrationConfigMock.getDefaultVibrationScaleLevelGain()) + .thenReturn(TEST_DEFAULT_SCALE_LEVEL_GAIN); when(mPackageManagerInternalMock.getSystemUiServiceComponent()) .thenReturn(new ComponentName("", "")); doAnswer(answer -> { @@ -146,7 +152,7 @@ public class VibrationThreadTest { Context context = InstrumentationRegistry.getContext(); mVibrationSettings = new VibrationSettings(context, new Handler(mTestLooper.getLooper()), mVibrationConfigMock); - mVibrationScaler = new VibrationScaler(context, mVibrationSettings); + mVibrationScaler = new VibrationScaler(mVibrationConfigMock, mVibrationSettings); mockVibrators(VIBRATOR_ID); diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java index c496bbb82630..79e272b7ec01 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorControlServiceTest.java @@ -37,6 +37,7 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.content.ComponentName; +import android.content.Context; import android.content.pm.PackageManagerInternal; import android.frameworks.vibrator.ScaleParam; import android.frameworks.vibrator.VibrationParam; @@ -46,6 +47,7 @@ import android.os.IBinder; import android.os.Process; import android.os.test.TestLooper; import android.os.vibrator.Flags; +import android.os.vibrator.VibrationConfig; import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; @@ -97,8 +99,9 @@ public class VibratorControlServiceTest { LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternalMock); TestLooper testLooper = new TestLooper(); - mVibrationSettings = new VibrationSettings( - ApplicationProvider.getApplicationContext(), new Handler(testLooper.getLooper())); + Context context = ApplicationProvider.getApplicationContext(); + mVibrationSettings = new VibrationSettings(context, new Handler(testLooper.getLooper()), + new VibrationConfig(context.getResources())); mFakeVibratorController = new FakeVibratorController(mTestLooper.getLooper()); mVibratorControlService = new VibratorControlService( |