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