Loading core/api/current.txt +5 −0 Original line number Diff line number Diff line Loading @@ -34266,9 +34266,14 @@ package android.os { method public final int areAllEffectsSupported(@NonNull int...); method public final boolean areAllPrimitivesSupported(@NonNull int...); method @NonNull public int[] areEffectsSupported(@NonNull int...); method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public boolean areEnvelopeEffectsSupported(); method @NonNull public boolean[] arePrimitivesSupported(@NonNull int...); method @RequiresPermission(android.Manifest.permission.VIBRATE) public abstract void cancel(); method public int getId(); method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public int getMaxEnvelopeEffectControlPointDurationMillis(); method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public int getMaxEnvelopeEffectDurationMillis(); method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public int getMaxEnvelopeEffectSize(); method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public int getMinEnvelopeEffectControlPointDurationMillis(); method @NonNull public int[] getPrimitiveDurations(@NonNull int...); method public float getQFactor(); method public float getResonantFrequency(); core/java/android/os/Vibrator.java +82 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.os; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -30,6 +31,7 @@ import android.content.Context; import android.content.res.Resources; import android.hardware.vibrator.IVibrator; import android.media.AudioAttributes; import android.os.vibrator.Flags; import android.os.vibrator.VibrationConfig; import android.os.vibrator.VibratorFrequencyProfile; import android.util.Log; Loading Loading @@ -312,6 +314,86 @@ public abstract class Vibrator { return getConfig().getHapticChannelMaximumAmplitude(); } /** * Checks whether the vibrator supports the creation of envelope effects. * * Envelope effects are defined by a series of frequency-amplitude pairs with specified * transition times, allowing the creation of more complex vibration patterns. * * @return True if the hardware supports creating envelope effects, false otherwise. */ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS) public boolean areEnvelopeEffectsSupported() { return getInfo().areEnvelopeEffectsSupported(); } /** * Retrieves the maximum duration supported for an envelope effect, in milliseconds. * * <p>If the device supports envelope effects (check {@link #areEnvelopeEffectsSupported}), * this value will be positive. Devices with envelope effects capabilities guarantees a * maximum duration equivalent to the product of {@link #getMaxEnvelopeEffectSize()} and * {@link #getMaxEnvelopeEffectControlPointDurationMillis()}. If the device does not support * envelope effects, this method will return 0. * * @return The maximum duration (in milliseconds) allowed for an envelope effect, or 0 if * envelope effects are not supported. */ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS) public int getMaxEnvelopeEffectDurationMillis() { return getInfo().getMaxEnvelopeEffectDurationMillis(); } /** * Retrieves the maximum number of control points supported for an envelope effect. * * <p>If the device supports envelope effects (check {@link #areEnvelopeEffectsSupported}), * this value will be positive. Devices with envelope effects capabilities guarantee support * for a minimum of 16 control points. If the device does not support envelope effects, * this method will return 0. * * @return the maximum number of control points allowed for an envelope effect, or 0 if * envelope effects are not supported. */ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS) public int getMaxEnvelopeEffectSize() { return getInfo().getMaxEnvelopeEffectSize(); } /** * Retrieves the minimum duration supported between two control points within an envelope * effect, in milliseconds. * * <p>If the device supports envelope effects (check {@link #areEnvelopeEffectsSupported}), * this value will be positive. Devices with envelope effects capabilities guarantee * support for durations down to at least 20 milliseconds. If the device does * not support envelope effects, this method will return 0. * * @return the minimum allowed duration between two control points in an envelope effect, * or 0 if envelope effects are not supported. */ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS) public int getMinEnvelopeEffectControlPointDurationMillis() { return getInfo().getMinEnvelopeEffectControlPointDurationMillis(); } /** * Retrieves the maximum duration supported between two control points within an envelope * effect, in milliseconds. * * <p>If the device supports envelope effects (check {@link #areEnvelopeEffectsSupported}), * this value will be positive. Devices with envelope effects capabilities guarantee support * for durations up to at least 1 second. If the device does not support envelope effects, * this method will return 0. * * @return the maximum allowed duration between two control points in an envelope effect, * or 0 if envelope effects are not supported. */ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS) public int getMaxEnvelopeEffectControlPointDurationMillis() { return getInfo().getMaxEnvelopeEffectControlPointDurationMillis(); } /** * Configure an always-on haptics effect. * Loading core/java/android/os/VibratorInfo.java +130 −4 Original line number Diff line number Diff line Loading @@ -60,6 +60,9 @@ public class VibratorInfo implements Parcelable { private final int mPwleSizeMax; private final float mQFactor; private final FrequencyProfile mFrequencyProfile; private final int mMaxEnvelopeEffectSize; private final int mMinEnvelopeEffectControlPointDurationMillis; private final int mMaxEnvelopeEffectControlPointDurationMillis; VibratorInfo(Parcel in) { mId = in.readInt(); Loading @@ -73,6 +76,9 @@ public class VibratorInfo implements Parcelable { mPwleSizeMax = in.readInt(); mQFactor = in.readFloat(); mFrequencyProfile = FrequencyProfile.CREATOR.createFromParcel(in); mMaxEnvelopeEffectSize = in.readInt(); mMinEnvelopeEffectControlPointDurationMillis = in.readInt(); mMaxEnvelopeEffectControlPointDurationMillis = in.readInt(); } public VibratorInfo(int id, @NonNull VibratorInfo baseVibratorInfo) { Loading @@ -80,7 +86,10 @@ public class VibratorInfo implements Parcelable { baseVibratorInfo.mSupportedBraking, baseVibratorInfo.mSupportedPrimitives, baseVibratorInfo.mPrimitiveDelayMax, baseVibratorInfo.mCompositionSizeMax, baseVibratorInfo.mPwlePrimitiveDurationMax, baseVibratorInfo.mPwleSizeMax, baseVibratorInfo.mQFactor, baseVibratorInfo.mFrequencyProfile); baseVibratorInfo.mQFactor, baseVibratorInfo.mFrequencyProfile, baseVibratorInfo.mMaxEnvelopeEffectSize, baseVibratorInfo.mMinEnvelopeEffectControlPointDurationMillis, baseVibratorInfo.mMaxEnvelopeEffectControlPointDurationMillis); } /** Loading Loading @@ -111,7 +120,9 @@ public class VibratorInfo implements Parcelable { @Nullable SparseBooleanArray supportedBraking, @NonNull SparseIntArray supportedPrimitives, int primitiveDelayMax, int compositionSizeMax, int pwlePrimitiveDurationMax, int pwleSizeMax, float qFactor, @NonNull FrequencyProfile frequencyProfile) { float qFactor, @NonNull FrequencyProfile frequencyProfile, int maxEnvelopeEffectSize, int minEnvelopeEffectControlPointDurationMillis, int maxEnvelopeEffectControlPointDurationMillis) { Preconditions.checkNotNull(supportedPrimitives); Preconditions.checkNotNull(frequencyProfile); mId = id; Loading @@ -125,6 +136,11 @@ public class VibratorInfo implements Parcelable { mPwleSizeMax = pwleSizeMax; mQFactor = qFactor; mFrequencyProfile = frequencyProfile; mMaxEnvelopeEffectSize = maxEnvelopeEffectSize; mMinEnvelopeEffectControlPointDurationMillis = minEnvelopeEffectControlPointDurationMillis; mMaxEnvelopeEffectControlPointDurationMillis = maxEnvelopeEffectControlPointDurationMillis; } @Override Loading @@ -140,6 +156,9 @@ public class VibratorInfo implements Parcelable { dest.writeInt(mPwleSizeMax); dest.writeFloat(mQFactor); mFrequencyProfile.writeToParcel(dest, flags); dest.writeInt(mMaxEnvelopeEffectSize); dest.writeInt(mMinEnvelopeEffectControlPointDurationMillis); dest.writeInt(mMaxEnvelopeEffectControlPointDurationMillis); } @Override Loading Loading @@ -186,7 +205,12 @@ public class VibratorInfo implements Parcelable { && Objects.equals(mSupportedEffects, that.mSupportedEffects) && Objects.equals(mSupportedBraking, that.mSupportedBraking) && Objects.equals(mQFactor, that.mQFactor) && Objects.equals(mFrequencyProfile, that.mFrequencyProfile); && Objects.equals(mFrequencyProfile, that.mFrequencyProfile) && mMaxEnvelopeEffectSize == that.mMaxEnvelopeEffectSize && mMinEnvelopeEffectControlPointDurationMillis == that.mMinEnvelopeEffectControlPointDurationMillis && mMaxEnvelopeEffectControlPointDurationMillis == that.mMaxEnvelopeEffectControlPointDurationMillis; } @Override Loading Loading @@ -215,6 +239,11 @@ public class VibratorInfo implements Parcelable { + ", mPwleSizeMax=" + mPwleSizeMax + ", mQFactor=" + mQFactor + ", mFrequencyProfile=" + mFrequencyProfile + ", mMaxEnvelopeEffectSize=" + mMaxEnvelopeEffectSize + ", mMinEnvelopeEffectControlPointDurationMillis=" + mMinEnvelopeEffectControlPointDurationMillis + ", mMaxEnvelopeEffectControlPointDurationMillis=" + mMaxEnvelopeEffectControlPointDurationMillis + '}'; } Loading @@ -234,6 +263,11 @@ public class VibratorInfo implements Parcelable { pw.println("pwleSizeMax = " + mPwleSizeMax); pw.println("q-factor = " + mQFactor); pw.println("frequencyProfile = " + mFrequencyProfile); pw.println("mMaxEnvelopeEffectSize = " + mMaxEnvelopeEffectSize); pw.println("mMinEnvelopeEffectControlPointDurationMillis = " + mMinEnvelopeEffectControlPointDurationMillis); pw.println("mMaxEnvelopeEffectControlPointDurationMillis = " + mMaxEnvelopeEffectControlPointDurationMillis); pw.decreaseIndent(); } Loading Loading @@ -413,6 +447,58 @@ public class VibratorInfo implements Parcelable { return mPwleSizeMax; } /** * Check whether the vibrator supports the creation of envelope effects. * * <p>See {@link Vibrator#areEnvelopeEffectsSupported()} for more information on envelope * effects. * * @return True if the hardware supports creating envelope effects, false otherwise. */ public boolean areEnvelopeEffectsSupported() { return hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2); } /** * Calculates the maximum allowed duration for an envelope effect, measured in milliseconds. * * @return The maximum duration (in milliseconds) that an envelope effect can have. */ public int getMaxEnvelopeEffectDurationMillis() { return mMaxEnvelopeEffectSize * mMaxEnvelopeEffectControlPointDurationMillis; } /** * Gets the maximum number of control points supported for envelope effects on this device. * * @return The maximum number of control points that can be used to define an envelope effect. */ public int getMaxEnvelopeEffectSize() { return mMaxEnvelopeEffectSize; } /** * Gets the minimum allowed duration for any individual segment within an envelope effect, * measured in milliseconds. * * @return The minimum duration (in milliseconds) that a segment within an envelope effect * can have. */ public int getMinEnvelopeEffectControlPointDurationMillis() { return mMinEnvelopeEffectControlPointDurationMillis; } /** * Gets the maximum allowed duration for any individual segment within an envelope effect, * measured in milliseconds. * * @return The maximum duration (in milliseconds) that a segment within an envelope effect * can have. */ public int getMaxEnvelopeEffectControlPointDurationMillis() { return mMaxEnvelopeEffectControlPointDurationMillis; } /** * Check against this vibrator capabilities. * Loading Loading @@ -489,6 +575,9 @@ public class VibratorInfo implements Parcelable { if (hasCapability(IVibrator.CAP_EXTERNAL_AMPLITUDE_CONTROL)) { names.add("EXTERNAL_AMPLITUDE_CONTROL"); } if (hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2)) { names.add("CAP_COMPOSE_PWLE_EFFECTS_V2"); } return names.toArray(new String[names.size()]); } Loading Loading @@ -745,6 +834,9 @@ public class VibratorInfo implements Parcelable { private float mQFactor = Float.NaN; private FrequencyProfile mFrequencyProfile = new FrequencyProfile(Float.NaN, Float.NaN, Float.NaN, null); private int mMaxEnvelopeEffectSize; private int mMinEnvelopeEffectControlPointDurationMillis; private int mMaxEnvelopeEffectControlPointDurationMillis; /** A builder class for a {@link VibratorInfo}. */ public Builder(int id) { Loading Loading @@ -821,12 +913,46 @@ public class VibratorInfo implements Parcelable { return this; } /** * Configure the maximum number of control points supported for envelope effects on this * device. */ @NonNull public Builder setMaxEnvelopeEffectSize(int maxEnvelopeEffectSize) { mMaxEnvelopeEffectSize = maxEnvelopeEffectSize; return this; } /** * Configure the minimum supported duration for any individual segment within an * envelope effect in milliseconds. */ @NonNull public Builder setMinEnvelopeEffectControlPointDurationMillis( int minEnvelopeEffectControlPointDuration) { mMinEnvelopeEffectControlPointDurationMillis = minEnvelopeEffectControlPointDuration; return this; } /** * Configure the maximum supported duration for any individual segment within an * envelope effect in milliseconds. */ @NonNull public Builder setMaxEnvelopeEffectControlPointDurationMillis( int maxEnvelopeEffectControlPointDuration) { mMaxEnvelopeEffectControlPointDurationMillis = maxEnvelopeEffectControlPointDuration; return this; } /** Build the configured {@link VibratorInfo}. */ @NonNull public VibratorInfo build() { return new VibratorInfo(mId, mCapabilities, mSupportedEffects, mSupportedBraking, mSupportedPrimitives, mPrimitiveDelayMax, mCompositionSizeMax, mPwlePrimitiveDurationMax, mPwleSizeMax, mQFactor, mFrequencyProfile); mPwlePrimitiveDurationMax, mPwleSizeMax, mQFactor, mFrequencyProfile, mMaxEnvelopeEffectSize, mMinEnvelopeEffectControlPointDurationMillis, mMaxEnvelopeEffectControlPointDurationMillis); } /** Loading core/java/android/os/vibrator/MultiVibratorInfo.java +7 −1 Original line number Diff line number Diff line Loading @@ -59,7 +59,13 @@ public final class MultiVibratorInfo extends VibratorInfo { integerLimitIntersection(vibrators, VibratorInfo::getPwlePrimitiveDurationMax), integerLimitIntersection(vibrators, VibratorInfo::getPwleSizeMax), floatPropertyIntersection(vibrators, VibratorInfo::getQFactor), mergedProfile); mergedProfile, integerLimitIntersection(vibrators, VibratorInfo::getMaxEnvelopeEffectSize), integerLimitIntersection(vibrators, VibratorInfo::getMinEnvelopeEffectControlPointDurationMillis), integerLimitIntersection(vibrators, VibratorInfo::getMaxEnvelopeEffectControlPointDurationMillis)); } private static int capabilitiesIntersection(VibratorInfo[] infos, Loading core/tests/vibrator/src/android/os/VibratorInfoTest.java +42 −10 Original line number Diff line number Diff line Loading @@ -138,6 +138,35 @@ public class VibratorInfoTest { assertEquals(0, emptyInfo.getPwleSizeMax()); } @Test public void testAreEnvelopeEffectsSupported() { VibratorInfo noCapabilities = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build(); assertFalse(noCapabilities.areEnvelopeEffectsSupported()); VibratorInfo envelopeEffectCapability = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2) .build(); assertTrue(envelopeEffectCapability.areEnvelopeEffectsSupported()); } @Test public void testEnvelopeEffectLimits() { VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setMaxEnvelopeEffectSize(16) .setMinEnvelopeEffectControlPointDurationMillis(20) .setMaxEnvelopeEffectControlPointDurationMillis(1_000) .build(); assertEquals(16, info.getMaxEnvelopeEffectSize()); assertEquals(20, info.getMinEnvelopeEffectControlPointDurationMillis()); assertEquals(1_000, info.getMaxEnvelopeEffectControlPointDurationMillis()); assertEquals(16_000, info.getMaxEnvelopeEffectDurationMillis()); VibratorInfo emptyInfo = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build(); assertEquals(0, emptyInfo.getMaxEnvelopeEffectSize()); assertEquals(0, emptyInfo.getMinEnvelopeEffectControlPointDurationMillis()); assertEquals(0, emptyInfo.getMaxEnvelopeEffectControlPointDurationMillis()); assertEquals(0, emptyInfo.getMaxEnvelopeEffectDurationMillis()); } @Test public void testGetDefaultBraking_returnsFirstSupportedBraking() { assertEquals(Braking.NONE, new VibratorInfo.Builder( Loading Loading @@ -272,7 +301,10 @@ public class VibratorInfoTest { .setPwlePrimitiveDurationMax(50) .setPwleSizeMax(20) .setQFactor(2f) .setFrequencyProfile(TEST_FREQUENCY_PROFILE); .setFrequencyProfile(TEST_FREQUENCY_PROFILE) .setMaxEnvelopeEffectSize(16) .setMinEnvelopeEffectControlPointDurationMillis(20) .setMaxEnvelopeEffectControlPointDurationMillis(1_000); } VibratorInfo complete = completeBuilder.build(); Loading Loading
core/api/current.txt +5 −0 Original line number Diff line number Diff line Loading @@ -34266,9 +34266,14 @@ package android.os { method public final int areAllEffectsSupported(@NonNull int...); method public final boolean areAllPrimitivesSupported(@NonNull int...); method @NonNull public int[] areEffectsSupported(@NonNull int...); method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public boolean areEnvelopeEffectsSupported(); method @NonNull public boolean[] arePrimitivesSupported(@NonNull int...); method @RequiresPermission(android.Manifest.permission.VIBRATE) public abstract void cancel(); method public int getId(); method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public int getMaxEnvelopeEffectControlPointDurationMillis(); method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public int getMaxEnvelopeEffectDurationMillis(); method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public int getMaxEnvelopeEffectSize(); method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public int getMinEnvelopeEffectControlPointDurationMillis(); method @NonNull public int[] getPrimitiveDurations(@NonNull int...); method public float getQFactor(); method public float getResonantFrequency();
core/java/android/os/Vibrator.java +82 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.os; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -30,6 +31,7 @@ import android.content.Context; import android.content.res.Resources; import android.hardware.vibrator.IVibrator; import android.media.AudioAttributes; import android.os.vibrator.Flags; import android.os.vibrator.VibrationConfig; import android.os.vibrator.VibratorFrequencyProfile; import android.util.Log; Loading Loading @@ -312,6 +314,86 @@ public abstract class Vibrator { return getConfig().getHapticChannelMaximumAmplitude(); } /** * Checks whether the vibrator supports the creation of envelope effects. * * Envelope effects are defined by a series of frequency-amplitude pairs with specified * transition times, allowing the creation of more complex vibration patterns. * * @return True if the hardware supports creating envelope effects, false otherwise. */ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS) public boolean areEnvelopeEffectsSupported() { return getInfo().areEnvelopeEffectsSupported(); } /** * Retrieves the maximum duration supported for an envelope effect, in milliseconds. * * <p>If the device supports envelope effects (check {@link #areEnvelopeEffectsSupported}), * this value will be positive. Devices with envelope effects capabilities guarantees a * maximum duration equivalent to the product of {@link #getMaxEnvelopeEffectSize()} and * {@link #getMaxEnvelopeEffectControlPointDurationMillis()}. If the device does not support * envelope effects, this method will return 0. * * @return The maximum duration (in milliseconds) allowed for an envelope effect, or 0 if * envelope effects are not supported. */ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS) public int getMaxEnvelopeEffectDurationMillis() { return getInfo().getMaxEnvelopeEffectDurationMillis(); } /** * Retrieves the maximum number of control points supported for an envelope effect. * * <p>If the device supports envelope effects (check {@link #areEnvelopeEffectsSupported}), * this value will be positive. Devices with envelope effects capabilities guarantee support * for a minimum of 16 control points. If the device does not support envelope effects, * this method will return 0. * * @return the maximum number of control points allowed for an envelope effect, or 0 if * envelope effects are not supported. */ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS) public int getMaxEnvelopeEffectSize() { return getInfo().getMaxEnvelopeEffectSize(); } /** * Retrieves the minimum duration supported between two control points within an envelope * effect, in milliseconds. * * <p>If the device supports envelope effects (check {@link #areEnvelopeEffectsSupported}), * this value will be positive. Devices with envelope effects capabilities guarantee * support for durations down to at least 20 milliseconds. If the device does * not support envelope effects, this method will return 0. * * @return the minimum allowed duration between two control points in an envelope effect, * or 0 if envelope effects are not supported. */ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS) public int getMinEnvelopeEffectControlPointDurationMillis() { return getInfo().getMinEnvelopeEffectControlPointDurationMillis(); } /** * Retrieves the maximum duration supported between two control points within an envelope * effect, in milliseconds. * * <p>If the device supports envelope effects (check {@link #areEnvelopeEffectsSupported}), * this value will be positive. Devices with envelope effects capabilities guarantee support * for durations up to at least 1 second. If the device does not support envelope effects, * this method will return 0. * * @return the maximum allowed duration between two control points in an envelope effect, * or 0 if envelope effects are not supported. */ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS) public int getMaxEnvelopeEffectControlPointDurationMillis() { return getInfo().getMaxEnvelopeEffectControlPointDurationMillis(); } /** * Configure an always-on haptics effect. * Loading
core/java/android/os/VibratorInfo.java +130 −4 Original line number Diff line number Diff line Loading @@ -60,6 +60,9 @@ public class VibratorInfo implements Parcelable { private final int mPwleSizeMax; private final float mQFactor; private final FrequencyProfile mFrequencyProfile; private final int mMaxEnvelopeEffectSize; private final int mMinEnvelopeEffectControlPointDurationMillis; private final int mMaxEnvelopeEffectControlPointDurationMillis; VibratorInfo(Parcel in) { mId = in.readInt(); Loading @@ -73,6 +76,9 @@ public class VibratorInfo implements Parcelable { mPwleSizeMax = in.readInt(); mQFactor = in.readFloat(); mFrequencyProfile = FrequencyProfile.CREATOR.createFromParcel(in); mMaxEnvelopeEffectSize = in.readInt(); mMinEnvelopeEffectControlPointDurationMillis = in.readInt(); mMaxEnvelopeEffectControlPointDurationMillis = in.readInt(); } public VibratorInfo(int id, @NonNull VibratorInfo baseVibratorInfo) { Loading @@ -80,7 +86,10 @@ public class VibratorInfo implements Parcelable { baseVibratorInfo.mSupportedBraking, baseVibratorInfo.mSupportedPrimitives, baseVibratorInfo.mPrimitiveDelayMax, baseVibratorInfo.mCompositionSizeMax, baseVibratorInfo.mPwlePrimitiveDurationMax, baseVibratorInfo.mPwleSizeMax, baseVibratorInfo.mQFactor, baseVibratorInfo.mFrequencyProfile); baseVibratorInfo.mQFactor, baseVibratorInfo.mFrequencyProfile, baseVibratorInfo.mMaxEnvelopeEffectSize, baseVibratorInfo.mMinEnvelopeEffectControlPointDurationMillis, baseVibratorInfo.mMaxEnvelopeEffectControlPointDurationMillis); } /** Loading Loading @@ -111,7 +120,9 @@ public class VibratorInfo implements Parcelable { @Nullable SparseBooleanArray supportedBraking, @NonNull SparseIntArray supportedPrimitives, int primitiveDelayMax, int compositionSizeMax, int pwlePrimitiveDurationMax, int pwleSizeMax, float qFactor, @NonNull FrequencyProfile frequencyProfile) { float qFactor, @NonNull FrequencyProfile frequencyProfile, int maxEnvelopeEffectSize, int minEnvelopeEffectControlPointDurationMillis, int maxEnvelopeEffectControlPointDurationMillis) { Preconditions.checkNotNull(supportedPrimitives); Preconditions.checkNotNull(frequencyProfile); mId = id; Loading @@ -125,6 +136,11 @@ public class VibratorInfo implements Parcelable { mPwleSizeMax = pwleSizeMax; mQFactor = qFactor; mFrequencyProfile = frequencyProfile; mMaxEnvelopeEffectSize = maxEnvelopeEffectSize; mMinEnvelopeEffectControlPointDurationMillis = minEnvelopeEffectControlPointDurationMillis; mMaxEnvelopeEffectControlPointDurationMillis = maxEnvelopeEffectControlPointDurationMillis; } @Override Loading @@ -140,6 +156,9 @@ public class VibratorInfo implements Parcelable { dest.writeInt(mPwleSizeMax); dest.writeFloat(mQFactor); mFrequencyProfile.writeToParcel(dest, flags); dest.writeInt(mMaxEnvelopeEffectSize); dest.writeInt(mMinEnvelopeEffectControlPointDurationMillis); dest.writeInt(mMaxEnvelopeEffectControlPointDurationMillis); } @Override Loading Loading @@ -186,7 +205,12 @@ public class VibratorInfo implements Parcelable { && Objects.equals(mSupportedEffects, that.mSupportedEffects) && Objects.equals(mSupportedBraking, that.mSupportedBraking) && Objects.equals(mQFactor, that.mQFactor) && Objects.equals(mFrequencyProfile, that.mFrequencyProfile); && Objects.equals(mFrequencyProfile, that.mFrequencyProfile) && mMaxEnvelopeEffectSize == that.mMaxEnvelopeEffectSize && mMinEnvelopeEffectControlPointDurationMillis == that.mMinEnvelopeEffectControlPointDurationMillis && mMaxEnvelopeEffectControlPointDurationMillis == that.mMaxEnvelopeEffectControlPointDurationMillis; } @Override Loading Loading @@ -215,6 +239,11 @@ public class VibratorInfo implements Parcelable { + ", mPwleSizeMax=" + mPwleSizeMax + ", mQFactor=" + mQFactor + ", mFrequencyProfile=" + mFrequencyProfile + ", mMaxEnvelopeEffectSize=" + mMaxEnvelopeEffectSize + ", mMinEnvelopeEffectControlPointDurationMillis=" + mMinEnvelopeEffectControlPointDurationMillis + ", mMaxEnvelopeEffectControlPointDurationMillis=" + mMaxEnvelopeEffectControlPointDurationMillis + '}'; } Loading @@ -234,6 +263,11 @@ public class VibratorInfo implements Parcelable { pw.println("pwleSizeMax = " + mPwleSizeMax); pw.println("q-factor = " + mQFactor); pw.println("frequencyProfile = " + mFrequencyProfile); pw.println("mMaxEnvelopeEffectSize = " + mMaxEnvelopeEffectSize); pw.println("mMinEnvelopeEffectControlPointDurationMillis = " + mMinEnvelopeEffectControlPointDurationMillis); pw.println("mMaxEnvelopeEffectControlPointDurationMillis = " + mMaxEnvelopeEffectControlPointDurationMillis); pw.decreaseIndent(); } Loading Loading @@ -413,6 +447,58 @@ public class VibratorInfo implements Parcelable { return mPwleSizeMax; } /** * Check whether the vibrator supports the creation of envelope effects. * * <p>See {@link Vibrator#areEnvelopeEffectsSupported()} for more information on envelope * effects. * * @return True if the hardware supports creating envelope effects, false otherwise. */ public boolean areEnvelopeEffectsSupported() { return hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2); } /** * Calculates the maximum allowed duration for an envelope effect, measured in milliseconds. * * @return The maximum duration (in milliseconds) that an envelope effect can have. */ public int getMaxEnvelopeEffectDurationMillis() { return mMaxEnvelopeEffectSize * mMaxEnvelopeEffectControlPointDurationMillis; } /** * Gets the maximum number of control points supported for envelope effects on this device. * * @return The maximum number of control points that can be used to define an envelope effect. */ public int getMaxEnvelopeEffectSize() { return mMaxEnvelopeEffectSize; } /** * Gets the minimum allowed duration for any individual segment within an envelope effect, * measured in milliseconds. * * @return The minimum duration (in milliseconds) that a segment within an envelope effect * can have. */ public int getMinEnvelopeEffectControlPointDurationMillis() { return mMinEnvelopeEffectControlPointDurationMillis; } /** * Gets the maximum allowed duration for any individual segment within an envelope effect, * measured in milliseconds. * * @return The maximum duration (in milliseconds) that a segment within an envelope effect * can have. */ public int getMaxEnvelopeEffectControlPointDurationMillis() { return mMaxEnvelopeEffectControlPointDurationMillis; } /** * Check against this vibrator capabilities. * Loading Loading @@ -489,6 +575,9 @@ public class VibratorInfo implements Parcelable { if (hasCapability(IVibrator.CAP_EXTERNAL_AMPLITUDE_CONTROL)) { names.add("EXTERNAL_AMPLITUDE_CONTROL"); } if (hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2)) { names.add("CAP_COMPOSE_PWLE_EFFECTS_V2"); } return names.toArray(new String[names.size()]); } Loading Loading @@ -745,6 +834,9 @@ public class VibratorInfo implements Parcelable { private float mQFactor = Float.NaN; private FrequencyProfile mFrequencyProfile = new FrequencyProfile(Float.NaN, Float.NaN, Float.NaN, null); private int mMaxEnvelopeEffectSize; private int mMinEnvelopeEffectControlPointDurationMillis; private int mMaxEnvelopeEffectControlPointDurationMillis; /** A builder class for a {@link VibratorInfo}. */ public Builder(int id) { Loading Loading @@ -821,12 +913,46 @@ public class VibratorInfo implements Parcelable { return this; } /** * Configure the maximum number of control points supported for envelope effects on this * device. */ @NonNull public Builder setMaxEnvelopeEffectSize(int maxEnvelopeEffectSize) { mMaxEnvelopeEffectSize = maxEnvelopeEffectSize; return this; } /** * Configure the minimum supported duration for any individual segment within an * envelope effect in milliseconds. */ @NonNull public Builder setMinEnvelopeEffectControlPointDurationMillis( int minEnvelopeEffectControlPointDuration) { mMinEnvelopeEffectControlPointDurationMillis = minEnvelopeEffectControlPointDuration; return this; } /** * Configure the maximum supported duration for any individual segment within an * envelope effect in milliseconds. */ @NonNull public Builder setMaxEnvelopeEffectControlPointDurationMillis( int maxEnvelopeEffectControlPointDuration) { mMaxEnvelopeEffectControlPointDurationMillis = maxEnvelopeEffectControlPointDuration; return this; } /** Build the configured {@link VibratorInfo}. */ @NonNull public VibratorInfo build() { return new VibratorInfo(mId, mCapabilities, mSupportedEffects, mSupportedBraking, mSupportedPrimitives, mPrimitiveDelayMax, mCompositionSizeMax, mPwlePrimitiveDurationMax, mPwleSizeMax, mQFactor, mFrequencyProfile); mPwlePrimitiveDurationMax, mPwleSizeMax, mQFactor, mFrequencyProfile, mMaxEnvelopeEffectSize, mMinEnvelopeEffectControlPointDurationMillis, mMaxEnvelopeEffectControlPointDurationMillis); } /** Loading
core/java/android/os/vibrator/MultiVibratorInfo.java +7 −1 Original line number Diff line number Diff line Loading @@ -59,7 +59,13 @@ public final class MultiVibratorInfo extends VibratorInfo { integerLimitIntersection(vibrators, VibratorInfo::getPwlePrimitiveDurationMax), integerLimitIntersection(vibrators, VibratorInfo::getPwleSizeMax), floatPropertyIntersection(vibrators, VibratorInfo::getQFactor), mergedProfile); mergedProfile, integerLimitIntersection(vibrators, VibratorInfo::getMaxEnvelopeEffectSize), integerLimitIntersection(vibrators, VibratorInfo::getMinEnvelopeEffectControlPointDurationMillis), integerLimitIntersection(vibrators, VibratorInfo::getMaxEnvelopeEffectControlPointDurationMillis)); } private static int capabilitiesIntersection(VibratorInfo[] infos, Loading
core/tests/vibrator/src/android/os/VibratorInfoTest.java +42 −10 Original line number Diff line number Diff line Loading @@ -138,6 +138,35 @@ public class VibratorInfoTest { assertEquals(0, emptyInfo.getPwleSizeMax()); } @Test public void testAreEnvelopeEffectsSupported() { VibratorInfo noCapabilities = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build(); assertFalse(noCapabilities.areEnvelopeEffectsSupported()); VibratorInfo envelopeEffectCapability = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2) .build(); assertTrue(envelopeEffectCapability.areEnvelopeEffectsSupported()); } @Test public void testEnvelopeEffectLimits() { VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setMaxEnvelopeEffectSize(16) .setMinEnvelopeEffectControlPointDurationMillis(20) .setMaxEnvelopeEffectControlPointDurationMillis(1_000) .build(); assertEquals(16, info.getMaxEnvelopeEffectSize()); assertEquals(20, info.getMinEnvelopeEffectControlPointDurationMillis()); assertEquals(1_000, info.getMaxEnvelopeEffectControlPointDurationMillis()); assertEquals(16_000, info.getMaxEnvelopeEffectDurationMillis()); VibratorInfo emptyInfo = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build(); assertEquals(0, emptyInfo.getMaxEnvelopeEffectSize()); assertEquals(0, emptyInfo.getMinEnvelopeEffectControlPointDurationMillis()); assertEquals(0, emptyInfo.getMaxEnvelopeEffectControlPointDurationMillis()); assertEquals(0, emptyInfo.getMaxEnvelopeEffectDurationMillis()); } @Test public void testGetDefaultBraking_returnsFirstSupportedBraking() { assertEquals(Braking.NONE, new VibratorInfo.Builder( Loading Loading @@ -272,7 +301,10 @@ public class VibratorInfoTest { .setPwlePrimitiveDurationMax(50) .setPwleSizeMax(20) .setQFactor(2f) .setFrequencyProfile(TEST_FREQUENCY_PROFILE); .setFrequencyProfile(TEST_FREQUENCY_PROFILE) .setMaxEnvelopeEffectSize(16) .setMinEnvelopeEffectControlPointDurationMillis(20) .setMaxEnvelopeEffectControlPointDurationMillis(1_000); } VibratorInfo complete = completeBuilder.build(); Loading