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 #include "Vibrator.h"
18 
19 #include <glob.h>
20 #include <hardware/hardware.h>
21 #include <hardware/vibrator.h>
22 #include <linux/version.h>
23 #include <log/log.h>
24 #include <stdio.h>
25 #include <utils/Trace.h>
26 
27 #include <cinttypes>
28 #include <cmath>
29 #include <fstream>
30 #include <iostream>
31 #include <memory>
32 #include <optional>
33 #include <sstream>
34 
35 #ifndef ARRAY_SIZE
36 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
37 #endif
38 
39 #ifdef LOG_TAG
40 #undef LOG_TAG
41 #define LOG_TAG std::getenv("HAPTIC_NAME")
42 #endif
43 
44 namespace aidl {
45 namespace android {
46 namespace hardware {
47 namespace vibrator {
48 static constexpr uint16_t FF_CUSTOM_DATA_LEN_MAX_COMP = 2044;  // (COMPOSE_SIZE_MAX + 1) * 8 + 4
49 static constexpr uint16_t FF_CUSTOM_DATA_LEN_MAX_PWLE = 2302;
50 
51 static constexpr uint32_t WAVEFORM_DOUBLE_CLICK_SILENCE_MS = 100;
52 
53 static constexpr uint32_t WAVEFORM_LONG_VIBRATION_THRESHOLD_MS = 50;
54 
55 static constexpr uint8_t VOLTAGE_SCALE_MAX = 100;
56 
57 static constexpr int8_t MAX_COLD_START_LATENCY_MS = 6;  // I2C Transaction + DSP Return-From-Standby
58 static constexpr int8_t MAX_PAUSE_TIMING_ERROR_MS = 1;  // ALERT Irq Handling
59 static constexpr uint32_t MAX_TIME_MS = UINT16_MAX;
60 
61 static constexpr auto ASYNC_COMPLETION_TIMEOUT = std::chrono::milliseconds(100);
62 static constexpr auto POLLING_TIMEOUT = 50;
63 static constexpr int32_t COMPOSE_DELAY_MAX_MS = 10000;
64 
65 /* nsections is 8 bits. Need to preserve 1 section for the first delay before the first effect. */
66 static constexpr int32_t COMPOSE_SIZE_MAX = 254;
67 static constexpr int32_t COMPOSE_PWLE_SIZE_MAX_DEFAULT = 127;
68 
69 // Measured resonant frequency, f0_measured, is represented by Q10.14 fixed
70 // point format on cs40l26 devices. The expression to calculate f0 is:
71 //   f0 = f0_measured / 2^Q14_BIT_SHIFT
72 // See the LRA Calibration Support documentation for more details.
73 static constexpr int32_t Q14_BIT_SHIFT = 14;
74 
75 // Measured ReDC. The LRA series resistance (ReDC), expressed as follows
76 // redc(ohms) = redc_measured / 2^Q15_BIT_SHIFT.
77 // This value represents the unit-specific ReDC input to the click compensation
78 // algorithm. It can be overwritten at a later time by writing to the redc_stored
79 // sysfs control.
80 // See the LRA Calibration Support documentation for more details.
81 static constexpr int32_t Q15_BIT_SHIFT = 15;
82 
83 // Measured Q factor, q_measured, is represented by Q8.16 fixed
84 // point format on cs40l26 devices. The expression to calculate q is:
85 //   q = q_measured / 2^Q16_BIT_SHIFT
86 // See the LRA Calibration Support documentation for more details.
87 static constexpr int32_t Q16_BIT_SHIFT = 16;
88 
89 static constexpr int32_t COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS = 16383;
90 
91 static constexpr uint32_t WT_LEN_CALCD = 0x00800000;
92 static constexpr uint8_t PWLE_CHIRP_BIT = 0x8;  // Dynamic/static frequency and voltage
93 static constexpr uint8_t PWLE_BRAKE_BIT = 0x4;
94 static constexpr uint8_t PWLE_AMP_REG_BIT = 0x2;
95 
96 static constexpr uint8_t PWLE_WT_TYPE = 12;
97 static constexpr uint8_t PWLE_HEADER_WORD_COUNT = 3;
98 static constexpr uint8_t PWLE_HEADER_FTR_SHIFT = 8;
99 static constexpr uint8_t PWLE_SVC_METADATA_WORD_COUNT = 3;
100 static constexpr uint32_t PWLE_SVC_METADATA_TERMINATOR = 0xFFFFFF;
101 static constexpr uint8_t PWLE_SEGMENT_WORD_COUNT = 2;
102 static constexpr uint8_t PWLE_HEADER_WCOUNT_WORD_OFFSET = 2;
103 static constexpr uint8_t PWLE_WORD_SIZE = sizeof(uint32_t);
104 
105 static constexpr uint8_t PWLE_SVC_NO_BRAKING = -1;
106 static constexpr uint8_t PWLE_SVC_CAT_BRAKING = 0;
107 static constexpr uint8_t PWLE_SVC_OPEN_BRAKING = 1;
108 static constexpr uint8_t PWLE_SVC_CLOSED_BRAKING = 2;
109 static constexpr uint8_t PWLE_SVC_MIXED_BRAKING = 3;
110 
111 static constexpr uint32_t PWLE_SVC_MAX_BRAKING_TIME_MS = 1000;
112 
113 static constexpr uint8_t PWLE_FTR_BUZZ_BIT = 0x80;
114 static constexpr uint8_t PWLE_FTR_CLICK_BIT = 0x00;
115 static constexpr uint8_t PWLE_FTR_DYNAMIC_F0_BIT = 0x10;
116 static constexpr uint8_t PWLE_FTR_SVC_METADATA_BIT = 0x04;
117 static constexpr uint8_t PWLE_FTR_DVL_BIT = 0x02;
118 static constexpr uint8_t PWLE_FTR_LF0T_BIT = 0x01;
119 
120 static constexpr float PWLE_LEVEL_MIN = 0.0;
121 static constexpr float PWLE_LEVEL_MAX = 1.0;
122 static constexpr float CS40L26_PWLE_LEVEL_MIN = -1.0;
123 static constexpr float CS40L26_PWLE_LEVEL_MAX = 0.9995118;
124 static constexpr float PWLE_FREQUENCY_RESOLUTION_HZ = 1.00;
125 static constexpr float PWLE_FREQUENCY_MIN_HZ = 1.00;
126 static constexpr float PWLE_FREQUENCY_MAX_HZ = 1000.00;
127 static constexpr float PWLE_BW_MAP_SIZE =
128         1 + ((PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ);
129 
130 /*
131  * [15] Edge, 0:Falling, 1:Rising
132  * [14:12] GPI_NUM, 1:GPI1 (with CS40L26A, 1 is the only supported GPI)
133  * [8] BANK, 0:RAM, 1:R0M
134  * [7] USE_BUZZGEN, 0:Not buzzgen, 1:buzzgen
135  * [6:0] WAVEFORM_INDEX
136  * 0x9100 = 1001 0001 0000 0000: Rising + GPI1 + RAM + Not buzzgen
137  */
138 static constexpr uint16_t GPIO_TRIGGER_CONFIG = 0x9100;
139 
amplitudeToScale(float amplitude,float maximum)140 static uint16_t amplitudeToScale(float amplitude, float maximum) {
141     float ratio = 100; /* Unit: % */
142     if (maximum != 0)
143         ratio = amplitude / maximum * 100;
144 
145     if (maximum == 0 || ratio > 100)
146         ratio = 100;
147 
148     return std::round(ratio);
149 }
150 
redcToFloat(std::string * caldata)151 static float redcToFloat(std::string *caldata) {
152     return static_cast<float>(std::stoul(*caldata, nullptr, 16)) / (1 << Q15_BIT_SHIFT);
153 }
154 
155 enum WaveformBankID : uint8_t {
156     RAM_WVFRM_BANK,
157     ROM_WVFRM_BANK,
158     OWT_WVFRM_BANK,
159 };
160 
161 enum WaveformIndex : uint16_t {
162     /* Physical waveform */
163     WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0,
164     WAVEFORM_RESERVED_INDEX_1 = 1,
165     WAVEFORM_CLICK_INDEX = 2,
166     WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX = 3,
167     WAVEFORM_THUD_INDEX = 4,
168     WAVEFORM_SPIN_INDEX = 5,
169     WAVEFORM_QUICK_RISE_INDEX = 6,
170     WAVEFORM_SLOW_RISE_INDEX = 7,
171     WAVEFORM_QUICK_FALL_INDEX = 8,
172     WAVEFORM_LIGHT_TICK_INDEX = 9,
173     WAVEFORM_LOW_TICK_INDEX = 10,
174     WAVEFORM_RESERVED_MFG_1,
175     WAVEFORM_RESERVED_MFG_2,
176     WAVEFORM_RESERVED_MFG_3,
177     WAVEFORM_MAX_PHYSICAL_INDEX,
178     /* OWT waveform */
179     WAVEFORM_COMPOSE = WAVEFORM_MAX_PHYSICAL_INDEX,
180     WAVEFORM_PWLE,
181     /*
182      * Refer to <linux/input.h>, the WAVEFORM_MAX_INDEX must not exceed 96.
183      * #define FF_GAIN		0x60  // 96 in decimal
184      * #define FF_MAX_EFFECTS	FF_GAIN
185      */
186     WAVEFORM_MAX_INDEX,
187 };
188 
189 std::vector<CompositePrimitive> defaultSupportedPrimitives = {
190         ndk::enum_range<CompositePrimitive>().begin(), ndk::enum_range<CompositePrimitive>().end()};
191 
192 enum vibe_state {
193     VIBE_STATE_STOPPED = 0,
194     VIBE_STATE_HAPTIC,
195     VIBE_STATE_ASP,
196 };
197 
198 std::mutex mActiveId_mutex;  // protects mActiveId
199 
200 class DspMemChunk {
201   private:
202     std::unique_ptr<uint8_t[]> head;
203     size_t bytes = 0;
204     uint8_t waveformType;
205     uint8_t *_current;
206     const uint8_t *_max;
207     uint32_t _cache = 0;
208     int _cachebits = 0;
209 
isEnd() const210     bool isEnd() const { return _current == _max; }
min(int x,int y)211     int min(int x, int y) { return x < y ? x : y; }
212 
write(int nbits,uint32_t val)213     int write(int nbits, uint32_t val) {
214         int nwrite, i;
215 
216         nwrite = min(24 - _cachebits, nbits);
217         _cache <<= nwrite;
218         _cache |= val >> (nbits - nwrite);
219         _cachebits += nwrite;
220         nbits -= nwrite;
221 
222         if (_cachebits == 24) {
223             if (isEnd())
224                 return -ENOSPC;
225 
226             _cache &= 0xFFFFFF;
227             for (i = 0; i < sizeof(_cache); i++, _cache <<= 8)
228                 *_current++ = (_cache & 0xFF000000) >> 24;
229 
230             bytes += sizeof(_cache);
231             _cachebits = 0;
232         }
233 
234         if (nbits)
235             return write(nbits, val);
236 
237         return 0;
238     }
239 
fToU16(float input,uint16_t * output,float scale,float min,float max)240    int fToU16(float input, uint16_t *output, float scale, float min, float max) {
241         if (input < min || input > max)
242             return -ERANGE;
243 
244         *output = roundf(input * scale);
245         return 0;
246     }
247 
constructPwleSegment(uint16_t delay,uint16_t amplitude,uint16_t frequency,uint8_t flags,uint32_t vbemfTarget=0)248     void constructPwleSegment(uint16_t delay, uint16_t amplitude, uint16_t frequency, uint8_t flags,
249                               uint32_t vbemfTarget = 0) {
250         write(16, delay);
251         write(12, amplitude);
252         write(12, frequency);
253         /* feature flags to control the chirp, CLAB braking, back EMF amplitude regulation */
254         write(8, (flags | 1) << 4);
255         if (flags & PWLE_AMP_REG_BIT) {
256             write(24, vbemfTarget); /* target back EMF voltage */
257         }
258     }
259 
260   public:
front() const261     uint8_t *front() const { return head.get(); }
type() const262     uint8_t type() const { return waveformType; }
size() const263     size_t size() const { return bytes; }
264 
DspMemChunk(uint8_t type,size_t size)265     DspMemChunk(uint8_t type, size_t size) : head(new uint8_t[size]{0x00}) {
266         waveformType = type;
267         _current = head.get();
268         _max = _current + size;
269 
270         if (waveformType == WAVEFORM_COMPOSE) {
271             write(8, 0); /* Padding */
272             write(8, 0); /* nsections placeholder */
273             write(8, 0); /* repeat */
274         } else if (waveformType == WAVEFORM_PWLE) {
275             write(16, (PWLE_FTR_BUZZ_BIT | PWLE_FTR_DVL_BIT)
276                               << PWLE_HEADER_FTR_SHIFT); /* Feature flag */
277             write(8, PWLE_WT_TYPE);                      /* type12 */
278             write(24, PWLE_HEADER_WORD_COUNT);           /* Header word count */
279             write(24, 0);                                /* Body word count placeholder */
280 
281 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
282             write(24, 0); /* Waveform length placeholder */
283             write(8, 0);  /* Repeat */
284             write(12, 0); /* Wait time between repeats */
285             write(8, 0);  /* nsections placeholder */
286 #endif
287         } else {
288             ALOGE("%s: Invalid type: %u", __func__, waveformType);
289         }
290     }
291 
flush()292     int flush() {
293         if (!_cachebits)
294             return 0;
295 
296         return write(24 - _cachebits, 0);
297     }
298 
constructComposeSegment(uint32_t effectVolLevel,uint32_t effectIndex,uint8_t repeat,uint8_t flags,uint16_t nextEffectDelay)299     int constructComposeSegment(uint32_t effectVolLevel, uint32_t effectIndex, uint8_t repeat,
300                                 uint8_t flags, uint16_t nextEffectDelay) {
301         if (waveformType != WAVEFORM_COMPOSE) {
302             ALOGE("%s: Invalid type: %d", __func__, waveformType);
303             return -EDOM;
304         }
305         if (effectVolLevel > 100 || effectIndex > WAVEFORM_MAX_PHYSICAL_INDEX) {
306             ALOGE("%s: Invalid argument: %u, %u", __func__, effectVolLevel, effectIndex);
307             return -EINVAL;
308         }
309         write(8, effectVolLevel);   /* amplitude */
310         write(8, effectIndex);      /* index */
311         write(8, repeat);           /* repeat */
312         write(8, flags);            /* flags */
313         write(16, nextEffectDelay); /* delay */
314         return 0;
315     }
316 
constructActiveSegment(int duration,float amplitude,float frequency,bool chirp)317     int constructActiveSegment(int duration, float amplitude, float frequency, bool chirp) {
318         uint16_t delay = 0;
319         uint16_t amp = 0;
320         uint16_t freq = 0;
321         uint8_t flags = 0x0;
322         if (waveformType != WAVEFORM_PWLE) {
323             ALOGE("%s: Invalid type: %d", __func__, waveformType);
324             return -EDOM;
325         }
326         if ((fToU16(duration, &delay, 4, 0.0f, COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) < 0) ||
327             (fToU16(amplitude, &amp, 2048, CS40L26_PWLE_LEVEL_MIN, CS40L26_PWLE_LEVEL_MAX) < 0) ||
328             (fToU16(frequency, &freq, 4, PWLE_FREQUENCY_MIN_HZ, PWLE_FREQUENCY_MAX_HZ) < 0)) {
329             ALOGE("%s: Invalid argument: %d, %f, %f", __func__, duration, amplitude, frequency);
330             return -ERANGE;
331         }
332         if (chirp) {
333             flags |= PWLE_CHIRP_BIT;
334         }
335         constructPwleSegment(delay, amp, freq, flags, 0 /*ignored*/);
336         return 0;
337     }
338 
constructBrakingSegment(int duration,Braking brakingType)339     int constructBrakingSegment(int duration, Braking brakingType) {
340         uint16_t delay = 0;
341         uint16_t freq = 0;
342         uint8_t flags = 0x00;
343         if (waveformType != WAVEFORM_PWLE) {
344             ALOGE("%s: Invalid type: %d", __func__, waveformType);
345             return -EDOM;
346         }
347         if (fToU16(duration, &delay, 4, 0.0f, COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) < 0) {
348             ALOGE("%s: Invalid argument: %d", __func__, duration);
349             return -ERANGE;
350         }
351         fToU16(PWLE_FREQUENCY_MIN_HZ, &freq, 4, PWLE_FREQUENCY_MIN_HZ, PWLE_FREQUENCY_MAX_HZ);
352         if (static_cast<std::underlying_type<Braking>::type>(brakingType)) {
353             flags |= PWLE_BRAKE_BIT;
354         }
355 
356         constructPwleSegment(delay, 0 /*ignored*/, freq, flags, 0 /*ignored*/);
357         return 0;
358     }
359 
updateWLength(uint32_t totalDuration)360     int updateWLength(uint32_t totalDuration) {
361         uint8_t *f = front();
362         if (f == nullptr) {
363             ALOGE("%s: head does not exist!", __func__);
364             return -ENOMEM;
365         }
366         if (waveformType != WAVEFORM_PWLE) {
367             ALOGE("%s: Invalid type: %d", __func__, waveformType);
368             return -EDOM;
369         }
370         if (totalDuration > 0x7FFFF) {
371             ALOGE("%s: Invalid argument: %u", __func__, totalDuration);
372             return -EINVAL;
373         }
374 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
375         f += PWLE_HEADER_WORD_COUNT * PWLE_WORD_SIZE;
376 #endif
377         totalDuration *= 8; /* Unit: 0.125 ms (since wlength played @ 8kHz). */
378         totalDuration |=
379                 WT_LEN_CALCD; /* Bit 23 is for WT_LEN_CALCD; Bit 22 is for WT_INDEFINITE. */
380         *(f + 0) = (totalDuration >> 24) & 0xFF;
381         *(f + 1) = (totalDuration >> 16) & 0xFF;
382         *(f + 2) = (totalDuration >> 8) & 0xFF;
383         *(f + 3) = totalDuration & 0xFF;
384         return 0;
385     }
386 
updateNSection(int segmentIdx)387     int updateNSection(int segmentIdx) {
388         uint8_t *f = front();
389         if (f == nullptr) {
390             ALOGE("%s: head does not exist!", __func__);
391             return -ENOMEM;
392         }
393 
394         if (waveformType == WAVEFORM_COMPOSE) {
395             if (segmentIdx > COMPOSE_SIZE_MAX + 1 /*1st effect may have a delay*/) {
396                 ALOGE("%s: Invalid argument: %d", __func__, segmentIdx);
397                 return -EINVAL;
398             }
399             *(f + 2) = (0xFF & segmentIdx);
400         } else if (waveformType == WAVEFORM_PWLE) {
401             if (segmentIdx > COMPOSE_PWLE_SIZE_MAX_DEFAULT) {
402                 ALOGE("%s: Invalid argument: %d", __func__, segmentIdx);
403                 return -EINVAL;
404             }
405 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
406             f += PWLE_HEADER_WORD_COUNT * PWLE_WORD_SIZE;
407 #endif
408             *(f + 7) |= (0xF0 & segmentIdx) >> 4; /* Bit 4 to 7 */
409             *(f + 9) |= (0x0F & segmentIdx) << 4; /* Bit 3 to 0 */
410         } else {
411             ALOGE("%s: Invalid type: %d", __func__, waveformType);
412             return -EDOM;
413         }
414 
415         return 0;
416     }
417 
updateWCount(int segmentCount)418     int updateWCount(int segmentCount) {
419         uint8_t *f = front();
420 
421         if (segmentCount > COMPOSE_SIZE_MAX + 1 /*1st effect may have a delay*/) {
422             ALOGE("%s: Invalid argument: %d", __func__, segmentCount);
423             return -EINVAL;
424         }
425         if (f == nullptr) {
426             ALOGE("%s: head does not exist!", __func__);
427             return -ENOMEM;
428         }
429         if (waveformType != WAVEFORM_PWLE) {
430             ALOGE("%s: Invalid type: %d", __func__, waveformType);
431             return -EDOM;
432         }
433 
434 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)
435         f += PWLE_HEADER_WORD_COUNT * PWLE_WORD_SIZE;
436 #endif
437         uint32_t dataSize = segmentCount * PWLE_SEGMENT_WORD_COUNT + PWLE_HEADER_WORD_COUNT;
438         *(f + 0) = (dataSize >> 24) & 0xFF;
439         *(f + 1) = (dataSize >> 16) & 0xFF;
440         *(f + 2) = (dataSize >> 8) & 0xFF;
441         *(f + 3) = dataSize & 0xFF;
442 
443         return 0;
444     }
445 };
446 
Vibrator(std::unique_ptr<HwApi> hwApiDefault,std::unique_ptr<HwCal> hwCalDefault,std::unique_ptr<HwApi> hwApiDual,std::unique_ptr<HwCal> hwCalDual,std::unique_ptr<HwGPIO> hwgpio)447 Vibrator::Vibrator(std::unique_ptr<HwApi> hwApiDefault, std::unique_ptr<HwCal> hwCalDefault,
448                    std::unique_ptr<HwApi> hwApiDual, std::unique_ptr<HwCal> hwCalDual,
449                    std::unique_ptr<HwGPIO> hwgpio)
450     : mHwApiDef(std::move(hwApiDefault)),
451       mHwCalDef(std::move(hwCalDefault)),
452       mHwApiDual(std::move(hwApiDual)),
453       mHwCalDual(std::move(hwCalDual)),
454       mHwGPIO(std::move(hwgpio)),
455       mAsyncHandle(std::async([] {})) {
456     int32_t longFrequencyShift;
457     std::string caldata{8, '0'};
458     uint32_t calVer;
459 
460     // ==================Single actuators and dual actuators checking =============================
461     if ((mHwApiDual != nullptr) && (mHwCalDual != nullptr))
462         mIsDual = true;
463 
464     // ==================INPUT Devices== Base =================
465     const char *inputEventName = std::getenv("INPUT_EVENT_NAME");
466     const char *inputEventPathName = std::getenv("INPUT_EVENT_PATH");
467     if ((strstr(inputEventName, "cs40l26") != nullptr) ||
468         (strstr(inputEventName, "cs40l26_dual_input") != nullptr)) {
469         glob_t inputEventPaths;
470         int fd = -1;
471         int ret;
472         uint32_t val = 0;
473         char str[20] = {0x00};
474         for (uint8_t retry = 0; retry < 10; retry++) {
475             ret = glob(inputEventPathName, 0, nullptr, &inputEventPaths);
476             if (ret) {
477                 ALOGE("Failed to get input event paths (%d): %s", errno, strerror(errno));
478             } else {
479                 for (int i = 0; i < inputEventPaths.gl_pathc; i++) {
480                     fd = TEMP_FAILURE_RETRY(open(inputEventPaths.gl_pathv[i], O_RDWR));
481                     if (fd > 0) {
482                         if (ioctl(fd, EVIOCGBIT(0, sizeof(val)), &val) > 0 &&
483                             (val & (1 << EV_FF)) && ioctl(fd, EVIOCGNAME(sizeof(str)), &str) > 0 &&
484                             strstr(str, inputEventName) != nullptr) {
485                             mInputFd.reset(fd);
486                             ALOGI("Control %s through %s", inputEventName,
487                                   inputEventPaths.gl_pathv[i]);
488                             break;
489                         }
490                         close(fd);
491                     }
492                 }
493             }
494 
495             if (ret == 0) {
496                 globfree(&inputEventPaths);
497             }
498             if (mInputFd.ok()) {
499                 break;
500             }
501 
502             sleep(1);
503             ALOGW("Retry #%d to search in %zu input devices.", retry, inputEventPaths.gl_pathc);
504         }
505 
506         if (!mInputFd.ok()) {
507             ALOGE("Failed to get an input event with name %s", inputEventName);
508         }
509     } else {
510         ALOGE("The input name %s is not cs40l26_input or cs40l26_dual_input", inputEventName);
511     }
512 
513     // ==================INPUT Devices== Flip =================
514     if (mIsDual) {
515         const char *inputEventNameDual = std::getenv("INPUT_EVENT_NAME_DUAL");
516         if ((strstr(inputEventNameDual, "cs40l26_dual_input") != nullptr)) {
517             glob_t inputEventPaths;
518             int fd = -1;
519             int ret;
520             uint32_t val = 0;
521             char str[20] = {0x00};
522             for (uint8_t retry = 0; retry < 10; retry++) {
523                 ret = glob(inputEventPathName, 0, nullptr, &inputEventPaths);
524                 if (ret) {
525                     ALOGE("Failed to get flip's input event paths (%d): %s", errno,
526                           strerror(errno));
527                 } else {
528                     for (int i = 0; i < inputEventPaths.gl_pathc; i++) {
529                         fd = TEMP_FAILURE_RETRY(open(inputEventPaths.gl_pathv[i], O_RDWR));
530                         if (fd > 0) {
531                             if (ioctl(fd, EVIOCGBIT(0, sizeof(val)), &val) > 0 &&
532                                 (val & (1 << EV_FF)) &&
533                                 ioctl(fd, EVIOCGNAME(sizeof(str)), &str) > 0 &&
534                                 strstr(str, inputEventNameDual) != nullptr) {
535                                 mInputFdDual.reset(fd);
536                                 ALOGI("Control %s through %s", inputEventNameDual,
537                                       inputEventPaths.gl_pathv[i]);
538                                 break;
539                             }
540                             close(fd);
541                         }
542                     }
543                 }
544 
545                 if (ret == 0) {
546                     globfree(&inputEventPaths);
547                 }
548                 if (mInputFdDual.ok()) {
549                     break;
550                 }
551 
552                 sleep(1);
553                 ALOGW("Retry #%d to search in %zu input devices.", retry, inputEventPaths.gl_pathc);
554             }
555 
556             if (!mInputFdDual.ok()) {
557                 ALOGE("Failed to get an input event with name %s", inputEventNameDual);
558             }
559             ALOGE("HWAPI: %s", std::getenv("HWAPI_PATH_PREFIX"));
560         } else {
561             ALOGE("The input name %s is not cs40l26_dual_input", inputEventNameDual);
562         }
563     }
564     // ====================HAL internal effect table== Base ==================================
565 
566     mFfEffects.resize(WAVEFORM_MAX_INDEX);
567     mEffectDurations.resize(WAVEFORM_MAX_INDEX);
568     mEffectDurations = {
569             1000, 100, 9, 1000, 300, 130, 150, 500, 100, 5, 12, 1000, 1000, 1000,
570     }; /* 11+3 waveforms. The duration must < UINT16_MAX */
571     mEffectBrakingDurations.resize(WAVEFORM_MAX_INDEX);
572     mEffectCustomData.reserve(WAVEFORM_MAX_INDEX);
573 
574     uint8_t effectIndex;
575     uint16_t numBytes = 0;
576     for (effectIndex = 0; effectIndex < WAVEFORM_MAX_INDEX; effectIndex++) {
577         if (effectIndex < WAVEFORM_MAX_PHYSICAL_INDEX) {
578             /* Initialize physical waveforms. */
579             mEffectCustomData.push_back({RAM_WVFRM_BANK, effectIndex});
580             mFfEffects[effectIndex] = {
581                     .type = FF_PERIODIC,
582                     .id = -1,
583                     // Length == 0 to allow firmware control of the duration
584                     .replay.length = 0,
585                     .u.periodic.waveform = FF_CUSTOM,
586                     .u.periodic.custom_data = mEffectCustomData[effectIndex].data(),
587                     .u.periodic.custom_len =
588                             static_cast<uint32_t>(mEffectCustomData[effectIndex].size()),
589             };
590             // Bypass the waveform update due to different input name
591             if ((strstr(inputEventName, "cs40l26") != nullptr) ||
592                 (strstr(inputEventName, "cs40l26_dual_input") != nullptr)) {
593                 // Let the firmware control the playback duration to avoid
594                 // cutting any effect that is played short
595                 if (!mHwApiDef->setFFEffect(
596                             mInputFd, &mFfEffects[effectIndex],
597                             mEffectDurations[effectIndex])) {
598                     ALOGE("Failed upload effect %d (%d): %s", effectIndex, errno, strerror(errno));
599                 }
600             }
601             if (mFfEffects[effectIndex].id != effectIndex) {
602                 ALOGW("Unexpected effect index: %d -> %d", effectIndex, mFfEffects[effectIndex].id);
603             }
604 
605             if (mHwApiDef->hasEffectBrakingTimeBank()) {
606                 mHwApiDef->setEffectBrakingTimeIndex(effectIndex);
607                 mHwApiDef->getEffectBrakingTimeMs(&mEffectBrakingDurations[effectIndex]);
608             }
609         } else {
610             /* Initiate placeholders for OWT effects. */
611             numBytes = effectIndex == WAVEFORM_COMPOSE ? FF_CUSTOM_DATA_LEN_MAX_COMP
612                                                        : FF_CUSTOM_DATA_LEN_MAX_PWLE;
613             std::vector<int16_t> tempVec(numBytes, 0);
614             mEffectCustomData.push_back(std::move(tempVec));
615             mFfEffects[effectIndex] = {
616                     .type = FF_PERIODIC,
617                     .id = -1,
618                     .replay.length = 0,
619                     .u.periodic.waveform = FF_CUSTOM,
620                     .u.periodic.custom_data = mEffectCustomData[effectIndex].data(),
621                     .u.periodic.custom_len = 0,
622             };
623         }
624     }
625 
626     // ====================HAL internal effect table== Flip ==================================
627     if (mIsDual) {
628         mFfEffectsDual.resize(WAVEFORM_MAX_INDEX);
629         mEffectCustomDataDual.reserve(WAVEFORM_MAX_INDEX);
630 
631         for (effectIndex = 0; effectIndex < WAVEFORM_MAX_INDEX; effectIndex++) {
632             if (effectIndex < WAVEFORM_MAX_PHYSICAL_INDEX) {
633                 /* Initialize physical waveforms. */
634                 mEffectCustomDataDual.push_back({RAM_WVFRM_BANK, effectIndex});
635                 mFfEffectsDual[effectIndex] = {
636                         .type = FF_PERIODIC,
637                         .id = -1,
638                         // Length == 0 to allow firmware control of the duration
639                         .replay.length = 0,
640                         .u.periodic.waveform = FF_CUSTOM,
641                         .u.periodic.custom_data = mEffectCustomDataDual[effectIndex].data(),
642                         .u.periodic.custom_len =
643                                 static_cast<uint32_t>(mEffectCustomDataDual[effectIndex].size()),
644                 };
645                 // Bypass the waveform update due to different input name
646                 if ((strstr(inputEventName, "cs40l26") != nullptr) ||
647                     (strstr(inputEventName, "cs40l26_dual_input") != nullptr)) {
648                     // Let the firmware control the playback duration to avoid
649                     // cutting any effect that is played short
650                     if (!mHwApiDual->setFFEffect(
651                                 mInputFdDual, &mFfEffectsDual[effectIndex],
652                                 mEffectDurations[effectIndex])) {
653                         ALOGE("Failed upload flip's effect %d (%d): %s", effectIndex, errno,
654                               strerror(errno));
655                     }
656                 }
657                 if (mFfEffectsDual[effectIndex].id != effectIndex) {
658                     ALOGW("Unexpected effect index: %d -> %d", effectIndex,
659                           mFfEffectsDual[effectIndex].id);
660                 }
661             } else {
662                 /* Initiate placeholders for OWT effects. */
663                 numBytes = effectIndex == WAVEFORM_COMPOSE ? FF_CUSTOM_DATA_LEN_MAX_COMP
664                                                        : FF_CUSTOM_DATA_LEN_MAX_PWLE;
665                 std::vector<int16_t> tempVec(numBytes, 0);
666                 mEffectCustomDataDual.push_back(std::move(tempVec));
667                 mFfEffectsDual[effectIndex] = {
668                         .type = FF_PERIODIC,
669                         .id = -1,
670                         .replay.length = 0,
671                         .u.periodic.waveform = FF_CUSTOM,
672                         .u.periodic.custom_data = mEffectCustomDataDual[effectIndex].data(),
673                         .u.periodic.custom_len = 0,
674                 };
675             }
676         }
677     }
678     // ==============Calibration data checking======================================
679 
680     if (mHwCalDef->getF0(&caldata)) {
681         mHwApiDef->setF0(caldata);
682         mResonantFrequency =
683                 static_cast<float>(std::stoul(caldata, nullptr, 16)) / (1 << Q14_BIT_SHIFT);
684     }
685     if (mHwCalDef->getRedc(&caldata)) {
686         mHwApiDef->setRedc(caldata);
687         mRedc = redcToFloat(&caldata);
688     }
689     if (mHwCalDef->getQ(&caldata)) {
690         mHwApiDef->setQ(caldata);
691     }
692 
693     if (mHwCalDef->getF0SyncOffset(&mF0Offset)) {
694         ALOGD("Vibrator::Vibrator: F0 offset calculated from both base and flip calibration data: "
695               "%u",
696               mF0Offset);
697     } else {
698         mHwCalDef->getLongFrequencyShift(&longFrequencyShift);
699         if (longFrequencyShift > 0) {
700             mF0Offset = longFrequencyShift * std::pow(2, 14);
701         } else if (longFrequencyShift < 0) {
702             mF0Offset = std::pow(2, 24) - std::abs(longFrequencyShift) * std::pow(2, 14);
703         } else {
704             mF0Offset = 0;
705         }
706         ALOGD("Vibrator::Vibrator: F0 offset calculated from long shift frequency: %u", mF0Offset);
707     }
708 
709     if (mIsDual) {
710         if (mHwCalDual->getF0(&caldata)) {
711             mHwApiDual->setF0(caldata);
712         }
713         if (mHwCalDual->getRedc(&caldata)) {
714             mHwApiDual->setRedc(caldata);
715         }
716         if (mHwCalDual->getQ(&caldata)) {
717             mHwApiDual->setQ(caldata);
718         }
719 
720         if (mHwCalDual->getF0SyncOffset(&mF0OffsetDual)) {
721             ALOGD("Vibrator::Vibrator: Dual: F0 offset calculated from both base and flip "
722                   "calibration data: "
723                   "%u",
724                   mF0OffsetDual);
725         }
726     }
727 
728     mHwCalDef->getVersion(&calVer);
729     if (calVer == 2) {
730         mHwCalDef->getTickVolLevels(&(mTickEffectVol));
731         mHwCalDef->getClickVolLevels(&(mClickEffectVol));
732         mHwCalDef->getLongVolLevels(&(mLongEffectVol));
733     } else {
734         ALOGW("Unsupported calibration version! Using the default calibration value");
735         mHwCalDef->getTickVolLevels(&(mTickEffectVol));
736         mHwCalDef->getClickVolLevels(&(mClickEffectVol));
737         mHwCalDef->getLongVolLevels(&(mLongEffectVol));
738     }
739 
740     // ================Project specific setting to driver===============================
741 
742     mHwApiDef->setF0CompEnable(mHwCalDef->isF0CompEnabled());
743     mHwApiDef->setRedcCompEnable(mHwCalDef->isRedcCompEnabled());
744     mHwApiDef->setMinOnOffInterval(MIN_ON_OFF_INTERVAL_US);
745     if (mIsDual) {
746         mHwApiDual->setF0CompEnable(mHwCalDual->isF0CompEnabled());
747         mHwApiDual->setRedcCompEnable(mHwCalDual->isRedcCompEnabled());
748         mHwApiDual->setMinOnOffInterval(MIN_ON_OFF_INTERVAL_US);
749     }
750     // ===============Audio coupled haptics bool init ========
751     mIsUnderExternalControl = false;
752 
753     // =============== Compose PWLE check =====================================
754     mIsChirpEnabled = mHwCalDef->isChirpEnabled();
755 
756     mHwCalDef->getSupportedPrimitives(&mSupportedPrimitivesBits);
757     if (mSupportedPrimitivesBits > 0) {
758         for (auto e : defaultSupportedPrimitives) {
759             if (mSupportedPrimitivesBits & (1 << uint32_t(e))) {
760                 mSupportedPrimitives.emplace_back(e);
761             }
762         }
763     } else {
764         for (auto e : defaultSupportedPrimitives) {
765             mSupportedPrimitivesBits |= (1 << uint32_t(e));
766         }
767         mSupportedPrimitives = defaultSupportedPrimitives;
768     }
769 
770     mPrimitiveMaxScale.resize(WAVEFORM_MAX_INDEX, 100);
771     mPrimitiveMaxScale[WAVEFORM_CLICK_INDEX] = 95;
772     mPrimitiveMaxScale[WAVEFORM_THUD_INDEX] = 75;
773     mPrimitiveMaxScale[WAVEFORM_SPIN_INDEX] = 90;
774     mPrimitiveMaxScale[WAVEFORM_LIGHT_TICK_INDEX] = 75;
775     mPrimitiveMaxScale[WAVEFORM_LOW_TICK_INDEX] = 75;
776 
777     mPrimitiveMinScale.resize(WAVEFORM_MAX_INDEX, 0);
778     mPrimitiveMinScale[WAVEFORM_CLICK_INDEX] = 1;
779     mPrimitiveMinScale[WAVEFORM_THUD_INDEX] = 11;
780     mPrimitiveMinScale[WAVEFORM_SPIN_INDEX] = 23;
781     mPrimitiveMinScale[WAVEFORM_SLOW_RISE_INDEX] = 25;
782     mPrimitiveMinScale[WAVEFORM_QUICK_FALL_INDEX] = 2;
783     mPrimitiveMinScale[WAVEFORM_LIGHT_TICK_INDEX] = 3;
784     mPrimitiveMinScale[WAVEFORM_LOW_TICK_INDEX] = 16;
785 
786     // ====== Get GPIO status and init it ================
787     mGPIOStatus = mHwGPIO->getGPIO();
788     if (!mGPIOStatus || !mHwGPIO->initGPIO()) {
789         ALOGE("Vibrator: GPIO initialization process error");
790     }
791 }
792 
getCapabilities(int32_t * _aidl_return)793 ndk::ScopedAStatus Vibrator::getCapabilities(int32_t *_aidl_return) {
794     ATRACE_NAME("Vibrator::getCapabilities");
795 
796     int32_t ret = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
797                   IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_GET_RESONANT_FREQUENCY |
798                   IVibrator::CAP_GET_Q_FACTOR;
799     if (hasHapticAlsaDevice()) {
800         ret |= IVibrator::CAP_EXTERNAL_CONTROL;
801     } else {
802         ALOGE("No haptics ALSA device");
803     }
804     if (mHwApiDef->hasOwtFreeSpace()) {
805         ret |= IVibrator::CAP_COMPOSE_EFFECTS;
806         if (mIsChirpEnabled) {
807             ret |= IVibrator::CAP_FREQUENCY_CONTROL | IVibrator::CAP_COMPOSE_PWLE_EFFECTS;
808         }
809     }
810     *_aidl_return = ret;
811     return ndk::ScopedAStatus::ok();
812 }
813 
off()814 ndk::ScopedAStatus Vibrator::off() {
815     ATRACE_NAME("Vibrator::off");
816     bool ret{true};
817     const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
818 
819     if (mActiveId >= 0) {
820         ALOGD("Off: Stop the active effect: %d", mActiveId);
821         /* Stop the active effect. */
822         if (!mHwApiDef->setFFPlay(mInputFd, mActiveId, false)) {
823             ALOGE("Off: Failed to stop effect %d (%d): %s", mActiveId, errno, strerror(errno));
824             ret = false;
825         }
826         if (mIsDual && (!mHwApiDual->setFFPlay(mInputFdDual, mActiveId, false))) {
827             ALOGE("Off: Failed to stop flip's effect %d (%d): %s", mActiveId, errno,
828                   strerror(errno));
829             ret = false;
830         }
831 
832         if (!mHwGPIO->setGPIOOutput(false)) {
833             ALOGE("Off: Failed to reset GPIO(%d): %s", errno, strerror(errno));
834             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
835         }
836     } else {
837         ALOGD("Off: Vibrator is already off");
838     }
839 
840     setGlobalAmplitude(false);
841     if (mF0Offset) {
842         mHwApiDef->setF0Offset(0);
843         if (mIsDual && mF0OffsetDual) {
844             mHwApiDual->setF0Offset(0);
845         }
846     }
847 
848     if (ret) {
849         ALOGD("Off: Done.");
850         mActiveId = -1;
851         return ndk::ScopedAStatus::ok();
852     } else {
853         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
854     }
855 }
856 
on(int32_t timeoutMs,const std::shared_ptr<IVibratorCallback> & callback)857 ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs,
858                                 const std::shared_ptr<IVibratorCallback> &callback) {
859     ATRACE_NAME("Vibrator::on");
860     ALOGD("Vibrator::on");
861 
862     if (timeoutMs > MAX_TIME_MS) {
863         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
864     }
865     const uint16_t index = (timeoutMs < WAVEFORM_LONG_VIBRATION_THRESHOLD_MS)
866                                    ? WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX
867                                    : WAVEFORM_LONG_VIBRATION_EFFECT_INDEX;
868     if (MAX_COLD_START_LATENCY_MS <= MAX_TIME_MS - timeoutMs) {
869         timeoutMs += MAX_COLD_START_LATENCY_MS;
870     }
871     setGlobalAmplitude(true);
872     if (mF0Offset) {
873         mHwApiDef->setF0Offset(mF0Offset);
874         if (mIsDual && mF0OffsetDual) {
875             mHwApiDual->setF0Offset(mF0OffsetDual);
876         }
877     }
878     return on(timeoutMs, index, nullptr /*ignored*/, callback);
879 }
880 
perform(Effect effect,EffectStrength strength,const std::shared_ptr<IVibratorCallback> & callback,int32_t * _aidl_return)881 ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength strength,
882                                      const std::shared_ptr<IVibratorCallback> &callback,
883                                      int32_t *_aidl_return) {
884     ATRACE_NAME("Vibrator::perform");
885     ALOGD("Vibrator::perform");
886     return performEffect(effect, strength, callback, _aidl_return);
887 }
888 
getSupportedEffects(std::vector<Effect> * _aidl_return)889 ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect> *_aidl_return) {
890     *_aidl_return = {Effect::TEXTURE_TICK, Effect::TICK, Effect::CLICK, Effect::HEAVY_CLICK,
891                      Effect::DOUBLE_CLICK};
892     return ndk::ScopedAStatus::ok();
893 }
894 
setAmplitude(float amplitude)895 ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
896     ATRACE_NAME("Vibrator::setAmplitude");
897 
898     if (amplitude <= 0.0f || amplitude > 1.0f) {
899         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
900     }
901 
902     mLongEffectScale = amplitude;
903     if (!isUnderExternalControl()) {
904         return setGlobalAmplitude(true);
905     } else {
906         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
907     }
908 }
909 
setExternalControl(bool enabled)910 ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) {
911     ATRACE_NAME("Vibrator::setExternalControl");
912 
913     setGlobalAmplitude(enabled);
914 
915     if (mHasHapticAlsaDevice || mConfigHapticAlsaDeviceDone || hasHapticAlsaDevice()) {
916         if (!mHwApiDef->setHapticPcmAmp(&mHapticPcm, enabled, mCard, mDevice)) {
917             ALOGE("Failed to %s haptic pcm device: %d", (enabled ? "enable" : "disable"), mDevice);
918             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
919         }
920     } else {
921         ALOGE("No haptics ALSA device");
922         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
923     }
924 
925     mIsUnderExternalControl = enabled;
926     return ndk::ScopedAStatus::ok();
927 }
928 
getCompositionDelayMax(int32_t * maxDelayMs)929 ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t *maxDelayMs) {
930     ATRACE_NAME("Vibrator::getCompositionDelayMax");
931     *maxDelayMs = COMPOSE_DELAY_MAX_MS;
932     return ndk::ScopedAStatus::ok();
933 }
934 
getCompositionSizeMax(int32_t * maxSize)935 ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t *maxSize) {
936     ATRACE_NAME("Vibrator::getCompositionSizeMax");
937     *maxSize = COMPOSE_SIZE_MAX;
938     return ndk::ScopedAStatus::ok();
939 }
940 
getSupportedPrimitives(std::vector<CompositePrimitive> * supported)941 ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive> *supported) {
942     *supported = mSupportedPrimitives;
943     return ndk::ScopedAStatus::ok();
944 }
945 
getPrimitiveDuration(CompositePrimitive primitive,int32_t * durationMs)946 ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive primitive,
947                                                   int32_t *durationMs) {
948     ndk::ScopedAStatus status;
949     uint32_t effectIndex;
950     if (primitive != CompositePrimitive::NOOP) {
951         status = getPrimitiveDetails(primitive, &effectIndex);
952         if (!status.isOk()) {
953             return status;
954         }
955 
956         *durationMs = mEffectDurations[effectIndex] + mEffectBrakingDurations[effectIndex];
957     } else {
958         *durationMs = 0;
959     }
960     return ndk::ScopedAStatus::ok();
961 }
962 
compose(const std::vector<CompositeEffect> & composite,const std::shared_ptr<IVibratorCallback> & callback)963 ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect> &composite,
964                                      const std::shared_ptr<IVibratorCallback> &callback) {
965     ATRACE_NAME("Vibrator::compose");
966     ALOGD("Vibrator::compose");
967     uint16_t size;
968     uint16_t nextEffectDelay;
969 
970     if (composite.size() > COMPOSE_SIZE_MAX || composite.empty()) {
971         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
972     }
973 
974     /* Check if there is a wait before the first effect. */
975     nextEffectDelay = composite.front().delayMs;
976     if (nextEffectDelay > COMPOSE_DELAY_MAX_MS || nextEffectDelay < 0) {
977         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
978     } else if (nextEffectDelay > 0) {
979         size = composite.size() + 1;
980     } else {
981         size = composite.size();
982     }
983 
984     DspMemChunk ch(WAVEFORM_COMPOSE, FF_CUSTOM_DATA_LEN_MAX_COMP);
985     const uint8_t header_count = ch.size();
986 
987     /* Insert 1 section for a wait before the first effect. */
988     if (nextEffectDelay) {
989         ch.constructComposeSegment(0 /*amplitude*/, 0 /*index*/, 0 /*repeat*/, 0 /*flags*/,
990                                    nextEffectDelay /*delay*/);
991     }
992 
993     for (uint32_t i_curr = 0, i_next = 1; i_curr < composite.size(); i_curr++, i_next++) {
994         auto &e_curr = composite[i_curr];
995         uint32_t effectIndex = 0;
996         uint32_t effectVolLevel = 0;
997         float effectScale = e_curr.scale;
998         if (effectScale < 0.0f || effectScale > 1.0f) {
999             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1000         }
1001 
1002         if (e_curr.primitive != CompositePrimitive::NOOP) {
1003             ndk::ScopedAStatus status;
1004             status = getPrimitiveDetails(e_curr.primitive, &effectIndex);
1005             if (!status.isOk()) {
1006                 return status;
1007             }
1008             effectVolLevel = intensityToVolLevel(effectScale, effectIndex);
1009         }
1010 
1011         /* Fetch the next composite effect delay and fill into the current section */
1012         nextEffectDelay = 0;
1013         if (i_next < composite.size()) {
1014             auto &e_next = composite[i_next];
1015             int32_t delay = e_next.delayMs;
1016 
1017             if (delay > COMPOSE_DELAY_MAX_MS || delay < 0) {
1018                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1019             }
1020             nextEffectDelay = delay;
1021         }
1022 
1023         if (effectIndex == 0 && nextEffectDelay == 0) {
1024             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1025         }
1026 
1027         nextEffectDelay += mEffectBrakingDurations[effectIndex];
1028 
1029         ch.constructComposeSegment(effectVolLevel, effectIndex, 0 /*repeat*/, 0 /*flags*/,
1030                                    nextEffectDelay /*delay*/);
1031     }
1032 
1033     ch.flush();
1034     if (ch.updateNSection(size) < 0) {
1035         ALOGE("%s: Failed to update the section count", __func__);
1036         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1037     }
1038     if (header_count == ch.size()) {
1039         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1040     } else {
1041         // Composition duration should be 0 to allow firmware to play the whole effect
1042         mFfEffects[WAVEFORM_COMPOSE].replay.length = 0;
1043         if (mIsDual) {
1044             mFfEffectsDual[WAVEFORM_COMPOSE].replay.length = 0;
1045         }
1046         return performEffect(WAVEFORM_MAX_INDEX /*ignored*/, VOLTAGE_SCALE_MAX /*ignored*/, &ch,
1047                              callback);
1048     }
1049 }
1050 
on(uint32_t timeoutMs,uint32_t effectIndex,const DspMemChunk * ch,const std::shared_ptr<IVibratorCallback> & callback)1051 ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex, const DspMemChunk *ch,
1052                                 const std::shared_ptr<IVibratorCallback> &callback) {
1053     ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
1054 
1055     if (effectIndex >= FF_MAX_EFFECTS) {
1056         ALOGE("Invalid waveform index %d", effectIndex);
1057         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1058     }
1059     if (mAsyncHandle.wait_for(ASYNC_COMPLETION_TIMEOUT) != std::future_status::ready) {
1060         ALOGE("Previous vibration pending: prev: %d, curr: %d", mActiveId, effectIndex);
1061         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1062     }
1063 
1064     if (ch) {
1065         /* Upload OWT effect. */
1066         if (ch->front() == nullptr) {
1067             ALOGE("Invalid OWT bank");
1068             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1069         }
1070 
1071         if (ch->type() != WAVEFORM_PWLE && ch->type() != WAVEFORM_COMPOSE) {
1072             ALOGE("Invalid OWT type");
1073             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1074         }
1075         effectIndex = ch->type();
1076 
1077         uint32_t freeBytes;
1078         mHwApiDef->getOwtFreeSpace(&freeBytes);
1079         if (ch->size() > freeBytes) {
1080             ALOGE("Invalid OWT length: Effect %d: %zu > %d!", effectIndex, ch->size(), freeBytes);
1081             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1082         }
1083         if (mIsDual) {
1084             mHwApiDual->getOwtFreeSpace(&freeBytes);
1085             if (ch-> size() > freeBytes) {
1086                 ALOGE("Invalid OWT length in flip: Effect %d: %zu > %d!", effectIndex,
1087                       ch-> size(), freeBytes);
1088                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1089             }
1090         }
1091 
1092         int errorStatus;
1093         if (mGPIOStatus && mIsDual) {
1094             mFfEffects[effectIndex].trigger.button = GPIO_TRIGGER_CONFIG | effectIndex;
1095             mFfEffectsDual[effectIndex].trigger.button = GPIO_TRIGGER_CONFIG | effectIndex;
1096         } else {
1097             ALOGD("Not dual haptics HAL and GPIO status fail");
1098         }
1099 
1100         if (!mHwApiDef->uploadOwtEffect(mInputFd, ch->front(), ch->size(), &mFfEffects[effectIndex],
1101                                         &effectIndex, &errorStatus)) {
1102             ALOGE("Invalid uploadOwtEffect");
1103             return ndk::ScopedAStatus::fromExceptionCode(errorStatus);
1104         }
1105         if (mIsDual && !mHwApiDual->uploadOwtEffect(mInputFdDual, ch->front(), ch->size(),
1106                                                     &mFfEffectsDual[effectIndex], &effectIndex,
1107                                                     &errorStatus)) {
1108             ALOGE("Invalid uploadOwtEffect in flip");
1109             return ndk::ScopedAStatus::fromExceptionCode(errorStatus);
1110         }
1111 
1112     } else if (effectIndex == WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX ||
1113                effectIndex == WAVEFORM_LONG_VIBRATION_EFFECT_INDEX) {
1114         /* Update duration for long/short vibration. */
1115         mFfEffects[effectIndex].replay.length = static_cast<uint16_t>(timeoutMs);
1116         if (mGPIOStatus && mIsDual) {
1117             mFfEffects[effectIndex].trigger.button = GPIO_TRIGGER_CONFIG | effectIndex;
1118             mFfEffectsDual[effectIndex].trigger.button = GPIO_TRIGGER_CONFIG | effectIndex;
1119         } else {
1120             ALOGD("Not dual haptics HAL and GPIO status fail");
1121         }
1122         if (!mHwApiDef->setFFEffect(mInputFd, &mFfEffects[effectIndex],
1123                                     static_cast<uint16_t>(timeoutMs))) {
1124             ALOGE("Failed to edit effect %d (%d): %s", effectIndex, errno, strerror(errno));
1125             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1126         }
1127         if (mIsDual) {
1128             mFfEffectsDual[effectIndex].replay.length = static_cast<uint16_t>(timeoutMs);
1129             if (!mHwApiDual->setFFEffect(mInputFdDual, &mFfEffectsDual[effectIndex],
1130                                          static_cast<uint16_t>(timeoutMs))) {
1131                 ALOGE("Failed to edit flip's effect %d (%d): %s", effectIndex, errno,
1132                       strerror(errno));
1133                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1134             }
1135         }
1136     }
1137 
1138     {
1139         const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
1140         /* Play the event now. */
1141         mActiveId = effectIndex;
1142         if (!mGPIOStatus) {
1143             ALOGE("GetVibrator: GPIO status error");
1144             // Do playcode to play effect
1145             if (!mHwApiDef->setFFPlay(mInputFd, effectIndex, true)) {
1146                 ALOGE("Failed to play effect %d (%d): %s", effectIndex, errno, strerror(errno));
1147                 mActiveId = -1;
1148                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1149             }
1150             if (mIsDual && !mHwApiDual->setFFPlay(mInputFdDual, effectIndex, true)) {
1151                 ALOGE("Failed to play flip's effect %d (%d): %s", effectIndex, errno,
1152                       strerror(errno));
1153                 mActiveId = -1;
1154                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1155             }
1156         } else {
1157             // Using GPIO to play effect
1158             if ((effectIndex == WAVEFORM_CLICK_INDEX || effectIndex == WAVEFORM_LIGHT_TICK_INDEX)) {
1159                 mFfEffects[effectIndex].trigger.button = GPIO_TRIGGER_CONFIG | effectIndex;
1160                 if (!mHwApiDef->setFFEffect(mInputFd, &mFfEffects[effectIndex],
1161                                             mFfEffects[effectIndex].replay.length)) {
1162                     ALOGE("Failed to edit effect %d (%d): %s", effectIndex, errno, strerror(errno));
1163                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1164                 }
1165                 if (mIsDual) {
1166                     mFfEffectsDual[effectIndex].trigger.button = GPIO_TRIGGER_CONFIG | effectIndex;
1167                     if (!mHwApiDual->setFFEffect(mInputFdDual, &mFfEffectsDual[effectIndex],
1168                                                  mFfEffectsDual[effectIndex].replay.length)) {
1169                         ALOGE("Failed to edit flip's effect %d (%d): %s", effectIndex, errno,
1170                               strerror(errno));
1171                         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1172                     }
1173                 }
1174             }
1175             if (!mHwGPIO->setGPIOOutput(true)) {
1176                 ALOGE("Failed to trigger effect %d (%d) by GPIO: %s", effectIndex, errno,
1177                       strerror(errno));
1178                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1179             }
1180         }
1181     }
1182 
1183     mAsyncHandle = std::async(&Vibrator::waitForComplete, this, callback);
1184     ALOGD("Vibrator::on, set done.");
1185     return ndk::ScopedAStatus::ok();
1186 }
1187 
setEffectAmplitude(float amplitude,float maximum)1188 ndk::ScopedAStatus Vibrator::setEffectAmplitude(float amplitude, float maximum) {
1189     uint16_t scale = amplitudeToScale(amplitude, maximum);
1190     if (!mHwApiDef->setFFGain(mInputFd, scale)) {
1191         ALOGE("Failed to set the gain to %u (%d): %s", scale, errno, strerror(errno));
1192         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1193     }
1194     if (mIsDual) {
1195         if (!mHwApiDual->setFFGain(mInputFdDual, scale)) {
1196             ALOGE("Failed to set flip's gain to %u (%d): %s", scale, errno, strerror(errno));
1197             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1198         }
1199     }
1200     return ndk::ScopedAStatus::ok();
1201 }
1202 
setGlobalAmplitude(bool set)1203 ndk::ScopedAStatus Vibrator::setGlobalAmplitude(bool set) {
1204     uint8_t amplitude = set ? roundf(mLongEffectScale * mLongEffectVol[1]) : VOLTAGE_SCALE_MAX;
1205     if (!set) {
1206         mLongEffectScale = 1.0;  // Reset the scale for the later new effect.
1207     }
1208 
1209     return setEffectAmplitude(amplitude, VOLTAGE_SCALE_MAX);
1210 }
1211 
getSupportedAlwaysOnEffects(std::vector<Effect> *)1212 ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect> * /*_aidl_return*/) {
1213     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1214 }
1215 
alwaysOnEnable(int32_t,Effect,EffectStrength)1216 ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t /*id*/, Effect /*effect*/,
1217                                             EffectStrength /*strength*/) {
1218     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1219 }
alwaysOnDisable(int32_t)1220 ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t /*id*/) {
1221     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1222 }
1223 
getResonantFrequency(float * resonantFreqHz)1224 ndk::ScopedAStatus Vibrator::getResonantFrequency(float *resonantFreqHz) {
1225     *resonantFreqHz = mResonantFrequency;
1226 
1227     return ndk::ScopedAStatus::ok();
1228 }
1229 
getQFactor(float * qFactor)1230 ndk::ScopedAStatus Vibrator::getQFactor(float *qFactor) {
1231     std::string caldata{8, '0'};
1232     if (!mHwCalDef->getQ(&caldata)) {
1233         ALOGE("Failed to get q factor (%d): %s", errno, strerror(errno));
1234         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1235     }
1236     *qFactor = static_cast<float>(std::stoul(caldata, nullptr, 16)) / (1 << Q16_BIT_SHIFT);
1237 
1238     return ndk::ScopedAStatus::ok();
1239 }
1240 
getFrequencyResolution(float * freqResolutionHz)1241 ndk::ScopedAStatus Vibrator::getFrequencyResolution(float *freqResolutionHz) {
1242     int32_t capabilities;
1243     Vibrator::getCapabilities(&capabilities);
1244     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
1245         *freqResolutionHz = PWLE_FREQUENCY_RESOLUTION_HZ;
1246         return ndk::ScopedAStatus::ok();
1247     } else {
1248         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1249     }
1250 }
1251 
getFrequencyMinimum(float * freqMinimumHz)1252 ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float *freqMinimumHz) {
1253     int32_t capabilities;
1254     Vibrator::getCapabilities(&capabilities);
1255     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
1256         *freqMinimumHz = PWLE_FREQUENCY_MIN_HZ;
1257         return ndk::ScopedAStatus::ok();
1258     } else {
1259         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1260     }
1261 }
1262 
getBandwidthAmplitudeMap(std::vector<float> * _aidl_return)1263 ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float> *_aidl_return) {
1264     // TODO(b/170919640): complete implementation
1265     int32_t capabilities;
1266     Vibrator::getCapabilities(&capabilities);
1267     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
1268         std::vector<float> bandwidthAmplitudeMap(PWLE_BW_MAP_SIZE, 1.0);
1269         *_aidl_return = bandwidthAmplitudeMap;
1270         return ndk::ScopedAStatus::ok();
1271     } else {
1272         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1273     }
1274 }
1275 
getPwlePrimitiveDurationMax(int32_t * durationMs)1276 ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t *durationMs) {
1277     int32_t capabilities;
1278     Vibrator::getCapabilities(&capabilities);
1279     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
1280         *durationMs = COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS;
1281         return ndk::ScopedAStatus::ok();
1282     } else {
1283         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1284     }
1285 }
1286 
getPwleCompositionSizeMax(int32_t * maxSize)1287 ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t *maxSize) {
1288     int32_t capabilities;
1289     Vibrator::getCapabilities(&capabilities);
1290     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
1291         *maxSize = COMPOSE_PWLE_SIZE_MAX_DEFAULT;
1292         return ndk::ScopedAStatus::ok();
1293     } else {
1294         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1295     }
1296 }
1297 
getSupportedBraking(std::vector<Braking> * supported)1298 ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking> *supported) {
1299     int32_t capabilities;
1300     Vibrator::getCapabilities(&capabilities);
1301     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
1302         *supported = {
1303                 Braking::NONE,
1304         };
1305         return ndk::ScopedAStatus::ok();
1306     } else {
1307         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1308     }
1309 }
1310 
resetPreviousEndAmplitudeEndFrequency(float * prevEndAmplitude,float * prevEndFrequency)1311 static void resetPreviousEndAmplitudeEndFrequency(float *prevEndAmplitude,
1312                                                   float *prevEndFrequency) {
1313     const float reset = -1.0;
1314     *prevEndAmplitude = reset;
1315     *prevEndFrequency = reset;
1316 }
1317 
incrementIndex(int * index)1318 static void incrementIndex(int *index) {
1319     *index += 1;
1320 }
1321 
composePwle(const std::vector<PrimitivePwle> & composite,const std::shared_ptr<IVibratorCallback> & callback)1322 ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle> &composite,
1323                                          const std::shared_ptr<IVibratorCallback> &callback) {
1324     ATRACE_NAME("Vibrator::composePwle");
1325     int32_t capabilities;
1326 
1327     Vibrator::getCapabilities(&capabilities);
1328     if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) == 0) {
1329         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1330     }
1331 
1332     if (composite.empty() || composite.size() > COMPOSE_PWLE_SIZE_MAX_DEFAULT) {
1333         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1334     }
1335 
1336     std::vector<Braking> supported;
1337     Vibrator::getSupportedBraking(&supported);
1338     bool isClabSupported =
1339             std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
1340 
1341     int segmentIdx = 0;
1342     uint32_t totalDuration = 0;
1343     float prevEndAmplitude;
1344     float prevEndFrequency;
1345     resetPreviousEndAmplitudeEndFrequency(&prevEndAmplitude, &prevEndFrequency);
1346     DspMemChunk ch(WAVEFORM_PWLE, FF_CUSTOM_DATA_LEN_MAX_PWLE);
1347     bool chirp = false;
1348 
1349     for (auto &e : composite) {
1350         switch (e.getTag()) {
1351             case PrimitivePwle::active: {
1352                 auto active = e.get<PrimitivePwle::active>();
1353                 if (active.duration < 0 ||
1354                     active.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
1355                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1356                 }
1357                 if (active.startAmplitude < PWLE_LEVEL_MIN ||
1358                     active.startAmplitude > PWLE_LEVEL_MAX ||
1359                     active.endAmplitude < PWLE_LEVEL_MIN || active.endAmplitude > PWLE_LEVEL_MAX) {
1360                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1361                 }
1362                 if (active.startAmplitude > CS40L26_PWLE_LEVEL_MAX) {
1363                     active.startAmplitude = CS40L26_PWLE_LEVEL_MAX;
1364                 }
1365                 if (active.endAmplitude > CS40L26_PWLE_LEVEL_MAX) {
1366                     active.endAmplitude = CS40L26_PWLE_LEVEL_MAX;
1367                 }
1368 
1369                 if (active.startFrequency < PWLE_FREQUENCY_MIN_HZ ||
1370                     active.startFrequency > PWLE_FREQUENCY_MAX_HZ ||
1371                     active.endFrequency < PWLE_FREQUENCY_MIN_HZ ||
1372                     active.endFrequency > PWLE_FREQUENCY_MAX_HZ) {
1373                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1374                 }
1375 
1376                 if (!((active.startAmplitude == prevEndAmplitude) &&
1377                       (active.startFrequency == prevEndFrequency))) {
1378                     if (ch.constructActiveSegment(0, active.startAmplitude, active.startFrequency,
1379                                                   false) < 0) {
1380                         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1381                     }
1382                     incrementIndex(&segmentIdx);
1383                 }
1384 
1385                 if (active.startFrequency != active.endFrequency) {
1386                     chirp = true;
1387                 }
1388                 if (ch.constructActiveSegment(active.duration, active.endAmplitude,
1389                                               active.endFrequency, chirp) < 0) {
1390                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1391                 }
1392                 incrementIndex(&segmentIdx);
1393 
1394                 prevEndAmplitude = active.endAmplitude;
1395                 prevEndFrequency = active.endFrequency;
1396                 totalDuration += active.duration;
1397                 chirp = false;
1398                 break;
1399             }
1400             case PrimitivePwle::braking: {
1401                 auto braking = e.get<PrimitivePwle::braking>();
1402                 if (braking.braking > Braking::CLAB) {
1403                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1404                 } else if (!isClabSupported && (braking.braking == Braking::CLAB)) {
1405                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1406                 }
1407 
1408                 if (braking.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
1409                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1410                 }
1411 
1412                 if (ch.constructBrakingSegment(0, braking.braking) < 0) {
1413                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1414                 }
1415                 incrementIndex(&segmentIdx);
1416 
1417                 if (ch.constructBrakingSegment(braking.duration, braking.braking) < 0) {
1418                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1419                 }
1420                 incrementIndex(&segmentIdx);
1421 
1422                 resetPreviousEndAmplitudeEndFrequency(&prevEndAmplitude, &prevEndFrequency);
1423                 totalDuration += braking.duration;
1424                 break;
1425             }
1426         }
1427 
1428         if (segmentIdx > COMPOSE_PWLE_SIZE_MAX_DEFAULT) {
1429             ALOGE("Too many PrimitivePwle section!");
1430             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1431         }
1432     }
1433     ch.flush();
1434 
1435     /* Update wlength */
1436     totalDuration += MAX_COLD_START_LATENCY_MS;
1437     if (totalDuration > 0x7FFFF) {
1438         ALOGE("Total duration is too long (%d)!", totalDuration);
1439         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1440     }
1441 
1442     /* Update word count */
1443     if (ch.updateWCount(segmentIdx) < 0) {
1444         ALOGE("%s: Failed to update the waveform word count", __func__);
1445         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1446     }
1447 
1448     /* Update waveform length */
1449     if (ch.updateWLength(totalDuration) < 0) {
1450         ALOGE("%s: Failed to update the waveform length length", __func__);
1451         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1452     }
1453 
1454     /* Update nsections */
1455     if (ch.updateNSection(segmentIdx) < 0) {
1456         ALOGE("%s: Failed to update the section count", __func__);
1457         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1458     }
1459 
1460     return performEffect(WAVEFORM_MAX_INDEX /*ignored*/, VOLTAGE_SCALE_MAX /*ignored*/, &ch,
1461                          callback);
1462 }
1463 
isUnderExternalControl()1464 bool Vibrator::isUnderExternalControl() {
1465     return mIsUnderExternalControl;
1466 }
1467 
1468 // BnCInterface APIs
1469 
dump(int fd,const char ** args,uint32_t numArgs)1470 binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) {
1471     if (fd < 0) {
1472         ALOGE("Called debug() with invalid fd.");
1473         return STATUS_OK;
1474     }
1475 
1476     (void)args;
1477     (void)numArgs;
1478 
1479     dprintf(fd, "AIDL:\n");
1480 
1481     dprintf(fd, "  Active Effect ID: %" PRId32 "\n", mActiveId);
1482     dprintf(fd, "  F0: %.02f\n", mResonantFrequency);
1483     dprintf(fd, "  F0 Offset: base: %" PRIu32 " flip: %" PRIu32 "\n", mF0Offset, mF0OffsetDual);
1484     dprintf(fd, "  Redc: %.02f\n", mRedc);
1485 
1486     dprintf(fd, "  Voltage Levels:\n");
1487     dprintf(fd, "    Tick Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mTickEffectVol[0],
1488             mTickEffectVol[1]);
1489     dprintf(fd, "    Click Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mClickEffectVol[0],
1490             mClickEffectVol[1]);
1491     dprintf(fd, "    Long Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mLongEffectVol[0],
1492             mLongEffectVol[1]);
1493 
1494     uint8_t effectId;
1495     dprintf(fd, "  Scales\n");
1496     dprintf(fd, "\tId\tMinScale\tMaxScale\n");
1497     for (effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) {
1498         dprintf(fd, "\t%d\t%d\t\t%d\n", effectId, mPrimitiveMinScale[effectId],
1499             mPrimitiveMaxScale[effectId]);
1500     }
1501 
1502     dprintf(fd, "  Base FF effect:\n");
1503     dprintf(fd, "    Physical waveform:\n");
1504     dprintf(fd, "\tId\tIndex\tt   ->\tt'\tBrake\ttrigger button\n");
1505     for (effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) {
1506         dprintf(fd, "\t%d\t%d\t%d\t%d\t%d\t%X\n", mFfEffects[effectId].id,
1507                 mFfEffects[effectId].u.periodic.custom_data[1], mEffectDurations[effectId],
1508                 mFfEffects[effectId].replay.length, mEffectBrakingDurations[effectId],
1509                 mFfEffects[effectId].trigger.button);
1510     }
1511     dprintf(fd, "    OWT waveform:\n");
1512     dprintf(fd, "\tId\tBytes\tData\tt\ttrigger button\n");
1513     for (effectId = WAVEFORM_MAX_PHYSICAL_INDEX; effectId < WAVEFORM_MAX_INDEX; effectId++) {
1514         uint32_t numBytes = mFfEffects[effectId].u.periodic.custom_len * 2;
1515         std::stringstream ss;
1516         ss << " ";
1517         for (int i = 0; i < numBytes; i++) {
1518             ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex
1519                << (uint16_t)(*(
1520                           reinterpret_cast<uint8_t *>(mFfEffects[effectId].u.periodic.custom_data) +
1521                           i))
1522                << " ";
1523         }
1524         dprintf(fd, "\t%d\t%d\t{%s}\t%u\t%X\n", mFfEffects[effectId].id, numBytes, ss.str().c_str(),
1525                 mFfEffectsDual[effectId].replay.length, mFfEffects[effectId].trigger.button);
1526     }
1527 
1528     if (mIsDual) {
1529         dprintf(fd, "  Flip FF effect:\n");
1530         dprintf(fd, "    Physical waveform:\n");
1531         dprintf(fd, "\tId\tIndex\tt   ->\tt'\tBrake\ttrigger button\n");
1532         for (effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) {
1533             dprintf(fd, "\t%d\t%d\t%d\t%d\t%d\t%X\n", mFfEffectsDual[effectId].id,
1534                     mFfEffectsDual[effectId].u.periodic.custom_data[1], mEffectDurations[effectId],
1535                     mFfEffectsDual[effectId].replay.length, mEffectBrakingDurations[effectId],
1536                     mFfEffectsDual[effectId].trigger.button);
1537         }
1538         dprintf(fd, "    OWT waveform:\n");
1539         dprintf(fd, "\tId\tBytes\tData\tt\ttrigger button\n");
1540         for (effectId = WAVEFORM_MAX_PHYSICAL_INDEX; effectId < WAVEFORM_MAX_INDEX; effectId++) {
1541             uint32_t numBytes = mFfEffectsDual[effectId].u.periodic.custom_len * 2;
1542             std::stringstream ss;
1543             ss << " ";
1544             for (int i = 0; i < numBytes; i++) {
1545                 ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex
1546                    << (uint16_t)(*(reinterpret_cast<uint8_t *>(
1547                                            mFfEffectsDual[effectId].u.periodic.custom_data) +
1548                                    i))
1549                    << " ";
1550             }
1551             dprintf(fd, "\t%d\t%d\t{%s}\t%u\t%X\n", mFfEffectsDual[effectId].id, numBytes,
1552                     ss.str().c_str(), mFfEffectsDual[effectId].replay.length,
1553                     mFfEffectsDual[effectId].trigger.button);
1554         }
1555     }
1556     dprintf(fd, "\n");
1557 
1558     dprintf(fd, "Versions:\n");
1559     const std::vector<std::pair<std::string, std::string>> moduleFolderNames = {
1560         {"cs40l26_core", "Haptics"}, {"cl_dsp_core", "DSP"}};
1561     const std::string firmwareFolder = "/vendor/firmware/";
1562     const std::string waveformName = "cs40l26.bin";
1563     const std::array<std::string, 2> firmwareFileNames = {"cs40l26.wmfw", "cs40l26-calib.wmfw"};
1564     const std::array<std::string, 4> tuningFileNames = {"cs40l26-svc.bin", "cs40l26-calib.bin",
1565                                                         "cs40l26-dvl.bin", "cs40l26-dbc.bin"};
1566     std::ifstream verFile;
1567     const auto verBinFileMode = std::ifstream::in | std::ifstream::binary;
1568     std::string ver;
1569     for (const auto &[folder, logTag] : moduleFolderNames) {
1570         verFile.open("/sys/module/" + folder + "/version");
1571         if (verFile.is_open()) {
1572             getline(verFile, ver);
1573             dprintf(fd, "  %s Driver: %s\n", logTag.c_str(), ver.c_str());
1574             verFile.close();
1575         }
1576     }
1577     for (auto &name : firmwareFileNames) {
1578         verFile.open(firmwareFolder + name, verBinFileMode);
1579         if (verFile.is_open()) {
1580             verFile.seekg(113);
1581             dprintf(fd, "  %s: %d.%d.%d\n", name.c_str(), verFile.get(), verFile.get(),
1582                     verFile.get());
1583             verFile.close();
1584         }
1585     }
1586     verFile.open(firmwareFolder + waveformName, verBinFileMode);
1587     if (verFile.is_open()) {
1588         while (getline(verFile, ver)) {
1589             auto pos = ver.find("Date: ");
1590             if (pos != std::string::npos) {
1591                 ver = ver.substr(pos + 6, pos + 15);
1592                 dprintf(fd, "  %s: %s\n", waveformName.c_str(), ver.c_str());
1593                 break;
1594             }
1595         }
1596         verFile.close();
1597     }
1598     for (auto &name : tuningFileNames) {
1599         verFile.open(firmwareFolder + name, verBinFileMode);
1600         if (verFile.is_open()) {
1601             verFile.seekg(36);
1602             getline(verFile, ver);
1603             ver = ver.substr(0, ver.find(".bin") + 4);
1604             ver = ver.substr(ver.rfind('\\') + 1);
1605             dprintf(fd, "  %s: %s\n", name.c_str(), ver.c_str());
1606             verFile.close();
1607         }
1608     }
1609 
1610     dprintf(fd, "\n");
1611 
1612     mHwApiDef->debug(fd);
1613 
1614     dprintf(fd, "\n");
1615 
1616     mHwCalDef->debug(fd);
1617 
1618     dprintf(fd, "\n");
1619 
1620     if (mIsDual) {
1621         mHwApiDual->debug(fd);
1622         dprintf(fd, "\n");
1623         mHwCalDual->debug(fd);
1624     }
1625 
1626     fsync(fd);
1627     return STATUS_OK;
1628 }
1629 
hasHapticAlsaDevice()1630 bool Vibrator::hasHapticAlsaDevice() {
1631     // We need to call findHapticAlsaDevice once only. Calling in the
1632     // constructor is too early in the boot process and the pcm file contents
1633     // are empty. Hence we make the call here once only right before we need to.
1634     if (!mConfigHapticAlsaDeviceDone) {
1635         if (mHwApiDef->getHapticAlsaDevice(&mCard, &mDevice)) {
1636             mHasHapticAlsaDevice = true;
1637             mConfigHapticAlsaDeviceDone = true;
1638         } else {
1639             ALOGE("Haptic ALSA device not supported");
1640         }
1641     } else {
1642         ALOGD("Haptic ALSA device configuration done.");
1643     }
1644     return mHasHapticAlsaDevice;
1645 }
1646 
getSimpleDetails(Effect effect,EffectStrength strength,uint32_t * outEffectIndex,uint32_t * outTimeMs,uint32_t * outVolLevel)1647 ndk::ScopedAStatus Vibrator::getSimpleDetails(Effect effect, EffectStrength strength,
1648                                               uint32_t *outEffectIndex, uint32_t *outTimeMs,
1649                                               uint32_t *outVolLevel) {
1650     uint32_t effectIndex;
1651     uint32_t timeMs;
1652     float intensity;
1653     uint32_t volLevel;
1654     switch (strength) {
1655         case EffectStrength::LIGHT:
1656             intensity = 0.5f;
1657             break;
1658         case EffectStrength::MEDIUM:
1659             intensity = 0.7f;
1660             break;
1661         case EffectStrength::STRONG:
1662             intensity = 1.0f;
1663             break;
1664         default:
1665             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1666     }
1667 
1668     switch (effect) {
1669         case Effect::TEXTURE_TICK:
1670             effectIndex = WAVEFORM_LIGHT_TICK_INDEX;
1671             intensity *= 0.5f;
1672             break;
1673         case Effect::TICK:
1674             effectIndex = WAVEFORM_CLICK_INDEX;
1675             intensity *= 0.5f;
1676             break;
1677         case Effect::CLICK:
1678             effectIndex = WAVEFORM_CLICK_INDEX;
1679             intensity *= 0.7f;
1680             break;
1681         case Effect::HEAVY_CLICK:
1682             effectIndex = WAVEFORM_CLICK_INDEX;
1683             intensity *= 1.0f;
1684             break;
1685         default:
1686             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1687     }
1688 
1689     volLevel = intensityToVolLevel(intensity, effectIndex);
1690     timeMs = mEffectDurations[effectIndex] + MAX_COLD_START_LATENCY_MS;
1691 
1692     *outEffectIndex = effectIndex;
1693     *outTimeMs = timeMs;
1694     *outVolLevel = volLevel;
1695     return ndk::ScopedAStatus::ok();
1696 }
1697 
getCompoundDetails(Effect effect,EffectStrength strength,uint32_t * outTimeMs,DspMemChunk * outCh)1698 ndk::ScopedAStatus Vibrator::getCompoundDetails(Effect effect, EffectStrength strength,
1699                                                 uint32_t *outTimeMs, DspMemChunk *outCh) {
1700     ndk::ScopedAStatus status;
1701     uint32_t timeMs = 0;
1702     uint32_t thisEffectIndex;
1703     uint32_t thisTimeMs;
1704     uint32_t thisVolLevel;
1705     switch (effect) {
1706         case Effect::DOUBLE_CLICK:
1707             status = getSimpleDetails(Effect::CLICK, strength, &thisEffectIndex, &thisTimeMs,
1708                                       &thisVolLevel);
1709             if (!status.isOk()) {
1710                 return status;
1711             }
1712             timeMs += thisTimeMs;
1713             outCh->constructComposeSegment(thisVolLevel, thisEffectIndex, 0 /*repeat*/, 0 /*flags*/,
1714                                            WAVEFORM_DOUBLE_CLICK_SILENCE_MS);
1715 
1716             timeMs += WAVEFORM_DOUBLE_CLICK_SILENCE_MS + MAX_PAUSE_TIMING_ERROR_MS;
1717 
1718             status = getSimpleDetails(Effect::HEAVY_CLICK, strength, &thisEffectIndex, &thisTimeMs,
1719                                       &thisVolLevel);
1720             if (!status.isOk()) {
1721                 return status;
1722             }
1723             timeMs += thisTimeMs;
1724 
1725             outCh->constructComposeSegment(thisVolLevel, thisEffectIndex, 0 /*repeat*/, 0 /*flags*/,
1726                                            0 /*delay*/);
1727             outCh->flush();
1728             if (outCh->updateNSection(2) < 0) {
1729                 ALOGE("%s: Failed to update the section count", __func__);
1730                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1731             }
1732 
1733             break;
1734         default:
1735             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1736     }
1737 
1738     *outTimeMs = timeMs;
1739     // Compositions should have 0 duration
1740     mFfEffects[WAVEFORM_COMPOSE].replay.length = 0;
1741     if (mIsDual) {
1742         mFfEffectsDual[WAVEFORM_COMPOSE].replay.length = 0;
1743     }
1744 
1745     return ndk::ScopedAStatus::ok();
1746 }
1747 
getPrimitiveDetails(CompositePrimitive primitive,uint32_t * outEffectIndex)1748 ndk::ScopedAStatus Vibrator::getPrimitiveDetails(CompositePrimitive primitive,
1749                                                  uint32_t *outEffectIndex) {
1750     uint32_t effectIndex;
1751     uint32_t primitiveBit = 1 << int32_t(primitive);
1752     if ((primitiveBit & mSupportedPrimitivesBits) == 0x0) {
1753         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1754     }
1755 
1756     switch (primitive) {
1757         case CompositePrimitive::NOOP:
1758             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1759         case CompositePrimitive::CLICK:
1760             effectIndex = WAVEFORM_CLICK_INDEX;
1761             break;
1762         case CompositePrimitive::THUD:
1763             effectIndex = WAVEFORM_THUD_INDEX;
1764             break;
1765         case CompositePrimitive::SPIN:
1766             effectIndex = WAVEFORM_SPIN_INDEX;
1767             break;
1768         case CompositePrimitive::QUICK_RISE:
1769             effectIndex = WAVEFORM_QUICK_RISE_INDEX;
1770             break;
1771         case CompositePrimitive::SLOW_RISE:
1772             effectIndex = WAVEFORM_SLOW_RISE_INDEX;
1773             break;
1774         case CompositePrimitive::QUICK_FALL:
1775             effectIndex = WAVEFORM_QUICK_FALL_INDEX;
1776             break;
1777         case CompositePrimitive::LIGHT_TICK:
1778             effectIndex = WAVEFORM_LIGHT_TICK_INDEX;
1779             break;
1780         case CompositePrimitive::LOW_TICK:
1781             effectIndex = WAVEFORM_LOW_TICK_INDEX;
1782             break;
1783         default:
1784             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1785     }
1786 
1787     *outEffectIndex = effectIndex;
1788 
1789     return ndk::ScopedAStatus::ok();
1790 }
1791 
performEffect(Effect effect,EffectStrength strength,const std::shared_ptr<IVibratorCallback> & callback,int32_t * outTimeMs)1792 ndk::ScopedAStatus Vibrator::performEffect(Effect effect, EffectStrength strength,
1793                                            const std::shared_ptr<IVibratorCallback> &callback,
1794                                            int32_t *outTimeMs) {
1795     ndk::ScopedAStatus status;
1796     uint32_t effectIndex;
1797     uint32_t timeMs = 0;
1798     uint32_t volLevel;
1799     std::optional<DspMemChunk> maybeCh;
1800     switch (effect) {
1801         case Effect::TEXTURE_TICK:
1802             // fall-through
1803         case Effect::TICK:
1804             // fall-through
1805         case Effect::CLICK:
1806             // fall-through
1807         case Effect::HEAVY_CLICK:
1808             status = getSimpleDetails(effect, strength, &effectIndex, &timeMs, &volLevel);
1809             break;
1810         case Effect::DOUBLE_CLICK:
1811             maybeCh.emplace(WAVEFORM_COMPOSE, FF_CUSTOM_DATA_LEN_MAX_COMP);
1812             status = getCompoundDetails(effect, strength, &timeMs, &*maybeCh);
1813             volLevel = VOLTAGE_SCALE_MAX;
1814             break;
1815         default:
1816             status = ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1817             break;
1818     }
1819     if (status.isOk()) {
1820         DspMemChunk *ch = maybeCh ? &*maybeCh : nullptr;
1821         status = performEffect(effectIndex, volLevel, ch, callback);
1822     }
1823 
1824     *outTimeMs = timeMs;
1825     return status;
1826 }
1827 
performEffect(uint32_t effectIndex,uint32_t volLevel,const DspMemChunk * ch,const std::shared_ptr<IVibratorCallback> & callback)1828 ndk::ScopedAStatus Vibrator::performEffect(uint32_t effectIndex, uint32_t volLevel,
1829                                            const DspMemChunk *ch,
1830                                            const std::shared_ptr<IVibratorCallback> &callback) {
1831     setEffectAmplitude(volLevel, VOLTAGE_SCALE_MAX);
1832 
1833     return on(MAX_TIME_MS, effectIndex, ch, callback);
1834 }
1835 
waitForComplete(std::shared_ptr<IVibratorCallback> && callback)1836 void Vibrator::waitForComplete(std::shared_ptr<IVibratorCallback> &&callback) {
1837     ALOGD("waitForComplete: Callback status in waitForComplete(): callBack: %d",
1838           (callback != nullptr));
1839 
1840     // Bypass checking flip part's haptic state
1841     if (!mHwApiDef->pollVibeState(VIBE_STATE_HAPTIC, POLLING_TIMEOUT)) {
1842         ALOGD("Failed to get state \"Haptic\"");
1843     }
1844 
1845     mHwApiDef->pollVibeState(VIBE_STATE_STOPPED);
1846     // Check flip's state after base was done
1847     if (mIsDual) {
1848         mHwApiDual->pollVibeState(VIBE_STATE_STOPPED);
1849     }
1850     ALOGD("waitForComplete: get STOP");
1851     {
1852         const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
1853         if (mActiveId >= WAVEFORM_MAX_PHYSICAL_INDEX) {
1854             if (!mHwApiDef->eraseOwtEffect(mInputFd, mActiveId, &mFfEffects)) {
1855                 ALOGE("Failed to clean up the composed effect %d", mActiveId);
1856             }
1857             if (mIsDual &&
1858                 (!mHwApiDual->eraseOwtEffect(mInputFdDual, mActiveId, &mFfEffectsDual))) {
1859                 ALOGE("Failed to clean up flip's composed effect %d", mActiveId);
1860             }
1861         } else {
1862             ALOGD("waitForComplete: Vibrator is already off");
1863         }
1864         mActiveId = -1;
1865         if (mGPIOStatus && !mHwGPIO->setGPIOOutput(false)) {
1866             ALOGE("waitForComplete: Failed to reset GPIO(%d): %s", errno, strerror(errno));
1867         }
1868         // Do waveform number checking
1869         uint32_t effectCount = WAVEFORM_MAX_PHYSICAL_INDEX;
1870         mHwApiDef->getEffectCount(&effectCount);
1871         if (effectCount > WAVEFORM_MAX_PHYSICAL_INDEX) {
1872             // Forcibly clean all OWT waveforms
1873             if (!mHwApiDef->eraseOwtEffect(mInputFd, WAVEFORM_MAX_INDEX, &mFfEffects)) {
1874                 ALOGE("Failed to clean up all base's composed effect");
1875             }
1876         }
1877 
1878         if (mIsDual) {
1879             // Forcibly clean all OWT waveforms
1880             effectCount = WAVEFORM_MAX_PHYSICAL_INDEX;
1881             mHwApiDual->getEffectCount(&effectCount);
1882             if ((effectCount > WAVEFORM_MAX_PHYSICAL_INDEX) &&
1883                 (!mHwApiDual->eraseOwtEffect(mInputFdDual, WAVEFORM_MAX_INDEX, &mFfEffectsDual))) {
1884                 ALOGE("Failed to clean up all flip's composed effect");
1885             }
1886         }
1887     }
1888 
1889     if (callback) {
1890         auto ret = callback->onComplete();
1891         if (!ret.isOk()) {
1892             ALOGE("Failed completion callback: %d", ret.getExceptionCode());
1893         }
1894     }
1895     ALOGD("waitForComplete: Done.");
1896 }
1897 
intensityToVolLevel(float intensity,uint32_t effectIndex)1898 uint32_t Vibrator::intensityToVolLevel(float intensity, uint32_t effectIndex) {
1899     uint32_t volLevel;
1900     auto calc = [](float intst, std::array<uint32_t, 2> v) -> uint32_t {
1901         return std::lround(intst * (v[1] - v[0])) + v[0];
1902     };
1903 
1904     switch (effectIndex) {
1905         case WAVEFORM_LIGHT_TICK_INDEX:
1906             volLevel = calc(intensity, mTickEffectVol);
1907             break;
1908         case WAVEFORM_QUICK_RISE_INDEX:
1909             // fall-through
1910         case WAVEFORM_QUICK_FALL_INDEX:
1911             volLevel = calc(intensity, mLongEffectVol);
1912             break;
1913         case WAVEFORM_CLICK_INDEX:
1914             // fall-through
1915         case WAVEFORM_THUD_INDEX:
1916             // fall-through
1917         case WAVEFORM_SPIN_INDEX:
1918             // fall-through
1919         case WAVEFORM_SLOW_RISE_INDEX:
1920             // fall-through
1921         default:
1922             volLevel = calc(intensity, mClickEffectVol);
1923             break;
1924     }
1925     // The waveform being played must fall within the allowable scale range
1926     if (effectIndex < WAVEFORM_MAX_INDEX) {
1927         if (volLevel > mPrimitiveMaxScale[effectIndex]) {
1928             volLevel = mPrimitiveMaxScale[effectIndex];
1929         }
1930         if (volLevel < mPrimitiveMinScale[effectIndex]) {
1931             volLevel = mPrimitiveMinScale[effectIndex];
1932         }
1933     }
1934 
1935     return volLevel;
1936 }
1937 
1938 }  // namespace vibrator
1939 }  // namespace hardware
1940 }  // namespace android
1941 }  // namespace aidl
1942