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