• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.TestApi;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.os.VibrationEffect;
25 import android.os.VibratorInfo;
26 
27 /**
28  * Representation of a single segment of a {@link VibrationEffect}.
29  *
30  * <p>Vibration effects are represented as a sequence of segments that describes how vibration
31  * amplitude and frequency changes over time. Segments can be described as one of the following:
32  *
33  * <ol>
34  *     <li>A predefined vibration effect;
35  *     <li>A composable effect primitive;
36  *     <li>Fixed amplitude and frequency values to be held for a specified duration;
37  *     <li>Pairs of amplitude and frequency values to be ramped to for a specified duration;
38  * </ol>
39  *
40  * @hide
41  */
42 @TestApi
43 @SuppressWarnings({"ParcelNotFinal", "ParcelCreator"}) // Parcel only extended here.
44 public abstract class VibrationEffectSegment implements Parcelable {
45     static final int PARCEL_TOKEN_PREBAKED = 1;
46     static final int PARCEL_TOKEN_PRIMITIVE = 2;
47     static final int PARCEL_TOKEN_STEP = 3;
48     static final int PARCEL_TOKEN_RAMP = 4;
49     static final int PARCEL_TOKEN_PWLE = 5;
50     static final int PARCEL_TOKEN_BASIC_PWLE = 6;
51 
52     /** Prevent subclassing from outside of this package */
VibrationEffectSegment()53     VibrationEffectSegment() {
54     }
55 
56     /**
57      * Gets the estimated duration of the segment in milliseconds.
58      *
59      * <p>For segments with an unknown duration (e.g. prebaked or primitive effects where the length
60      * is device and potentially run-time dependent), this returns -1.
61      */
getDuration()62     public abstract long getDuration();
63 
64     /**
65      * Gets the estimated duration of the segment for given vibrator, in milliseconds.
66      *
67      * <p>For segments with hardware-dependent constants (e.g. primitives), this returns the
68      * estimated duration based on the given {@link VibratorInfo}. For all other effects this will
69      * return the same as {@link #getDuration()}.
70      *
71      * @hide
72      */
getDuration(@ullable VibratorInfo vibratorInfo)73     public long getDuration(@Nullable VibratorInfo vibratorInfo) {
74         return getDuration();
75     }
76 
77     /**
78      * Checks if a given {@link android.os.Vibrator} can play this segment as intended. See
79      * {@link android.os.Vibrator#areVibrationFeaturesSupported(VibrationEffect)} for more
80      * information about what counts as supported by a vibrator, and what counts as not.
81      *
82      * @hide
83      */
areVibrationFeaturesSupported(@onNull VibratorInfo vibratorInfo)84     public abstract boolean areVibrationFeaturesSupported(@NonNull VibratorInfo vibratorInfo);
85 
86     /**
87      * Returns true if this segment could be a haptic feedback effect candidate.
88      *
89      * @see VibrationEffect#isHapticFeedbackCandidate()
90      * @hide
91      */
isHapticFeedbackCandidate()92     public abstract boolean isHapticFeedbackCandidate();
93 
94     /**
95      * Validates the segment, throwing exceptions if any parameter is invalid.
96      *
97      * @hide
98      */
validate()99     public abstract void validate();
100 
101     /**
102      * Resolves amplitudes set to {@link VibrationEffect#DEFAULT_AMPLITUDE}.
103      *
104      * <p>This might fail with {@link IllegalArgumentException} if value is non-positive or larger
105      * than {@link VibrationEffect#MAX_AMPLITUDE}.
106      *
107      * @hide
108      */
109     @NonNull
resolve(int defaultAmplitude)110     public abstract <T extends VibrationEffectSegment> T resolve(int defaultAmplitude);
111 
112     /**
113      * Scale the segment intensity with the given factor.
114      *
115      * <p> This scale is not necessarily linear and may apply a gamma correction to the scale
116      * factor before using it.
117      *
118      * @param scaleFactor scale factor to be applied to the intensity. Values within [0,1) will
119      *                    scale down the intensity, values larger than 1 will scale up
120      *
121      * @hide
122      */
123     @NonNull
scale(float scaleFactor)124     public abstract <T extends VibrationEffectSegment> T scale(float scaleFactor);
125 
126     /**
127      * Performs a linear scaling on the segment intensity with the given factor.
128      *
129      * @param scaleFactor scale factor to be applied to the intensity. Values within [0,1) will
130      *                    scale down the intensity, values larger than 1 will scale up
131      *
132      * @hide
133      */
134     @NonNull
scaleLinearly(float scaleFactor)135     public abstract <T extends VibrationEffectSegment> T scaleLinearly(float scaleFactor);
136 
137     /**
138      * Applies given effect strength to prebaked effects.
139      *
140      * @param effectStrength new effect strength to be applied, one of
141      *                       VibrationEffect.EFFECT_STRENGTH_*.
142      *
143      * @hide
144      */
145     @NonNull
applyEffectStrength(int effectStrength)146     public abstract <T extends VibrationEffectSegment> T applyEffectStrength(int effectStrength);
147 
148     /**
149      * Returns a compact version of the {@link #toString()} result for debugging purposes.
150      *
151      * @hide
152      */
toDebugString()153     public abstract String toDebugString();
154 
155     /**
156      * Checks the given frequency argument is valid to represent a vibration effect frequency in
157      * hertz, i.e. a finite non-negative value.
158      *
159      * @param value the frequency argument value to be checked
160      * @param name the argument name for the error message.
161      *
162      * @hide
163      */
checkFrequencyArgument(float value, @NonNull String name)164     public static void checkFrequencyArgument(float value, @NonNull String name) {
165         // Similar to combining Preconditions checkArgumentFinite + checkArgumentNonnegative,
166         // but this implementation doesn't create the error message unless a check fail.
167         if (Float.isNaN(value)) {
168             throw new IllegalArgumentException(name + " must not be NaN");
169         }
170         if (Float.isInfinite(value)) {
171             throw new IllegalArgumentException(name + " must not be infinite");
172         }
173         if (value < 0) {
174             throw new IllegalArgumentException(name + " must be >= 0, got " + value);
175         }
176     }
177 
178     /**
179      * Checks the given duration argument is valid, i.e. a non-negative value.
180      *
181      * @param value the duration value to be checked
182      * @param name the argument name for the error message.
183      *
184      * @hide
185      */
checkDurationArgument(long value, @NonNull String name)186     public static void checkDurationArgument(long value, @NonNull String name) {
187         if (value < 0) {
188             throw new IllegalArgumentException(name + " must be >= 0, got " + value);
189         }
190     }
191 
192     /**
193      * Helper method to check if an amplitude requires a vibrator to have amplitude control to play.
194      *
195      * @hide
196      */
amplitudeRequiresAmplitudeControl(float amplitude)197     protected static boolean amplitudeRequiresAmplitudeControl(float amplitude) {
198         return (amplitude != 0)
199                 && (amplitude != 1)
200                 && (amplitude != VibrationEffect.DEFAULT_AMPLITUDE);
201     }
202 
203     /**
204      * Helper method to check if a frequency requires a vibrator to have frequency control to play.
205      *
206      * @hide
207      */
frequencyRequiresFrequencyControl(float frequency)208     protected static boolean frequencyRequiresFrequencyControl(float frequency) {
209         // Anything other than the default frequency value (represented with "0") requires frequency
210         // control.
211         return frequency != 0;
212     }
213 
214     @NonNull
215     public static final Creator<VibrationEffectSegment> CREATOR =
216             new Creator<VibrationEffectSegment>() {
217                 @Override
218                 public VibrationEffectSegment createFromParcel(Parcel in) {
219                     switch (in.readInt()) {
220                         case PARCEL_TOKEN_STEP:
221                             return new StepSegment(in);
222                         case PARCEL_TOKEN_RAMP:
223                             return new RampSegment(in);
224                         case PARCEL_TOKEN_PREBAKED:
225                             return new PrebakedSegment(in);
226                         case PARCEL_TOKEN_PRIMITIVE:
227                             return new PrimitiveSegment(in);
228                         case PARCEL_TOKEN_PWLE:
229                             if (Flags.normalizedPwleEffects()) {
230                                 return new PwleSegment(in);
231                             }
232                             // Fall through to default if the flag is not enabled.
233                         case PARCEL_TOKEN_BASIC_PWLE:
234                             if (Flags.normalizedPwleEffects()) {
235                                 return new BasicPwleSegment(in);
236                             }
237                             // Fall through to default if the flag is not enabled.
238                         default:
239                             throw new IllegalStateException(
240                                     "Unexpected vibration event type token in parcel.");
241                     }
242                 }
243 
244                 @Override
245                 public VibrationEffectSegment[] newArray(int size) {
246                     return new VibrationEffectSegment[size];
247                 }
248             };
249 }
250