• 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.TestApi;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.os.VibrationEffect;
24 
25 /**
26  * Representation of a single segment of a {@link VibrationEffect}.
27  *
28  * <p>Vibration effects are represented as a sequence of segments that describes how vibration
29  * amplitude and frequency changes over time. Segments can be described as one of the following:
30  *
31  * <ol>
32  *     <li>A predefined vibration effect;
33  *     <li>A composable effect primitive;
34  *     <li>Fixed amplitude and frequency values to be held for a specified duration;
35  *     <li>Pairs of amplitude and frequency values to be ramped to for a specified duration;
36  * </ol>
37  *
38  * @hide
39  */
40 @TestApi
41 @SuppressWarnings({"ParcelNotFinal", "ParcelCreator"}) // Parcel only extended here.
42 public abstract class VibrationEffectSegment implements Parcelable {
43     static final int PARCEL_TOKEN_PREBAKED = 1;
44     static final int PARCEL_TOKEN_PRIMITIVE = 2;
45     static final int PARCEL_TOKEN_STEP = 3;
46     static final int PARCEL_TOKEN_RAMP = 4;
47 
48     /** Prevent subclassing from outside of this package */
VibrationEffectSegment()49     VibrationEffectSegment() {
50     }
51 
52     /**
53      * Gets the estimated duration of the segment in milliseconds.
54      *
55      * <p>For segments with an unknown duration (e.g. prebaked or primitive effects where the length
56      * is device and potentially run-time dependent), this returns -1.
57      */
getDuration()58     public abstract long getDuration();
59 
60     /**
61      * Returns true if this segment could be a haptic feedback effect candidate.
62      *
63      * @see VibrationEffect#isHapticFeedbackCandidate()
64      * @hide
65      */
isHapticFeedbackCandidate()66     public abstract boolean isHapticFeedbackCandidate();
67 
68     /**
69      * Returns true if this segment plays at a non-zero amplitude at some point.
70      *
71      * @hide
72      */
hasNonZeroAmplitude()73     public abstract boolean hasNonZeroAmplitude();
74 
75     /**
76      * Validates the segment, throwing exceptions if any parameter is invalid.
77      *
78      * @hide
79      */
validate()80     public abstract void validate();
81 
82     /**
83      * Resolves amplitudes set to {@link VibrationEffect#DEFAULT_AMPLITUDE}.
84      *
85      * <p>This might fail with {@link IllegalArgumentException} if value is non-positive or larger
86      * than {@link VibrationEffect#MAX_AMPLITUDE}.
87      *
88      * @hide
89      */
90     @NonNull
resolve(int defaultAmplitude)91     public abstract <T extends VibrationEffectSegment> T resolve(int defaultAmplitude);
92 
93     /**
94      * Scale the segment intensity with the given factor.
95      *
96      * @param scaleFactor scale factor to be applied to the intensity. Values within [0,1) will
97      *                    scale down the intensity, values larger than 1 will scale up
98      *
99      * @hide
100      */
101     @NonNull
scale(float scaleFactor)102     public abstract <T extends VibrationEffectSegment> T scale(float scaleFactor);
103 
104     /**
105      * Applies given effect strength to prebaked effects.
106      *
107      * @param effectStrength new effect strength to be applied, one of
108      *                       VibrationEffect.EFFECT_STRENGTH_*.
109      *
110      * @hide
111      */
112     @NonNull
applyEffectStrength(int effectStrength)113     public abstract <T extends VibrationEffectSegment> T applyEffectStrength(int effectStrength);
114 
115     /**
116      * Checks the given frequency argument is valid to represent a vibration effect frequency in
117      * hertz, i.e. a finite non-negative value.
118      *
119      * @param value the frequency argument value to be checked
120      * @param name the argument name for the error message.
121      *
122      * @hide
123      */
checkFrequencyArgument(float value, @NonNull String name)124     public static void checkFrequencyArgument(float value, @NonNull String name) {
125         // Similar to combining Preconditions checkArgumentFinite + checkArgumentNonnegative,
126         // but this implementation doesn't create the error message unless a check fail.
127         if (Float.isNaN(value)) {
128             throw new IllegalArgumentException(name + " must not be NaN");
129         }
130         if (Float.isInfinite(value)) {
131             throw new IllegalArgumentException(name + " must not be infinite");
132         }
133         if (value < 0) {
134             throw new IllegalArgumentException(name + " must be >= 0, got " + value);
135         }
136     }
137 
138     /**
139      * Checks the given duration argument is valid, i.e. a non-negative value.
140      *
141      * @param value the duration value to be checked
142      * @param name the argument name for the error message.
143      *
144      * @hide
145      */
checkDurationArgument(long value, @NonNull String name)146     public static void checkDurationArgument(long value, @NonNull String name) {
147         if (value < 0) {
148             throw new IllegalArgumentException(name + " must be >= 0, got " + value);
149         }
150     }
151 
152     @NonNull
153     public static final Creator<VibrationEffectSegment> CREATOR =
154             new Creator<VibrationEffectSegment>() {
155                 @Override
156                 public VibrationEffectSegment createFromParcel(Parcel in) {
157                     switch (in.readInt()) {
158                         case PARCEL_TOKEN_STEP:
159                             return new StepSegment(in);
160                         case PARCEL_TOKEN_RAMP:
161                             return new RampSegment(in);
162                         case PARCEL_TOKEN_PREBAKED:
163                             return new PrebakedSegment(in);
164                         case PARCEL_TOKEN_PRIMITIVE:
165                             return new PrimitiveSegment(in);
166                         default:
167                             throw new IllegalStateException(
168                                     "Unexpected vibration event type token in parcel.");
169                     }
170                 }
171 
172                 @Override
173                 public VibrationEffectSegment[] newArray(int size) {
174                     return new VibrationEffectSegment[size];
175                 }
176             };
177 }
178