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     /** Returns true if this segment plays at a non-zero amplitude at some point. */
hasNonZeroAmplitude()61     public abstract boolean hasNonZeroAmplitude();
62 
63     /** Validates the segment, throwing exceptions if any parameter is invalid. */
validate()64     public abstract void validate();
65 
66     /**
67      * Resolves amplitudes set to {@link VibrationEffect#DEFAULT_AMPLITUDE}.
68      *
69      * <p>This might fail with {@link IllegalArgumentException} if value is non-positive or larger
70      * than {@link VibrationEffect#MAX_AMPLITUDE}.
71      */
72     @NonNull
resolve(int defaultAmplitude)73     public abstract <T extends VibrationEffectSegment> T resolve(int defaultAmplitude);
74 
75     /**
76      * Scale the segment intensity with the given factor.
77      *
78      * @param scaleFactor scale factor to be applied to the intensity. Values within [0,1) will
79      *                    scale down the intensity, values larger than 1 will scale up
80      */
81     @NonNull
scale(float scaleFactor)82     public abstract <T extends VibrationEffectSegment> T scale(float scaleFactor);
83 
84     /**
85      * Applies given effect strength to prebaked effects.
86      *
87      * @param effectStrength new effect strength to be applied, one of
88      *                       VibrationEffect.EFFECT_STRENGTH_*.
89      */
90     @NonNull
applyEffectStrength(int effectStrength)91     public abstract <T extends VibrationEffectSegment> T applyEffectStrength(int effectStrength);
92 
93     @NonNull
94     public static final Creator<VibrationEffectSegment> CREATOR =
95             new Creator<VibrationEffectSegment>() {
96                 @Override
97                 public VibrationEffectSegment createFromParcel(Parcel in) {
98                     switch (in.readInt()) {
99                         case PARCEL_TOKEN_STEP:
100                             return new StepSegment(in);
101                         case PARCEL_TOKEN_RAMP:
102                             return new RampSegment(in);
103                         case PARCEL_TOKEN_PREBAKED:
104                             return new PrebakedSegment(in);
105                         case PARCEL_TOKEN_PRIMITIVE:
106                             return new PrimitiveSegment(in);
107                         default:
108                             throw new IllegalStateException(
109                                     "Unexpected vibration event type token in parcel.");
110                     }
111                 }
112 
113                 @Override
114                 public VibrationEffectSegment[] newArray(int size) {
115                     return new VibrationEffectSegment[size];
116                 }
117             };
118 }
119