• 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 <glob.h>
20 #include <hardware/hardware.h>
21 #include <hardware/vibrator.h>
22 #include <log/log.h>
23 #include <stdio.h>
24 #include <utils/Trace.h>
25 
26 #include <cinttypes>
27 #include <cmath>
28 #include <fstream>
29 #include <iostream>
30 #include <sstream>
31 
32 #ifndef ARRAY_SIZE
33 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
34 #endif
35 
36 namespace aidl {
37 namespace android {
38 namespace hardware {
39 namespace vibrator {
40 static constexpr uint8_t FF_CUSTOM_DATA_LEN = 2;
41 static constexpr uint16_t FF_CUSTOM_DATA_LEN_MAX_COMP = 2044;  // (COMPOSE_SIZE_MAX + 1) * 8 + 4
42 static constexpr uint16_t FF_CUSTOM_DATA_LEN_MAX_PWLE = 2302;
43 
44 static constexpr uint32_t WAVEFORM_DOUBLE_CLICK_SILENCE_MS = 100;
45 
46 static constexpr uint32_t WAVEFORM_LONG_VIBRATION_THRESHOLD_MS = 50;
47 
48 static constexpr uint8_t VOLTAGE_SCALE_MAX = 100;
49 
50 static constexpr int8_t MAX_COLD_START_LATENCY_MS = 6;  // I2C Transaction + DSP Return-From-Standby
51 static constexpr uint32_t MIN_ON_OFF_INTERVAL_US = 8500;  // SVC initialization time
52 static constexpr int8_t MAX_PAUSE_TIMING_ERROR_MS = 1;  // ALERT Irq Handling
53 static constexpr uint32_t MAX_TIME_MS = UINT16_MAX;
54 
55 static constexpr auto ASYNC_COMPLETION_TIMEOUT = std::chrono::milliseconds(100);
56 static constexpr auto POLLING_TIMEOUT = 20;
57 static constexpr int32_t COMPOSE_DELAY_MAX_MS = 10000;
58 
59 /* nsections is 8 bits. Need to preserve 1 section for the first delay before the first effect. */
60 static constexpr int32_t COMPOSE_SIZE_MAX = 254;
61 static constexpr int32_t COMPOSE_PWLE_SIZE_MAX_DEFAULT = 127;
62 
63 // Measured resonant frequency, f0_measured, is represented by Q10.14 fixed
64 // point format on cs40l26 devices. The expression to calculate f0 is:
65 //   f0 = f0_measured / 2^Q14_BIT_SHIFT
66 // See the LRA Calibration Support documentation for more details.
67 static constexpr int32_t Q14_BIT_SHIFT = 14;
68 
69 // Measured Q factor, q_measured, is represented by Q8.16 fixed
70 // point format on cs40l26 devices. The expression to calculate q is:
71 //   q = q_measured / 2^Q16_BIT_SHIFT
72 // See the LRA Calibration Support documentation for more details.
73 static constexpr int32_t Q16_BIT_SHIFT = 16;
74 
75 static constexpr int32_t COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS = 16383;
76 
77 static constexpr uint32_t WT_LEN_CALCD = 0x00800000;
78 static constexpr uint8_t PWLE_CHIRP_BIT = 0x8;  // Dynamic/static frequency and voltage
79 static constexpr uint8_t PWLE_BRAKE_BIT = 0x4;
80 static constexpr uint8_t PWLE_AMP_REG_BIT = 0x2;
81 
82 static constexpr float PWLE_LEVEL_MIN = 0.0;
83 static constexpr float PWLE_LEVEL_MAX = 1.0;
84 static constexpr float CS40L26_PWLE_LEVEL_MIX = -1.0;
85 static constexpr float CS40L26_PWLE_LEVEL_MAX = 0.9995118;
86 static constexpr float PWLE_FREQUENCY_RESOLUTION_HZ = 1.00;
87 static constexpr float PWLE_FREQUENCY_MIN_HZ = 1.00;
88 static constexpr float PWLE_FREQUENCY_MAX_HZ = 1000.00;
89 static constexpr float PWLE_BW_MAP_SIZE =
90         1 + ((PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ);
91 
amplitudeToScale(float amplitude,float maximum)92 static uint16_t amplitudeToScale(float amplitude, float maximum) {
93     float ratio = 100; /* Unit: % */
94     if (maximum != 0)
95         ratio = amplitude / maximum * 100;
96 
97     if (maximum == 0 || ratio > 100)
98         ratio = 100;
99 
100     return std::round(ratio);
101 }
102 
103 enum WaveformBankID : uint8_t {
104     RAM_WVFRM_BANK,
105     ROM_WVFRM_BANK,
106     OWT_WVFRM_BANK,
107 };
108 
109 enum WaveformIndex : uint16_t {
110     /* Physical waveform */
111     WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0,
112     WAVEFORM_RESERVED_INDEX_1 = 1,
113     WAVEFORM_CLICK_INDEX = 2,
114     WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX = 3,
115     WAVEFORM_THUD_INDEX = 4,
116     WAVEFORM_SPIN_INDEX = 5,
117     WAVEFORM_QUICK_RISE_INDEX = 6,
118     WAVEFORM_SLOW_RISE_INDEX = 7,
119     WAVEFORM_QUICK_FALL_INDEX = 8,
120     WAVEFORM_LIGHT_TICK_INDEX = 9,
121     WAVEFORM_LOW_TICK_INDEX = 10,
122     WAVEFORM_RESERVED_MFG_1,
123     WAVEFORM_RESERVED_MFG_2,
124     WAVEFORM_RESERVED_MFG_3,
125     WAVEFORM_MAX_PHYSICAL_INDEX,
126     /* OWT waveform */
127     WAVEFORM_COMPOSE = WAVEFORM_MAX_PHYSICAL_INDEX,
128     WAVEFORM_PWLE,
129     /*
130      * Refer to <linux/input.h>, the WAVEFORM_MAX_INDEX must not exceed 96.
131      * #define FF_GAIN		0x60  // 96 in decimal
132      * #define FF_MAX_EFFECTS	FF_GAIN
133      */
134     WAVEFORM_MAX_INDEX,
135 };
136 
137 std::vector<CompositePrimitive> defaultSupportedPrimitives = {
138         ndk::enum_range<CompositePrimitive>().begin(), ndk::enum_range<CompositePrimitive>().end()};
139 
140 enum vibe_state {
141     VIBE_STATE_STOPPED = 0,
142     VIBE_STATE_HAPTIC,
143     VIBE_STATE_ASP,
144 };
145 
146 std::mutex mActiveId_mutex;  // protects mActiveId
147 
min(int x,int y)148 static int min(int x, int y) {
149     return x < y ? x : y;
150 }
151 
floatToUint16(float input,uint16_t * output,float scale,float min,float max)152 static int floatToUint16(float input, uint16_t *output, float scale, float min, float max) {
153     if (input < min || input > max)
154         return -ERANGE;
155 
156     *output = roundf(input * scale);
157     return 0;
158 }
159 
160 struct dspmem_chunk {
161     uint8_t *head;
162     uint8_t *current;
163     uint8_t *max;
164     int bytes;
165 
166     uint32_t cache;
167     int cachebits;
168 };
169 
dspmem_chunk_create(void * data,int size)170 static dspmem_chunk *dspmem_chunk_create(void *data, int size) {
171     auto ch = new dspmem_chunk{
172             .head = reinterpret_cast<uint8_t *>(data),
173             .current = reinterpret_cast<uint8_t *>(data),
174             .max = reinterpret_cast<uint8_t *>(data) + size,
175     };
176 
177     return ch;
178 }
179 
dspmem_chunk_end(struct dspmem_chunk * ch)180 static bool dspmem_chunk_end(struct dspmem_chunk *ch) {
181     return ch->current == ch->max;
182 }
183 
dspmem_chunk_bytes(struct dspmem_chunk * ch)184 static int dspmem_chunk_bytes(struct dspmem_chunk *ch) {
185     return ch->bytes;
186 }
187 
dspmem_chunk_write(struct dspmem_chunk * ch,int nbits,uint32_t val)188 static int dspmem_chunk_write(struct dspmem_chunk *ch, int nbits, uint32_t val) {
189     int nwrite, i;
190 
191     nwrite = min(24 - ch->cachebits, nbits);
192     ch->cache <<= nwrite;
193     ch->cache |= val >> (nbits - nwrite);
194     ch->cachebits += nwrite;
195     nbits -= nwrite;
196 
197     if (ch->cachebits == 24) {
198         if (dspmem_chunk_end(ch))
199             return -ENOSPC;
200 
201         ch->cache &= 0xFFFFFF;
202         for (i = 0; i < sizeof(ch->cache); i++, ch->cache <<= 8)
203             *ch->current++ = (ch->cache & 0xFF000000) >> 24;
204 
205         ch->bytes += sizeof(ch->cache);
206         ch->cachebits = 0;
207     }
208 
209     if (nbits)
210         return dspmem_chunk_write(ch, nbits, val);
211 
212     return 0;
213 }
214 
dspmem_chunk_flush(struct dspmem_chunk * ch)215 static int dspmem_chunk_flush(struct dspmem_chunk *ch) {
216     if (!ch->cachebits)
217         return 0;
218 
219     return dspmem_chunk_write(ch, 24 - ch->cachebits, 0);
220 }
221 
Vibrator(std::unique_ptr<HwApi> hwapi,std::unique_ptr<HwCal> hwcal)222 Vibrator::Vibrator(std::unique_ptr<HwApi> hwapi, std::unique_ptr<HwCal> hwcal)
223     : mHwApi(std::move(hwapi)), mHwCal(std::move(hwcal)), mAsyncHandle(std::async([] {})) {
224     int32_t longFrequencyShift;
225     std::string caldata{8, '0'};
226     uint32_t calVer;
227 
228     const char *inputEventName = std::getenv("INPUT_EVENT_NAME");
229     const char *inputEventPathName = std::getenv("INPUT_EVENT_PATH");
230     if ((strstr(inputEventName, "cs40l26") != nullptr) ||
231         (strstr(inputEventName, "cs40l26_dual_input") != nullptr)) {
232         glob_t inputEventPaths;
233         int fd = -1;
234         int ret;
235         uint32_t val = 0;
236         char str[20] = {0x00};
237         for (uint8_t retry = 0; retry < 10; retry++) {
238             ret = glob(inputEventPathName, 0, nullptr, &inputEventPaths);
239             if (ret) {
240                 ALOGE("Fail to get input event paths (%d): %s", errno, strerror(errno));
241             } else {
242                 for (int i = 0; i < inputEventPaths.gl_pathc; i++) {
243                     fd = TEMP_FAILURE_RETRY(open(inputEventPaths.gl_pathv[i], O_RDWR));
244                     if (fd > 0) {
245                         if (ioctl(fd, EVIOCGBIT(0, sizeof(val)), &val) > 0 &&
246                             (val & (1 << EV_FF)) && ioctl(fd, EVIOCGNAME(sizeof(str)), &str) > 0 &&
247                             strstr(str, inputEventName) != nullptr) {
248                             mInputFd.reset(fd);
249                             ALOGI("Control %s through %s", inputEventName,
250                                   inputEventPaths.gl_pathv[i]);
251                             break;
252                         }
253                         close(fd);
254                     }
255                 }
256             }
257 
258             if (ret == 0) {
259                 globfree(&inputEventPaths);
260             }
261             if (mInputFd.ok()) {
262                 break;
263             }
264 
265             sleep(1);
266             ALOGW("Retry #%d to search in %zu input devices.", retry, inputEventPaths.gl_pathc);
267         }
268 
269         if (!mInputFd.ok()) {
270             ALOGE("Fail to get an input event with name %s", inputEventName);
271         }
272     } else {
273         ALOGE("The input name %s is not cs40l26_input or cs40l26_dual_input", inputEventName);
274     }
275 
276     mFfEffects.resize(WAVEFORM_MAX_INDEX);
277     mEffectDurations.resize(WAVEFORM_MAX_INDEX);
278     mEffectDurations = {
279             1000, 100, 30, 1000, 300, 130, 150, 500, 100, 15, 20, 1000, 1000, 1000,
280     }; /* 11+3 waveforms. The duration must < UINT16_MAX */
281 
282     uint8_t effectIndex;
283     for (effectIndex = 0; effectIndex < WAVEFORM_MAX_INDEX; effectIndex++) {
284         if (effectIndex < WAVEFORM_MAX_PHYSICAL_INDEX) {
285             /* Initialize physical waveforms. */
286             mFfEffects[effectIndex] = {
287                     .type = FF_PERIODIC,
288                     .id = -1,
289                     .replay.length = static_cast<uint16_t>(mEffectDurations[effectIndex]),
290                     .u.periodic.waveform = FF_CUSTOM,
291                     .u.periodic.custom_data = new int16_t[2]{RAM_WVFRM_BANK, effectIndex},
292                     .u.periodic.custom_len = FF_CUSTOM_DATA_LEN,
293             };
294             // Bypass the waveform update due to different input name
295             if ((strstr(inputEventName, "cs40l26") != nullptr) ||
296                 (strstr(inputEventName, "cs40l26_dual_input") != nullptr)) {
297                 if (!mHwApi->setFFEffect(
298                             mInputFd, &mFfEffects[effectIndex],
299                             static_cast<uint16_t>(mFfEffects[effectIndex].replay.length))) {
300                     ALOGE("Failed upload effect %d (%d): %s", effectIndex, errno, strerror(errno));
301                 }
302             }
303             if (mFfEffects[effectIndex].id != effectIndex) {
304                 ALOGW("Unexpected effect index: %d -> %d", effectIndex, mFfEffects[effectIndex].id);
305             }
306         } else {
307             /* Initiate placeholders for OWT effects. */
308             mFfEffects[effectIndex] = {
309                     .type = FF_PERIODIC,
310                     .id = -1,
311                     .replay.length = 0,
312                     .u.periodic.waveform = FF_CUSTOM,
313                     .u.periodic.custom_data = nullptr,
314                     .u.periodic.custom_len = 0,
315             };
316         }
317     }
318 
319     if (mHwCal->getF0(&caldata)) {
320         mHwApi->setF0(caldata);
321     }
322     if (mHwCal->getRedc(&caldata)) {
323         mHwApi->setRedc(caldata);
324     }
325     if (mHwCal->getQ(&caldata)) {
326         mHwApi->setQ(caldata);
327     }
328 
329     mHwCal->getLongFrequencyShift(&longFrequencyShift);
330     if (longFrequencyShift > 0) {
331         mF0Offset = longFrequencyShift * std::pow(2, 14);
332     } else if (longFrequencyShift < 0) {
333         mF0Offset = std::pow(2, 24) - std::abs(longFrequencyShift) * std::pow(2, 14);
334     } else {
335         mF0Offset = 0;
336     }
337 
338     mHwCal->getVersion(&calVer);
339     if (calVer == 2) {
340         mHwCal->getTickVolLevels(&mTickEffectVol);
341         mHwCal->getClickVolLevels(&mClickEffectVol);
342         mHwCal->getLongVolLevels(&mLongEffectVol);
343     } else {
344         ALOGD("Unsupported calibration version: %u!", calVer);
345     }
346 
347     mHwApi->setF0CompEnable(mHwCal->isF0CompEnabled());
348     mHwApi->setRedcCompEnable(mHwCal->isRedcCompEnabled());
349 
350     mIsUnderExternalControl = false;
351 
352     mIsChirpEnabled = mHwCal->isChirpEnabled();
353 
354     mHwCal->getSupportedPrimitives(&mSupportedPrimitivesBits);
355     if (mSupportedPrimitivesBits > 0) {
356         for (auto e : defaultSupportedPrimitives) {
357             if (mSupportedPrimitivesBits & (1 << uint32_t(e))) {
358                 mSupportedPrimitives.emplace_back(e);
359             }
360         }
361     } else {
362         for (auto e : defaultSupportedPrimitives) {
363             mSupportedPrimitivesBits |= (1 << uint32_t(e));
364         }
365         mSupportedPrimitives = defaultSupportedPrimitives;
366     }
367 
368     mHwApi->setMinOnOffInterval(MIN_ON_OFF_INTERVAL_US);
369 }
370 
getCapabilities(int32_t * _aidl_return)371 ndk::ScopedAStatus Vibrator::getCapabilities(int32_t *_aidl_return) {
372     ATRACE_NAME("Vibrator::getCapabilities");
373 
374     int32_t ret = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
375                   IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_GET_RESONANT_FREQUENCY |
376                   IVibrator::CAP_GET_Q_FACTOR;
377     if (hasHapticAlsaDevice()) {
378         ret |= IVibrator::CAP_EXTERNAL_CONTROL;
379     } else {
380         ALOGE("No haptics ALSA device");
381     }
382     if (mHwApi->hasOwtFreeSpace()) {
383         ret |= IVibrator::CAP_COMPOSE_EFFECTS;
384         if (mIsChirpEnabled) {
385             ret |= IVibrator::CAP_FREQUENCY_CONTROL | IVibrator::CAP_COMPOSE_PWLE_EFFECTS;
386         }
387     }
388     *_aidl_return = ret;
389     return ndk::ScopedAStatus::ok();
390 }
391 
off()392 ndk::ScopedAStatus Vibrator::off() {
393     ATRACE_NAME("Vibrator::off");
394     bool ret{true};
395     const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
396 
397     if (mActiveId >= 0) {
398         /* Stop the active effect. */
399         if (!mHwApi->setFFPlay(mInputFd, mActiveId, false)) {
400             ALOGE("Failed to stop effect %d (%d): %s", mActiveId, errno, strerror(errno));
401             ret = false;
402         }
403 
404         if ((mActiveId >= WAVEFORM_MAX_PHYSICAL_INDEX) &&
405             (!mHwApi->eraseOwtEffect(mInputFd, mActiveId, &mFfEffects))) {
406             ALOGE("Failed to clean up the composed effect %d", mActiveId);
407             ret = false;
408         }
409     } else {
410         ALOGV("Vibrator is already off");
411     }
412 
413     mActiveId = -1;
414     setGlobalAmplitude(false);
415     if (mF0Offset) {
416         mHwApi->setF0Offset(0);
417     }
418 
419     if (ret) {
420         return ndk::ScopedAStatus::ok();
421     } else {
422         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
423     }
424 }
425 
on(int32_t timeoutMs,const std::shared_ptr<IVibratorCallback> & callback)426 ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs,
427                                 const std::shared_ptr<IVibratorCallback> &callback) {
428     ATRACE_NAME("Vibrator::on");
429     if (timeoutMs > MAX_TIME_MS) {
430         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
431     }
432     const uint16_t index = (timeoutMs < WAVEFORM_LONG_VIBRATION_THRESHOLD_MS)
433                                    ? WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX
434                                    : WAVEFORM_LONG_VIBRATION_EFFECT_INDEX;
435     if (MAX_COLD_START_LATENCY_MS <= MAX_TIME_MS - timeoutMs) {
436         timeoutMs += MAX_COLD_START_LATENCY_MS;
437     }
438     setGlobalAmplitude(true);
439     if (mF0Offset) {
440         mHwApi->setF0Offset(mF0Offset);
441     }
442     return on(timeoutMs, index, nullptr /*ignored*/, callback);
443 }
444 
perform(Effect effect,EffectStrength strength,const std::shared_ptr<IVibratorCallback> & callback,int32_t * _aidl_return)445 ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength strength,
446                                      const std::shared_ptr<IVibratorCallback> &callback,
447                                      int32_t *_aidl_return) {
448     ATRACE_NAME("Vibrator::perform");
449     return performEffect(effect, strength, callback, _aidl_return);
450 }
451 
getSupportedEffects(std::vector<Effect> * _aidl_return)452 ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect> *_aidl_return) {
453     *_aidl_return = {Effect::TEXTURE_TICK, Effect::TICK, Effect::CLICK, Effect::HEAVY_CLICK,
454                      Effect::DOUBLE_CLICK};
455     return ndk::ScopedAStatus::ok();
456 }
457 
setAmplitude(float amplitude)458 ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
459     ATRACE_NAME("Vibrator::setAmplitude");
460     if (amplitude <= 0.0f || amplitude > 1.0f) {
461         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
462     }
463 
464     mLongEffectScale = amplitude;
465     if (!isUnderExternalControl()) {
466         return setGlobalAmplitude(true);
467     } else {
468         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
469     }
470 }
471 
setExternalControl(bool enabled)472 ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) {
473     ATRACE_NAME("Vibrator::setExternalControl");
474     setGlobalAmplitude(enabled);
475 
476     if (mHasHapticAlsaDevice || mConfigHapticAlsaDeviceDone || hasHapticAlsaDevice()) {
477         if (!mHwApi->setHapticPcmAmp(&mHapticPcm, enabled, mCard, mDevice)) {
478             ALOGE("Failed to %s haptic pcm device: %d", (enabled ? "enable" : "disable"), mDevice);
479             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
480         }
481     } else {
482         ALOGE("No haptics ALSA device");
483         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
484     }
485 
486     mIsUnderExternalControl = enabled;
487     return ndk::ScopedAStatus::ok();
488 }
489 
getCompositionDelayMax(int32_t * maxDelayMs)490 ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t *maxDelayMs) {
491     ATRACE_NAME("Vibrator::getCompositionDelayMax");
492     *maxDelayMs = COMPOSE_DELAY_MAX_MS;
493     return ndk::ScopedAStatus::ok();
494 }
495 
getCompositionSizeMax(int32_t * maxSize)496 ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t *maxSize) {
497     ATRACE_NAME("Vibrator::getCompositionSizeMax");
498     *maxSize = COMPOSE_SIZE_MAX;
499     return ndk::ScopedAStatus::ok();
500 }
501 
getSupportedPrimitives(std::vector<CompositePrimitive> * supported)502 ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive> *supported) {
503     *supported = mSupportedPrimitives;
504     return ndk::ScopedAStatus::ok();
505 }
506 
getPrimitiveDuration(CompositePrimitive primitive,int32_t * durationMs)507 ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive primitive,
508                                                   int32_t *durationMs) {
509     ndk::ScopedAStatus status;
510     uint32_t effectIndex;
511     if (primitive != CompositePrimitive::NOOP) {
512         status = getPrimitiveDetails(primitive, &effectIndex);
513         if (!status.isOk()) {
514             return status;
515         }
516 
517         *durationMs = mEffectDurations[effectIndex];
518     } else {
519         *durationMs = 0;
520     }
521     return ndk::ScopedAStatus::ok();
522 }
523 
compose(const std::vector<CompositeEffect> & composite,const std::shared_ptr<IVibratorCallback> & callback)524 ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect> &composite,
525                                      const std::shared_ptr<IVibratorCallback> &callback) {
526     ATRACE_NAME("Vibrator::compose");
527     uint16_t size;
528     uint16_t nextEffectDelay;
529 
530     auto ch = dspmem_chunk_create(new uint8_t[FF_CUSTOM_DATA_LEN_MAX_COMP]{0x00},
531                                   FF_CUSTOM_DATA_LEN_MAX_COMP);
532 
533     if (composite.size() > COMPOSE_SIZE_MAX || composite.empty()) {
534         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
535     }
536 
537     /* Check if there is a wait before the first effect. */
538     nextEffectDelay = composite.front().delayMs;
539     if (nextEffectDelay > COMPOSE_DELAY_MAX_MS || nextEffectDelay < 0) {
540         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
541     } else if (nextEffectDelay > 0) {
542         size = composite.size() + 1;
543     } else {
544         size = composite.size();
545     }
546 
547     dspmem_chunk_write(ch, 8, 0);                      /* Padding */
548     dspmem_chunk_write(ch, 8, (uint8_t)(0xFF & size)); /* nsections */
549     dspmem_chunk_write(ch, 8, 0);                      /* repeat */
550     uint8_t header_count = dspmem_chunk_bytes(ch);
551 
552     /* Insert 1 section for a wait before the first effect. */
553     if (nextEffectDelay) {
554         dspmem_chunk_write(ch, 32, 0); /* amplitude, index, repeat & flags */
555         dspmem_chunk_write(ch, 16, (uint16_t)(0xFFFF & nextEffectDelay)); /* delay */
556     }
557 
558     for (uint32_t i_curr = 0, i_next = 1; i_curr < composite.size(); i_curr++, i_next++) {
559         auto &e_curr = composite[i_curr];
560         uint32_t effectIndex = 0;
561         uint32_t effectVolLevel = 0;
562         if (e_curr.scale < 0.0f || e_curr.scale > 1.0f) {
563             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
564         }
565 
566         if (e_curr.primitive != CompositePrimitive::NOOP) {
567             ndk::ScopedAStatus status;
568             status = getPrimitiveDetails(e_curr.primitive, &effectIndex);
569             if (!status.isOk()) {
570                 return status;
571             }
572             effectVolLevel = intensityToVolLevel(e_curr.scale, effectIndex);
573         }
574 
575         /* Fetch the next composite effect delay and fill into the current section */
576         nextEffectDelay = 0;
577         if (i_next < composite.size()) {
578             auto &e_next = composite[i_next];
579             int32_t delay = e_next.delayMs;
580 
581             if (delay > COMPOSE_DELAY_MAX_MS || delay < 0) {
582                 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
583             }
584             nextEffectDelay = delay;
585         }
586 
587         if (effectIndex == 0 && nextEffectDelay == 0) {
588             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
589         }
590 
591         dspmem_chunk_write(ch, 8, (uint8_t)(0xFF & effectVolLevel));      /* amplitude */
592         dspmem_chunk_write(ch, 8, (uint8_t)(0xFF & effectIndex));         /* index */
593         dspmem_chunk_write(ch, 8, 0);                                     /* repeat */
594         dspmem_chunk_write(ch, 8, 0);                                     /* flags */
595         dspmem_chunk_write(ch, 16, (uint16_t)(0xFFFF & nextEffectDelay)); /* delay */
596     }
597     dspmem_chunk_flush(ch);
598     if (header_count == dspmem_chunk_bytes(ch)) {
599         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
600     } else {
601         return performEffect(WAVEFORM_MAX_INDEX /*ignored*/, VOLTAGE_SCALE_MAX /*ignored*/, ch,
602                              callback);
603     }
604 }
605 
on(uint32_t timeoutMs,uint32_t effectIndex,dspmem_chunk * ch,const std::shared_ptr<IVibratorCallback> & callback)606 ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex, dspmem_chunk *ch,
607                                 const std::shared_ptr<IVibratorCallback> &callback) {
608     ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
609 
610     if (effectIndex >= FF_MAX_EFFECTS) {
611         ALOGE("Invalid waveform index %d", effectIndex);
612         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
613     }
614     if (mAsyncHandle.wait_for(ASYNC_COMPLETION_TIMEOUT) != std::future_status::ready) {
615         ALOGE("Previous vibration pending: prev: %d, curr: %d", mActiveId, effectIndex);
616         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
617     }
618 
619     if (ch) {
620         /* Upload OWT effect. */
621         if (ch->head == nullptr) {
622             ALOGE("Invalid OWT bank");
623             delete ch;
624             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
625         }
626         bool isPwle = (*reinterpret_cast<uint16_t *>(ch->head) != 0x0000);
627         effectIndex = isPwle ? WAVEFORM_PWLE : WAVEFORM_COMPOSE;
628 
629         uint32_t freeBytes;
630         mHwApi->getOwtFreeSpace(&freeBytes);
631         if (dspmem_chunk_bytes(ch) > freeBytes) {
632             ALOGE("Invalid OWT length: Effect %d: %d > %d!", effectIndex, dspmem_chunk_bytes(ch),
633                   freeBytes);
634             delete ch;
635             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
636         }
637         int errorStatus;
638         if (!mHwApi->uploadOwtEffect(mInputFd, ch->head, dspmem_chunk_bytes(ch),
639                                      &mFfEffects[effectIndex], &effectIndex, &errorStatus)) {
640             delete ch;
641             ALOGE("Invalid uploadOwtEffect");
642             return ndk::ScopedAStatus::fromExceptionCode(errorStatus);
643         }
644         delete ch;
645 
646     } else if (effectIndex == WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX ||
647                effectIndex == WAVEFORM_LONG_VIBRATION_EFFECT_INDEX) {
648         /* Update duration for long/short vibration. */
649         mFfEffects[effectIndex].replay.length = static_cast<uint16_t>(timeoutMs);
650         if (!mHwApi->setFFEffect(mInputFd, &mFfEffects[effectIndex],
651                                  static_cast<uint16_t>(timeoutMs))) {
652             ALOGE("Failed to edit effect %d (%d): %s", effectIndex, errno, strerror(errno));
653             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
654         }
655     }
656 
657     const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
658     mActiveId = effectIndex;
659     /* Play the event now. */
660     if (!mHwApi->setFFPlay(mInputFd, effectIndex, true)) {
661         ALOGE("Failed to play effect %d (%d): %s", effectIndex, errno, strerror(errno));
662         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
663     }
664 
665     mAsyncHandle = std::async(&Vibrator::waitForComplete, this, callback);
666     return ndk::ScopedAStatus::ok();
667 }
668 
setEffectAmplitude(float amplitude,float maximum)669 ndk::ScopedAStatus Vibrator::setEffectAmplitude(float amplitude, float maximum) {
670     uint16_t scale = amplitudeToScale(amplitude, maximum);
671     if (!mHwApi->setFFGain(mInputFd, scale)) {
672         ALOGE("Failed to set the gain to %u (%d): %s", scale, errno, strerror(errno));
673         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
674     }
675     return ndk::ScopedAStatus::ok();
676 }
677 
setGlobalAmplitude(bool set)678 ndk::ScopedAStatus Vibrator::setGlobalAmplitude(bool set) {
679     uint8_t amplitude = set ? roundf(mLongEffectScale * mLongEffectVol[1]) : VOLTAGE_SCALE_MAX;
680     if (!set) {
681         mLongEffectScale = 1.0;  // Reset the scale for the later new effect.
682     }
683     return setEffectAmplitude(amplitude, VOLTAGE_SCALE_MAX);
684 }
685 
getSupportedAlwaysOnEffects(std::vector<Effect> *)686 ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect> * /*_aidl_return*/) {
687     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
688 }
689 
alwaysOnEnable(int32_t,Effect,EffectStrength)690 ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t /*id*/, Effect /*effect*/,
691                                             EffectStrength /*strength*/) {
692     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
693 }
alwaysOnDisable(int32_t)694 ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t /*id*/) {
695     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
696 }
697 
getResonantFrequency(float * resonantFreqHz)698 ndk::ScopedAStatus Vibrator::getResonantFrequency(float *resonantFreqHz) {
699     std::string caldata{8, '0'};
700     if (!mHwCal->getF0(&caldata)) {
701         ALOGE("Failed to get resonant frequency (%d): %s", errno, strerror(errno));
702         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
703     }
704     *resonantFreqHz = static_cast<float>(std::stoul(caldata, nullptr, 16)) / (1 << Q14_BIT_SHIFT);
705 
706     return ndk::ScopedAStatus::ok();
707 }
708 
getQFactor(float * qFactor)709 ndk::ScopedAStatus Vibrator::getQFactor(float *qFactor) {
710     std::string caldata{8, '0'};
711     if (!mHwCal->getQ(&caldata)) {
712         ALOGE("Failed to get q factor (%d): %s", errno, strerror(errno));
713         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
714     }
715     *qFactor = static_cast<float>(std::stoul(caldata, nullptr, 16)) / (1 << Q16_BIT_SHIFT);
716 
717     return ndk::ScopedAStatus::ok();
718 }
719 
getFrequencyResolution(float * freqResolutionHz)720 ndk::ScopedAStatus Vibrator::getFrequencyResolution(float *freqResolutionHz) {
721     int32_t capabilities;
722     Vibrator::getCapabilities(&capabilities);
723     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
724         *freqResolutionHz = PWLE_FREQUENCY_RESOLUTION_HZ;
725         return ndk::ScopedAStatus::ok();
726     } else {
727         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
728     }
729 }
730 
getFrequencyMinimum(float * freqMinimumHz)731 ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float *freqMinimumHz) {
732     int32_t capabilities;
733     Vibrator::getCapabilities(&capabilities);
734     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
735         *freqMinimumHz = PWLE_FREQUENCY_MIN_HZ;
736         return ndk::ScopedAStatus::ok();
737     } else {
738         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
739     }
740 }
741 
getBandwidthAmplitudeMap(std::vector<float> * _aidl_return)742 ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float> *_aidl_return) {
743     // TODO(b/170919640): complete implementation
744     int32_t capabilities;
745     Vibrator::getCapabilities(&capabilities);
746     if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
747         std::vector<float> bandwidthAmplitudeMap(PWLE_BW_MAP_SIZE, 1.0);
748         *_aidl_return = bandwidthAmplitudeMap;
749         return ndk::ScopedAStatus::ok();
750     } else {
751         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
752     }
753 }
754 
getPwlePrimitiveDurationMax(int32_t * durationMs)755 ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t *durationMs) {
756     int32_t capabilities;
757     Vibrator::getCapabilities(&capabilities);
758     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
759         *durationMs = COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS;
760         return ndk::ScopedAStatus::ok();
761     } else {
762         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
763     }
764 }
765 
getPwleCompositionSizeMax(int32_t * maxSize)766 ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t *maxSize) {
767     int32_t capabilities;
768     Vibrator::getCapabilities(&capabilities);
769     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
770         *maxSize = COMPOSE_PWLE_SIZE_MAX_DEFAULT;
771         return ndk::ScopedAStatus::ok();
772     } else {
773         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
774     }
775 }
776 
getSupportedBraking(std::vector<Braking> * supported)777 ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking> *supported) {
778     int32_t capabilities;
779     Vibrator::getCapabilities(&capabilities);
780     if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
781         *supported = {
782                 Braking::NONE,
783         };
784         return ndk::ScopedAStatus::ok();
785     } else {
786         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
787     }
788 }
789 
resetPreviousEndAmplitudeEndFrequency(float * prevEndAmplitude,float * prevEndFrequency)790 static void resetPreviousEndAmplitudeEndFrequency(float *prevEndAmplitude,
791                                                   float *prevEndFrequency) {
792     const float reset = -1.0;
793     *prevEndAmplitude = reset;
794     *prevEndFrequency = reset;
795 }
796 
incrementIndex(int * index)797 static void incrementIndex(int *index) {
798     *index += 1;
799 }
800 
constructPwleSegment(dspmem_chunk * ch,uint16_t delay,uint16_t amplitude,uint16_t frequency,uint8_t flags,uint32_t vbemfTarget=0)801 static void constructPwleSegment(dspmem_chunk *ch, uint16_t delay, uint16_t amplitude,
802                                  uint16_t frequency, uint8_t flags, uint32_t vbemfTarget = 0) {
803     dspmem_chunk_write(ch, 16, delay);
804     dspmem_chunk_write(ch, 12, amplitude);
805     dspmem_chunk_write(ch, 12, frequency);
806     /* feature flags to control the chirp, CLAB braking, back EMF amplitude regulation */
807     dspmem_chunk_write(ch, 8, (flags | 1) << 4);
808     if (flags & PWLE_AMP_REG_BIT) {
809         dspmem_chunk_write(ch, 24, vbemfTarget); /* target back EMF voltage */
810     }
811 }
812 
constructActiveSegment(dspmem_chunk * ch,int duration,float amplitude,float frequency,bool chirp)813 static int constructActiveSegment(dspmem_chunk *ch, int duration, float amplitude, float frequency,
814                                   bool chirp) {
815     uint16_t delay = 0;
816     uint16_t amp = 0;
817     uint16_t freq = 0;
818     uint8_t flags = 0x0;
819     if ((floatToUint16(duration, &delay, 4, 0.0f, COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) < 0) ||
820         (floatToUint16(amplitude, &amp, 2048, CS40L26_PWLE_LEVEL_MIX, CS40L26_PWLE_LEVEL_MAX) <
821          0) ||
822         (floatToUint16(frequency, &freq, 4, PWLE_FREQUENCY_MIN_HZ, PWLE_FREQUENCY_MAX_HZ) < 0)) {
823         ALOGE("Invalid argument: %d, %f, %f", duration, amplitude, frequency);
824         return -ERANGE;
825     }
826     if (chirp) {
827         flags |= PWLE_CHIRP_BIT;
828     }
829     constructPwleSegment(ch, delay, amp, freq, flags, 0 /*ignored*/);
830     return 0;
831 }
832 
constructBrakingSegment(dspmem_chunk * ch,int duration,Braking brakingType)833 static int constructBrakingSegment(dspmem_chunk *ch, int duration, Braking brakingType) {
834     uint16_t delay = 0;
835     uint16_t freq = 0;
836     uint8_t flags = 0x00;
837     if (floatToUint16(duration, &delay, 4, 0.0f, COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) < 0) {
838         ALOGE("Invalid argument: %d", duration);
839         return -ERANGE;
840     }
841     floatToUint16(PWLE_FREQUENCY_MIN_HZ, &freq, 4, PWLE_FREQUENCY_MIN_HZ, PWLE_FREQUENCY_MAX_HZ);
842     if (static_cast<std::underlying_type<Braking>::type>(brakingType)) {
843         flags |= PWLE_BRAKE_BIT;
844     }
845 
846     constructPwleSegment(ch, delay, 0 /*ignored*/, freq, flags, 0 /*ignored*/);
847     return 0;
848 }
849 
updateWLength(dspmem_chunk * ch,uint32_t totalDuration)850 static void updateWLength(dspmem_chunk *ch, uint32_t totalDuration) {
851     totalDuration *= 8;            /* Unit: 0.125 ms (since wlength played @ 8kHz). */
852     totalDuration |= WT_LEN_CALCD; /* Bit 23 is for WT_LEN_CALCD; Bit 22 is for WT_INDEFINITE. */
853     *(ch->head + 0) = (totalDuration >> 24) & 0xFF;
854     *(ch->head + 1) = (totalDuration >> 16) & 0xFF;
855     *(ch->head + 2) = (totalDuration >> 8) & 0xFF;
856     *(ch->head + 3) = totalDuration & 0xFF;
857 }
858 
updateNSection(dspmem_chunk * ch,int segmentIdx)859 static void updateNSection(dspmem_chunk *ch, int segmentIdx) {
860     *(ch->head + 7) |= (0xF0 & segmentIdx) >> 4; /* Bit 4 to 7 */
861     *(ch->head + 9) |= (0x0F & segmentIdx) << 4; /* Bit 3 to 0 */
862 }
863 
composePwle(const std::vector<PrimitivePwle> & composite,const std::shared_ptr<IVibratorCallback> & callback)864 ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle> &composite,
865                                          const std::shared_ptr<IVibratorCallback> &callback) {
866     ATRACE_NAME("Vibrator::composePwle");
867     int32_t capabilities;
868 
869     Vibrator::getCapabilities(&capabilities);
870     if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) == 0) {
871         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
872     }
873 
874     if (composite.empty() || composite.size() > COMPOSE_PWLE_SIZE_MAX_DEFAULT) {
875         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
876     }
877 
878     std::vector<Braking> supported;
879     Vibrator::getSupportedBraking(&supported);
880     bool isClabSupported =
881             std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
882 
883     int segmentIdx = 0;
884     uint32_t totalDuration = 0;
885     float prevEndAmplitude;
886     float prevEndFrequency;
887     resetPreviousEndAmplitudeEndFrequency(&prevEndAmplitude, &prevEndFrequency);
888     auto ch = dspmem_chunk_create(new uint8_t[FF_CUSTOM_DATA_LEN_MAX_PWLE]{0x00},
889                                   FF_CUSTOM_DATA_LEN_MAX_PWLE);
890     bool chirp = false;
891 
892     dspmem_chunk_write(ch, 24, 0x000000); /* Waveform length placeholder */
893     dspmem_chunk_write(ch, 8, 0);         /* Repeat */
894     dspmem_chunk_write(ch, 12, 0);        /* Wait time between repeats */
895     dspmem_chunk_write(ch, 8, 0x00);      /* nsections placeholder */
896 
897     for (auto &e : composite) {
898         switch (e.getTag()) {
899             case PrimitivePwle::active: {
900                 auto active = e.get<PrimitivePwle::active>();
901                 if (active.duration < 0 ||
902                     active.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
903                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
904                 }
905                 if (active.startAmplitude < PWLE_LEVEL_MIN ||
906                     active.startAmplitude > PWLE_LEVEL_MAX ||
907                     active.endAmplitude < PWLE_LEVEL_MIN || active.endAmplitude > PWLE_LEVEL_MAX) {
908                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
909                 }
910                 if (active.startAmplitude > CS40L26_PWLE_LEVEL_MAX) {
911                     active.startAmplitude = CS40L26_PWLE_LEVEL_MAX;
912                 }
913                 if (active.endAmplitude > CS40L26_PWLE_LEVEL_MAX) {
914                     active.endAmplitude = CS40L26_PWLE_LEVEL_MAX;
915                 }
916 
917                 if (active.startFrequency < PWLE_FREQUENCY_MIN_HZ ||
918                     active.startFrequency > PWLE_FREQUENCY_MAX_HZ ||
919                     active.endFrequency < PWLE_FREQUENCY_MIN_HZ ||
920                     active.endFrequency > PWLE_FREQUENCY_MAX_HZ) {
921                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
922                 }
923 
924                 if (!((active.startAmplitude == prevEndAmplitude) &&
925                       (active.startFrequency == prevEndFrequency))) {
926                     if (constructActiveSegment(ch, 0, active.startAmplitude, active.startFrequency,
927                                                false) < 0) {
928                         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
929                     }
930                     incrementIndex(&segmentIdx);
931                 }
932 
933                 if (active.startFrequency != active.endFrequency) {
934                     chirp = true;
935                 }
936                 if (constructActiveSegment(ch, active.duration, active.endAmplitude,
937                                            active.endFrequency, chirp) < 0) {
938                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
939                 }
940                 incrementIndex(&segmentIdx);
941 
942                 prevEndAmplitude = active.endAmplitude;
943                 prevEndFrequency = active.endFrequency;
944                 totalDuration += active.duration;
945                 chirp = false;
946                 break;
947             }
948             case PrimitivePwle::braking: {
949                 auto braking = e.get<PrimitivePwle::braking>();
950                 if (braking.braking > Braking::CLAB) {
951                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
952                 } else if (!isClabSupported && (braking.braking == Braking::CLAB)) {
953                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
954                 }
955 
956                 if (braking.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
957                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
958                 }
959 
960                 if (constructBrakingSegment(ch, 0, braking.braking) < 0) {
961                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
962                 }
963                 incrementIndex(&segmentIdx);
964 
965                 if (constructBrakingSegment(ch, braking.duration, braking.braking) < 0) {
966                     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
967                 }
968                 incrementIndex(&segmentIdx);
969 
970                 resetPreviousEndAmplitudeEndFrequency(&prevEndAmplitude, &prevEndFrequency);
971                 totalDuration += braking.duration;
972                 break;
973             }
974         }
975 
976         if (segmentIdx > COMPOSE_PWLE_SIZE_MAX_DEFAULT) {
977             ALOGE("Too many PrimitivePwle section!");
978             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
979         }
980     }
981     dspmem_chunk_flush(ch);
982 
983     /* Update wlength */
984     totalDuration += MAX_COLD_START_LATENCY_MS;
985     if (totalDuration > 0x7FFFF) {
986         ALOGE("Total duration is too long (%d)!", totalDuration);
987         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
988     }
989     updateWLength(ch, totalDuration);
990 
991     /* Update nsections */
992     updateNSection(ch, segmentIdx);
993 
994     return performEffect(WAVEFORM_MAX_INDEX /*ignored*/, VOLTAGE_SCALE_MAX /*ignored*/, ch,
995                          callback);
996 }
997 
isUnderExternalControl()998 bool Vibrator::isUnderExternalControl() {
999     return mIsUnderExternalControl;
1000 }
1001 
dump(int fd,const char ** args,uint32_t numArgs)1002 binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) {
1003     if (fd < 0) {
1004         ALOGE("Called debug() with invalid fd.");
1005         return STATUS_OK;
1006     }
1007 
1008     (void)args;
1009     (void)numArgs;
1010 
1011     dprintf(fd, "AIDL:\n");
1012 
1013     dprintf(fd, "  F0 Offset: %" PRIu32 "\n", mF0Offset);
1014 
1015     dprintf(fd, "  Voltage Levels:\n");
1016     dprintf(fd, "    Tick Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mTickEffectVol[0],
1017             mTickEffectVol[1]);
1018     dprintf(fd, "    Click Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mClickEffectVol[0],
1019             mClickEffectVol[1]);
1020     dprintf(fd, "    Long Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mLongEffectVol[0],
1021             mLongEffectVol[1]);
1022 
1023     dprintf(fd, "  FF effect:\n");
1024     dprintf(fd, "    Physical waveform:\n");
1025     dprintf(fd, "\tId\tIndex\tt   ->\tt'\n");
1026     for (uint8_t effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) {
1027         dprintf(fd, "\t%d\t%d\t%d\t%d\n", mFfEffects[effectId].id,
1028                 mFfEffects[effectId].u.periodic.custom_data[1], mEffectDurations[effectId],
1029                 mFfEffects[effectId].replay.length);
1030     }
1031     dprintf(fd, "    OWT waveform:\n");
1032     dprintf(fd, "\tId\tBytes\tData\n");
1033     for (uint8_t effectId = WAVEFORM_MAX_PHYSICAL_INDEX; effectId < WAVEFORM_MAX_INDEX;
1034          effectId++) {
1035         uint32_t numBytes = mFfEffects[effectId].u.periodic.custom_len * 2;
1036         std::stringstream ss;
1037         ss << " ";
1038         for (int i = 0; i < numBytes; i++) {
1039             ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex
1040                << (uint16_t)(*(
1041                           reinterpret_cast<uint8_t *>(mFfEffects[effectId].u.periodic.custom_data) +
1042                           i))
1043                << " ";
1044         }
1045         dprintf(fd, "\t%d\t%d\t{%s}\n", mFfEffects[effectId].id, numBytes, ss.str().c_str());
1046     }
1047 
1048     dprintf(fd, "\n");
1049     dprintf(fd, "\n");
1050 
1051     mHwApi->debug(fd);
1052 
1053     dprintf(fd, "\n");
1054 
1055     mHwCal->debug(fd);
1056 
1057     fsync(fd);
1058     return STATUS_OK;
1059 }
1060 
hasHapticAlsaDevice()1061 bool Vibrator::hasHapticAlsaDevice() {
1062     // We need to call findHapticAlsaDevice once only. Calling in the
1063     // constructor is too early in the boot process and the pcm file contents
1064     // are empty. Hence we make the call here once only right before we need to.
1065     if (!mConfigHapticAlsaDeviceDone) {
1066         if (mHwApi->getHapticAlsaDevice(&mCard, &mDevice)) {
1067             mHasHapticAlsaDevice = true;
1068             mConfigHapticAlsaDeviceDone = true;
1069         } else {
1070             ALOGE("Haptic ALSA device not supported");
1071         }
1072     } else {
1073         ALOGD("Haptic ALSA device configuration done.");
1074     }
1075     return mHasHapticAlsaDevice;
1076 }
1077 
getSimpleDetails(Effect effect,EffectStrength strength,uint32_t * outEffectIndex,uint32_t * outTimeMs,uint32_t * outVolLevel)1078 ndk::ScopedAStatus Vibrator::getSimpleDetails(Effect effect, EffectStrength strength,
1079                                               uint32_t *outEffectIndex, uint32_t *outTimeMs,
1080                                               uint32_t *outVolLevel) {
1081     uint32_t effectIndex;
1082     uint32_t timeMs;
1083     float intensity;
1084     uint32_t volLevel;
1085     switch (strength) {
1086         case EffectStrength::LIGHT:
1087             intensity = 0.5f;
1088             break;
1089         case EffectStrength::MEDIUM:
1090             intensity = 0.7f;
1091             break;
1092         case EffectStrength::STRONG:
1093             intensity = 1.0f;
1094             break;
1095         default:
1096             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1097     }
1098 
1099     switch (effect) {
1100         case Effect::TEXTURE_TICK:
1101             effectIndex = WAVEFORM_LIGHT_TICK_INDEX;
1102             intensity *= 0.5f;
1103             break;
1104         case Effect::TICK:
1105             effectIndex = WAVEFORM_CLICK_INDEX;
1106             intensity *= 0.5f;
1107             break;
1108         case Effect::CLICK:
1109             effectIndex = WAVEFORM_CLICK_INDEX;
1110             intensity *= 0.7f;
1111             break;
1112         case Effect::HEAVY_CLICK:
1113             effectIndex = WAVEFORM_CLICK_INDEX;
1114             intensity *= 1.0f;
1115             break;
1116         default:
1117             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1118     }
1119 
1120     volLevel = intensityToVolLevel(intensity, effectIndex);
1121     timeMs = mEffectDurations[effectIndex] + MAX_COLD_START_LATENCY_MS;
1122 
1123     *outEffectIndex = effectIndex;
1124     *outTimeMs = timeMs;
1125     *outVolLevel = volLevel;
1126     return ndk::ScopedAStatus::ok();
1127 }
1128 
getCompoundDetails(Effect effect,EffectStrength strength,uint32_t * outTimeMs,dspmem_chunk * outCh)1129 ndk::ScopedAStatus Vibrator::getCompoundDetails(Effect effect, EffectStrength strength,
1130                                                 uint32_t *outTimeMs, dspmem_chunk *outCh) {
1131     ndk::ScopedAStatus status;
1132     uint32_t timeMs = 0;
1133     uint32_t thisEffectIndex;
1134     uint32_t thisTimeMs;
1135     uint32_t thisVolLevel;
1136     switch (effect) {
1137         case Effect::DOUBLE_CLICK:
1138             dspmem_chunk_write(outCh, 8, 0); /* Padding */
1139             dspmem_chunk_write(outCh, 8, 2); /* nsections */
1140             dspmem_chunk_write(outCh, 8, 0); /* repeat */
1141 
1142             status = getSimpleDetails(Effect::CLICK, strength, &thisEffectIndex, &thisTimeMs,
1143                                       &thisVolLevel);
1144             if (!status.isOk()) {
1145                 return status;
1146             }
1147             timeMs += thisTimeMs;
1148 
1149             dspmem_chunk_write(outCh, 8, (uint8_t)(0xFF & thisVolLevel));    /* amplitude */
1150             dspmem_chunk_write(outCh, 8, (uint8_t)(0xFF & thisEffectIndex)); /* index */
1151             dspmem_chunk_write(outCh, 8, 0);                                 /* repeat */
1152             dspmem_chunk_write(outCh, 8, 0);                                 /* flags */
1153             dspmem_chunk_write(outCh, 16,
1154                                (uint16_t)(0xFFFF & WAVEFORM_DOUBLE_CLICK_SILENCE_MS)); /* delay */
1155 
1156             timeMs += WAVEFORM_DOUBLE_CLICK_SILENCE_MS + MAX_PAUSE_TIMING_ERROR_MS;
1157 
1158             status = getSimpleDetails(Effect::HEAVY_CLICK, strength, &thisEffectIndex, &thisTimeMs,
1159                                       &thisVolLevel);
1160             if (!status.isOk()) {
1161                 return status;
1162             }
1163             timeMs += thisTimeMs;
1164 
1165             dspmem_chunk_write(outCh, 8, (uint8_t)(0xFF & thisVolLevel));    /* amplitude */
1166             dspmem_chunk_write(outCh, 8, (uint8_t)(0xFF & thisEffectIndex)); /* index */
1167             dspmem_chunk_write(outCh, 8, 0);                                 /* repeat */
1168             dspmem_chunk_write(outCh, 8, 0);                                 /* flags */
1169             dspmem_chunk_write(outCh, 16, 0);                                /* delay */
1170             dspmem_chunk_flush(outCh);
1171 
1172             break;
1173         default:
1174             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1175     }
1176 
1177     *outTimeMs = timeMs;
1178 
1179     return ndk::ScopedAStatus::ok();
1180 }
1181 
getPrimitiveDetails(CompositePrimitive primitive,uint32_t * outEffectIndex)1182 ndk::ScopedAStatus Vibrator::getPrimitiveDetails(CompositePrimitive primitive,
1183                                                  uint32_t *outEffectIndex) {
1184     uint32_t effectIndex;
1185     uint32_t primitiveBit = 1 << int32_t(primitive);
1186     if ((primitiveBit & mSupportedPrimitivesBits) == 0x0) {
1187         return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1188     }
1189 
1190     switch (primitive) {
1191         case CompositePrimitive::NOOP:
1192             return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1193         case CompositePrimitive::CLICK:
1194             effectIndex = WAVEFORM_CLICK_INDEX;
1195             break;
1196         case CompositePrimitive::THUD:
1197             effectIndex = WAVEFORM_THUD_INDEX;
1198             break;
1199         case CompositePrimitive::SPIN:
1200             effectIndex = WAVEFORM_SPIN_INDEX;
1201             break;
1202         case CompositePrimitive::QUICK_RISE:
1203             effectIndex = WAVEFORM_QUICK_RISE_INDEX;
1204             break;
1205         case CompositePrimitive::SLOW_RISE:
1206             effectIndex = WAVEFORM_SLOW_RISE_INDEX;
1207             break;
1208         case CompositePrimitive::QUICK_FALL:
1209             effectIndex = WAVEFORM_QUICK_FALL_INDEX;
1210             break;
1211         case CompositePrimitive::LIGHT_TICK:
1212             effectIndex = WAVEFORM_LIGHT_TICK_INDEX;
1213             break;
1214         case CompositePrimitive::LOW_TICK:
1215             effectIndex = WAVEFORM_LOW_TICK_INDEX;
1216             break;
1217         default:
1218             return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1219     }
1220 
1221     *outEffectIndex = effectIndex;
1222 
1223     return ndk::ScopedAStatus::ok();
1224 }
1225 
performEffect(Effect effect,EffectStrength strength,const std::shared_ptr<IVibratorCallback> & callback,int32_t * outTimeMs)1226 ndk::ScopedAStatus Vibrator::performEffect(Effect effect, EffectStrength strength,
1227                                            const std::shared_ptr<IVibratorCallback> &callback,
1228                                            int32_t *outTimeMs) {
1229     ndk::ScopedAStatus status;
1230     uint32_t effectIndex;
1231     uint32_t timeMs = 0;
1232     uint32_t volLevel;
1233     dspmem_chunk *ch = nullptr;
1234     switch (effect) {
1235         case Effect::TEXTURE_TICK:
1236             // fall-through
1237         case Effect::TICK:
1238             // fall-through
1239         case Effect::CLICK:
1240             // fall-through
1241         case Effect::HEAVY_CLICK:
1242             status = getSimpleDetails(effect, strength, &effectIndex, &timeMs, &volLevel);
1243             break;
1244         case Effect::DOUBLE_CLICK:
1245             ch = dspmem_chunk_create(new uint8_t[FF_CUSTOM_DATA_LEN_MAX_COMP]{0x00},
1246                                      FF_CUSTOM_DATA_LEN_MAX_COMP);
1247             status = getCompoundDetails(effect, strength, &timeMs, ch);
1248             volLevel = VOLTAGE_SCALE_MAX;
1249             break;
1250         default:
1251             status = ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1252             break;
1253     }
1254     if (!status.isOk()) {
1255         goto exit;
1256     }
1257 
1258     status = performEffect(effectIndex, volLevel, ch, callback);
1259 
1260 exit:
1261     *outTimeMs = timeMs;
1262     return status;
1263 }
1264 
performEffect(uint32_t effectIndex,uint32_t volLevel,dspmem_chunk * ch,const std::shared_ptr<IVibratorCallback> & callback)1265 ndk::ScopedAStatus Vibrator::performEffect(uint32_t effectIndex, uint32_t volLevel,
1266                                            dspmem_chunk *ch,
1267                                            const std::shared_ptr<IVibratorCallback> &callback) {
1268     setEffectAmplitude(volLevel, VOLTAGE_SCALE_MAX);
1269 
1270     return on(MAX_TIME_MS, effectIndex, ch, callback);
1271 }
1272 
waitForComplete(std::shared_ptr<IVibratorCallback> && callback)1273 void Vibrator::waitForComplete(std::shared_ptr<IVibratorCallback> &&callback) {
1274     if (!mHwApi->pollVibeState(VIBE_STATE_HAPTIC, POLLING_TIMEOUT)) {
1275         ALOGW("Failed to get state \"Haptic\"");
1276     }
1277     mHwApi->pollVibeState(VIBE_STATE_STOPPED);
1278 
1279     const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
1280     uint32_t effectCount = WAVEFORM_MAX_PHYSICAL_INDEX;
1281     if ((mActiveId >= WAVEFORM_MAX_PHYSICAL_INDEX) &&
1282         (!mHwApi->eraseOwtEffect(mInputFd, mActiveId, &mFfEffects))) {
1283         ALOGE("Failed to clean up the composed effect %d", mActiveId);
1284     } else {
1285         ALOGD("waitForComplete: Vibrator is already off");
1286     }
1287     mHwApi->getEffectCount(&effectCount);
1288     // Do waveform number checking
1289     if ((effectCount > WAVEFORM_MAX_PHYSICAL_INDEX) &&
1290         (!mHwApi->eraseOwtEffect(mInputFd, WAVEFORM_MAX_INDEX, &mFfEffects))) {
1291         ALOGE("Failed to forcibly clean up all composed effect");
1292     }
1293 
1294     mActiveId = -1;
1295 
1296     if (callback) {
1297         auto ret = callback->onComplete();
1298         if (!ret.isOk()) {
1299             ALOGE("Failed completion callback: %d", ret.getExceptionCode());
1300         }
1301     }
1302 }
1303 
intensityToVolLevel(float intensity,uint32_t effectIndex)1304 uint32_t Vibrator::intensityToVolLevel(float intensity, uint32_t effectIndex) {
1305     uint32_t volLevel;
1306     auto calc = [](float intst, std::array<uint32_t, 2> v) -> uint32_t {
1307         return std::lround(intst * (v[1] - v[0])) + v[0];
1308     };
1309 
1310     switch (effectIndex) {
1311         case WAVEFORM_LIGHT_TICK_INDEX:
1312             volLevel = calc(intensity, mTickEffectVol);
1313             break;
1314         case WAVEFORM_QUICK_RISE_INDEX:
1315             // fall-through
1316         case WAVEFORM_QUICK_FALL_INDEX:
1317             volLevel = calc(intensity, mLongEffectVol);
1318             break;
1319         case WAVEFORM_CLICK_INDEX:
1320             // fall-through
1321         case WAVEFORM_THUD_INDEX:
1322             // fall-through
1323         case WAVEFORM_SPIN_INDEX:
1324             // fall-through
1325         case WAVEFORM_SLOW_RISE_INDEX:
1326             // fall-through
1327         default:
1328             volLevel = calc(intensity, mClickEffectVol);
1329             break;
1330     }
1331     return volLevel;
1332 }
1333 
1334 }  // namespace vibrator
1335 }  // namespace hardware
1336 }  // namespace android
1337 }  // namespace aidl
1338