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