1 /* 2 * Copyright (C) 2024 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.google.android.msdl.data.repository 18 19 import android.os.VibrationEffect 20 import com.google.android.msdl.data.model.HapticComposition 21 import com.google.android.msdl.data.model.HapticCompositionPrimitive 22 import com.google.android.msdl.data.model.HapticToken 23 import com.google.android.msdl.data.model.SoundToken 24 25 /** A [MSDLRepository] that holds haptic compositions as haptic data. */ 26 internal class MSDLRepositoryImpl : MSDLRepository { 27 getAudioDatanull28 override fun getAudioData(soundToken: SoundToken): MSDLSoundData? { 29 // TODO(b/345248875) Implement a caching strategy in accordance to the audio file strategy 30 return null 31 } 32 getHapticDatanull33 override fun getHapticData(hapticToken: HapticToken): MSDLHapticData? = HAPTIC_DATA[hapticToken] 34 35 companion object { 36 // Timings and amplitudes that recreate a composition of three SPIN primitives as a waveform 37 private val SPIN_TIMINGS = longArrayOf(20, 20, 3, 43, 20, 20, 3) 38 private val SPIN_AMPLITUDES = intArrayOf(40, 80, 40, 0, 40, 80, 40) 39 private const val SPIN_DELAY = 56L 40 private const val SPIN_BREAK = 10 41 private val SPIN_WAVEFORM_TIMINGS = 42 SPIN_TIMINGS + SPIN_DELAY + SPIN_TIMINGS + SPIN_DELAY + SPIN_TIMINGS 43 private val SPIN_WAVEFORM_AMPLITUDES = 44 SPIN_AMPLITUDES + SPIN_BREAK + SPIN_AMPLITUDES + SPIN_BREAK + SPIN_AMPLITUDES 45 46 private val HAPTIC_DATA: Map<HapticToken, MSDLHapticData> = 47 mapOf( 48 HapticToken.NEGATIVE_CONFIRMATION_HIGH_EMPHASIS to 49 MSDLHapticData { 50 HapticComposition( 51 listOf( 52 HapticCompositionPrimitive( 53 VibrationEffect.Composition.PRIMITIVE_SPIN, 54 scale = 1f, 55 delayMillis = 0, 56 ), 57 HapticCompositionPrimitive( 58 VibrationEffect.Composition.PRIMITIVE_SPIN, 59 scale = 1f, 60 delayMillis = SPIN_DELAY.toInt(), 61 ), 62 HapticCompositionPrimitive( 63 VibrationEffect.Composition.PRIMITIVE_SPIN, 64 scale = 1f, 65 delayMillis = SPIN_DELAY.toInt(), 66 ), 67 ), 68 VibrationEffect.createWaveform( 69 SPIN_WAVEFORM_TIMINGS, 70 SPIN_WAVEFORM_AMPLITUDES, 71 -1, 72 ), 73 ) 74 }, 75 HapticToken.NEGATIVE_CONFIRMATION_MEDIUM_EMPHASIS to 76 MSDLHapticData { 77 HapticComposition( 78 listOf( 79 HapticCompositionPrimitive( 80 VibrationEffect.Composition.PRIMITIVE_CLICK, 81 scale = 1f, 82 delayMillis = 0, 83 ), 84 HapticCompositionPrimitive( 85 VibrationEffect.Composition.PRIMITIVE_CLICK, 86 scale = 1f, 87 delayMillis = 114, 88 ), 89 HapticCompositionPrimitive( 90 VibrationEffect.Composition.PRIMITIVE_CLICK, 91 scale = 1f, 92 delayMillis = 114, 93 ), 94 ), 95 VibrationEffect.createWaveform( 96 longArrayOf(10, 10, 10, 114, 10, 10, 10, 114, 10, 10, 10), 97 intArrayOf(10, 255, 20, 0, 10, 255, 20, 0, 10, 255, 20), 98 -1, 99 ), 100 ) 101 }, 102 HapticToken.POSITIVE_CONFIRMATION_HIGH_EMPHASIS to 103 MSDLHapticData { 104 HapticComposition( 105 listOf( 106 HapticCompositionPrimitive( 107 VibrationEffect.Composition.PRIMITIVE_CLICK, 108 scale = 1f, 109 delayMillis = 0, 110 ), 111 HapticCompositionPrimitive( 112 VibrationEffect.Composition.PRIMITIVE_CLICK, 113 scale = 1f, 114 delayMillis = 114, 115 ), 116 ), 117 VibrationEffect.createWaveform( 118 longArrayOf(10, 10, 10, 114, 10, 10, 10), 119 intArrayOf(10, 255, 20, 0, 10, 255, 20), 120 -1, 121 ), 122 ) 123 }, 124 HapticToken.POSITIVE_CONFIRMATION_MEDIUM_EMPHASIS to 125 MSDLHapticData { 126 HapticComposition( 127 listOf( 128 HapticCompositionPrimitive( 129 VibrationEffect.Composition.PRIMITIVE_CLICK, 130 scale = 1f, 131 delayMillis = 0, 132 ), 133 HapticCompositionPrimitive( 134 VibrationEffect.Composition.PRIMITIVE_CLICK, 135 scale = 1f, 136 delayMillis = 52, 137 ), 138 ), 139 VibrationEffect.createWaveform( 140 longArrayOf(10, 10, 10, 52, 10, 10, 10), 141 intArrayOf(10, 255, 20, 0, 10, 255, 20), 142 -1, 143 ), 144 ) 145 }, 146 HapticToken.POSITIVE_CONFIRMATION_LOW_EMPHASIS to 147 MSDLHapticData { 148 HapticComposition( 149 listOf( 150 HapticCompositionPrimitive( 151 VibrationEffect.Composition.PRIMITIVE_TICK, 152 scale = 1f, 153 delayMillis = 0, 154 ), 155 HapticCompositionPrimitive( 156 VibrationEffect.Composition.PRIMITIVE_CLICK, 157 scale = 1f, 158 delayMillis = 52, 159 ), 160 ), 161 VibrationEffect.createWaveform( 162 longArrayOf(5, 52, 10, 10, 10), 163 intArrayOf(100, 0, 10, 255, 20), 164 -1, 165 ), 166 ) 167 }, 168 HapticToken.NEUTRAL_CONFIRMATION_HIGH_EMPHASIS to 169 MSDLHapticData { 170 HapticComposition( 171 listOf( 172 HapticCompositionPrimitive( 173 VibrationEffect.Composition.PRIMITIVE_THUD, 174 scale = 1f, 175 delayMillis = 0, 176 ) 177 ), 178 VibrationEffect.createWaveform( 179 longArrayOf(50, 100, 100, 50), 180 intArrayOf(5, 50, 20, 10), 181 -1, 182 ), 183 ) 184 }, 185 HapticToken.NEUTRAL_CONFIRMATION_MEDIUM_EMPHASIS to 186 MSDLHapticData { 187 HapticComposition( 188 listOf( 189 HapticCompositionPrimitive( 190 VibrationEffect.Composition.PRIMITIVE_CLICK, 191 scale = 1f, 192 delayMillis = 0, 193 ) 194 ), 195 VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), 196 ) 197 }, 198 HapticToken.LONG_PRESS to 199 MSDLHapticData { 200 HapticComposition( 201 listOf( 202 HapticCompositionPrimitive( 203 VibrationEffect.Composition.PRIMITIVE_CLICK, 204 scale = 1f, 205 delayMillis = 0, 206 ) 207 ), 208 VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), 209 ) 210 }, 211 HapticToken.SWIPE_THRESHOLD_INDICATOR to 212 MSDLHapticData { 213 HapticComposition( 214 listOf( 215 HapticCompositionPrimitive( 216 VibrationEffect.Composition.PRIMITIVE_CLICK, 217 scale = 0.7f, 218 delayMillis = 0, 219 ) 220 ), 221 VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), 222 ) 223 }, 224 HapticToken.TAP_HIGH_EMPHASIS to 225 MSDLHapticData { 226 HapticComposition( 227 listOf( 228 HapticCompositionPrimitive( 229 VibrationEffect.Composition.PRIMITIVE_CLICK, 230 scale = 0.7f, 231 delayMillis = 0, 232 ) 233 ), 234 VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), 235 ) 236 }, 237 HapticToken.TAP_MEDIUM_EMPHASIS to 238 MSDLHapticData { 239 HapticComposition( 240 listOf( 241 HapticCompositionPrimitive( 242 VibrationEffect.Composition.PRIMITIVE_CLICK, 243 scale = 0.5f, 244 delayMillis = 0, 245 ) 246 ), 247 VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), 248 ) 249 }, 250 HapticToken.DRAG_THRESHOLD_INDICATOR to 251 MSDLHapticData { 252 HapticComposition( 253 listOf( 254 HapticCompositionPrimitive( 255 VibrationEffect.Composition.PRIMITIVE_CLICK, 256 scale = 1f, 257 delayMillis = 0, 258 ) 259 ), 260 VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK), 261 ) 262 }, 263 HapticToken.DRAG_INDICATOR_CONTINUOUS to 264 MSDLHapticData { 265 HapticComposition( 266 List(size = 5) { 267 HapticCompositionPrimitive( 268 VibrationEffect.Composition.PRIMITIVE_LOW_TICK, 269 scale = 0.3f, 270 delayMillis = 0, 271 ) 272 }, 273 VibrationEffect.createWaveform( 274 longArrayOf(10, 20, 20, 10), 275 intArrayOf(10, 30, 50, 10), 276 -1, 277 ), 278 ) 279 }, 280 HapticToken.DRAG_INDICATOR_DISCRETE to 281 MSDLHapticData { 282 HapticComposition( 283 listOf( 284 HapticCompositionPrimitive( 285 VibrationEffect.Composition.PRIMITIVE_TICK, 286 scale = 0.5f, 287 delayMillis = 0, 288 ) 289 ), 290 VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK), 291 ) 292 }, 293 HapticToken.TAP_LOW_EMPHASIS to 294 MSDLHapticData { 295 HapticComposition( 296 listOf( 297 HapticCompositionPrimitive( 298 VibrationEffect.Composition.PRIMITIVE_CLICK, 299 scale = 0.3f, 300 delayMillis = 0, 301 ) 302 ), 303 VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), 304 ) 305 }, 306 HapticToken.KEYPRESS_STANDARD to 307 MSDLHapticData { 308 HapticComposition( 309 listOf( 310 HapticCompositionPrimitive( 311 VibrationEffect.Composition.PRIMITIVE_TICK, 312 scale = 0.7f, 313 delayMillis = 0, 314 ) 315 ), 316 VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK), 317 ) 318 }, 319 HapticToken.KEYPRESS_SPACEBAR to 320 MSDLHapticData { 321 HapticComposition( 322 listOf( 323 HapticCompositionPrimitive( 324 VibrationEffect.Composition.PRIMITIVE_CLICK, 325 scale = 0.7f, 326 delayMillis = 0, 327 ) 328 ), 329 VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), 330 ) 331 }, 332 HapticToken.KEYPRESS_RETURN to 333 MSDLHapticData { 334 HapticComposition( 335 listOf( 336 HapticCompositionPrimitive( 337 VibrationEffect.Composition.PRIMITIVE_CLICK, 338 scale = 0.7f, 339 delayMillis = 0, 340 ) 341 ), 342 VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), 343 ) 344 }, 345 HapticToken.KEYPRESS_DELETE to 346 MSDLHapticData { 347 HapticComposition( 348 listOf( 349 HapticCompositionPrimitive( 350 VibrationEffect.Composition.PRIMITIVE_CLICK, 351 scale = 1f, 352 delayMillis = 0, 353 ) 354 ), 355 VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), 356 ) 357 }, 358 ) 359 } 360 } 361