diff options
| -rw-r--r-- | core/api/current.txt | 15 | ||||
| -rw-r--r-- | core/java/android/os/VibrationEffect.java | 9 | ||||
| -rw-r--r-- | core/java/android/os/Vibrator.java | 84 | ||||
| -rw-r--r-- | core/java/android/os/VibratorInfo.java | 2 | ||||
| -rw-r--r-- | core/java/android/os/vibrator/VibratorEnvelopeEffectInfo.java | 197 | ||||
| -rw-r--r-- | services/core/java/com/android/server/vibrator/SplitPwleSegmentsAdapter.java | 2 |
6 files changed, 240 insertions, 69 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index c8fe24df5c8b..0e9910bf7a50 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -34614,12 +34614,9 @@ package android.os { 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 @FlaggedApi("android.os.vibrator.normalized_pwle_effects") @NonNull public android.os.vibrator.VibratorEnvelopeEffectInfo getEnvelopeEffectInfo(); method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") @Nullable public android.os.vibrator.VibratorFrequencyProfile getFrequencyProfile(); 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(); @@ -34970,6 +34967,16 @@ package android.os.strictmode { package android.os.vibrator { + @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public final class VibratorEnvelopeEffectInfo implements android.os.Parcelable { + method public int describeContents(); + method public long getMaxControlPointDurationMillis(); + method public long getMaxDurationMillis(); + method public int getMaxSize(); + method public long getMinControlPointDurationMillis(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.VibratorEnvelopeEffectInfo> CREATOR; + } + @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public final class VibratorFrequencyProfile { method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") @NonNull public android.util.SparseArray<java.lang.Float> getFrequenciesOutputAcceleration(); method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") @Nullable public android.util.Range<java.lang.Float> getFrequencyRange(float); diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index 0cffd9f990fd..a721a2208f24 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -41,6 +41,7 @@ import android.os.vibrator.PwleSegment; import android.os.vibrator.RampSegment; import android.os.vibrator.StepSegment; import android.os.vibrator.VibrationEffectSegment; +import android.os.vibrator.VibratorEnvelopeEffectInfo; import android.os.vibrator.VibratorFrequencyProfileLegacy; import android.util.MathUtils; @@ -1819,12 +1820,12 @@ public abstract class VibrationEffect implements Parcelable { * * <p>You can use the following APIs to obtain these limits: * <ul> - * <li>Maximum envelope control points: {@link Vibrator#getMaxEnvelopeEffectSize()}</li> + * <li>Maximum envelope control points: {@link VibratorEnvelopeEffectInfo#getMaxSize()} * <li>Minimum control point duration: - * {@link Vibrator#getMinEnvelopeEffectControlPointDurationMillis()}</li> + * {@link VibratorEnvelopeEffectInfo#getMinControlPointDurationMillis()} * <li>Maximum control point duration: - * {@link Vibrator#getMaxEnvelopeEffectControlPointDurationMillis()}</li> - * <li>Maximum total effect duration: {@link Vibrator#getMaxEnvelopeEffectDurationMillis()}</li> + * {@link VibratorEnvelopeEffectInfo#getMaxControlPointDurationMillis()} + * <li>Maximum total effect duration: {@link VibratorEnvelopeEffectInfo#getMaxDurationMillis()} * </ul> * * @see VibrationEffect#startWaveformEnvelope() diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java index 53f8a9267499..86209140ce51 100644 --- a/core/java/android/os/Vibrator.java +++ b/core/java/android/os/Vibrator.java @@ -35,6 +35,7 @@ import android.media.AudioAttributes; import android.os.vibrator.Flags; import android.os.vibrator.VendorVibrationSession; import android.os.vibrator.VibrationConfig; +import android.os.vibrator.VibratorEnvelopeEffectInfo; import android.os.vibrator.VibratorFrequencyProfile; import android.os.vibrator.VibratorFrequencyProfileLegacy; import android.util.Log; @@ -137,6 +138,9 @@ public abstract class Vibrator { @Nullable private volatile VibrationConfig mVibrationConfig; + private VibratorFrequencyProfile mVibratorFrequencyProfile; + private VibratorEnvelopeEffectInfo mVibratorEnvelopeEffectInfo; + /** * @hide to prevent subclassing from outside of the framework */ @@ -351,7 +355,11 @@ public abstract class Vibrator { return null; } - return new VibratorFrequencyProfile(frequencyProfile); + if (mVibratorFrequencyProfile == null) { + mVibratorFrequencyProfile = new VibratorFrequencyProfile(frequencyProfile); + } + + return mVibratorFrequencyProfile; } /** @@ -383,70 +391,28 @@ public abstract class Vibrator { } /** - * 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. + * Retrieves the vibrator's capabilities and limitations for envelope effects. * - * @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>These parameters can be used with {@link VibrationEffect.WaveformEnvelopeBuilder} + * to create custom envelope effects. * - * <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 vibrator's envelope effect information, or null if not supported. If this + * vibrator is a composite of multiple physical devices then this will return a profile + * supported in all devices, or null if the intersection is empty or not available. * - * @return the minimum allowed duration between two control points in an envelope effect, - * or 0 if envelope effects are not supported. + * @see VibrationEffect.WaveformEnvelopeBuilder */ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS) - public int getMinEnvelopeEffectControlPointDurationMillis() { - return getInfo().getMinEnvelopeEffectControlPointDurationMillis(); - } + @NonNull + public VibratorEnvelopeEffectInfo getEnvelopeEffectInfo() { + if (mVibratorEnvelopeEffectInfo == null) { + mVibratorEnvelopeEffectInfo = new VibratorEnvelopeEffectInfo( + getInfo().getMaxEnvelopeEffectSize(), + getInfo().getMinEnvelopeEffectControlPointDurationMillis(), + getInfo().getMaxEnvelopeEffectControlPointDurationMillis()); + } - /** - * 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(); + return mVibratorEnvelopeEffectInfo; } /** diff --git a/core/java/android/os/VibratorInfo.java b/core/java/android/os/VibratorInfo.java index 9dec8673f019..84325a4ac70b 100644 --- a/core/java/android/os/VibratorInfo.java +++ b/core/java/android/os/VibratorInfo.java @@ -121,7 +121,7 @@ public class VibratorInfo implements Parcelable { * @param qFactor The vibrator quality factor. * @param frequencyProfileLegacy The description of the vibrator supported frequencies and max * amplitude mappings. - * @param frequencyProfile The description of the vibrator supported frequencies and + * @param frequencyProfile The description of the vibrator supported frequencies and * output acceleration mappings. * @param maxEnvelopeEffectSize The maximum number of control points supported for an * envelope effect. diff --git a/core/java/android/os/vibrator/VibratorEnvelopeEffectInfo.java b/core/java/android/os/vibrator/VibratorEnvelopeEffectInfo.java new file mode 100644 index 000000000000..f2ad7a402b60 --- /dev/null +++ b/core/java/android/os/vibrator/VibratorEnvelopeEffectInfo.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os.vibrator; + +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.VibrationEffect; + +import java.util.Objects; + +/** + * Provides information about the vibrator hardware capabilities and limitations regarding + * waveform envelope effects. This includes: + * <ul> + * <li>Maximum number of control points supported. + * <li>Minimum and maximum duration for individual segments. + * <li>Maximum total duration for an envelope effect. + * </ul> + * + * <p>This information can be used to help construct waveform envelope effects with + * {@link VibrationEffect#startWaveformEnvelope()}. When designing these effects, it is also + * recommended to check the {@link VibratorFrequencyProfile} for information about the supported + * frequency range and the vibrator's output response. + * + * @see VibrationEffect#startWaveformEnvelope() + * @see VibratorFrequencyProfile + */ +@FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS) +public final class VibratorEnvelopeEffectInfo implements Parcelable { + private final int mMaxSize; + private final long mMinControlPointDurationMillis; + private final long mMaxControlPointDurationMillis; + + VibratorEnvelopeEffectInfo(Parcel in) { + mMaxSize = in.readInt(); + mMinControlPointDurationMillis = in.readLong(); + mMaxControlPointDurationMillis = in.readLong(); + } + + /** + * Default constructor. + * + * @param maxSize The maximum number of control points supported for an + * envelope effect. + * @param minControlPointDurationMillis The minimum duration supported between two control + * points within an envelope effect. + * @param maxControlPointDurationMillis The maximum duration supported between two control + * points within an envelope effect. + * @hide + */ + public VibratorEnvelopeEffectInfo(int maxSize, + long minControlPointDurationMillis, + long maxControlPointDurationMillis) { + mMaxSize = maxSize; + mMinControlPointDurationMillis = minControlPointDurationMillis; + mMaxControlPointDurationMillis = maxControlPointDurationMillis; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mMaxSize); + dest.writeLong(mMinControlPointDurationMillis); + dest.writeLong(mMaxControlPointDurationMillis); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof VibratorEnvelopeEffectInfo)) { + return false; + } + VibratorEnvelopeEffectInfo other = (VibratorEnvelopeEffectInfo) o; + return mMaxSize == other.mMaxSize + && mMinControlPointDurationMillis == other.mMinControlPointDurationMillis + && mMaxControlPointDurationMillis == other.mMaxControlPointDurationMillis; + } + + @Override + public int hashCode() { + return Objects.hash(mMaxSize, + mMinControlPointDurationMillis, + mMaxControlPointDurationMillis); + } + + @Override + public String toString() { + return "VibratorEnvelopeEffectInfo{" + + ", mMaxSize=" + mMaxSize + + ", mMinControlPointDurationMillis=" + mMinControlPointDurationMillis + + ", mMaxControlPointDurationMillis=" + mMaxControlPointDurationMillis + + '}'; + } + + @NonNull + public static final Creator<VibratorEnvelopeEffectInfo> CREATOR = + new Creator<VibratorEnvelopeEffectInfo>() { + @Override + public VibratorEnvelopeEffectInfo createFromParcel(Parcel in) { + return new VibratorEnvelopeEffectInfo(in); + } + + @Override + public VibratorEnvelopeEffectInfo[] newArray(int size) { + return new VibratorEnvelopeEffectInfo[size]; + } + }; + + /** + * Retrieves the maximum duration supported for an envelope effect, in milliseconds. + * + * <p>If the device supports envelope effects + * (check {@link android.os.VibratorInfo#areEnvelopeEffectsSupported}), this value will be + * positive. Devices with envelope effects capabilities guarantees a maximum duration + * equivalent to the product of {@link #getMaxSize()} and + * {@link #getMaxControlPointDurationMillis()}. 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. + */ + public long getMaxDurationMillis() { + return mMaxSize * mMaxControlPointDurationMillis; + } + + /** + * Retrieves the maximum number of control points supported for an envelope effect. + * + * <p>If the device supports envelope effects + * (check {@link android.os.VibratorInfo#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. + */ + public int getMaxSize() { + return mMaxSize; + } + + /** + * Retrieves the minimum duration supported between two control points within an envelope + * effect, in milliseconds. + * + * <p>If the device supports envelope effects + * (check {@link android.os.VibratorInfo#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. + */ + public long getMinControlPointDurationMillis() { + return mMinControlPointDurationMillis; + } + + /** + * Retrieves the maximum duration supported between two control points within an envelope + * effect, in milliseconds. + * + * <p>If the device supports envelope effects + * (check {@link android.os.VibratorInfo#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. + */ + public long getMaxControlPointDurationMillis() { + return mMaxControlPointDurationMillis; + } +} diff --git a/services/core/java/com/android/server/vibrator/SplitPwleSegmentsAdapter.java b/services/core/java/com/android/server/vibrator/SplitPwleSegmentsAdapter.java index ad44227d935a..a8c4ac8cdeeb 100644 --- a/services/core/java/com/android/server/vibrator/SplitPwleSegmentsAdapter.java +++ b/services/core/java/com/android/server/vibrator/SplitPwleSegmentsAdapter.java @@ -44,7 +44,7 @@ final class SplitPwleSegmentsAdapter implements VibrationSegmentsAdapter { // The vibrator does not have PWLE v2 capability, so keep the segments unchanged. return repeatIndex; } - int maxPwleDuration = info.getMaxEnvelopeEffectDurationMillis(); + int maxPwleDuration = (int) info.getMaxEnvelopeEffectDurationMillis(); if (maxPwleDuration <= 0) { // No limit set to PWLE primitive duration. return repeatIndex; |