• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.os.vibrator;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.NonNull;
21 import android.annotation.TestApi;
22 import android.os.Parcel;
23 import android.os.VibrationEffect;
24 import android.os.VibratorInfo;
25 
26 import com.android.internal.util.Preconditions;
27 
28 import java.util.Locale;
29 import java.util.Objects;
30 
31 /**
32  * A {@link VibrationEffectSegment} that represents a smooth transition from the starting
33  * intensity and sharpness to new values over a specified duration.
34  *
35  * <p>The intensity and sharpness are expressed by float values in the range [0, 1], where
36  * intensity represents the user-perceived strength of the vibration, while sharpness represents
37  * the crispness of the vibration.
38  *
39  * @hide
40  */
41 @TestApi
42 @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
43 public final class BasicPwleSegment extends VibrationEffectSegment {
44     private final float mStartIntensity;
45     private final float mEndIntensity;
46     private final float mStartSharpness;
47     private final float mEndSharpness;
48     private final long mDuration;
49 
BasicPwleSegment(@onNull Parcel in)50     BasicPwleSegment(@NonNull Parcel in) {
51         this(in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat(), in.readLong());
52     }
53 
54     /** @hide */
55     @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
BasicPwleSegment(float startIntensity, float endIntensity, float startSharpness, float endSharpness, long duration)56     public BasicPwleSegment(float startIntensity, float endIntensity, float startSharpness,
57             float endSharpness, long duration) {
58         mStartIntensity = startIntensity;
59         mEndIntensity = endIntensity;
60         mStartSharpness = startSharpness;
61         mEndSharpness = endSharpness;
62         mDuration = duration;
63     }
64 
getStartIntensity()65     public float getStartIntensity() {
66         return mStartIntensity;
67     }
68 
getEndIntensity()69     public float getEndIntensity() {
70         return mEndIntensity;
71     }
72 
getStartSharpness()73     public float getStartSharpness() {
74         return mStartSharpness;
75     }
76 
getEndSharpness()77     public float getEndSharpness() {
78         return mEndSharpness;
79     }
80 
81     @Override
getDuration()82     public long getDuration() {
83         return mDuration;
84     }
85 
86     @Override
equals(Object o)87     public boolean equals(Object o) {
88         if (!(o instanceof BasicPwleSegment)) {
89             return false;
90         }
91         BasicPwleSegment other = (BasicPwleSegment) o;
92         return Float.compare(mStartIntensity, other.mStartIntensity) == 0
93                 && Float.compare(mEndIntensity, other.mEndIntensity) == 0
94                 && Float.compare(mStartSharpness, other.mStartSharpness) == 0
95                 && Float.compare(mEndSharpness, other.mEndSharpness) == 0
96                 && mDuration == other.mDuration;
97     }
98 
99     /** @hide */
100     @Override
areVibrationFeaturesSupported(@onNull VibratorInfo vibratorInfo)101     public boolean areVibrationFeaturesSupported(@NonNull VibratorInfo vibratorInfo) {
102         return vibratorInfo.areEnvelopeEffectsSupported();
103     }
104 
105     /** @hide */
106     @Override
isHapticFeedbackCandidate()107     public boolean isHapticFeedbackCandidate() {
108         return true;
109     }
110 
111     /** @hide */
112     @Override
validate()113     public void validate() {
114         Preconditions.checkArgumentInRange(mStartSharpness, 0f, 1f, "startSharpness");
115         Preconditions.checkArgumentInRange(mEndSharpness, 0f, 1f, "endSharpness");
116         Preconditions.checkArgumentInRange(mStartIntensity, 0f, 1f, "startIntensity");
117         Preconditions.checkArgumentInRange(mEndIntensity, 0f, 1f, "endIntensity");
118         Preconditions.checkArgumentPositive(mDuration, "Time must be greater than zero.");
119     }
120 
121     /** @hide */
122     @NonNull
123     @Override
resolve(int defaultAmplitude)124     public BasicPwleSegment resolve(int defaultAmplitude) {
125         return this;
126     }
127 
128     /** @hide */
129     @NonNull
130     @Override
scale(float scaleFactor)131     public BasicPwleSegment scale(float scaleFactor) {
132         float newStartIntensity = VibrationEffect.scale(mStartIntensity, scaleFactor);
133         float newEndIntensity = VibrationEffect.scale(mEndIntensity, scaleFactor);
134         if (Float.compare(mStartIntensity, newStartIntensity) == 0
135                 && Float.compare(mEndIntensity, newEndIntensity) == 0) {
136             return this;
137         }
138         return new BasicPwleSegment(newStartIntensity, newEndIntensity, mStartSharpness,
139                 mEndSharpness,
140                 mDuration);
141     }
142 
143     /** @hide */
144     @NonNull
145     @Override
scaleLinearly(float scaleFactor)146     public BasicPwleSegment scaleLinearly(float scaleFactor) {
147         float newStartIntensity = VibrationEffect.scaleLinearly(mStartIntensity, scaleFactor);
148         float newEndIntensity = VibrationEffect.scaleLinearly(mEndIntensity, scaleFactor);
149         if (Float.compare(mStartIntensity, newStartIntensity) == 0
150                 && Float.compare(mEndIntensity, newEndIntensity) == 0) {
151             return this;
152         }
153         return new BasicPwleSegment(newStartIntensity, newEndIntensity, mStartSharpness,
154                 mEndSharpness,
155                 mDuration);
156     }
157 
158     /** @hide */
159     @NonNull
160     @Override
applyEffectStrength(int effectStrength)161     public BasicPwleSegment applyEffectStrength(int effectStrength) {
162         return this;
163     }
164 
165     @Override
hashCode()166     public int hashCode() {
167         return Objects.hash(mStartIntensity, mEndIntensity, mStartSharpness, mEndSharpness,
168                 mDuration);
169     }
170 
171     @Override
toString()172     public String toString() {
173         return "BasicPwle{startIntensity=" + mStartIntensity
174                 + ", endIntensity=" + mEndIntensity
175                 + ", startSharpness=" + mStartSharpness
176                 + ", endSharpness=" + mEndSharpness
177                 + ", duration=" + mDuration
178                 + "}";
179     }
180 
181     /** @hide */
182     @Override
toDebugString()183     public String toDebugString() {
184         return String.format(Locale.US, "Pwle=%dms(intensity=%.2f @ %.2f to %.2f @ %.2f)",
185                 mDuration,
186                 mStartIntensity,
187                 mStartSharpness,
188                 mEndIntensity,
189                 mEndSharpness);
190     }
191 
192     @Override
describeContents()193     public int describeContents() {
194         return 0;
195     }
196 
197     @Override
writeToParcel(@onNull Parcel dest, int flags)198     public void writeToParcel(@NonNull Parcel dest, int flags) {
199         dest.writeInt(PARCEL_TOKEN_PWLE);
200         dest.writeFloat(mStartIntensity);
201         dest.writeFloat(mEndIntensity);
202         dest.writeFloat(mStartSharpness);
203         dest.writeFloat(mEndSharpness);
204         dest.writeLong(mDuration);
205     }
206 
207     @NonNull
208     public static final Creator<BasicPwleSegment> CREATOR =
209             new Creator<BasicPwleSegment>() {
210                 @Override
211                 public BasicPwleSegment createFromParcel(Parcel in) {
212                     // Skip the type token
213                     in.readInt();
214                     return new BasicPwleSegment(in);
215                 }
216 
217                 @Override
218                 public BasicPwleSegment[] newArray(int size) {
219                     return new BasicPwleSegment[size];
220                 }
221             };
222 }
223