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 import com.android.internal.util.Preconditions; 28 29 import java.util.Objects; 30 31 /** 32 * Representation of {@link VibrationEffectSegment} that plays a primitive vibration effect after a 33 * specified delay and applying a given scale. 34 * 35 * @hide 36 */ 37 @TestApi 38 public final class PrimitiveSegment extends VibrationEffectSegment { 39 40 /** @hide */ 41 public static final float DEFAULT_SCALE = 1f; 42 43 /** @hide */ 44 public static final int DEFAULT_DELAY_MILLIS = 0; 45 46 private final int mPrimitiveId; 47 private final float mScale; 48 private final int mDelay; 49 PrimitiveSegment(@onNull Parcel in)50 PrimitiveSegment(@NonNull Parcel in) { 51 this(in.readInt(), in.readFloat(), in.readInt()); 52 } 53 54 /** @hide */ PrimitiveSegment(int id, float scale, int delay)55 public PrimitiveSegment(int id, float scale, int delay) { 56 mPrimitiveId = id; 57 mScale = scale; 58 mDelay = delay; 59 } 60 getPrimitiveId()61 public int getPrimitiveId() { 62 return mPrimitiveId; 63 } 64 getScale()65 public float getScale() { 66 return mScale; 67 } 68 getDelay()69 public int getDelay() { 70 return mDelay; 71 } 72 73 @Override getDuration()74 public long getDuration() { 75 return -1; 76 } 77 78 /** @hide */ 79 @Override areVibrationFeaturesSupported(@onNull VibratorInfo vibratorInfo)80 public boolean areVibrationFeaturesSupported(@NonNull VibratorInfo vibratorInfo) { 81 return vibratorInfo.isPrimitiveSupported(mPrimitiveId); 82 } 83 84 /** @hide */ 85 @Override isHapticFeedbackCandidate()86 public boolean isHapticFeedbackCandidate() { 87 return true; 88 } 89 90 /** @hide */ 91 @NonNull 92 @Override resolve(int defaultAmplitude)93 public PrimitiveSegment resolve(int defaultAmplitude) { 94 return this; 95 } 96 97 /** @hide */ 98 @NonNull 99 @Override scale(float scaleFactor)100 public PrimitiveSegment scale(float scaleFactor) { 101 float newScale = VibrationEffect.scale(mScale, scaleFactor); 102 if (Float.compare(mScale, newScale) == 0) { 103 return this; 104 } 105 106 return new PrimitiveSegment(mPrimitiveId, newScale, mDelay); 107 } 108 109 /** @hide */ 110 @NonNull 111 @Override scaleLinearly(float scaleFactor)112 public PrimitiveSegment scaleLinearly(float scaleFactor) { 113 float newScale = VibrationEffect.scaleLinearly(mScale, scaleFactor); 114 if (Float.compare(mScale, newScale) == 0) { 115 return this; 116 } 117 118 return new PrimitiveSegment(mPrimitiveId, newScale, mDelay); 119 } 120 121 /** @hide */ 122 @NonNull 123 @Override applyEffectStrength(int effectStrength)124 public PrimitiveSegment applyEffectStrength(int effectStrength) { 125 return this; 126 } 127 128 /** @hide */ 129 @Override validate()130 public void validate() { 131 Preconditions.checkArgumentInRange(mPrimitiveId, VibrationEffect.Composition.PRIMITIVE_NOOP, 132 VibrationEffect.Composition.PRIMITIVE_LOW_TICK, "primitiveId"); 133 Preconditions.checkArgumentInRange(mScale, 0f, 1f, "scale"); 134 VibrationEffectSegment.checkDurationArgument(mDelay, "delay"); 135 } 136 137 @Override writeToParcel(@onNull Parcel dest, int flags)138 public void writeToParcel(@NonNull Parcel dest, int flags) { 139 dest.writeInt(PARCEL_TOKEN_PRIMITIVE); 140 dest.writeInt(mPrimitiveId); 141 dest.writeFloat(mScale); 142 dest.writeInt(mDelay); 143 } 144 145 @Override describeContents()146 public int describeContents() { 147 return 0; 148 } 149 150 @Override toString()151 public String toString() { 152 return "Primitive{" 153 + "primitive=" + VibrationEffect.Composition.primitiveToString(mPrimitiveId) 154 + ", scale=" + mScale 155 + ", delay=" + mDelay 156 + '}'; 157 } 158 159 /** @hide */ 160 @Override toDebugString()161 public String toDebugString() { 162 return String.format("Primitive=%s(scale=%.2f, delay=%dms)", 163 VibrationEffect.Composition.primitiveToString(mPrimitiveId), mScale, mDelay); 164 } 165 166 @Override equals(@ullable Object o)167 public boolean equals(@Nullable Object o) { 168 if (this == o) return true; 169 if (o == null || getClass() != o.getClass()) return false; 170 PrimitiveSegment that = (PrimitiveSegment) o; 171 return mPrimitiveId == that.mPrimitiveId 172 && Float.compare(that.mScale, mScale) == 0 173 && mDelay == that.mDelay; 174 } 175 176 @Override hashCode()177 public int hashCode() { 178 return Objects.hash(mPrimitiveId, mScale, mDelay); 179 } 180 181 @NonNull 182 public static final Parcelable.Creator<PrimitiveSegment> CREATOR = 183 new Parcelable.Creator<PrimitiveSegment>() { 184 @Override 185 public PrimitiveSegment createFromParcel(Parcel in) { 186 // Skip the type token 187 in.readInt(); 188 return new PrimitiveSegment(in); 189 } 190 191 @Override 192 public PrimitiveSegment[] newArray(int size) { 193 return new PrimitiveSegment[size]; 194 } 195 }; 196 } 197