1 /* 2 * Copyright (C) 2023 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 com.android.internal.vibrator.persistence; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.os.VibrationEffect; 23 import android.os.VibrationEffect.Composition.DelayType; 24 import android.os.VibrationEffect.Composition.PrimitiveType; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.util.Locale; 29 30 /** 31 * Constants used for vibration XML serialization and parsing. 32 * 33 * @hide 34 */ 35 public final class XmlConstants { 36 37 public static final String NAMESPACE = null; 38 39 public static final String TAG_VIBRATION_EFFECT = "vibration-effect"; 40 public static final String TAG_VIBRATION_SELECT = "vibration-select"; 41 42 public static final String TAG_PREDEFINED_EFFECT = "predefined-effect"; 43 public static final String TAG_PRIMITIVE_EFFECT = "primitive-effect"; 44 public static final String TAG_VENDOR_EFFECT = "vendor-effect"; 45 public static final String TAG_WAVEFORM_ENVELOPE_EFFECT = "waveform-envelope-effect"; 46 public static final String TAG_BASIC_ENVELOPE_EFFECT = "basic-envelope-effect"; 47 public static final String TAG_WAVEFORM_EFFECT = "waveform-effect"; 48 public static final String TAG_REPEATING_EFFECT = "repeating-effect"; 49 public static final String TAG_WAVEFORM_ENTRY = "waveform-entry"; 50 public static final String TAG_REPEATING = "repeating"; 51 public static final String TAG_PREAMBLE = "preamble"; 52 public static final String TAG_CONTROL_POINT = "control-point"; 53 54 public static final String ATTRIBUTE_NAME = "name"; 55 public static final String ATTRIBUTE_FALLBACK = "fallback"; 56 public static final String ATTRIBUTE_DURATION_MS = "durationMs"; 57 public static final String ATTRIBUTE_AMPLITUDE = "amplitude"; 58 public static final String ATTRIBUTE_FREQUENCY_HZ = "frequencyHz"; 59 public static final String ATTRIBUTE_INITIAL_FREQUENCY_HZ = "initialFrequencyHz"; 60 public static final String ATTRIBUTE_INTENSITY = "intensity"; 61 public static final String ATTRIBUTE_SHARPNESS = "sharpness"; 62 public static final String ATTRIBUTE_INITIAL_SHARPNESS = "initialSharpness"; 63 public static final String ATTRIBUTE_SCALE = "scale"; 64 public static final String ATTRIBUTE_DELAY_MS = "delayMs"; 65 public static final String ATTRIBUTE_DELAY_TYPE = "delayType"; 66 67 public static final String VALUE_AMPLITUDE_DEFAULT = "default"; 68 69 /** 70 * Allow {@link VibrationEffect} hidden APIs to be used during parsing/serializing. 71 * 72 * <p>Use the schema at services/core/xsd/vibrator/vibration/vibration-plus-hidden-apis.xsd. 73 */ 74 public static final int FLAG_ALLOW_HIDDEN_APIS = 1 << 0; 75 76 /** @hide */ 77 @IntDef(prefix = { "FLAG_" }, flag = true, value = { 78 FLAG_ALLOW_HIDDEN_APIS 79 }) 80 @Retention(RetentionPolicy.SOURCE) 81 public @interface Flags {} 82 83 /** Represent supported values for attribute name in {@link #TAG_PRIMITIVE_EFFECT} */ 84 public enum PrimitiveEffectName { 85 LOW_TICK(VibrationEffect.Composition.PRIMITIVE_LOW_TICK), 86 TICK(VibrationEffect.Composition.PRIMITIVE_TICK), 87 CLICK(VibrationEffect.Composition.PRIMITIVE_CLICK), 88 SLOW_RISE(VibrationEffect.Composition.PRIMITIVE_SLOW_RISE), 89 QUICK_RISE(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE), 90 QUICK_FALL(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL), 91 SPIN(VibrationEffect.Composition.PRIMITIVE_SPIN), 92 THUD(VibrationEffect.Composition.PRIMITIVE_THUD); 93 94 @PrimitiveType private final int mPrimitiveId; 95 PrimitiveEffectName(@rimitiveType int id)96 PrimitiveEffectName(@PrimitiveType int id) { 97 mPrimitiveId = id; 98 } 99 100 /** 101 * Return the {@link PrimitiveEffectName} that represents given primitive id, or null if 102 * none of the available names map to the given id. 103 */ 104 @Nullable findById(int primitiveId)105 public static PrimitiveEffectName findById(int primitiveId) { 106 for (PrimitiveEffectName name : PrimitiveEffectName.values()) { 107 if (name.mPrimitiveId == primitiveId) { 108 return name; 109 } 110 } 111 return null; 112 } 113 114 /** 115 * Return the {@link PrimitiveEffectName} that represents given primitive name, or null if 116 * none of the available names maps to the given name. 117 */ 118 @Nullable findByName(@onNull String primitiveName)119 public static PrimitiveEffectName findByName(@NonNull String primitiveName) { 120 try { 121 return PrimitiveEffectName.valueOf(primitiveName.toUpperCase(Locale.ROOT)); 122 } catch (IllegalArgumentException e) { 123 return null; 124 } 125 } 126 127 @PrimitiveType getPrimitiveId()128 public int getPrimitiveId() { 129 return mPrimitiveId; 130 } 131 132 @Override toString()133 public String toString() { 134 return name().toLowerCase(Locale.ROOT); 135 } 136 } 137 138 /** Represent supported values for attribute name in {@link #TAG_PREDEFINED_EFFECT} */ 139 public enum PredefinedEffectName { 140 // Public effects 141 TICK(VibrationEffect.EFFECT_TICK, true), 142 CLICK(VibrationEffect.EFFECT_CLICK, true), 143 HEAVY_CLICK(VibrationEffect.EFFECT_HEAVY_CLICK, true), 144 DOUBLE_CLICK(VibrationEffect.EFFECT_DOUBLE_CLICK, true), 145 146 // Hidden effects 147 TEXTURE_TICK(VibrationEffect.EFFECT_TEXTURE_TICK, false), 148 THUD(VibrationEffect.EFFECT_THUD, false), 149 POP(VibrationEffect.EFFECT_POP, false), 150 RINGTONE_1(VibrationEffect.RINGTONES[0], false), 151 RINGTONE_2(VibrationEffect.RINGTONES[1], false), 152 RINGTONE_3(VibrationEffect.RINGTONES[2], false), 153 RINGTONE_4(VibrationEffect.RINGTONES[3], false), 154 RINGTONE_5(VibrationEffect.RINGTONES[4], false), 155 RINGTONE_6(VibrationEffect.RINGTONES[5], false), 156 RINGTONE_7(VibrationEffect.RINGTONES[6], false), 157 RINGTONE_8(VibrationEffect.RINGTONES[7], false), 158 RINGTONE_9(VibrationEffect.RINGTONES[8], false), 159 RINGTONE_10(VibrationEffect.RINGTONES[9], false), 160 RINGTONE_11(VibrationEffect.RINGTONES[10], false), 161 RINGTONE_12(VibrationEffect.RINGTONES[11], false), 162 RINGTONE_13(VibrationEffect.RINGTONES[12], false), 163 RINGTONE_14(VibrationEffect.RINGTONES[13], false), 164 RINGTONE_15(VibrationEffect.RINGTONES[14], false); 165 166 private final int mEffectId; 167 private final boolean mIsPublic; 168 PredefinedEffectName(int id, boolean isPublic)169 PredefinedEffectName(int id, boolean isPublic) { 170 mEffectId = id; 171 mIsPublic = isPublic; 172 } 173 174 /** 175 * Return the {@link PredefinedEffectName} that represents given effect id, or null if 176 * none of the available names maps to the given id. 177 */ 178 @Nullable findById(int effectId, @XmlConstants.Flags int flags)179 public static PredefinedEffectName findById(int effectId, @XmlConstants.Flags int flags) { 180 boolean allowHidden = (flags & XmlConstants.FLAG_ALLOW_HIDDEN_APIS) != 0; 181 for (PredefinedEffectName name : PredefinedEffectName.values()) { 182 if (name.mEffectId == effectId) { 183 return (name.mIsPublic || allowHidden) ? name : null; 184 } 185 } 186 return null; 187 } 188 189 /** 190 * Return the {@link PredefinedEffectName} that represents given effect name, or null if 191 * none of the available names maps to the given name. 192 */ 193 @Nullable findByName(@onNull String effectName, @XmlConstants.Flags int flags)194 public static PredefinedEffectName findByName(@NonNull String effectName, 195 @XmlConstants.Flags int flags) { 196 boolean allowHidden = (flags & XmlConstants.FLAG_ALLOW_HIDDEN_APIS) != 0; 197 try { 198 PredefinedEffectName name = PredefinedEffectName.valueOf( 199 effectName.toUpperCase(Locale.ROOT)); 200 return (name.mIsPublic || allowHidden) ? name : null; 201 } catch (IllegalArgumentException e) { 202 return null; 203 } 204 } 205 getEffectId()206 public int getEffectId() { 207 return mEffectId; 208 } 209 210 @Override toString()211 public String toString() { 212 return name().toLowerCase(Locale.ROOT); 213 } 214 } 215 216 /** Represent supported values for attribute delay type in {@link #TAG_PRIMITIVE_EFFECT} */ 217 public enum PrimitiveDelayType { 218 PAUSE(VibrationEffect.Composition.DELAY_TYPE_PAUSE), 219 RELATIVE_START_OFFSET(VibrationEffect.Composition.DELAY_TYPE_RELATIVE_START_OFFSET); 220 221 @DelayType private final int mDelayType; 222 PrimitiveDelayType(@elayType int type)223 PrimitiveDelayType(@DelayType int type) { 224 mDelayType = type; 225 } 226 227 /** 228 * Return the {@link PrimitiveEffectName} that represents given primitive id, or null if 229 * none of the available names maps to the given id. 230 */ 231 @Nullable findByType(int delayType)232 public static PrimitiveDelayType findByType(int delayType) { 233 for (PrimitiveDelayType type : PrimitiveDelayType.values()) { 234 if (type.mDelayType == delayType) { 235 return type; 236 } 237 } 238 return null; 239 } 240 241 /** 242 * Return the {@link PrimitiveEffectName} that represents given primitive name, or null if 243 * none of the available names maps to the given name. 244 */ 245 @Nullable findByName(@onNull String delayType)246 public static PrimitiveDelayType findByName(@NonNull String delayType) { 247 try { 248 return PrimitiveDelayType.valueOf(delayType.toUpperCase(Locale.ROOT)); 249 } catch (IllegalArgumentException e) { 250 return null; 251 } 252 } 253 254 @DelayType getDelayType()255 public int getDelayType() { 256 return mDelayType; 257 } 258 259 @Override toString()260 public String toString() { 261 return name().toLowerCase(Locale.ROOT); 262 } 263 } 264 } 265