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