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 26 import java.util.Objects; 27 28 /** 29 * Representation of {@link VibrationEffectSegment} that plays a prebaked vibration effect. 30 * 31 * @hide 32 */ 33 @TestApi 34 public final class PrebakedSegment extends VibrationEffectSegment { 35 private final int mEffectId; 36 private final boolean mFallback; 37 private final int mEffectStrength; 38 PrebakedSegment(@onNull Parcel in)39 PrebakedSegment(@NonNull Parcel in) { 40 mEffectId = in.readInt(); 41 mFallback = in.readByte() != 0; 42 mEffectStrength = in.readInt(); 43 } 44 45 /** @hide */ PrebakedSegment(int effectId, boolean shouldFallback, int effectStrength)46 public PrebakedSegment(int effectId, boolean shouldFallback, int effectStrength) { 47 mEffectId = effectId; 48 mFallback = shouldFallback; 49 mEffectStrength = effectStrength; 50 } 51 getEffectId()52 public int getEffectId() { 53 return mEffectId; 54 } 55 getEffectStrength()56 public int getEffectStrength() { 57 return mEffectStrength; 58 } 59 60 /** Return true if a fallback effect should be played if this effect is not supported. */ shouldFallback()61 public boolean shouldFallback() { 62 return mFallback; 63 } 64 65 @Override getDuration()66 public long getDuration() { 67 return -1; 68 } 69 70 @Override hasNonZeroAmplitude()71 public boolean hasNonZeroAmplitude() { 72 return true; 73 } 74 75 @NonNull 76 @Override resolve(int defaultAmplitude)77 public PrebakedSegment resolve(int defaultAmplitude) { 78 return this; 79 } 80 81 @NonNull 82 @Override scale(float scaleFactor)83 public PrebakedSegment scale(float scaleFactor) { 84 // Prebaked effect strength cannot be scaled with this method. 85 return this; 86 } 87 88 @NonNull 89 @Override applyEffectStrength(int effectStrength)90 public PrebakedSegment applyEffectStrength(int effectStrength) { 91 if (effectStrength != mEffectStrength && isValidEffectStrength(effectStrength)) { 92 return new PrebakedSegment(mEffectId, mFallback, effectStrength); 93 } 94 return this; 95 } 96 isValidEffectStrength(int strength)97 private static boolean isValidEffectStrength(int strength) { 98 switch (strength) { 99 case VibrationEffect.EFFECT_STRENGTH_LIGHT: 100 case VibrationEffect.EFFECT_STRENGTH_MEDIUM: 101 case VibrationEffect.EFFECT_STRENGTH_STRONG: 102 return true; 103 default: 104 return false; 105 } 106 } 107 108 @Override validate()109 public void validate() { 110 switch (mEffectId) { 111 case VibrationEffect.EFFECT_CLICK: 112 case VibrationEffect.EFFECT_DOUBLE_CLICK: 113 case VibrationEffect.EFFECT_TICK: 114 case VibrationEffect.EFFECT_TEXTURE_TICK: 115 case VibrationEffect.EFFECT_THUD: 116 case VibrationEffect.EFFECT_POP: 117 case VibrationEffect.EFFECT_HEAVY_CLICK: 118 break; 119 default: 120 int[] ringtones = VibrationEffect.RINGTONES; 121 if (mEffectId < ringtones[0] || mEffectId > ringtones[ringtones.length - 1]) { 122 throw new IllegalArgumentException( 123 "Unknown prebaked effect type (value=" + mEffectId + ")"); 124 } 125 } 126 if (!isValidEffectStrength(mEffectStrength)) { 127 throw new IllegalArgumentException( 128 "Unknown prebaked effect strength (value=" + mEffectStrength + ")"); 129 } 130 } 131 132 @Override equals(@ullable Object o)133 public boolean equals(@Nullable Object o) { 134 if (!(o instanceof PrebakedSegment)) { 135 return false; 136 } 137 PrebakedSegment other = (PrebakedSegment) o; 138 return mEffectId == other.mEffectId 139 && mFallback == other.mFallback 140 && mEffectStrength == other.mEffectStrength; 141 } 142 143 @Override hashCode()144 public int hashCode() { 145 return Objects.hash(mEffectId, mFallback, mEffectStrength); 146 } 147 148 @Override toString()149 public String toString() { 150 return "Prebaked{effect=" + VibrationEffect.effectIdToString(mEffectId) 151 + ", strength=" + VibrationEffect.effectStrengthToString(mEffectStrength) 152 + ", fallback=" + mFallback 153 + "}"; 154 } 155 156 @Override describeContents()157 public int describeContents() { 158 return 0; 159 } 160 161 @Override writeToParcel(@onNull Parcel out, int flags)162 public void writeToParcel(@NonNull Parcel out, int flags) { 163 out.writeInt(PARCEL_TOKEN_PREBAKED); 164 out.writeInt(mEffectId); 165 out.writeByte((byte) (mFallback ? 1 : 0)); 166 out.writeInt(mEffectStrength); 167 } 168 169 @NonNull 170 public static final Parcelable.Creator<PrebakedSegment> CREATOR = 171 new Parcelable.Creator<PrebakedSegment>() { 172 @Override 173 public PrebakedSegment createFromParcel(Parcel in) { 174 // Skip the type token 175 in.readInt(); 176 return new PrebakedSegment(in); 177 } 178 179 @Override 180 public PrebakedSegment[] newArray(int size) { 181 return new PrebakedSegment[size]; 182 } 183 }; 184 } 185